com_err.texinfo revision ccfedb17b110d8eec6343a1c3a6a2437fea4dbc2
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.info 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@c smallbook 28 29@iftex 30@finalout 31@end iftex 32 33@ifinfo 34This file documents the use of the Common Error Description library. 35 36Copyright (C) 1987, 1988 Student Information Processing Board of the 37Massachusetts Institute of Technology. 38 39Permission to use, copy, modify, and distribute this software and its 40documentation for any purpose and without fee is hereby granted, provided 41that the above copyright notice appear in all copies and that both that 42copyright notice and this permission notice appear in supporting 43documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be 44used in advertising or publicity pertaining to distribution of the software 45without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B. 46make no representations about the suitability of this software for any 47purpose. It is provided "as is" without express or implied warranty. 48 49Note that the file texinfo.tex, provided with this distribution, is from 50the Free Software Foundation, and is under different copyright restrictions 51from the remainder of this package. 52 53@ignore 54Permission is granted to process this file through Tex and print the 55results, provided the printed document carries copying permission 56notice identical to this one except for the removal of this paragraph 57(this paragraph not being relevant to the printed manual). 58 59@end ignore 60@end ifinfo 61 62@setchapternewpage odd 63 64@titlepage 65@center @titlefont{A Common Error Description} 66@center @titlefont{Library for UNIX} 67@sp 2 68@center Ken Raeburn 69@center Bill Sommerfeld 70@sp 1 71@center MIT Student Information Processing Board 72@sp 3 73@center last updated 1 January 1989 74@center for version 1.2 75@center ***DRAFT COPY ONLY*** 76 77@vskip 2in 78 79@center @b{Abstract} 80 81UNIX has always had a clean and simple system call interface, with a 82standard set of error codes passed between the kernel and user 83programs. Unfortunately, the same cannot be said of many of the 84libraries layered on top of the primitives provided by the kernel. 85Typically, each one has used a different style of indicating errors to 86their callers, leading to a total hodgepodge of error handling, and 87considerable amounts of work for the programmer. This paper describes 88a library and associated utilities which allows a more uniform way for 89libraries to return errors to their callers, and for programs to 90describe errors and exceptional conditions to their users. 91 92@page 93@vskip 0pt plus 1filll 94 95Copyright @copyright{} 1987, 1988 by the Student Information Processing 96Board of the Massachusetts Institute of Technology. 97 98Permission to use, copy, modify, and distribute this software and its 99documentation for any purpose and without fee is hereby granted, provided 100that the above copyright notice appear in all copies and that both that 101copyright notice and this permission notice appear in supporting 102documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be 103used in advertising or publicity pertaining to distribution of the software 104without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B. 105make no representations about the suitability of this software for any 106purpose. It is provided "as is" without express or implied warranty. 107 108Note that the file texinfo.tex, provided with this distribution, is from 109the Free Software Foundation, and is under different copyright restrictions 110from the remainder of this package. 111 112@end titlepage 113 114@ifinfo 115@node Top, Why com_err?, (dir), (dir) 116 117@top A Common Error Description Library for UNIX 118 119This manual documents the com_err library. 120 121@menu 122* Why com_err?:: 123* Error codes:: 124* Error table source file:: 125* The error-table compiler:: 126* Run-time support routines:: 127* Coding Conventions:: 128* Building and Installation:: 129* Bug Reports:: 130* Acknowledgements:: 131@end menu 132 133@page 134@end ifinfo 135 136@node Why com_err?, Error codes, Top, Top 137@chapter Why com_err? 138 139In building application software packages, a programmer often has to 140deal with a number of libraries, each of which can use a different 141error-reporting mechanism. Sometimes one of two values is returned, 142indicating simply SUCCESS or FAILURE, with no description of errors 143encountered. Sometimes it is an index into a table of text strings, 144where the name of the table used is dependent on the library being 145used when the error is generated; since each table starts numbering at 1460 or 1, additional information as to the source of the error code is 147needed to determine which table to look at. Sometimes no text messages are 148supplied at all, and the programmer must supply them at any point at which 149he may wish to report error conditions. 150Often, a global variable is assigned some value describing the error, but 151the programmer has to know in each case whether to look at @code{errno}, 152@code{h_errno}, the return value from @code{hes_err()}, or whatever other 153variables or routines are specified. 154And what happens if something 155in the procedure of 156examining or reporting the error changes the same variable? 157 158The package we have developed is an attempt to present a common 159error-handling mechanism to manipulate the most common form of error code 160in a fashion that does not have the problems listed above. 161 162A list of up to 256 text messages is supplied to a translator we have 163written, along with the three- to four-character ``name'' of the error 164table. The library using this error table need only call a routine 165generated from this error-table source to make the table ``known'' to the 166com_err library, and any error code the library generates can be converted 167to the corresponding error message. There is also a default format for 168error codes accidentally returned before making the table known, which is 169of the form @samp{unknown code foo 32}, where @samp{foo} would be the name 170of the table. 171 172@node Error codes, Error table source file, Why com_err?, Top 173@chapter Error codes 174 175Error codes themselves are 32 bit (signed) integers, of which the high 176order 24 bits are an identifier of which error table the error code is 177from, and the low order 8 bits are a sequential error number within 178the table. An error code may thus be easily decomposed into its component 179parts. Only the lowest 32 bits of an error code are considered significant 180on systems which support wider values. 181 182Error table 0 is defined to match the UNIX system call error table 183(@code{sys_errlist}); this allows @code{errno} values to be used directly 184in the library (assuming that @code{errno} is of a type with the same width 185as @t{long}). Other error table numbers are formed by compacting together 186the first four characters of the error table name. The mapping between 187characters in the name and numeric values in the error code are defined in 188a system-independent fashion, so that two systems that can pass integral 189values between them can reliably pass error codes without loss of meaning; 190this should work even if the character sets used are not the same. 191(However, if this is to be done, error table 0 should be avoided, since the 192local system call error tables may differ.) 193 194Any variable which is to contain an error code should be declared @t{long}. 195The draft proposed American National Standard for C (as of May, 1988) 196requires that @t{long} variables be at least 32 bits; any system which does 197not support 32-bit @t{long} values cannot make use of this package (nor 198much other software that assumes an ANSI-C environment base) without 199significant effort. 200 201@node Error table source file, The error-table compiler, Error codes, Top 202@chapter Error table source file 203 204The error table source file begins with the declaration of the table name, 205as 206 207@example 208error_table @var{tablename} 209@end example 210 211Individual error codes are 212specified with 213 214@example 215error_code @var{ERROR_NAME}, @var{"text message"} 216@end example 217 218where @samp{ec} can also be used as a short form of @samp{error_code}. To 219indicate the end of the table, use @samp{end}. Thus, a (short) sample 220error table might be: 221 222@example 223 224 error_table dsc 225 226 error_code DSC_DUP_MTG_NAME, 227 "Meeting already exists" 228 229 ec DSC_BAD_PATH, 230 "A bad meeting pathname was given" 231 232 ec DSC_BAD_MODES, 233 "Invalid mode for this access control list" 234 235 end 236 237@end example 238 239@node The error-table compiler, Run-time support routines, Error table source file, Top 240@chapter The error-table compiler 241 242The error table compiler is named @code{compile_et}. It takes one 243argument, the pathname of a file (ending in @samp{.et}, e.g., 244@samp{dsc_err.et}) containing an error table source file. It parses the 245error table, and generates two output files -- a C header file 246(@samp{discuss_err.h}) which contains definitions of the numerical values 247of the error codes defined in the error table, and a C source file which 248should be compiled and linked with the executable. The header file must be 249included in the source of a module which wishes to reference the error 250codes defined; the object module generated from the C code may be linked in 251to a program which wishes to use the printed forms of the error codes. 252 253@node Run-time support routines, Coding Conventions, The error-table compiler, Top 254@chapter Run-time support routines 255 256Any source file which uses the routines supplied with or produced by the 257com_err package should include the header file @file{<com_err.h>}. It 258contains declarations and definitions which may be needed on some systems. 259(Some functions cannot be referenced properly without the return type 260declarations in this file. Some functions may work properly on most 261architectures even without the header file, but relying on this is not 262recommended.) 263 264The run-time support routines and variables provided via this package 265include the following: 266 267@example 268void initialize_@var{xxxx}_error_table (void); 269@end example 270 271One of these routines is built by the error compiler for each error table. 272It makes the @var{xxxx} error table ``known'' to the error reporting 273system. By convention, this routine should be called in the initialization 274routine of the @var{xxxx} library. If the library has no initialization 275routine, some combination of routines which form the core of the library 276should ensure that this routine is called. It is not advised to leave it 277the caller to make this call. 278 279There is no harm in calling this routine more than once. 280 281@example 282#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L 283@end example 284 285This symbol contains the value of the first error code entry in the 286specified table. 287This rarely needs be used by the 288programmer. 289 290@deftypefun const char *error_message (long @var{code}); 291 292This routine returns the character string error message associated 293with @code{code}; if this is associated with an unknown error table, or 294if the code is associated with a known error table but the code is not 295in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is 296returned, where @var{xxxx} is the error table name produced by 297reversing the compaction performed on the error table number implied 298by that error code, and @var{nn} is the offset from that base value. 299 300Although this routine is available for use when needed, its use should be 301left to circumstances which render @code{com_err} (below) unusable. 302 303@end deftypefun 304 305@deftypefun void com_err (const char *@var{whoami}, long @var{error_code}, const char *@var{format}, ...); 306 307This routine provides an alternate way to print error messages to 308standard error; it allows the error message to be passed in as a 309parameter, rather than in an external variable. @emph{Provide grammatical 310context for ``message.''} 311 312The module reporting the error should be passed in via @var{whoami}. 313If @var{format} is @code{(char *)NULL}, the formatted message will not be 314printed. @var{format} may not be omitted. 315 316@end deftypefun 317 318@deftypefun void com_err_va (const char *@var{whoami}, long @var{error_code}, const char *@var{format}, va_list @var{args}); 319 320This routine provides an interface, equivalent to @code{com_err} above, 321which may be used by higher-level variadic functions (functions which 322accept variable numbers of arguments). 323 324@end deftypefun 325 326@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})); 327 328@deftypefunx void reset_com_err_hook (); 329 330These two routines allow a routine to be dynamically substituted for 331@samp{com_err}. After @samp{set_com_err_hook} has been called, 332calls to @samp{com_err} will turn into calls to the new hook routine. 333@samp{reset_com_err_hook} turns off this hook. This may intended to 334be used in daemons (to use a routine which calls @cite{syslog(3)}), or 335in a window system application (which could pop up a dialogue box). 336 337If a program is to be used in an environment in which simply printing 338messages to the @code{stderr} stream would be inappropriate (such as in a 339daemon program which runs without a terminal attached), 340@code{set_com_err_hook} may be used to redirect output from @code{com_err}. 341The following is an example of an error handler which uses @cite{syslog(3)} 342as supplied in BSD 4.3: 343 344@example 345#include <stdio.h> 346#include <stdarg.h> 347#include <syslog.h> 348 349/* extern openlog (const char * name, int logopt, int facility); */ 350/* extern syslog (int priority, char * message, ...); */ 351 352void hook (const char * whoami, long code, 353 const char * format, va_list args) 354@{ 355 char buffer[BUFSIZ]; 356 static int initialized = 0; 357 if (!initialized) @{ 358 openlog (whoami, 359 LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY, 360 LOG_DAEMON); 361 initialized = 1; 362 @} 363 vsprintf (buffer, format, args); 364 syslog (LOG_ERR, "%s %s", error_message (code), buffer); 365@} 366@end example 367 368After making the call 369@code{set_com_err_hook (hook);}, 370any calls to @code{com_err} will result in messages being sent to the 371@var{syslogd} daemon for logging. 372The name of the program, @samp{whoami}, is supplied to the 373@samp{openlog()} call, and the message is formatted into a buffer and 374passed to @code{syslog}. 375 376Note that since the extra arguments to @code{com_err} are passed by 377reference via the @code{va_list} value @code{args}, the hook routine may 378place any form of interpretation on them, including ignoring them. For 379consistency, @code{printf}-style interpretation is suggested, via 380@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for 381the ANSI C library). 382 383@end deftypefun 384 385@node Coding Conventions, Building and Installation, Run-time support routines, Top 386@chapter 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 consistancy 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@node Building and Installation, Bug Reports, Coding Conventions, Top 497@chapter Building and Installation 498 499The distribution of this package will probably be done as a compressed 500``tar''-format file available via anonymous FTP from SIPB.MIT.EDU. 501Retrieve @samp{pub/com_err.tar.Z} and extract the contents. A subdirectory 502@t{profiled} should be created to hold objects compiled for profiling. 503Running ``make all'' should then be sufficient to build the library and 504error-table compiler. The files @samp{libcom_err.a}, 505@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be 506installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be 507installed as manual pages. 508 509@node Bug Reports, Acknowledgements, Building and Installation, Top 510@chapter Bug Reports 511 512The principal author of this library is: Ken 513Raeburn, @t{raeburn@@MIT.EDU}. 514 515This version of the com_err library is being maintained by Theodore 516Ts'o, and so bugs and comments should be sent to @t{tytso@@thunk.org}. 517 518 519@node Acknowledgements, , Bug Reports, Top 520@chapter Acknowledgements 521 522I would like to thank: Bill Sommerfeld, for his help with some of this 523documentation, and catching some of the bugs the first time around; 524Honeywell Information Systems, for not killing off the @emph{Multics} 525operating system before I had an opportunity to use it; Honeywell's 526customers, who persuaded them not to do so, for a while; Ted Anderson of 527CMU, for catching some problems before version 1.2 left the nest; Stan 528Zanarotti and several others of MIT's Student Information Processing Board, 529for getting us started with ``discuss,'' for which this package was 530originally written; and everyone I've talked into --- I mean, asked to read 531this document and the ``man'' pages. 532 533@contents 534@bye 535