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