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