ReactOS  0.4.13-dev-241-g63286c6
comerr.c
Go to the documentation of this file.
1 /* @(#)comerr.c 1.44 17/03/13 Copyright 1985-1989, 1995-2017 J. Schilling */
2 /*
3  * Routines for printing command errors
4  *
5  * Copyright (c) 1985-1989, 1995-2017 J. Schilling
6  */
7 /*
8  * The contents of this file are subject to the terms of the
9  * Common Development and Distribution License, Version 1.0 only
10  * (the "License"). You may not use this file except in compliance
11  * with the License.
12  *
13  * See the file CDDL.Schily.txt in this distribution for details.
14  * A copy of the CDDL is also available via the Internet at
15  * http://www.opensource.org/licenses/cddl1.txt
16  *
17  * When distributing Covered Code, include this CDDL HEADER in each
18  * file and include the License file CDDL.Schily.txt from this distribution.
19  */
20 
21 #include <schily/mconfig.h>
22 #include <schily/unistd.h> /* include <sys/types.h> try to get size_t */
23 #include <schily/stdio.h> /* Try again for size_t */
24 #include <schily/stdlib.h> /* Try again for size_t */
25 #include <schily/standard.h>
26 #include <schily/varargs.h>
27 #include <schily/string.h>
28 #include <schily/schily.h>
29 #include <schily/errno.h>
30 
31 EXPORT int on_comerr __PR((void (*fun)(int, void *), void *arg));
32 EXPORT void comerr __PR((const char *, ...));
33 EXPORT void xcomerr __PR((int, const char *, ...));
34 EXPORT void comerrno __PR((int, const char *, ...));
35 EXPORT void xcomerrno __PR((int, int, const char *, ...));
36 EXPORT int errmsg __PR((const char *, ...));
37 EXPORT int errmsgno __PR((int, const char *, ...));
38 EXPORT int _comerr __PR((FILE *, int, int, int,
39  const char *, va_list));
40 LOCAL int _ex_clash __PR((int));
41 EXPORT void comexit __PR((int));
42 EXPORT char *errmsgstr __PR((int));
43 
44 typedef struct ex {
45  struct ex *next;
46  void (*func) __PR((int, void *));
47  void *arg;
48 } ex_t;
49 
51 
52 /*
53  * Set list of callback functions to call with *comerr() and comexit().
54  * The function set up last with on_comerr() is called first on exit;
55  * in other words: call order is the reverse order of registration.
56  */
57 EXPORT int
59  void (*func) __PR((int, void *));
60  void *arg;
61 {
62  ex_t *fp;
63 
64  fp = malloc(sizeof (*fp));
65  if (fp == NULL)
66  return (-1);
67 
68  fp->func = func;
69  fp->arg = arg;
70  fp->next = exfuncs;
71  exfuncs = fp;
72  return (0);
73 }
74 
75 /*
76  * Fetch current errno, print a related message and exit(errno).
77  */
78 /* VARARGS1 */
79 #ifdef PROTOTYPES
80 EXPORT void
81 comerr(const char *msg, ...)
82 #else
83 EXPORT void
84 comerr(msg, va_alist)
85  char *msg;
86  va_dcl
87 #endif
88 {
89  va_list args;
90 
91 #ifdef PROTOTYPES
92  va_start(args, msg);
93 #else
94  va_start(args);
95 #endif
96  (void) _comerr(stderr, COMERR_EXIT, 0, geterrno(), msg, args);
97  /* NOTREACHED */
98  va_end(args);
99 }
100 
101 /*
102  * Fetch current errno, print a related message and exit(exc).
103  */
104 /* VARARGS2 */
105 #ifdef PROTOTYPES
106 EXPORT void
107 xcomerr(int exc, const char *msg, ...)
108 #else
109 EXPORT void
110 xcomerr(exc, msg, va_alist)
111  int exc;
112  char *msg;
113  va_dcl
114 #endif
115 {
116  va_list args;
117 
118 #ifdef PROTOTYPES
119  va_start(args, msg);
120 #else
121  va_start(args);
122 #endif
123  (void) _comerr(stderr, COMERR_EXCODE, exc, geterrno(), msg, args);
124  /* NOTREACHED */
125  va_end(args);
126 }
127 
128 /*
129  * Print a message related to err and exit(err).
130  */
131 /* VARARGS2 */
132 #ifdef PROTOTYPES
133 EXPORT void
134 comerrno(int err, const char *msg, ...)
135 #else
136 EXPORT void
137 comerrno(err, msg, va_alist)
138  int err;
139  char *msg;
140  va_dcl
141 #endif
142 {
143  va_list args;
144 
145 #ifdef PROTOTYPES
146  va_start(args, msg);
147 #else
148  va_start(args);
149 #endif
150  (void) _comerr(stderr, COMERR_EXIT, 0, err, msg, args);
151  /* NOTREACHED */
152  va_end(args);
153 }
154 
155 /*
156  * Print a message related to err and exit(exc).
157  */
158 /* VARARGS3 */
159 #ifdef PROTOTYPES
160 EXPORT void
161 xcomerrno(int exc, int err, const char *msg, ...)
162 #else
163 EXPORT void
164 xcomerrno(exc, err, msg, va_alist)
165  int exc;
166  int err;
167  char *msg;
168  va_dcl
169 #endif
170 {
171  va_list args;
172 
173 #ifdef PROTOTYPES
174  va_start(args, msg);
175 #else
176  va_start(args);
177 #endif
178  (void) _comerr(stderr, COMERR_EXCODE, exc, err, msg, args);
179  /* NOTREACHED */
180  va_end(args);
181 }
182 
183 /*
184  * Fetch current errno, print a related message and return(errno).
185  */
186 /* VARARGS1 */
187 #ifdef PROTOTYPES
188 EXPORT int
189 errmsg(const char *msg, ...)
190 #else
191 EXPORT int
192 errmsg(msg, va_alist)
193  char *msg;
194  va_dcl
195 #endif
196 {
197  va_list args;
198  int ret;
199 
200 #ifdef PROTOTYPES
201  va_start(args, msg);
202 #else
203  va_start(args);
204 #endif
205  ret = _comerr(stderr, COMERR_RETURN, 0, geterrno(), msg, args);
206  va_end(args);
207  return (ret);
208 }
209 
210 /*
211  * Print a message related to err and return(err).
212  */
213 /* VARARGS2 */
214 #ifdef PROTOTYPES
215 EXPORT int
216 errmsgno(int err, const char *msg, ...)
217 #else
218 EXPORT int
219 errmsgno(err, msg, va_alist)
220  int err;
221  char *msg;
222  va_dcl
223 #endif
224 {
225  va_list args;
226  int ret;
227 
228 #ifdef PROTOTYPES
229  va_start(args, msg);
230 #else
231  va_start(args);
232 #endif
233  ret = _comerr(stderr, COMERR_RETURN, 0, err, msg, args);
234  va_end(args);
235  return (ret);
236 }
237 
238 #if defined(__BEOS__) || defined(__HAIKU__)
239  /*
240  * On BeOS errno is a big negative number (0x80000000 + small number).
241  * We assume that small negative numbers are safe to be used as special
242  * values that prevent printing the errno text.
243  *
244  * We tried to use #if EIO < 0 but this does not work because EIO is
245  * defined to a enum. ENODEV may work as ENODEV is defined to a number
246  * directly.
247  */
248 #define silent_error(e) ((e) < 0 && (e) >= -1024)
249 #else
250  /*
251  * On UNIX errno is a small non-negative number, so we assume that
252  * negative values cannot be a valid errno and don't print the error
253  * string in this case. However the value may still be used as exit()
254  * code if 'exflg' is set.
255  */
256 #define silent_error(e) ((e) < 0)
257 #endif
258 EXPORT int
259 _comerr(f, exflg, exc, err, msg, args)
260  FILE *f; /* FILE * to print to */
261  int exflg; /* COMERR_RETURN, COMERR_EXIT, COMERR_EXCODE */
262  int exc; /* Use for exit() if exflg & COMERR_EXCODE */
263  int err; /* Errno for text, exit(err) if !COMERR_EXIT*/
264  const char *msg; /* printf() format */
265  va_list args; /* printf() args for format */
266 {
267  char errbuf[20];
268  char *errnam;
269  char *prognam = get_progname();
270 
271  if (silent_error(err)) {
272  js_fprintf(f, "%s: %r", prognam, msg, args);
273  } else {
274  errnam = errmsgstr(err);
275  if (errnam == NULL) {
276  (void) js_snprintf(errbuf, sizeof (errbuf),
277  "Error %d", err);
278  errnam = errbuf;
279  }
280  js_fprintf(f, "%s: %s. %r", prognam, errnam, msg, args);
281  }
282  if (exflg) {
283  if (exflg & COMERR_EXCODE)
284  err = exc;
285  else
286  err = _ex_clash(err);
287  comexit(err);
288  /* NOTREACHED */
289  }
290  return (err);
291 }
292 
293 LOCAL int
295  int exc;
296 {
297  int exmod = exc % 256;
298 
299  /*
300  * On a recent POSIX System that supports waitid(), siginfo.si_status
301  * holds the exit(2) value as an int. So if waitid() is used to wait
302  * for the process, we do not have problems from folded exit codes.
303  * All other wait*() functions fold the exit code by masking it
304  * with 0377.
305  *
306  * Exit codes used with comerr*()/comexit() are frequently errno values
307  * that have been in the range 0..31 with UNIX.V5 in the mid 1970s and
308  * that now are in the range 0..151 on Solaris. These values do not
309  * cause problems from folding to 8 bits, but "sysexits.h" contains
310  * definitions in the range 64..79 that cause (even unfolded) clashes
311  * with errno values.
312  *
313  * To avoid clashes with errno values, "schily/standard.h" defines
314  * EX_BAD (-1) as default error exit code and
315  * EX_CLASH (-64) as marker for clashes.
316  * Exit codes in the range -2..-63 (254..193 seen as unsigned two's
317  * complement) are available as software specific exit codes.
318  * We map all other negative exit codes to EX_CLASH if they would fold
319  * to -2..-63.
320  */
321  if (exc != exmod && exmod <= 0 && exmod >= EX_CLASH)
322  exc = EX_CLASH;
323  return (exc);
324 }
325 
326 /*
327  * Do a program exit() with previously calling functions registered via
328  * on_comerr().
329  */
330 EXPORT void
332  int err;
333 {
334  while (exfuncs) {
335  ex_t *fp;
336 
337  (*exfuncs->func)(err, exfuncs->arg);
338  fp = exfuncs;
339  exfuncs = exfuncs->next;
340  free(fp);
341  }
342  exit(err);
343  /* NOTREACHED */
344 }
345 
346 /*
347  * Wrapper around the strange POSIX strerror().
348  * If there is a problem with retrieving the correct error text,
349  * return NULL.
350  */
351 EXPORT char *
353  int err;
354 {
355 #ifdef HAVE_STRERROR
356  /*
357  * POSIX compliance may look strange...
358  */
359  int errsav = geterrno();
360  char *ret;
361 
362  seterrno(0);
363  ret = strerror(err);
364  err = geterrno();
365  seterrno(errsav);
366 
367  if (ret == NULL || err)
368  return (NULL);
369  return (ret);
370 #else
371  if (err < 0 || err >= sys_nerr) {
372  return (NULL);
373  } else {
374  return (sys_errlist[err]);
375  }
376 #endif
377 }
GLenum func
Definition: glext.h:6028
Definition: comerr.c:44
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
EXPORT void comerr(char *msg, va_alist)
Definition: comerr.c:84
EXPORT void xcomerr(int exc, char *msg, va_alist)
Definition: comerr.c:110
EXPORT char * errmsgstr(int err)
Definition: comerr.c:352
#define free
Definition: debug_ros.c:5
EXPORT int on_comerr __PR((void(*fun)(int, void *), void *arg))
int sys_nerr
EXPORT int _comerr(FILE *f, int exflg, int exc, int err, const char *msg, va_list args)
Definition: comerr.c:259
void * arg
Definition: msvc.h:12
EXPORT int on_comerr(void *func, void *arg)
Definition: comerr.c:58
Definition: match.c:390
const char * strerror(int err)
Definition: compat_str.c:23
#define va_end(ap)
Definition: acmsvcex.h:90
EXPORT int js_snprintf(char *buf, unsigned maxcnt, char *form, va_alist)
Definition: jssnprintf.c:62
void * arg
Definition: comerr.c:47
#define silent_error(e)
Definition: comerr.c:256
smooth NULL
Definition: ftsmooth.c:416
EXPORT int errmsg(char *msg, va_alist)
Definition: comerr.c:192
char * va_list
Definition: acmsvcex.h:78
#define LOCAL(type)
Definition: jmorecfg.h:289
GLfloat f
Definition: glext.h:7540
EXPORT int seterrno(int err)
Definition: seterrno.c:34
EXPORT int geterrno()
Definition: geterrno.c:34
#define EX_CLASH
Definition: standard.h:63
int ret
void func __PR((int, void *))
#define err(...)
EXPORT void comexit(int err)
Definition: comerr.c:331
EXPORT char * get_progname()
Definition: saveargs.c:151
struct ex * next
Definition: comerr.c:45
#define f
Definition: ke_i.h:83
EXPORT int js_fprintf(FILE *file, char *form, va_alist)
Definition: jsprintf.c:71
char * sys_errlist[]
#define va_start(ap, A)
Definition: acmsvcex.h:91
LOCAL ex_t * exfuncs
Definition: comerr.c:50
EXPORT void comerrno(int err, char *msg, va_alist)
Definition: comerr.c:137
EXPORT void xcomerrno(int exc, int err, char *msg, va_alist)
Definition: comerr.c:164
#define msg(x)
Definition: auth_time.c:54
FILE * stderr
LOCAL int _ex_clash(int exc)
Definition: comerr.c:294
#define malloc
Definition: debug_ros.c:4
void exit(int exitcode)
Definition: _exit.c:33
#define args
Definition: format.c:66
struct ex ex_t
EXPORT int errmsgno(int err, char *msg, va_alist)
Definition: comerr.c:219