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