By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,876 Members | 1,239 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,876 IT Pros & Developers. It's quick & easy.

updating deprecated sys_errlist? Simple Question?

P: n/a
Hi there,

First I'll apologise for my ignorance!

I have been attempting to compile some code that I found on the net.

AFAICT it's intended to be portable code (it was available as source and
as a DOS binary, but mention was made of UNIX in the readme - I am
compiling under Mac OS X, fwiw).

It probably once was portable, but apparently uses some obsolete
snippets because it wouldn't compile without some changes.

After searching the web I managed to get the code to compile but it
required that I simplify some error handling which I feel ought to be
better 'updated'.

Here are the relevant bits:
//#include <malloc.h> // commented out by me
#include <stdlib.h> // added by me

//plenty of unaltered code snipped

FILE *
efopen(name,mode)
char *name;
char *mode;
{
FILE *f;
extern int errno;

// extern char *sys_errlist[]; // commented out by me
// extern int sys_nerr; // commented out by me

char *errmess;

if ( (f=fopen(name,mode)) == NULL ) {
(void) fprintf(stderr,"*** ERROR *** Cannot open '%s'!\n",name);

/* // this chunk commented out by me

if ( errno <= sys_nerr )
errmess = sys_errlist[errno];
else
errmess = "Unknown error!";

*/

errmess = strerror(errno); // added by me

(void) fprintf(stderr,"************* Reason: %s\n",errmess);
exit(1);
}
return(f);
}

This code compiles just fine, and it also works as intended, but I
assume it will fail much less gracefully if I send a 'bad' file to the
program.

I assume I did the right thing changing the #include directive from
malloc.h to stdlib.h

I realised I needed to find a more modern equivalent of sys_errlist and
sys_nerr, - a web search led me to discover that sys_errlist is
deprecated, and to put together the single line I added.

I also learned that strerror is provided by stdio.h (which was already
#included). All well and good, but I have no clue how to reinstate the
'if' test and make the error handling more robust.

Thanks in advance for any assistance!
Mar 19 '06 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Brennan Young opined:
Hi there,

First I'll apologise for my ignorance!

I have been attempting to compile some code that I found on the net.

AFAICT it's intended to be portable code (it was available as source
and as a DOS binary, but mention was made of UNIX in the readme - I
am compiling under Mac OS X, fwiw).

It probably once was portable, but apparently uses some obsolete
snippets because it wouldn't compile without some changes.

After searching the web I managed to get the code to compile but it
required that I simplify some error handling which I feel ought to be
better 'updated'.

Here are the relevant bits:
//#include <malloc.h> // commented out by me
#include <stdlib.h> // added by me
#include <errno.h>
#include <string.h>

You'll need it below...

//plenty of unaltered code snipped

FILE *
efopen(name,mode)
char *name;
char *mode;
This is ancient style. It's better:

FILE *efopen(char *name, char *mode)
{
FILE *f;
extern int errno;
Now you don't need the line above (errno is declared in errno.h).
// extern char *sys_errlist[]; // commented out by me
// extern int sys_nerr; // commented out by me
This is some ancient, system-specific system of mapping error messages
to error codes. Now you should use `strerr()`.
char *errmess;
You could put:

errno = 0;

as the Standard only specifies that it's set to 0 at program startup,
and library function /may/ set it to positive value (NB, error or no
error!), but never to zero. Here's also the relevant paragraph from
the Standard:

7.5p3
The value of errno is zero at program startup, but is never set
to zero by any library function. The value of errno may be
set to nonzero by a library function call whether or not there
is an error, provided the use of errno is not documented in the
description of the function in this International Standard.
if ( (f=fopen(name,mode)) == NULL ) {
(void) fprintf(stderr,"*** ERROR *** Cannot open
'%s'!\n",name);

/* // this chunk commented out by me

if ( errno <= sys_nerr )
errmess = sys_errlist[errno];
else
errmess = "Unknown error!";

*/
if (errno)
errmess = strerror(errno); // added by me

Is what you want here.

(void) fprintf(stderr,"************* Reason: %s\n",errmess);
exit(1);
}
return(f);
}

This code compiles just fine, and it also works as intended, but I
assume it will fail much less gracefully if I send a 'bad' file to
the program.
It may, or it may not, depending on the implementation. I think
Standard does not guarantee that `strerror()` will return anything
sensible (it just talks of returning a pointer to "a message").
I assume I did the right thing changing the #include directive from
malloc.h to stdlib.h
Yes. You also need <errno.h> and <string.h> for error handling.
I realised I needed to find a more modern equivalent of sys_errlist
and sys_nerr, - a web search led me to discover that sys_errlist is
deprecated, and to put together the single line I added.

I also learned that strerror is provided by stdio.h (which was
already #included).


I think it's only in <string.h>, but may be wrong.

HTH

--
BR, Vladimir

You will pioneer the first Martian colony.

Mar 19 '06 #2

P: n/a
Brennan Young wrote:
Hi there,

First I'll apologise for my ignorance!

I have been attempting to compile some code that I found on the net.

AFAICT it's intended to be portable code (it was available as source and
as a DOS binary, but mention was made of UNIX in the readme - I am
compiling under Mac OS X, fwiw).

It probably once was portable, but apparently uses some obsolete
snippets because it wouldn't compile without some changes.

After searching the web I managed to get the code to compile but it
required that I simplify some error handling which I feel ought to be
better 'updated'.

Here are the relevant bits:
//#include <malloc.h> // commented out by me
#include <stdlib.h> // added by me

//plenty of unaltered code snipped

FILE *
efopen(name,mode)
char *name;
char *mode;
{
FILE *f;
extern int errno;

// extern char *sys_errlist[]; // commented out by me
This most likely contains mappings for the error number to the error
text, however without seeing the actual definitions all I can do is
guess. If this is the case, take a look at strerror(). Also perror()
would work just fine here.
// extern int sys_nerr; // commented out by me
There is errno which is provided by errno.h that you can use for this.

char *errmess;

if ( (f=fopen(name,mode)) == NULL ) {
(void) fprintf(stderr,"*** ERROR *** Cannot open '%s'!\n",name);
Given the above information, this can be changed to:

if((f = fopen(name, mode)) == NULL) {
perror("fopen");

/* // this chunk commented out by me

if ( errno <= sys_nerr )
errmess = sys_errlist[errno];
else
errmess = "Unknown error!";

*/
You can leave this out. We are already doing this above with perror().

errmess = strerror(errno); // added by me

(void) fprintf(stderr,"************* Reason: %s\n",errmess);
The above two lines are redundant now as well.
exit(1);
Sloppy. You might want to use EXIT_FAILURE here instead.
}
return(f);
}

This code compiles just fine, and it also works as intended, but I
assume it will fail much less gracefully if I send a 'bad' file to the
program.
Actually no, it won't. It will fail just as gracefully as it did before
you made the changes, the only different is that with your changes it
will not print out an error message upon failure (which could be a Bad
Thing(tm)).

I assume I did the right thing changing the #include directive from
malloc.h to stdlib.h
Yes.

I realised I needed to find a more modern equivalent of sys_errlist and
sys_nerr, - a web search led me to discover that sys_errlist is
deprecated, and to put together the single line I added.
You don't need either one of those.

I also learned that strerror is provided by stdio.h (which was already
#included). All well and good, but I have no clue how to reinstate the
'if' test and make the error handling more robust.
The error handling looks perfectly fine to me. If fopen() returns NULL
then simply call perror("fopen") to see the error message.

Thanks in advance for any assistance!


No problem, hope that gets you pointed in the right direction.

Joe
Mar 19 '06 #3

P: n/a
On 2006-03-19, Joe Estock <je*****@NOSPAMnutextonline.com> wrote:
Brennan Young wrote:
Hi there,

First I'll apologise for my ignorance!

I have been attempting to compile some code that I found on the net.

AFAICT it's intended to be portable code (it was available as source and
as a DOS binary, but mention was made of UNIX in the readme - I am
compiling under Mac OS X, fwiw).

It probably once was portable, but apparently uses some obsolete
snippets because it wouldn't compile without some changes.

After searching the web I managed to get the code to compile but it
required that I simplify some error handling which I feel ought to be
better 'updated'.

Here are the relevant bits:
//#include <malloc.h> // commented out by me
#include <stdlib.h> // added by me

//plenty of unaltered code snipped

FILE *
efopen(name,mode)
char *name;
char *mode;
{
FILE *f;
extern int errno;

// extern char *sys_errlist[]; // commented out by me


This most likely contains mappings for the error number to the error
text, however without seeing the actual definitions all I can do is
guess. If this is the case, take a look at strerror(). Also perror()
would work just fine here.
// extern int sys_nerr; // commented out by me


There is errno which is provided by errno.h that you can use for this.


sys_nerr is the total number of entries in sys_errlist, NOT an index.

[well, it can be whatever an implementation wants it to be, but my guess
is more likely to be right than yours]
char *errmess;

if ( (f=fopen(name,mode)) == NULL ) {
(void) fprintf(stderr,"*** ERROR *** Cannot open '%s'!\n",name);


Given the above information, this can be changed to:

if((f = fopen(name, mode)) == NULL) {
perror("fopen");


I'd have used perror(name) instead.
Mar 19 '06 #4

P: n/a
Vladimir S. Oka wrote:
Brennan Young opined:
Hi there,

First I'll apologise for my ignorance!
Being ignorant is not a problem. It's those who do not recognise their
ignorance that are the problem!
I have been attempting to compile some code that I found on the net.

AFAICT it's intended to be portable code (it was available as source
and as a DOS binary, but mention was made of UNIX in the readme - I
am compiling under Mac OS X, fwiw).

It probably once was portable, but apparently uses some obsolete
snippets because it wouldn't compile without some changes.

After searching the web I managed to get the code to compile but it
required that I simplify some error handling which I feel ought to be
better 'updated'.

Here are the relevant bits:
//#include <malloc.h> // commented out by me
#include <stdlib.h> // added by me
Changing it to stdlib.h was correct. However, you should not use //
style comments because they were only added to the C standard in C99 and
C99 is not generally implemented. Also, // style comments don't survive
line wrapping.
#include <errno.h>
#include <string.h>

You'll need it below...
//plenty of unaltered code snipped

FILE *
efopen(name,mode)
char *name;
char *mode;


This is ancient style. It's better:

FILE *efopen(char *name, char *mode)


You should also change any declarations to this style, and ensure that
there is always a declaration (or definition) at some point before a
function is called.
{
FILE *f;
extern int errno;


Now you don't need the line above (errno is declared in errno.h).


It's worse than that. errno is not guaranteed to be an object and on
many systems it is not! It is not that long back that I was dealing with
some old code and it failed to run because errno was explicitly declared
like this instead of errno.h being included. On such systems, declaring
errno like this and including errno.h would be likely to lead to a
compilation error.

<snip good stuff>
if ( (f=fopen(name,mode)) == NULL ) {
(void) fprintf(stderr,"*** ERROR *** Cannot open
'%s'!\n",name);

/* // this chunk commented out by me

if ( errno <= sys_nerr )
errmess = sys_errlist[errno];
else
errmess = "Unknown error!";

*/


if (errno)
errmess = strerror(errno); // added by me

Is what you want here.


You also want:
else
errmess = "Unknown error!";

from the original code. Otherwise errmess is not set to anything if
errno==0.

(void) fprintf(stderr,"************* Reason: %s\n",errmess);
exit(1);
exit(1) is not portable. In fact, under VMS it would be a success code!
exit(EXIT_FAILURE);
}
return(f);
}


<snip>

A final point, since we are so often told we spend all our time
complaining about off topic posts.

The original post by Brennan Young was on topic, showed that he had made
an effort and explained clearly what he wanted to know.

Welcome to the group Brennan. The question may be simple but it is what
we are here for.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Mar 21 '06 #5

P: n/a
On 2006-03-21, Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Vladimir S. Oka wrote:
Brennan Young opined:
Hi there,

First I'll apologise for my ignorance!
Being ignorant is not a problem. It's those who do not recognise their
ignorance that are the problem!
I have been attempting to compile some code that I found on the net.

AFAICT it's intended to be portable code (it was available as source
and as a DOS binary, but mention was made of UNIX in the readme - I
am compiling under Mac OS X, fwiw).

It probably once was portable, but apparently uses some obsolete
snippets because it wouldn't compile without some changes.

After searching the web I managed to get the code to compile but it
required that I simplify some error handling which I feel ought to be
better 'updated'.

Here are the relevant bits:
//#include <malloc.h> // commented out by me
#include <stdlib.h> // added by me
Changing it to stdlib.h was correct. However, you should not use //
style comments because they were only added to the C standard in C99 and
C99 is not generally implemented. Also, // style comments don't survive
line wrapping.
#include <errno.h>
#include <string.h>

You'll need it below...
//plenty of unaltered code snipped

FILE *
efopen(name,mode)
char *name;
char *mode;


This is ancient style. It's better:

FILE *efopen(char *name, char *mode)


You should also change any declarations to this style, and ensure that
there is always a declaration (or definition) at some point before a
function is called.
{
FILE *f;
extern int errno;


Now you don't need the line above (errno is declared in errno.h).


It's worse than that. errno is not guaranteed to be an object and on
many systems it is not! It is not that long back that I was dealing with
some old code and it failed to run because errno was explicitly declared
like this instead of errno.h being included. On such systems, declaring
errno like this and including errno.h would be likely to lead to a
compilation error.

<snip good stuff>
if ( (f=fopen(name,mode)) == NULL ) {
(void) fprintf(stderr,"*** ERROR *** Cannot open
'%s'!\n",name);

/* // this chunk commented out by me

if ( errno <= sys_nerr )
errmess = sys_errlist[errno];
else
errmess = "Unknown error!";

*/


if (errno)
errmess = strerror(errno); // added by me

Is what you want here.


You also want:
else
errmess = "Unknown error!";

from the original code. Otherwise errmess is not set to anything if
errno==0.


strerror(0) doesn't return anything? on mine, it returns "Success".

Also, you're misreading it - "Unknown Error!" is set NOT on errno 0, but
on errno that's larger than the largest value for which an error message
is defined [on a typical modern system, strerror would return "Unknown \
Error 500" for that case]
Mar 22 '06 #6

P: n/a
Jordan Abel wrote:
On 2006-03-21, Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Vladimir S. Oka wrote:
Brennan Young opined:
<snip>
if ( (f=fopen(name,mode)) == NULL ) {
(void) fprintf(stderr,"*** ERROR *** Cannot open
'%s'!\n",name);

/* // this chunk commented out by me

if ( errno <= sys_nerr )
errmess = sys_errlist[errno];
else
errmess = "Unknown error!";

*/
if (errno)
errmess = strerror(errno); // added by me

Is what you want here. You also want:
else
errmess = "Unknown error!";

from the original code. Otherwise errmess is not set to anything if
errno==0.


strerror(0) doesn't return anything? on mine, it returns "Success".


A program that reports, "*** ERROR *** Cannot open whatever, Success"
would generally be considered a poor program.
Also, you're misreading it - "Unknown Error!" is set NOT on errno 0, but
on errno that's larger than the largest value for which an error message
is defined [on a typical modern system, strerror would return "Unknown \
Error 500" for that case]


strerror will return a message for any value of errno that the
implementation uses. My change is so that you get something vaguely
sensible if fopen does not set errno.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Mar 22 '06 #7

P: n/a
On 2006-03-22, Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Jordan Abel wrote:
On 2006-03-21, Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Vladimir S. Oka wrote:
> /* // this chunk commented out by me
>
> if ( errno <= sys_nerr )
> errmess = sys_errlist[errno];
> else
> errmess = "Unknown error!";
>
> */
if (errno)
errmess = strerror(errno); // added by me

Is what you want here.
You also want:
else
errmess = "Unknown error!";

from the original code. Otherwise errmess is not set to anything if
errno==0.


strerror(0) doesn't return anything? on mine, it returns "Success".


A program that reports, "*** ERROR *** Cannot open whatever, Success"
would generally be considered a poor program.


Actually having errno set to 0 without knowing it might be 0, though, is
rare. I will agree, though, that "losing" the value of errno because
another intervening call sets it to something else, is poor coding
practice.
Also, you're misreading it - "Unknown Error!" is set NOT on errno 0, but
on errno that's larger than the largest value for which an error message
is defined [on a typical modern system, strerror would return "Unknown \
Error 500" for that case]


strerror will return a message for any value of errno that the
implementation uses. My change is so that you get something vaguely
sensible if fopen does not set errno.


Your change isn't anything near equivalent to the original code, though,
so I was thrown off. Also, errno will be whatever was there before, NOT
zero. No library function sets errno to 0, and it's often set to
something other than 0 even by a successful function [on many systems,
the first call to any stdio function will set it if either stdin or
stdout is not an interactive device]

My point was that handling errno==0 is not what the original code's
errmess="Unknown error!"; did, so just leaving it in wouldn't really
help. I just realized that he changed the semantics to if(errno), so it
might make sense to have the else clause regardless, but you'd then have
to initialize errno to 0 yourself. Whether fopen sets it and what it
sets it to is, of course, implementation-defined, but it will never
_clear_ errno.
Mar 22 '06 #8

P: n/a
Jordan Abel wrote:
On 2006-03-22, Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Jordan Abel wrote:
On 2006-03-21, Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Vladimir S. Oka wrote:
>> /* // this chunk commented out by me
>>
>> if ( errno <= sys_nerr )
>> errmess = sys_errlist[errno];
>> else
>> errmess = "Unknown error!";
>>
>> */
> if (errno)
> errmess = strerror(errno); // added by me
>
> Is what you want here.
You also want:
else
errmess = "Unknown error!";

from the original code. Otherwise errmess is not set to anything if
errno==0.
strerror(0) doesn't return anything? on mine, it returns "Success". A program that reports, "*** ERROR *** Cannot open whatever, Success"
would generally be considered a poor program.


Actually having errno set to 0 without knowing it might be 0, though, is
rare. I will agree, though, that "losing" the value of errno because
another intervening call sets it to something else, is poor coding
practice.


fopen is not required to set errno, so the program has to allow for it.
Also, you're misreading it - "Unknown Error!" is set NOT on errno 0, but
on errno that's larger than the largest value for which an error message
is defined [on a typical modern system, strerror would return "Unknown \
Error 500" for that case]

strerror will return a message for any value of errno that the
implementation uses. My change is so that you get something vaguely
sensible if fopen does not set errno.


Your change isn't anything near equivalent to the original code, though,
so I was thrown off. Also, errno will be whatever was there before, NOT
zero. No library function sets errno to 0, and it's often set to
something other than 0 even by a successful function [on many systems,
the first call to any stdio function will set it if either stdin or
stdout is not an interactive device]


If I recall correctly the code Vladimir posted set errno to 0 before
calling fopen, and I believe he was correct to do this.
My point was that handling errno==0 is not what the original code's
errmess="Unknown error!"; did, so just leaving it in wouldn't really
help.
Agreed. I was improving Vladimir's version, not the original.
I just realized that he changed the semantics to if(errno), so it
might make sense to have the else clause regardless, but you'd then have
to initialize errno to 0 yourself. Whether fopen sets it and what it
sets it to is, of course, implementation-defined, but it will never
_clear_ errno.


OK, in that case I think we probably agree on the correct thing which is
to set errno to 0 before the call (which I believe was done) and trap it
being 0 so that you know if fopen has not set it.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Mar 22 '06 #9

P: n/a
In article <46************@news.flash-gordon.me.uk>,
Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Welcome to the group Brennan. The question may be simple but it is what
we are here for.


Thanks! And thanks to all who responded, I now feel more confident about
my changes. I don't know if I can ever hope to have the kind of grasp of
C implementations as you guys (where do you learn all that?), but it's
nice to know where to come with such questions.

;)
Mar 23 '06 #10

P: n/a
Brennan Young wrote:
In article <46************@news.flash-gordon.me.uk>,
Flash Gordon <sp**@flash-gordon.me.uk> wrote:
Welcome to the group Brennan. The question may be simple but it is what
we are here for.


Thanks! And thanks to all who responded, I now feel more confident about
my changes. I don't know if I can ever hope to have the kind of grasp of
C implementations as you guys (where do you learn all that?), but it's
nice to know where to come with such questions.

;)


We learn by posting here and having our errors pointed out to us ;-)

Also reading good books, the comp.lang.c FAQ, and experience.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Mar 23 '06 #11

This discussion thread is closed

Replies have been disabled for this discussion.