Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!thunder.mcrcim.mcgill.edu!mouse From: mouse@thunder.mcrcim.mcgill.edu (der Mouse) Newsgroups: comp.unix.questions Subject: Re: errno Keywords: errno Message-ID: <1991Jun15.151924.24619@thunder.mcrcim.mcgill.edu> Date: 15 Jun 91 15:19:24 GMT References: <212@sleepy.UUCP> Organization: McGill Research Centre for Intelligent Machines Lines: 98 In article <212@sleepy.UUCP>, allyn@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 > #include > #include > #include > #include > #include Why in the world are you including all those things? The only ones that have any relevance are and (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' 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 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 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@larry.mcrcim.mcgill.edu