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