ReactOS 0.4.16-dev-340-g0540c21
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
31EXPORT int on_comerr __PR((void (*fun)(int, void *), void *arg));
32EXPORT void comerr __PR((const char *, ...));
33EXPORT void xcomerr __PR((int, const char *, ...));
34EXPORT void comerrno __PR((int, const char *, ...));
35EXPORT void xcomerrno __PR((int, int, const char *, ...));
36EXPORT int errmsg __PR((const char *, ...));
37EXPORT int errmsgno __PR((int, const char *, ...));
38EXPORT int _comerr __PR((FILE *, int, int, int,
39 const char *, va_list));
40LOCAL int _ex_clash __PR((int));
41EXPORT void comexit __PR((int));
42EXPORT char *errmsgstr __PR((int));
43
44typedef struct ex {
45 struct ex *next;
46 void (*func) __PR((int, void *));
47 void *arg;
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 */
57EXPORT 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
80EXPORT void
81comerr(const char *msg, ...)
82#else
83EXPORT void
84comerr(msg, va_alist)
85 char *msg;
86 va_dcl
87#endif
88{
90
91#ifdef PROTOTYPES
93#else
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
106EXPORT void
107xcomerr(int exc, const char *msg, ...)
108#else
109EXPORT void
110xcomerr(exc, msg, va_alist)
111 int exc;
112 char *msg;
113 va_dcl
114#endif
115{
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
133EXPORT void
134comerrno(int err, const char *msg, ...)
135#else
136EXPORT void
137comerrno(err, msg, va_alist)
138 int err;
139 char *msg;
140 va_dcl
141#endif
142{
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
160EXPORT void
161xcomerrno(int exc, int err, const char *msg, ...)
162#else
163EXPORT void
164xcomerrno(exc, err, msg, va_alist)
165 int exc;
166 int err;
167 char *msg;
168 va_dcl
169#endif
170{
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
188EXPORT int
189errmsg(const char *msg, ...)
190#else
191EXPORT int
192errmsg(msg, va_alist)
193 char *msg;
194 va_dcl
195#endif
196{
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
215EXPORT int
216errmsgno(int err, const char *msg, ...)
217#else
218EXPORT int
219errmsgno(err, msg, va_alist)
220 int err;
221 char *msg;
222 va_dcl
223#endif
224{
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
258EXPORT 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
293LOCAL 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 */
330EXPORT void
332 int err;
333{
334 while (exfuncs) {
335 ex_t *fp;
336
337 (*exfuncs->func)(err, exfuncs->arg);
338 fp = exfuncs;
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 */
351EXPORT 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}
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define msg(x)
Definition: auth_time.c:54
EXPORT int _comerr(FILE *f, int exflg, int exc, int err, const char *msg, va_list args)
Definition: comerr.c:259
EXPORT char * errmsgstr(int err)
Definition: comerr.c:352
LOCAL ex_t * exfuncs
Definition: comerr.c:50
EXPORT void xcomerr(int exc, char *msg, va_alist)
Definition: comerr.c:110
EXPORT void comerrno(int err, char *msg, va_alist)
Definition: comerr.c:137
struct ex ex_t
EXPORT void xcomerrno(int exc, int err, char *msg, va_alist)
Definition: comerr.c:164
EXPORT int errmsgno(int err, char *msg, va_alist)
Definition: comerr.c:219
EXPORT int on_comerr(void *func, void *arg)
Definition: comerr.c:58
LOCAL int _ex_clash(int exc)
Definition: comerr.c:294
#define silent_error(e)
Definition: comerr.c:256
EXPORT void comexit(int err)
Definition: comerr.c:331
EXPORT void comerr(char *msg, va_alist)
Definition: comerr.c:84
EXPORT int errmsg(char *msg, va_alist)
Definition: comerr.c:192
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
EXPORT int geterrno()
Definition: geterrno.c:34
GLenum func
Definition: glext.h:6028
GLfloat f
Definition: glext.h:7540
#define stderr
Definition: stdio.h:100
#define sys_errlist
Definition: stdlib.h:1346
#define sys_nerr
Definition: stdlib.h:1347
#define LOCAL(type)
Definition: jmorecfg.h:289
EXPORT int js_fprintf(FILE *file, char *form, va_alist)
Definition: jsprintf.c:71
EXPORT int js_snprintf(char *buf, unsigned maxcnt, char *form, va_alist)
Definition: jssnprintf.c:62
#define f
Definition: ke_i.h:83
const char * strerror(int err)
Definition: compat_str.c:23
#define __PR(a)
Definition: prototyp.h:106
#define err(...)
EXPORT char * get_progname()
Definition: saveargs.c:151
#define exit(n)
Definition: config.h:202
#define args
Definition: format.c:66
EXPORT int seterrno(int err)
Definition: seterrno.c:34
#define EX_CLASH
Definition: standard.h:63
Definition: match.c:390
Definition: comerr.c:44
void func __PR((int, void *))
struct ex * next
Definition: comerr.c:45
void * arg
Definition: comerr.c:47
int ret
void * arg
Definition: msvc.h:10