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