[comp.lang.c] A better perror

molly@killer.UUCP (08/18/87)

In article <853@mcgill-vision.UUCP>, mouse@mcgill-vision.UUCP (der Mouse) writes:
> In article <28700015@ccvaxa>, aglew@ccvaxa.UUCP quotes:
> > I have always thought that perror(str) was silly - sometimes I want
> > str to be the command name, sometimes the command plus all
> > arguments...
> 
> [ ... ] Wish perror() were printflike, perhaps like
> syslog() - syslog() accepts a printf format, except that %m means
> insert sys_errlst[errno].

I have seen a few public domain printf's come down the line (the most
recent even had a %R option for Roman Numerals - just what I need
next time a write a clock program ...

The varargs functions and whatnot look more than adaquate for doing
something like this.  What exactly is `syslog()', and how would I get
ahold of it?

If there ain't a PD syslog, I might be convinced to convert a printf()
into one if someone mails the man-page ... it might just get done in
time for Christmas.

Molly
-- 
       Molly Fredericks       UUCP: { any place real }!ihnp4!killer!molly
    Disclaimer:  Neither me, nor my cat, had anything to do with any of this
  "I love giving my cat a bath, except for all those hairs I get on my tongue"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

guy%gorodish@Sun.COM (Guy Harris) (08/18/87)

> The varargs functions and whatnot look more than adaquate for doing
> something like this.  What exactly is `syslog()', and how would I get
> ahold of it?

"syslog" is a routine that sends a message to the "syslog" daemon on 4.2BSD and
4.3BSD.  It is definitely NOT a replacement for "printf", since it won't print
its message to a file or stuff it into a string; the "syslog" daemon will send
the message to the system console (NOT to your terminal!)  or to a log file.
It is intended for system log messages (hence the name).

The way "syslog" implements "%m" is fairly trivial; it has an internal buffer,
and it copies the format string to that buffer, replacing all occurrences of
"%m" with the text of the error message corresponding to the system error code.
It then uses the string in that buffer, rather than using the format string
passed to it, as the format string for "sprintf" when it generates the text of
the message.

I tend to agree with Doug Gwyn that a version of "perror" that returns the
error message for a given error code as a string is a better idea; not all
error messages are generated by "perror", and you wouldn't want to have to add
other "%<mumble>" codes for error codes from other packages.  (In general,
you probably couldn't do so, even if you wanted to; what if you bought a DBMS
that has its own set of error codes and routines to generate error strings from
them?  How would you extend "printf" to handle them?  What happens if you run
out of format codes?)
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

wendt@arizona.UUCP (08/19/87)

Another problem with error reporting on Unix is that there's no way
that I know of to translate open file id's back into filenames.
Also, I've run on versions that report the error: Bad File ID when you
try to write on a read-only file.  This always takes me weeks to
find.  The system should say Bad Universe, meaning that you're
running your program in an unfortunate alternate universe, in which
this file happens not to be writeable.

Automatic messages generated by the combination of these two
crocks tend to be pretty mysterious.

Alan W.

drw@cullvax.UUCP (Dale Worley) (08/20/87)

wendt@arizona.edu (Alan Lee Wendt) writes:
> Another problem with error reporting on Unix is that there's no way
> that I know of to translate open file id's back into filenames.

Basically, because there is no such translation.  You've got an i-node
open, and it may have many names.  The name you opened it under may
not even exist anymore!  (What happens if you've got the file open,
and *all* links to the i-node are deleted?)

Dale

-- 
Dale Worley	Cullinet Software		ARPA: cullvax!drw@eddie.mit.edu
UUCP: ...!seismo!harvard!mit-eddie!cullvax!drw
OS/2: Yesterday's software tomorrow	    Nuclear war?  There goes my career!

wendt@arizona.edu (Alan Lee Wendt) (08/21/87)

> > Another problem with error reporting on Unix is that there's no way
> > that I know of to translate open file id's back into filenames.
> 
> Basically, because there is no such translation.  You've got an i-node
> open, and it may have many names. 

It could give me back the name I opened it under, or "stdin", "stdout",
or "stderr".  That would be a lot better than nothing.  I currently
accomplish this for my own systems by redefining Unix library calls
ie "#define open uxopen" and stashing the text string in uxopen.  But
I would sleep better if I didn't have to do such disgusting things.

Alan W.

rlk@chinet.UUCP (08/21/87)

In article <1351@killer.UUCP> molly@killer.UUCP (Molly Fredericks) writes:
>In article <853@mcgill-vision.UUCP>, mouse@mcgill-vision.UUCP (der Mouse) writes:
>> In article <28700015@ccvaxa>, aglew@ccvaxa.UUCP quotes:
>> > I have always thought that perror(str) was silly - sometimes I want
>> > str to be the command name, sometimes the command plus all
>> > arguments...
>> 
>> [ ... ] Wish perror() were printflike, perhaps like
>> syslog() - syslog() accepts a printf format, except that %m means
>> insert sys_errlst[errno].
>
>I have seen a few public domain printf's come down the line (the most
...

My solution to this is

	extern int	errno;
	extern char	*sys_errlist[];

	#define	SYS_ERRMSG	sys_errlist[errno]

	.
	.
	printf("..whatever..: %s\n", args_for_whatever, SYS_ERRMSG);

This method assumes that 'errno' has been correctly supplied a value.
(e.i., That an error occured.)

Do an 'nm' command on libc.a to confirm the existence of these names,
if not using a standard UN*X (works on SYSV, and on my BSD-derived
system.)



-- 
---
UUCP: ..!ihnp4!chinet!uklpl!rlk || MCIMail: rklappal || Compuserve: 74106,1021
      ..!ihnp4!ihu1h!rlk
---

guy%gorodish@Sun.COM (Guy Harris) (08/21/87)

(This has ceased to be a discussion of C, and has become a discussion of
features of UNIX.  It is being redirected to comp.unix.questions.)

> 	extern int	errno;
> 	extern char	*sys_errlist[];
> 
> Do an 'nm' command on libc.a to confirm the existence of these names,
> if not using a standard UN*X (works on SYSV, and on my BSD-derived
> system.)

Or, instead of outsmarting yourself by using a technique too clever by half,
just look in the Effing Manual!  You'll find "sys_errlist" listed in the
"perror" manual page somewhere in some subsection of section 3, and "errno"
described in the "intro" manual page in section 2, unless your vendor has
totally screwed up their documentation.

If it doesn't have "errno", it's not only not "standard UN*X", it's not any
sort of UN*X; the number of programs that would be broken by omitting "errno"
is very large.  If it doesn't have "sys_errlist", fewer programs will be
broken, but some will be.

BTW, do NOT assume that the value in "errno" is a valid index into the
"sys_errlist" array!  The chances are good that it is, but it is NOT certain;
check the "errno" value against "sys_nerr" (described along with "sys_errlist"
in the manual) and make sure it's greater than zero.  If it's not a valid
index, generate the message some other way, preferably including the value of
"errno" in decimal.  (If it IS a valid index, NEVER print the value of "errno"
in decimal; programs like "cpio" have a tendency to print the error number and
NOT print the message, which is incredibly idiotic.)
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

mouse@mcgill-vision.UUCP (09/07/87)

In article <1427@chinet.UUCP>, rlk@chinet.UUCP (Richard Klappal) writes:
> In article <1351@killer.UUCP> molly@killer.UUCP (Molly Fredericks) writes:
>> In article <853@mcgill-vision.UUCP>, mouse@mcgill-vision.UUCP (der Mouse) writes:
>>> In article <28700015@ccvaxa>, aglew@ccvaxa.UUCP quotes:
>>>> I have always thought that perror(str) was silly - sometimes I
>>>> want str to be the command name, sometimes the command plus all
>>>> arguments...
>>> Wish perror() were printflike, perhaps like syslog() [which]
>>> accepts a printf format, except that %m means insert
>>> sys_errlst[errno].
(Or close to that, at least - if errno is an unknown error, it inserts
"Unknown error" (stock perror) or "Unknown error (%d)" with the number
inserted (my perror).)
> My solution to this is
> 	extern int	errno;
> 	extern char	*sys_errlist[];
> 	#define	SYS_ERRMSG	sys_errlist[errno]
> 	:
> 	printf("..whatever..: %s\n", args_for_whatever, SYS_ERRMSG);
> This method assumes that 'errno' has been correctly supplied a value.
> (e.i.[sic], That an error occured.)

It also assumes that the value in errno is a valid index into
sys_errlist!  The warning in the man page is there for a reason.
Wouldn't it be just wonderful to see

Cannot open input file foo.in: ^ZA^DZPPPYPYXU^I^S^B^QzQYh^Y^CB^DYPYoZ#^B

because whoever did the UNIX port your code happens to be compiled on
neglected to add their new error codes to sys_errlist[]?

					der Mouse

				(mouse@mcgill-vision.uucp)