Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 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 | |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 17 | @setfilename com_err.info |
Theodore Ts'o | 541d173 | 2002-02-23 21:23:26 -0500 | [diff] [blame] | 18 | @settitle A Common Error Description Library for UNIX |
| 19 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 20 | @ifinfo |
Theodore Ts'o | 541d173 | 2002-02-23 21:23:26 -0500 | [diff] [blame] | 21 | @dircategory Development |
Dmitry V. Levin | 710bac8 | 2007-10-20 22:09:13 +0400 | [diff] [blame] | 22 | @direntry |
Theodore Ts'o | 0d8b673 | 2007-06-24 16:59:36 -0400 | [diff] [blame] | 23 | * Com_err: (com_err). A Common Error Description Library for UNIX. |
Dmitry V. Levin | 710bac8 | 2007-10-20 22:09:13 +0400 | [diff] [blame] | 24 | @end direntry |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 25 | @end ifinfo |
| 26 | |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 27 | @c smallbook |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 28 | |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 29 | @iftex |
| 30 | @finalout |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 31 | @end iftex |
| 32 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 33 | @ifinfo |
| 34 | This file documents the use of the Common Error Description library. |
| 35 | |
| 36 | Copyright (C) 1987, 1988 Student Information Processing Board of the |
| 37 | Massachusetts Institute of Technology. |
| 38 | |
| 39 | Permission to use, copy, modify, and distribute this software and its |
| 40 | documentation for any purpose and without fee is hereby granted, provided |
| 41 | that the above copyright notice appear in all copies and that both that |
| 42 | copyright notice and this permission notice appear in supporting |
| 43 | documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be |
| 44 | used in advertising or publicity pertaining to distribution of the software |
| 45 | without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B. |
| 46 | make no representations about the suitability of this software for any |
| 47 | purpose. It is provided "as is" without express or implied warranty. |
| 48 | |
| 49 | Note that the file texinfo.tex, provided with this distribution, is from |
| 50 | the Free Software Foundation, and is under different copyright restrictions |
| 51 | from the remainder of this package. |
| 52 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 53 | @ignore |
| 54 | Permission is granted to process this file through Tex and print the |
| 55 | results, provided the printed document carries copying permission |
| 56 | notice 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 |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 60 | @end ifinfo |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 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 | |
| 81 | UNIX has always had a clean and simple system call interface, with a |
| 82 | standard set of error codes passed between the kernel and user |
| 83 | programs. Unfortunately, the same cannot be said of many of the |
| 84 | libraries layered on top of the primitives provided by the kernel. |
| 85 | Typically, each one has used a different style of indicating errors to |
| 86 | their callers, leading to a total hodgepodge of error handling, and |
| 87 | considerable amounts of work for the programmer. This paper describes |
| 88 | a library and associated utilities which allows a more uniform way for |
| 89 | libraries to return errors to their callers, and for programs to |
| 90 | describe errors and exceptional conditions to their users. |
| 91 | |
| 92 | @page |
| 93 | @vskip 0pt plus 1filll |
| 94 | |
| 95 | Copyright @copyright{} 1987, 1988 by the Student Information Processing |
| 96 | Board of the Massachusetts Institute of Technology. |
| 97 | |
| 98 | Permission to use, copy, modify, and distribute this software and its |
| 99 | documentation for any purpose and without fee is hereby granted, provided |
| 100 | that the above copyright notice appear in all copies and that both that |
| 101 | copyright notice and this permission notice appear in supporting |
| 102 | documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be |
| 103 | used in advertising or publicity pertaining to distribution of the software |
| 104 | without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B. |
| 105 | make no representations about the suitability of this software for any |
| 106 | purpose. It is provided "as is" without express or implied warranty. |
| 107 | |
| 108 | Note that the file texinfo.tex, provided with this distribution, is from |
| 109 | the Free Software Foundation, and is under different copyright restrictions |
| 110 | from the remainder of this package. |
| 111 | |
| 112 | @end titlepage |
| 113 | |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 114 | @ifinfo |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 115 | @node Top, Why com_err?, (dir), (dir) |
| 116 | |
| 117 | @top A Common Error Description Library for UNIX |
| 118 | |
| 119 | This 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 | |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 133 | @page |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 134 | @end ifinfo |
| 135 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 136 | @node Why com_err?, Error codes, Top, Top |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 137 | @chapter Why com_err? |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 138 | |
| 139 | In building application software packages, a programmer often has to |
| 140 | deal with a number of libraries, each of which can use a different |
| 141 | error-reporting mechanism. Sometimes one of two values is returned, |
| 142 | indicating simply SUCCESS or FAILURE, with no description of errors |
| 143 | encountered. Sometimes it is an index into a table of text strings, |
| 144 | where the name of the table used is dependent on the library being |
| 145 | used when the error is generated; since each table starts numbering at |
| 146 | 0 or 1, additional information as to the source of the error code is |
| 147 | needed to determine which table to look at. Sometimes no text messages are |
| 148 | supplied at all, and the programmer must supply them at any point at which |
| 149 | he may wish to report error conditions. |
| 150 | Often, a global variable is assigned some value describing the error, but |
| 151 | the 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 |
| 153 | variables or routines are specified. |
| 154 | And what happens if something |
| 155 | in the procedure of |
| 156 | examining or reporting the error changes the same variable? |
| 157 | |
| 158 | The package we have developed is an attempt to present a common |
| 159 | error-handling mechanism to manipulate the most common form of error code |
| 160 | in a fashion that does not have the problems listed above. |
| 161 | |
| 162 | A list of up to 256 text messages is supplied to a translator we have |
| 163 | written, along with the three- to four-character ``name'' of the error |
| 164 | table. The library using this error table need only call a routine |
| 165 | generated from this error-table source to make the table ``known'' to the |
| 166 | com_err library, and any error code the library generates can be converted |
| 167 | to the corresponding error message. There is also a default format for |
| 168 | error codes accidentally returned before making the table known, which is |
| 169 | of the form @samp{unknown code foo 32}, where @samp{foo} would be the name |
| 170 | of the table. |
| 171 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 172 | @node Error codes, Error table source file, Why com_err?, Top |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 173 | @chapter Error codes |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 174 | |
| 175 | Error codes themselves are 32 bit (signed) integers, of which the high |
| 176 | order 24 bits are an identifier of which error table the error code is |
| 177 | from, and the low order 8 bits are a sequential error number within |
| 178 | the table. An error code may thus be easily decomposed into its component |
| 179 | parts. Only the lowest 32 bits of an error code are considered significant |
| 180 | on systems which support wider values. |
| 181 | |
| 182 | Error 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 |
| 184 | in the library (assuming that @code{errno} is of a type with the same width |
| 185 | as @t{long}). Other error table numbers are formed by compacting together |
| 186 | the first four characters of the error table name. The mapping between |
| 187 | characters in the name and numeric values in the error code are defined in |
| 188 | a system-independent fashion, so that two systems that can pass integral |
| 189 | values between them can reliably pass error codes without loss of meaning; |
| 190 | this 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 |
| 192 | local system call error tables may differ.) |
| 193 | |
| 194 | Any variable which is to contain an error code should be declared @t{long}. |
| 195 | The draft proposed American National Standard for C (as of May, 1988) |
| 196 | requires that @t{long} variables be at least 32 bits; any system which does |
| 197 | not support 32-bit @t{long} values cannot make use of this package (nor |
| 198 | much other software that assumes an ANSI-C environment base) without |
| 199 | significant effort. |
| 200 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 201 | @node Error table source file, The error-table compiler, Error codes, Top |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 202 | @chapter Error table source file |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 203 | |
| 204 | The error table source file begins with the declaration of the table name, |
| 205 | as |
| 206 | |
| 207 | @example |
| 208 | error_table @var{tablename} |
| 209 | @end example |
| 210 | |
| 211 | Individual error codes are |
| 212 | specified with |
| 213 | |
| 214 | @example |
| 215 | error_code @var{ERROR_NAME}, @var{"text message"} |
| 216 | @end example |
| 217 | |
| 218 | where @samp{ec} can also be used as a short form of @samp{error_code}. To |
| 219 | indicate the end of the table, use @samp{end}. Thus, a (short) sample |
| 220 | error 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 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 239 | @node The error-table compiler, Run-time support routines, Error table source file, Top |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 240 | @chapter The error-table compiler |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 241 | |
| 242 | The error table compiler is named @code{compile_et}. It takes one |
| 243 | argument, 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 |
| 245 | error table, and generates two output files -- a C header file |
| 246 | (@samp{discuss_err.h}) which contains definitions of the numerical values |
| 247 | of the error codes defined in the error table, and a C source file which |
| 248 | should be compiled and linked with the executable. The header file must be |
| 249 | included in the source of a module which wishes to reference the error |
| 250 | codes defined; the object module generated from the C code may be linked in |
| 251 | to a program which wishes to use the printed forms of the error codes. |
| 252 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 253 | @node Run-time support routines, Coding Conventions, The error-table compiler, Top |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 254 | @chapter Run-time support routines |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 255 | |
| 256 | Any source file which uses the routines supplied with or produced by the |
| 257 | com_err package should include the header file @file{<com_err.h>}. It |
| 258 | contains declarations and definitions which may be needed on some systems. |
| 259 | (Some functions cannot be referenced properly without the return type |
| 260 | declarations in this file. Some functions may work properly on most |
| 261 | architectures even without the header file, but relying on this is not |
| 262 | recommended.) |
| 263 | |
| 264 | The run-time support routines and variables provided via this package |
| 265 | include the following: |
| 266 | |
| 267 | @example |
| 268 | void initialize_@var{xxxx}_error_table (void); |
| 269 | @end example |
| 270 | |
| 271 | One of these routines is built by the error compiler for each error table. |
| 272 | It makes the @var{xxxx} error table ``known'' to the error reporting |
| 273 | system. By convention, this routine should be called in the initialization |
| 274 | routine of the @var{xxxx} library. If the library has no initialization |
| 275 | routine, some combination of routines which form the core of the library |
| 276 | should ensure that this routine is called. It is not advised to leave it |
| 277 | the caller to make this call. |
| 278 | |
| 279 | There 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 | |
| 285 | This symbol contains the value of the first error code entry in the |
| 286 | specified table. |
| 287 | This rarely needs be used by the |
| 288 | programmer. |
| 289 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 290 | @deftypefun const char *error_message (long @var{code}); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 291 | |
| 292 | This routine returns the character string error message associated |
| 293 | with @code{code}; if this is associated with an unknown error table, or |
| 294 | if the code is associated with a known error table but the code is not |
| 295 | in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is |
| 296 | returned, where @var{xxxx} is the error table name produced by |
| 297 | reversing the compaction performed on the error table number implied |
| 298 | by that error code, and @var{nn} is the offset from that base value. |
| 299 | |
| 300 | Although this routine is available for use when needed, its use should be |
| 301 | left to circumstances which render @code{com_err} (below) unusable. |
| 302 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 303 | @end deftypefun |
| 304 | |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 305 | @deftypefun void com_err (const char *@var{whoami}, long @var{error_code}, const char *@var{format}, ...); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 306 | |
| 307 | This routine provides an alternate way to print error messages to |
| 308 | standard error; it allows the error message to be passed in as a |
| 309 | parameter, rather than in an external variable. @emph{Provide grammatical |
| 310 | context for ``message.''} |
| 311 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 312 | The module reporting the error should be passed in via @var{whoami}. |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 313 | If @var{format} is @code{(char *)NULL}, the formatted message will not be |
| 314 | printed. @var{format} may not be omitted. |
| 315 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 316 | @end deftypefun |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 317 | |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 318 | @deftypefun void com_err_va (const char *@var{whoami}, long @var{error_code}, const char *@var{format}, va_list @var{args}); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 319 | |
| 320 | This routine provides an interface, equivalent to @code{com_err} above, |
| 321 | which may be used by higher-level variadic functions (functions which |
| 322 | accept variable numbers of arguments). |
| 323 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 324 | @end deftypefun |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 325 | |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 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})); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 327 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 328 | @deftypefunx void reset_com_err_hook (); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 329 | |
| 330 | These two routines allow a routine to be dynamically substituted for |
| 331 | @samp{com_err}. After @samp{set_com_err_hook} has been called, |
| 332 | calls 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 |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 334 | be used in daemons (to use a routine which calls @cite{syslog(3)}), or |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 335 | in a window system application (which could pop up a dialogue box). |
| 336 | |
| 337 | If a program is to be used in an environment in which simply printing |
| 338 | messages to the @code{stderr} stream would be inappropriate (such as in a |
| 339 | daemon program which runs without a terminal attached), |
| 340 | @code{set_com_err_hook} may be used to redirect output from @code{com_err}. |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 341 | The following is an example of an error handler which uses @cite{syslog(3)} |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 342 | as 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 | |
| 352 | void 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 | |
| 368 | After making the call |
| 369 | @code{set_com_err_hook (hook);}, |
| 370 | any calls to @code{com_err} will result in messages being sent to the |
| 371 | @var{syslogd} daemon for logging. |
| 372 | The name of the program, @samp{whoami}, is supplied to the |
| 373 | @samp{openlog()} call, and the message is formatted into a buffer and |
| 374 | passed to @code{syslog}. |
| 375 | |
| 376 | Note that since the extra arguments to @code{com_err} are passed by |
| 377 | reference via the @code{va_list} value @code{args}, the hook routine may |
| 378 | place any form of interpretation on them, including ignoring them. For |
| 379 | consistency, @code{printf}-style interpretation is suggested, via |
| 380 | @code{vsprintf} (or @code{_doprnt} on BSD systems without full support for |
| 381 | the ANSI C library). |
| 382 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 383 | @end deftypefun |
| 384 | |
| 385 | @node Coding Conventions, Building and Installation, Run-time support routines, Top |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 386 | @chapter Coding Conventions |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 387 | |
| 388 | The following conventions are just some general stylistic conventions |
| 389 | to follow when writing robust libraries and programs. Conventions |
| 390 | similar to this are generally followed inside the UNIX kernel and most |
| 391 | routines in the Multics operating system. In general, a routine |
| 392 | either succeeds (returning a zero error code, and doing some side |
| 393 | effects in the process), or it fails, doing minimal side effects; in |
| 394 | any event, any invariant which the library assumes must be maintained. |
| 395 | |
| 396 | In general, it is not in the domain of non user-interface library |
| 397 | routines to write error messages to the user's terminal, or halt the |
| 398 | process. Such forms of ``error handling'' should be reserved for |
| 399 | failures of internal invariants and consistancy checks only, as it |
| 400 | provides the user of the library no way to clean up for himself in the |
| 401 | event of total failure. |
| 402 | |
| 403 | Library routines which can fail should be set up to return an error |
| 404 | code. This should usually be done as the return value of the |
| 405 | function; if this is not acceptable, the routine should return a |
| 406 | ``null'' value, and put the error code into a parameter passed by |
| 407 | reference. |
| 408 | |
| 409 | Routines which use the first style of interface can be used from |
| 410 | user-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 | |
| 427 | A caller which fails to check the return status is in error. It is |
| 428 | possible to look for code which ignores error returns by using lint; |
| 429 | look for error messages of the form ``foobar returns value which is |
| 430 | sometimes ignored'' or ``foobar returns value which is always |
| 431 | ignored.'' |
| 432 | |
| 433 | Since libraries may be built out of other libraries, it is often necessary |
| 434 | for the success of one routine to depend on another. When a lower level |
| 435 | routine returns an error code, the middle level routine has a few possible |
| 436 | options. It can simply return the error code to its caller after doing |
| 437 | some form of cleanup, it can substitute one of its own, or it can take |
| 438 | corrective action of its own and continue normally. For instance, a |
| 439 | library routine which makes a ``connect'' system call to make a network |
| 440 | connection may reflect the system error code @code{ECONNREFUSED} |
| 441 | (Connection refused) to its caller, or it may return a ``server not |
| 442 | available, try again later,'' or it may try a different server. |
| 443 | |
| 444 | Cleanup which is typically necessary may include, but not be limited |
| 445 | to, freeing allocated memory which will not be needed any more, |
| 446 | unlocking concurrancy locks, dropping reference counts, closing file |
| 447 | descriptors, or otherwise undoing anything which the procedure did up |
| 448 | to this point. When there are a lot of things which can go wrong, it |
| 449 | is generally good to write one block of error-handling code which is |
| 450 | branched to, using a goto, in the event of failure. A common source |
| 451 | of errors in UNIX programs is failing to close file descriptors on |
| 452 | error returns; this leaves a number of ``zombied'' file descriptors |
| 453 | open, which eventually causes the process to run out of file |
| 454 | descriptors 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 | |
| 488 | error: |
| 489 | if (f1) fclose(f1); |
| 490 | if (f2) fclose(f2); |
| 491 | if (f3) fclose(f3); |
| 492 | return status; |
| 493 | @} |
| 494 | @end example |
| 495 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 496 | @node Building and Installation, Bug Reports, Coding Conventions, Top |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 497 | @chapter Building and Installation |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 498 | |
| 499 | The distribution of this package will probably be done as a compressed |
| 500 | ``tar''-format file available via anonymous FTP from SIPB.MIT.EDU. |
| 501 | Retrieve @samp{pub/com_err.tar.Z} and extract the contents. A subdirectory |
| 502 | @t{profiled} should be created to hold objects compiled for profiling. |
| 503 | Running ``make all'' should then be sufficient to build the library and |
| 504 | error-table compiler. The files @samp{libcom_err.a}, |
| 505 | @samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be |
| 506 | installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be |
| 507 | installed as manual pages. |
| 508 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 509 | @node Bug Reports, Acknowledgements, Building and Installation, Top |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 510 | @chapter Bug Reports |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 511 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 512 | The principal author of this library is: Ken |
| 513 | Raeburn, @t{raeburn@@MIT.EDU}. |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 514 | |
Theodore Ts'o | 5966f36 | 2001-09-11 00:38:03 -0400 | [diff] [blame] | 515 | This version of the com_err library is being maintained by Theodore |
| 516 | Ts'o, and so bugs and comments should be sent to @t{tytso@@thunk.org}. |
| 517 | |
| 518 | |
| 519 | @node Acknowledgements, , Bug Reports, Top |
Theodore Ts'o | ccfedb1 | 2013-01-02 10:06:09 -0500 | [diff] [blame] | 520 | @chapter Acknowledgements |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 521 | |
| 522 | I would like to thank: Bill Sommerfeld, for his help with some of this |
| 523 | documentation, and catching some of the bugs the first time around; |
| 524 | Honeywell Information Systems, for not killing off the @emph{Multics} |
| 525 | operating system before I had an opportunity to use it; Honeywell's |
| 526 | customers, who persuaded them not to do so, for a while; Ted Anderson of |
| 527 | CMU, for catching some problems before version 1.2 left the nest; Stan |
| 528 | Zanarotti and several others of MIT's Student Information Processing Board, |
| 529 | for getting us started with ``discuss,'' for which this package was |
| 530 | originally written; and everyone I've talked into --- I mean, asked to read |
| 531 | this document and the ``man'' pages. |
| 532 | |
Theodore Ts'o | 4534f8b | 2009-11-29 20:19:10 -0500 | [diff] [blame] | 533 | @contents |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 534 | @bye |