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