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