'exit(1);' considered useless (slight flame)

dm%bbn-unix at sri-unix.UUCP dm%bbn-unix at sri-unix.UUCP
Sat Feb 11 05:54:07 AEST 1984


From:  Dave Mankins <dm at bbn-unix>

What's wrong with PERROR is that it's dreadfully limited.  Since
perror only allows you to give a canned, inflexible message (plus
the error message), the amount of detail you can stick into an
error message is restricted. 

BBN has a set of routines (the cmderr family, and errmsg) which
do this very well.  Cmderr, unfortunately depends on the
non-portable "%r" (for "remote") printf format discussed in this
forum a few months ago. 

I recently moved to a new computer system (at MIT's Project
Athena) which doesn't have these, and the first thing I did was
add errmsg (which is portable), at least, and I put it into a
LIBRARY (and wrote a manual page, too, of course) so I could use
it in every program I write or modify:

/* ---------------------- e r r m s g --------------------------- */
/*
 *  Returns system error string.
 *  Argument:
 *      if error is positive, assume that it is an error number.
 *      if error is 0, then use the message associated with the
 *      current value in errno.
 */
char *
errmsg(error)
    int error;
{
    extern int errno;

    if(error == 0)
	error = errno;
    if(error <= 0 && error > sys_nerr)
	return("Unknown error");
    else
	return(sys_errlist[error]);
}

(Forgive me, I'm reconstructing this from memory, and I don't
have access to the Athena system right now--I think the
declarations of char *sys_errlist[] and int sys_nerr are
available from some include file on 4.xBSD.  If you don't have
those, look at the source for perror, and see where it gets its
error message strings (if you don't have the source for perror, I
guess you could use adb on a program which uses it, and
rebuild the table--I can't tell you, cause Mother Bell wouldn't like
it if I did).)

This routine then allows: 

    if((file_pointer = fopen(file, "r")) == NULL)
    {
	fprintf(stderr, "%s: Can't open \"%s\"; %s.\n",
	    progname, file, errmsg(0));
	...
    }

Which produces an error message:

	rabbit: Can't open "/usr/dm/lettuce";  No such file or directory.

And which is almost as easy to use as perror, except that it
ENCOURAGES your error message to contain more information.
[Sigh, it's still not as easy to use as cmderr...]

It's amazing how quickly you can find and fix problems when your
error messages contain that much information.  I'm truly tired of
programs which say "Can't open file." Can't open what file?  Why
not?  As a system maintainer I don't have time to look at the
sources of some god-awful huge program to figure out what it's
complaining about. 

Now, the problem with this scheme is that it requires the error
messages to be compiled into the program, so programs compiled a
long time ago won't know about new system error codes (I don't
believe in semantic overloading of error messages) when they
appear.  At BBN, where new kernel-originated network error codes
appear with some frequency, this is a problem.  At Project
Athena, where new kernel-originated distributed filesystem errors
will be appearing with some frequency, it will also be a problem.
A better solution (which is, in fact, how BBN's stuff does all
that) is to store the error messages in a file, and open the file
and read it to get the error message.  Of course, if the error
message in question is "Too many open files" you won't be able to
open the file to read the message, so you have to watch out for
that case, (and similar cases) but that CAN be done. 

[The possibilities of errors in your error routines reminds me of
an error message which would appear occasionally on a TENEX system
I used to work on (a "JSYS" is a system call): 

    rabbit: Can't open <dm>lettuce.txt; JSYS error in JSYS 
        error routine!  AAAIIIEEEEeeee.......! 

I never did get out of the habit of looking over at the machine
to see if the lights were still flickering when that message
appeared...]



More information about the Comp.unix mailing list