com_err.texinfo revision 5622
1\input texinfo @c -*-texinfo-*-
2
3@c $Header$
4@c $Source$
5@c $Locker$
6
7@c Note that although this source file is in texinfo format (more
8@c or less), it is not yet suitable for turning into an ``info''
9@c file.  Sorry, maybe next time.
10@c
11@c In order to produce hardcopy documentation from a texinfo file,
12@c run ``tex com_err.texinfo'' which will load in texinfo.tex,
13@c provided in this distribution.  (texinfo.tex is from the Free
14@c Software Foundation, and is under different copyright restrictions
15@c from the rest of this package.)
16
17@ifinfo
18@barfo
19@end ifinfo
20
21@iftex
22@tolerance 10000
23
24@c Mutate section headers...
25@begingroup
26  @catcode#=6
27  @gdef@secheading#1#2#3{@secheadingi {#3@enspace #1}}
28@endgroup
29@end iftex
30
31@setfilename com_err
32@settitle A Common Error Description Library for UNIX
33
34@ifinfo
35This file documents the use of the Common Error Description library.
36
37Copyright (C) 1987, 1988 Student Information Processing Board of the
38Massachusetts Institute of Technology.
39
40Permission to use, copy, modify, and distribute this software and its
41documentation for any purpose and without fee is hereby granted, provided
42that the above copyright notice appear in all copies and that both that
43copyright notice and this permission notice appear in supporting
44documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
45used in advertising or publicity pertaining to distribution of the software
46without specific, written prior permission.  M.I.T. and the M.I.T. S.I.P.B.
47make no representations about the suitability of this software for any
48purpose.  It is provided "as is" without express or implied warranty.
49
50Note that the file texinfo.tex, provided with this distribution, is from
51the Free Software Foundation, and is under different copyright restrictions
52from the remainder of this package.
53
54@end ifinfo
55
56@ignore
57Permission is granted to process this file through Tex and print the
58results, provided the printed document carries copying permission
59notice identical to this one except for the removal of this paragraph
60(this paragraph not being relevant to the printed manual).
61
62@end ignore
63
64@setchapternewpage odd
65
66@titlepage
67@center @titlefont{A Common Error Description}
68@center @titlefont{Library for UNIX}
69@sp 2
70@center Ken Raeburn
71@center Bill Sommerfeld
72@sp 1
73@center MIT Student Information Processing Board
74@sp 3
75@center last updated 1 January 1989
76@center for version 1.2
77@center ***DRAFT COPY ONLY***
78
79@vskip 2in
80
81@center @b{Abstract}
82
83UNIX has always had a clean and simple system call interface, with a
84standard set of error codes passed between the kernel and user
85programs.  Unfortunately, the same cannot be said of many of the
86libraries layered on top of the primitives provided by the kernel.
87Typically, each one has used a different style of indicating errors to
88their callers, leading to a total hodgepodge of error handling, and
89considerable amounts of work for the programmer.  This paper describes
90a library and associated utilities which allows a more uniform way for
91libraries to return errors to their callers, and for programs to
92describe errors and exceptional conditions to their users.
93
94@page
95@vskip 0pt plus 1filll
96
97Copyright @copyright{} 1987, 1988 by the Student Information Processing
98Board of the Massachusetts Institute of Technology.
99
100Permission to use, copy, modify, and distribute this software and its
101documentation for any purpose and without fee is hereby granted, provided
102that the above copyright notice appear in all copies and that both that
103copyright notice and this permission notice appear in supporting
104documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
105used in advertising or publicity pertaining to distribution of the software
106without specific, written prior permission.  M.I.T. and the M.I.T. S.I.P.B.
107make no representations about the suitability of this software for any
108purpose.  It is provided "as is" without express or implied warranty.
109
110Note that the file texinfo.tex, provided with this distribution, is from
111the Free Software Foundation, and is under different copyright restrictions
112from the remainder of this package.
113
114@end titlepage
115
116@ifinfo
117@c should put a menu here someday....
118@end ifinfo
119
120@page
121
122@section Why com_err?
123
124In building application software packages, a programmer often has to
125deal with a number of libraries, each of which can use a different
126error-reporting mechanism.  Sometimes one of two values is returned,
127indicating simply SUCCESS or FAILURE, with no description of errors
128encountered.  Sometimes it is an index into a table of text strings,
129where the name of the table used is dependent on the library being
130used when the error is generated; since each table starts numbering at
1310 or 1, additional information as to the source of the error code is
132needed to determine which table to look at.  Sometimes no text messages are
133supplied at all, and the programmer must supply them at any point at which
134he may wish to report error conditions.
135Often, a global variable is assigned some value describing the error, but
136the programmer has to know in each case whether to look at @code{errno},
137@code{h_errno}, the return value from @code{hes_err()}, or whatever other
138variables or routines are specified.
139And what happens if something
140in the procedure of
141examining or reporting the error changes the same variable?
142
143The package we have developed is an attempt to present a common
144error-handling mechanism to manipulate the most common form of error code
145in a fashion that does not have the problems listed above.
146
147A list of up to 256 text messages is supplied to a translator we have
148written, along with the three- to four-character ``name'' of the error
149table.  The library using this error table need only call a routine
150generated from this error-table source to make the table ``known'' to the
151com_err library, and any error code the library generates can be converted
152to the corresponding error message.  There is also a default format for
153error codes accidentally returned before making the table known, which is
154of the form @samp{unknown code foo 32}, where @samp{foo} would be the name
155of the table.
156
157@section Error codes
158
159Error codes themselves are 32 bit (signed) integers, of which the high
160order 24 bits are an identifier of which error table the error code is
161from, and the low order 8 bits are a sequential error number within
162the table.  An error code may thus be easily decomposed into its component
163parts.  Only the lowest 32 bits of an error code are considered significant
164on systems which support wider values.
165
166Error table 0 is defined to match the UNIX system call error table
167(@code{sys_errlist}); this allows @code{errno} values to be used directly
168in the library (assuming that @code{errno} is of a type with the same width
169as @t{long}).  Other error table numbers are formed by compacting together
170the first four characters of the error table name.  The mapping between
171characters in the name and numeric values in the error code are defined in
172a system-independent fashion, so that two systems that can pass integral
173values between them can reliably pass error codes without loss of meaning;
174this should work even if the character sets used are not the same.
175(However, if this is to be done, error table 0 should be avoided, since the
176local system call error tables may differ.)
177
178Any variable which is to contain an error code should be declared @t{long}.
179The draft proposed American National Standard for C (as of May, 1988)
180requires that @t{long} variables be at least 32 bits; any system which does
181not support 32-bit @t{long} values cannot make use of this package (nor
182much other software that assumes an ANSI-C environment base) without
183significant effort.
184
185@section Error table source file
186
187The error table source file begins with the declaration of the table name,
188as
189
190@example
191error_table @var{tablename}
192@end example
193
194Individual error codes are
195specified with
196
197@example
198error_code @var{ERROR_NAME}, @var{"text message"}
199@end example
200
201where @samp{ec} can also be used as a short form of @samp{error_code}.  To
202indicate the end of the table, use @samp{end}.  Thus, a (short) sample
203error table might be:
204
205@example
206
207        error_table     dsc
208
209        error_code      DSC_DUP_MTG_NAME,
210                        "Meeting already exists"
211
212        ec              DSC_BAD_PATH,
213                        "A bad meeting pathname was given"
214
215        ec              DSC_BAD_MODES,
216                        "Invalid mode for this access control list"
217
218        end
219
220@end example
221
222@section The error-table compiler
223
224The error table compiler is named @code{compile_et}.  It takes one
225argument, the pathname of a file (ending in @samp{.et}, e.g.,
226@samp{dsc_err.et}) containing an error table source file.  It parses the
227error table, and generates two output files -- a C header file
228(@samp{discuss_err.h}) which contains definitions of the numerical values
229of the error codes defined in the error table, and a C source file which
230should be compiled and linked with the executable.  The header file must be
231included in the source of a module which wishes to reference the error
232codes defined; the object module generated from the C code may be linked in
233to a program which wishes to use the printed forms of the error codes.
234
235This translator accepts a @kbd{-language @var{lang}} argument, which
236determines for which language (or language variant) the output should be
237written.  At the moment, @var{lang} is currently limited to @kbd{ANSI-C}
238and @kbd{K&R-C}, and some abbreviated forms of each.  Eventually, this will
239be extended to include some support for C++.  The default is currently
240@kbd{K&R-C}, though the generated sources will have ANSI-C code
241conditionalized on the symbol @t{__STDC__}.
242
243@section Run-time support routines
244
245Any source file which uses the routines supplied with or produced by the
246com_err package should include the header file @file{<com_err.h>}.  It
247contains declarations and definitions which may be needed on some systems.
248(Some functions cannot be referenced properly without the return type
249declarations in this file.  Some functions may work properly on most
250architectures even without the header file, but relying on this is not
251recommended.)
252
253The run-time support routines and variables provided via this package
254include the following:
255
256@example
257void initialize_@var{xxxx}_error_table (void);
258@end example
259
260One of these routines is built by the error compiler for each error table.
261It makes the @var{xxxx} error table ``known'' to the error reporting
262system.  By convention, this routine should be called in the initialization
263routine of the @var{xxxx} library.  If the library has no initialization
264routine, some combination of routines which form the core of the library
265should ensure that this routine is called.  It is not advised to leave it
266the caller to make this call.
267
268There is no harm in calling this routine more than once.
269
270@example
271#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L
272@end example
273
274This symbol contains the value of the first error code entry in the
275specified table.
276This rarely needs be used by the
277programmer.
278
279@example
280const char *error_message (long code);
281@end example
282
283This routine returns the character string error message associated
284with @code{code}; if this is associated with an unknown error table, or
285if the code is associated with a known error table but the code is not
286in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is
287returned, where @var{xxxx} is the error table name produced by
288reversing the compaction performed on the error table number implied
289by that error code, and @var{nn} is the offset from that base value.
290
291Although this routine is available for use when needed, its use should be
292left to circumstances which render @code{com_err} (below) unusable.
293
294@example
295void com_err (const char *whoami,  /* module reporting error */
296              long code,           /* error code */
297              const char *format,  /* format for additional detail */
298              ...);                /*  (extra parameters) */
299@end example
300
301This routine provides an alternate way to print error messages to
302standard error; it allows the error message to be passed in as a
303parameter, rather than in an external variable.  @emph{Provide grammatical
304context for ``message.''}
305
306If @var{format} is @code{(char *)NULL}, the formatted message will not be
307printed.  @var{format} may not be omitted.
308
309@example
310#include <stdarg.h>
311
312void com_err_va (const char *whoami,
313                 long code,
314                 const char *format,
315                 va_list args);
316@end example
317
318This routine provides an interface, equivalent to @code{com_err} above,
319which may be used by higher-level variadic functions (functions which
320accept variable numbers of arguments).
321
322@example
323#include <stdarg.h>
324
325void (*set_com_err_hook (void (*proc) ())) ();
326
327void (*@var{proc}) (const char *whoami, long code, va_list args);
328
329void reset_com_err_hook ();
330@end example
331
332These two routines allow a routine to be dynamically substituted for
333@samp{com_err}.  After @samp{set_com_err_hook} has been called,
334calls to @samp{com_err} will turn into calls to the new hook routine.
335@samp{reset_com_err_hook} turns off this hook.  This may intended to
336be used in daemons (to use a routine which calls @var{syslog(3)}), or
337in a window system application (which could pop up a dialogue box).
338
339If a program is to be used in an environment in which simply printing
340messages to the @code{stderr} stream would be inappropriate (such as in a
341daemon program which runs without a terminal attached),
342@code{set_com_err_hook} may be used to redirect output from @code{com_err}.
343The following is an example of an error handler which uses @var{syslog(3)}
344as supplied in BSD 4.3:
345
346@example
347#include <stdio.h>
348#include <stdarg.h>
349#include <syslog.h>
350
351/* extern openlog (const char * name, int logopt, int facility); */
352/* extern syslog (int priority, char * message, ...); */
353
354void hook (const char * whoami, long code,
355           const char * format, va_list args)
356@{
357    char buffer[BUFSIZ];
358    static int initialized = 0;
359    if (!initialized) @{
360        openlog (whoami,
361                 LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY,
362                 LOG_DAEMON);
363        initialized = 1;
364    @}
365    vsprintf (buffer, format, args);
366    syslog (LOG_ERR, "%s %s", error_message (code), buffer);
367@}
368@end example
369
370After making the call
371@code{set_com_err_hook (hook);},
372any calls to @code{com_err} will result in messages being sent to the
373@var{syslogd} daemon for logging.
374The name of the program, @samp{whoami}, is supplied to the
375@samp{openlog()} call, and the message is formatted into a buffer and
376passed to @code{syslog}.
377
378Note that since the extra arguments to @code{com_err} are passed by
379reference via the @code{va_list} value @code{args}, the hook routine may
380place any form of interpretation on them, including ignoring them.  For
381consistency, @code{printf}-style interpretation is suggested, via
382@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for
383the ANSI C library).
384
385@section Coding Conventions
386
387The following conventions are just some general stylistic conventions
388to follow when writing robust libraries and programs.  Conventions
389similar to this are generally followed inside the UNIX kernel and most
390routines in the Multics operating system.  In general, a routine
391either succeeds (returning a zero error code, and doing some side
392effects in the process), or it fails, doing minimal side effects; in
393any event, any invariant which the library assumes must be maintained.
394
395In general, it is not in the domain of non user-interface library
396routines to write error messages to the user's terminal, or halt the
397process.  Such forms of ``error handling'' should be reserved for
398failures of internal invariants and consistancy checks only, as it
399provides the user of the library no way to clean up for himself in the
400event of total failure.
401
402Library routines which can fail should be set up to return an error
403code.  This should usually be done as the return value of the
404function; if this is not acceptable, the routine should return a
405``null'' value, and put the error code into a parameter passed by
406reference.
407
408Routines which use the first style of interface can be used from
409user-interface levels of a program as follows:
410
411@example
412@{
413    if ((code = initialize_world(getuid(), random())) != 0) @{
414        com_err("demo", code,
415                "when trying to initialize world");
416        exit(1);
417    @}
418    if ((database = open_database("my_secrets", &code))==NULL) @{
419        com_err("demo", code,
420                "while opening my_secrets");
421        exit(1);
422    @}
423@}
424@end example
425
426A caller which fails to check the return status is in error.  It is
427possible to look for code which ignores error returns by using lint;
428look for error messages of the form ``foobar returns value which is
429sometimes ignored'' or ``foobar returns value which is always
430ignored.''
431
432Since libraries may be built out of other libraries, it is often necessary
433for the success of one routine to depend on another.  When a lower level
434routine returns an error code, the middle level routine has a few possible
435options.  It can simply return the error code to its caller after doing
436some form of cleanup, it can substitute one of its own, or it can take
437corrective action of its own and continue normally.  For instance, a
438library routine which makes a ``connect'' system call to make a network
439connection may reflect the system error code @code{ECONNREFUSED}
440(Connection refused) to its caller, or it may return a ``server not
441available, try again later,'' or it may try a different server.
442
443Cleanup which is typically necessary may include, but not be limited
444to, freeing allocated memory which will not be needed any more,
445unlocking concurrancy locks, dropping reference counts, closing file
446descriptors, or otherwise undoing anything which the procedure did up
447to this point.  When there are a lot of things which can go wrong, it
448is generally good to write one block of error-handling code which is
449branched to, using a goto, in the event of failure.  A common source
450of errors in UNIX programs is failing to close file descriptors on
451error returns; this leaves a number of ``zombied'' file descriptors
452open, which eventually causes the process to run out of file
453descriptors and fall over.
454
455@example
456@{
457    FILE *f1=NULL, *f2=NULL, *f3=NULL;
458    int status = 0;
459
460    if ( (f1 = fopen(FILE1, "r")) == NULL) @{
461        status = errno;
462        goto error;
463    @}
464
465    /*
466     * Crunch for a while
467     */
468
469    if ( (f2 = fopen(FILE2, "w")) == NULL) @{
470        status = errno;
471        goto error;
472    @}
473
474    if ( (f3 = fopen(FILE3, "a+")) == NULL) @{
475        status = errno;
476            goto error;
477    @}
478
479    /*
480     * Do more processing.
481     */
482    fclose(f1);
483    fclose(f2);
484    fclose(f3);
485    return 0;
486
487error:
488    if (f1) fclose(f1);
489    if (f2) fclose(f2);
490    if (f3) fclose(f3);
491    return status;
492@}
493@end example
494
495@section Building and Installation
496
497The distribution of this package will probably be done as a compressed
498``tar''-format file available via anonymous FTP from SIPB.MIT.EDU.
499Retrieve @samp{pub/com_err.tar.Z} and extract the contents.  A subdirectory
500@t{profiled} should be created to hold objects compiled for profiling.
501Running ``make all'' should then be sufficient to build the library and
502error-table compiler.  The files @samp{libcom_err.a},
503@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be
504installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be
505installed as manual pages.
506
507Potential problems:
508
509@itemize @bullet
510
511@item Use of @code{strcasecmp}, a routine provided in BSD for
512case-insensitive string comparisons.  If an equivalent routine is
513available, you can modify @code{CFLAGS} in the makefile to define
514@code{strcasecmp} to the name of that routine.
515
516@item Compilers that defined @code{__STDC__} without providing the header
517file @code{<stdarg.h>}.  One such example is Metaware's High ``C''
518compiler, as provided at Project Athena on the IBM RT/PC workstation; if
519@code{__HIGHC__} is defined, it is assumed that @code{<stdarg.h>} is not
520available, and therefore @code{<varargs.h>} must be used.  If the symbol
521@code{VARARGS} is defined (e.g., in the makefile), @code{<varargs.h>} will
522be used.
523
524@item If your linker rejects symbols that are simultaneously defined in two
525library files, edit @samp{Makefile} to remove @samp{perror.c} from the
526library.  This file contains a version of @var{perror(3)} which calls
527@code{com_err} instead of calling @code{write} directly.
528
529@end itemize
530
531As I do not have access to non-BSD systems, there are probably
532bugs present that may interfere with building or using this package on
533other systems.  If they are reported to me, they can probably be fixed for
534the next version.
535
536@section Bug Reports
537
538Please send any comments or bug reports to the principal author: Ken
539Raeburn, @t{Raeburn@@Athena.MIT.EDU}.
540
541@section Acknowledgements
542
543I would like to thank: Bill Sommerfeld, for his help with some of this
544documentation, and catching some of the bugs the first time around;
545Honeywell Information Systems, for not killing off the @emph{Multics}
546operating system before I had an opportunity to use it; Honeywell's
547customers, who persuaded them not to do so, for a while; Ted Anderson of
548CMU, for catching some problems before version 1.2 left the nest; Stan
549Zanarotti and several others of MIT's Student Information Processing Board,
550for getting us started with ``discuss,'' for which this package was
551originally written; and everyone I've talked into --- I mean, asked to read
552this document and the ``man'' pages.
553
554@bye
555