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