xref: /freebsd/crypto/krb5/src/util/et/com_err.texinfo (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1\input texinfo @c -*-texinfo-*-
2
3@c util/et/com_err.texinfo
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@setfilename com_err
30@settitle A Common Error Description Library for UNIX
31
32@ifinfo
33This file documents the use of the Common Error Description library.
34
35Copyright (C) 1987, 1988 Student Information Processing Board of the
36Massachusetts Institute of Technology.
37
38Permission to use, copy, modify, and distribute this software and its
39documentation for any purpose and without fee is hereby granted, provided
40that the above copyright notice appear in all copies and that both that
41copyright notice and this permission notice appear in supporting
42documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
43used in advertising or publicity pertaining to distribution of the software
44without specific, written prior permission.  Furthermore if you modify this
45software you must label your software as modified software and not
46distribute it in such a fashion that it might be confused with the
47original M.I.T. software.  M.I.T. and the M.I.T. S.I.P.B.
48make no representations about the suitability of this software for any
49purpose.  It is provided "as is" without express or implied warranty.
50
51Note that the file texinfo.tex, provided with this distribution, is from
52the Free Software Foundation, and is under different copyright restrictions
53from the remainder of this package.
54
55@end ifinfo
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@ifinfo
118@c should put a menu here someday....
119@end ifinfo
120
121@page
122
123@section Why com_err?
124
125In building application software packages, a programmer often has to
126deal with a number of libraries, each of which can use a different
127error-reporting mechanism.  Sometimes one of two values is returned,
128indicating simply SUCCESS or FAILURE, with no description of errors
129encountered.  Sometimes it is an index into a table of text strings,
130where the name of the table used is dependent on the library being
131used when the error is generated; since each table starts numbering at
1320 or 1, additional information as to the source of the error code is
133needed to determine which table to look at.  Sometimes no text messages are
134supplied at all, and the programmer must supply them at any point at which
135he may wish to report error conditions.
136Often, a global variable is assigned some value describing the error, but
137the programmer has to know in each case whether to look at @code{errno},
138@code{h_errno}, the return value from @code{hes_err()}, or whatever other
139variables or routines are specified.
140And what happens if something
141in the procedure of
142examining or reporting the error changes the same variable?
143
144The package we have developed is an attempt to present a common
145error-handling mechanism to manipulate the most common form of error code
146in a fashion that does not have the problems listed above.
147
148A list of up to 256 text messages is supplied to a translator we have
149written, along with the three- to four-character ``name'' of the error
150table.  The library using this error table need only call a routine
151generated from this error-table source to make the table ``known'' to the
152com_err library, and any error code the library generates can be converted
153to the corresponding error message.  There is also a default format for
154error codes accidentally returned before making the table known, which is
155of the form @samp{unknown code foo 32}, where @samp{foo} would be the name
156of the table.
157
158@section Error codes
159
160Error codes themselves are 32 bit (signed) integers, of which the high
161order 24 bits are an identifier of which error table the error code is
162from, and the low order 8 bits are a sequential error number within
163the table.  An error code may thus be easily decomposed into its component
164parts.  Only the lowest 32 bits of an error code are considered significant
165on systems which support wider values.
166
167Error table 0 is defined to match the UNIX system call error table
168(@code{sys_errlist}); this allows @code{errno} values to be used directly
169in the library (assuming that @code{errno} is of a type with the same width
170as @t{long}).  Other error table numbers are formed by compacting together
171the first four characters of the error table name.  The mapping between
172characters in the name and numeric values in the error code are defined in
173a system-independent fashion, so that two systems that can pass integral
174values between them can reliably pass error codes without loss of meaning;
175this should work even if the character sets used are not the same.
176(However, if this is to be done, error table 0 should be avoided, since the
177local system call error tables may differ.)
178
179Any variable which is to contain an error code should be declared @t{long}.
180The draft proposed American National Standard for C (as of May, 1988)
181requires that @t{long} variables be at least 32 bits; any system which does
182not support 32-bit @t{long} values cannot make use of this package (nor
183much other software that assumes an ANSI-C environment base) without
184significant effort.
185
186@section Error table source file
187
188The error table source file begins with the declaration of the table name,
189as
190
191@example
192error_table @var{tablename}
193@end example
194
195Individual error codes are
196specified with
197
198@example
199error_code @var{ERROR_NAME}, @var{"text message"}
200@end example
201
202where @samp{ec} can also be used as a short form of @samp{error_code}.  To
203indicate the end of the table, use @samp{end}.  Thus, a (short) sample
204error table might be:
205
206@example
207
208        error_table     dsc
209
210        error_code      DSC_DUP_MTG_NAME,
211                        "Meeting already exists"
212
213        ec              DSC_BAD_PATH,
214                        "A bad meeting pathname was given"
215
216        ec              DSC_BAD_MODES,
217                        "Invalid mode for this access control list"
218
219        end
220
221@end example
222
223@section The error-table compiler
224
225The error table compiler is named @code{compile_et}.  It takes one
226argument, the pathname of a file (ending in @samp{.et}, e.g.,
227@samp{dsc_err.et}) containing an error table source file.  It parses the
228error table, and generates two output files -- a C header file
229(@samp{discuss_err.h}) which contains definitions of the numerical values
230of the error codes defined in the error table, and a C source file which
231should be compiled and linked with the executable.  The header file must be
232included in the source of a module which wishes to reference the error
233codes defined; the object module generated from the C code may be linked in
234to a program which wishes to use the printed forms of the error codes.
235
236This translator accepts a @kbd{-language @var{lang}} argument, which
237determines for which language (or language variant) the output should be
238written.  At the moment, @var{lang} is currently limited to @kbd{ANSI-C}
239and @kbd{K&R-C}, and some abbreviated forms of each.  Eventually, this will
240be extended to include some support for C++.  The default is currently
241@kbd{K&R-C}, though the generated sources will have ANSI-C code
242conditionalized on the symbol @t{__STDC__}.
243
244@section Run-time support routines
245
246Any source file which uses the routines supplied with or produced by the
247com_err package should include the header file @file{<com_err.h>}.  It
248contains declarations and definitions which may be needed on some systems.
249(Some functions cannot be referenced properly without the return type
250declarations in this file.  Some functions may work properly on most
251architectures even without the header file, but relying on this is not
252recommended.)
253
254The run-time support routines and variables provided via this package
255include the following:
256
257@example
258void initialize_@var{xxxx}_error_table (void);
259@end example
260
261One of these routines is built by the error compiler for each error table.
262It makes the @var{xxxx} error table ``known'' to the error reporting
263system.  By convention, this routine should be called in the initialization
264routine of the @var{xxxx} library.  If the library has no initialization
265routine, some combination of routines which form the core of the library
266should ensure that this routine is called.  It is not advised to leave it
267the caller to make this call.
268
269There is no harm in calling this routine more than once.
270
271@example
272#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L
273@end example
274
275This symbol contains the value of the first error code entry in the
276specified table.
277This rarely needs be used by the
278programmer.
279
280@example
281const char *error_message (long code);
282@end example
283
284This routine returns the character string error message associated
285with @code{code}; if this is associated with an unknown error table, or
286if the code is associated with a known error table but the code is not
287in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is
288returned, where @var{xxxx} is the error table name produced by
289reversing the compaction performed on the error table number implied
290by that error code, and @var{nn} is the offset from that base value.
291
292Although this routine is available for use when needed, its use should be
293left to circumstances which render @code{com_err} (below) unusable.
294
295@example
296void com_err (const char *whoami,  /* module reporting error */
297              long code,           /* error code */
298              const char *format,  /* format for additional detail */
299              ...);                /*  (extra parameters) */
300@end example
301
302This routine provides an alternate way to print error messages to
303standard error; it allows the error message to be passed in as a
304parameter, rather than in an external variable.  @emph{Provide grammatical
305context for ``message.''}
306
307If @var{format} is @code{(char *)NULL}, the formatted message will not be
308printed.  @var{format} may not be omitted.
309
310@example
311#include <stdarg.h>
312
313void com_err_va (const char *whoami,
314                 long code,
315                 const char *format,
316                 va_list args);
317@end example
318
319This routine provides an interface, equivalent to @code{com_err} above,
320which may be used by higher-level variadic functions (functions which
321accept variable numbers of arguments).
322
323@example
324#include <stdarg.h>
325
326void (*set_com_err_hook (void (*proc) ())) ();
327
328void (*@var{proc}) (const char *whoami, long code, va_list args);
329
330void reset_com_err_hook ();
331@end example
332
333These two routines allow a routine to be dynamically substituted for
334@samp{com_err}.  After @samp{set_com_err_hook} has been called,
335calls to @samp{com_err} will turn into calls to the new hook routine.
336@samp{reset_com_err_hook} turns off this hook.  This may intended to
337be used in daemons (to use a routine which calls @var{syslog(3)}), or
338in a window system application (which could pop up a dialogue box).
339
340If a program is to be used in an environment in which simply printing
341messages to the @code{stderr} stream would be inappropriate (such as in a
342daemon program which runs without a terminal attached),
343@code{set_com_err_hook} may be used to redirect output from @code{com_err}.
344The following is an example of an error handler which uses @var{syslog(3)}
345as supplied in BSD 4.3:
346
347@example
348#include <stdio.h>
349#include <stdarg.h>
350#include <syslog.h>
351
352/* extern openlog (const char * name, int logopt, int facility); */
353/* extern syslog (int priority, char * message, ...); */
354
355void hook (const char * whoami, long code,
356           const char * format, va_list args)
357@{
358    char buffer[BUFSIZ];
359    static int initialized = 0;
360    if (!initialized) @{
361        openlog (whoami,
362                 LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY,
363                 LOG_DAEMON);
364        initialized = 1;
365    @}
366    vsprintf (buffer, format, args);
367    syslog (LOG_ERR, "%s %s", error_message (code), buffer);
368@}
369@end example
370
371After making the call
372@code{set_com_err_hook (hook);},
373any calls to @code{com_err} will result in messages being sent to the
374@var{syslogd} daemon for logging.
375The name of the program, @samp{whoami}, is supplied to the
376@samp{openlog()} call, and the message is formatted into a buffer and
377passed to @code{syslog}.
378
379Note that since the extra arguments to @code{com_err} are passed by
380reference via the @code{va_list} value @code{args}, the hook routine may
381place any form of interpretation on them, including ignoring them.  For
382consistency, @code{printf}-style interpretation is suggested, via
383@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for
384the ANSI C library).
385
386@section 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 consistency 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@section Building and Installation
497
498The distribution of this package will probably be done as a compressed
499``tar''-format file available via anonymous FTP from SIPB.MIT.EDU.
500Retrieve @samp{pub/com_err.tar.Z} and extract the contents.  A subdirectory
501@t{profiled} should be created to hold objects compiled for profiling.
502Running ``make all'' should then be sufficient to build the library and
503error-table compiler.  The files @samp{libcom_err.a},
504@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be
505installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be
506installed as manual pages.
507
508Potential problems:
509
510@itemize @bullet
511
512@item Use of @code{strcasecmp}, a routine provided in BSD for
513case-insensitive string comparisons.  If an equivalent routine is
514available, you can modify @code{CFLAGS} in the makefile to define
515@code{strcasecmp} to the name of that routine.
516
517@item Compilers that defined @code{__STDC__} without providing the header
518file @code{<stdarg.h>}.  One such example is Metaware's High ``C''
519compiler, as provided at Project Athena on the IBM RT/PC workstation; if
520@code{__HIGHC__} is defined, it is assumed that @code{<stdarg.h>} is not
521available, and therefore @code{<varargs.h>} must be used.  If the symbol
522@code{VARARGS} is defined (e.g., in the makefile), @code{<varargs.h>} will
523be used.
524
525@item If your linker rejects symbols that are simultaneously defined in two
526library files, edit @samp{Makefile} to remove @samp{perror.c} from the
527library.  This file contains a version of @var{perror(3)} which calls
528@code{com_err} instead of calling @code{write} directly.
529
530@end itemize
531
532As I do not have access to non-BSD systems, there are probably
533bugs present that may interfere with building or using this package on
534other systems.  If they are reported to me, they can probably be fixed for
535the next version.
536
537@section Bug Reports
538
539Please send any comments or bug reports to the principal author: Ken
540Raeburn, @t{Raeburn@@Athena.MIT.EDU}.
541
542@section Acknowledgements
543
544I would like to thank: Bill Sommerfeld, for his help with some of this
545documentation, and catching some of the bugs the first time around;
546Honeywell Information Systems, for not killing off the @emph{Multics}
547operating system before I had an opportunity to use it; Honeywell's
548customers, who persuaded them not to do so, for a while; Ted Anderson of
549CMU, for catching some problems before version 1.2 left the nest; Stan
550Zanarotti and several others of MIT's Student Information Processing Board,
551for getting us started with ``discuss,'' for which this package was
552originally written; and everyone I've talked into --- I mean, asked to read
553this document and the ``man'' pages.
554
555@bye
556