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