errno

der Mouse mouse at thunder.mcrcim.mcgill.edu
Sun Jun 16 01:19:24 AEST 1991


In article <212 at sleepy.UUCP>, allyn at sleepy.UUCP (Mark Allyn) writes:

> I need to be able to take what is printed when you call perror and
> put it into a string variable to be used in a c program.

> I know that the errno variable is an external variable which points
> to some internal table in the kernel called sys_errlist.

Not in the kernel; it's part of the C library.

> Is there some way of getting at that table so that I can get at the
> error messages?

Certainly.

> I tried the following logical solution after RTFM but it did not work
> (it got a seg fault)

Let's have a look....

> #include <stdio.h>
> #include <signal.h>
> #include <sys/types.h>
> #include <sys/vfs.h>
> #include <sys/syslog.h>
> #include <errno.h>

Why in the world are you including all those things?  The only ones
that have any relevance are <stdio.h> and <errno.h> (and see my fifth
note below for a remark about the latter).

> main()
> {
> extern char **sys_errlist;

It's an array, not a pointer (try `extern char *sys_errlist[];').

> FILE *fpp;
> int ctr1;
> 
> fpp=fopen("/goo","w");
> perror("");
> printf("errno is %d\n",errno);
> printf("%d\n",(int)*(sys_errlist+errno));

First, fopen is not guaranteed to leave anything useful in errno, at
least not generally.  (Your system may make such a promise, but it is
not portable to assume so.)  It frequently will do so, but you can't
count on it.

Second, the perror and printf calls may destroy errno, since it is no
part of their contract to preserve it.  You should save it in a
variable of your own.

Third, you should check that errno is within the range [0..sys_nerr),
because the sys_errlist table may lag the system for new error codes.

Fourth, why are you casting the string from sys_errlist to an int?!

Fifth, a minor point: not all systems' <errno.h> actually declare
errno.  For portability you have to declare it yourself.  (Yes, I agree
this is a botch.  Portability sometimes means putting up with botches.)
And since this is the only thing <errno.h> does for you in this case,
you can get rid of it once you add the declaration - though in a real
program, where you use some of the Exxx values, you have to keep it.)

> }

Putting all this together, we get the following.  (Well, most of it;
this modified version still assumes that fopen() will leave something
useful in errno.  To do it right you should call open(2) directly,
followed by fdopen() if the open() succeeds and you need a FILE *.)

#include <stdio.h>

main()
{
 extern int errno;
 extern int sys_nerr;
 extern char *sys_errlist[];
 FILE *fpp;
 int save_errno;

 fpp=fopen("/goo","w");
 save_errno = errno;
 perror("");
 printf("errno is %d\n",save_errno);
 if ((save_errno >= 0) && (save_errno < sys_nerr))
    printf("%s\n",sys_errlist[save_errno]);
 else
    printf("Unknown error code %d\n",save_errno);
}

					der Mouse

			old: mcgill-vision!mouse
			new: mouse at larry.mcrcim.mcgill.edu



More information about the Comp.unix.questions mailing list