]> git.saurik.com Git - apple/libc.git/blame - gen/FreeBSD/err.c
Libc-1244.1.7.tar.gz
[apple/libc.git] / gen / FreeBSD / err.c
CommitLineData
9385eb3d 1/*-
e9ce8d39
A
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
e9ce8d39
A
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
9385eb3d
A
30#if defined(LIBC_SCCS) && !defined(lint)
31static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
32#endif /* LIBC_SCCS and not lint */
33#include <sys/cdefs.h>
1f2f436a 34__FBSDID("$FreeBSD: src/lib/libc/gen/err.c,v 1.15 2008/04/03 20:36:44 imp Exp $");
e9ce8d39 35
9385eb3d 36#include "namespace.h"
e9ce8d39
A
37#include <err.h>
38#include <errno.h>
9385eb3d 39#include <stdarg.h>
e9ce8d39
A
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
ad3c9f2a 43#include <vis.h>
9385eb3d 44#include "un-namespace.h"
e9ce8d39 45
ad3c9f2a
A
46#ifdef __BLOCKS__
47#include <Block.h>
48#endif /* __BLOCKS__ */
9385eb3d 49#include "libc_private.h"
e9ce8d39 50
ad3c9f2a
A
51#define ERR_EXIT_UNDEF 0
52#ifdef __BLOCKS__
53#define ERR_EXIT_BLOCK 1
54#endif /* __BLOCKS__ */
55#define ERR_EXIT_FUNC 2
56struct _e_err_exit {
57 unsigned int type;
58#ifdef __BLOCKS__
59 union {
60#endif /* __BLOCKS__ */
61 void (*func)(int);
62#ifdef __BLOCKS__
63 void (^block)(int);
64 };
65#endif /* __BLOCKS__ */
66};
67
68#ifdef BUILDING_VARIANT
69
70__private_extern__ FILE *_e_err_file; /* file to use for error output */
71__private_extern__ struct _e_err_exit _e_err_exit;
72__private_extern__ void _e_visprintf(FILE * __restrict, const char * __restrict, va_list);
73
74#else /* !BUILDING_VARIANT */
75
76__private_extern__ FILE *_e_err_file = NULL; /* file to use for error output */
77__private_extern__ struct _e_err_exit _e_err_exit = {ERR_EXIT_UNDEF};
78
79/*
80 * zero means pass as is
81 * 255 means use \nnn (octal)
82 * otherwise use \x (x is value)
83 * (NUL isn't used)
84 */
6465356a 85static const unsigned char escape[256] = {
ad3c9f2a
A
86 /* NUL */
87 0, /* Unused: strings can't contain nulls */
88 /* SOH STX ETX EOT ENQ ACK BEL */
89 255, 255, 255, 255, 255, 255, 'a',
90 /* BS HT NL VT NP CR SO SI */
91 'b', 0, 0, 'v', 'f', 'r', 255, 255,
92 /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
93 255, 255, 255, 255, 255, 255, 255, 255,
94 /* CAN EM SUB ESC FS GS RS US */
95 255, 255, 255, 255, 255, 255, 255, 255,
96 /* the rest are zero */
97};
98
99/*
100 * Make characters visible. If we can't allocate enough
101 * memory, we fall back on vfprintf().
102 */
103__private_extern__ void
104_e_visprintf(FILE * __restrict stream, const char * __restrict format, va_list ap)
105{
106 int failed = 0;
107 char *str, *visstr;
108 va_list backup;
109
110 va_copy(backup, ap);
111 vasprintf(&str, format, ap);
112 if (str != NULL) {
113 if ((visstr = malloc(4 * strlen(str) + 1)) != NULL) {
114 unsigned char *fp = (unsigned char *)str;
115 unsigned char *tp = (unsigned char *)visstr;
116 while(*fp) {
117 switch(escape[*fp]) {
118 case 0:
119 *tp++ = *fp;
120 break;
121 case 255:
122 sprintf((char *)tp, "\\%03o", *fp);
123 tp += 4;
124 break;
125 default:
126 *tp++ = '\\';
127 *tp++ = escape[*fp];
128 break;
129 }
130 fp++;
131 }
132 *tp = 0;
133 fputs(visstr, stream);
134 free(visstr);
135 } else
136 failed = 1;
137 free(str);
138 } else
139 failed = 1;
140 if (failed)
141 vfprintf(stream, format, backup);
142 va_end(backup);
143}
9385eb3d
A
144
145/*
146 * This is declared to take a `void *' so that the caller is not required
147 * to include <stdio.h> first. However, it is really a `FILE *', and the
148 * manual page documents it as such.
149 */
150void
151err_set_file(void *fp)
152{
153 if (fp)
ad3c9f2a 154 _e_err_file = fp;
9385eb3d 155 else
ad3c9f2a 156 _e_err_file = stderr;
9385eb3d
A
157}
158
159void
160err_set_exit(void (*ef)(int))
161{
b061a43b
A
162#ifdef __BLOCKS__
163 if (_e_err_exit.type == ERR_EXIT_BLOCK) {
164 Block_release(_e_err_exit.block);
165 _e_err_exit.block = NULL;
166 }
167#endif /* __BLOCKS__ */
974e3884 168 _e_err_exit.type = ef ? ERR_EXIT_FUNC : ERR_EXIT_UNDEF;
ad3c9f2a
A
169 _e_err_exit.func = ef;
170}
171
172#ifdef __BLOCKS__
173void
174err_set_exit_b(void (^ef)(int))
175{
b061a43b
A
176 if (_e_err_exit.type == ERR_EXIT_BLOCK) {
177 Block_release(_e_err_exit.block);
178 }
974e3884 179 _e_err_exit.type = ef ? ERR_EXIT_BLOCK : ERR_EXIT_UNDEF;
ad3c9f2a 180 _e_err_exit.block = Block_copy(ef);
9385eb3d 181}
ad3c9f2a
A
182#endif /* __BLOCKS__ */
183#endif /* !BUILDING_VARIANT */
9385eb3d
A
184
185__weak_reference(_err, err);
186
187void
188_err(int eval, const char *fmt, ...)
e9ce8d39
A
189{
190 va_list ap;
e9ce8d39 191 va_start(ap, fmt);
9385eb3d 192 verrc(eval, errno, fmt, ap);
e9ce8d39
A
193 va_end(ap);
194}
195
9385eb3d 196void
e9ce8d39
A
197verr(eval, fmt, ap)
198 int eval;
199 const char *fmt;
200 va_list ap;
201{
9385eb3d
A
202 verrc(eval, errno, fmt, ap);
203}
e9ce8d39 204
9385eb3d
A
205void
206errc(int eval, int code, const char *fmt, ...)
207{
208 va_list ap;
209 va_start(ap, fmt);
210 verrc(eval, code, fmt, ap);
211 va_end(ap);
212}
213
214void
1f2f436a 215verrc(int eval, int code, const char *fmt, va_list ap)
9385eb3d 216{
ad3c9f2a 217 if (_e_err_file == 0)
9385eb3d 218 err_set_file((FILE *)0);
ad3c9f2a 219 fprintf(_e_err_file, "%s: ", _getprogname());
e9ce8d39 220 if (fmt != NULL) {
ad3c9f2a
A
221 _e_visprintf(_e_err_file, fmt, ap);
222 fprintf(_e_err_file, ": ");
e9ce8d39 223 }
ad3c9f2a 224 fprintf(_e_err_file, "%s\n", strerror(code));
6465356a 225 if (_e_err_exit.type) {
ad3c9f2a 226#ifdef __BLOCKS__
6465356a 227 if (_e_err_exit.type == ERR_EXIT_BLOCK) {
ad3c9f2a 228 _e_err_exit.block(eval);
6465356a 229 } else {
ad3c9f2a 230 _e_err_exit.func(eval);
6465356a
A
231 }
232#else
233 _e_err_exit.func(eval);
234#endif /* __BLOCKS__ */
235 }
e9ce8d39
A
236 exit(eval);
237}
238
9385eb3d 239void
e9ce8d39 240errx(int eval, const char *fmt, ...)
e9ce8d39
A
241{
242 va_list ap;
e9ce8d39 243 va_start(ap, fmt);
e9ce8d39
A
244 verrx(eval, fmt, ap);
245 va_end(ap);
246}
247
9385eb3d 248void
1f2f436a 249verrx(int eval, const char *fmt, va_list ap)
e9ce8d39 250{
ad3c9f2a 251 if (_e_err_file == 0)
9385eb3d 252 err_set_file((FILE *)0);
ad3c9f2a 253 fprintf(_e_err_file, "%s: ", _getprogname());
e9ce8d39 254 if (fmt != NULL)
ad3c9f2a
A
255 _e_visprintf(_e_err_file, fmt, ap);
256 fprintf(_e_err_file, "\n");
6465356a 257 if (_e_err_exit.type) {
ad3c9f2a 258#ifdef __BLOCKS__
6465356a 259 if (_e_err_exit.type == ERR_EXIT_BLOCK) {
ad3c9f2a 260 _e_err_exit.block(eval);
6465356a 261 } else {
ad3c9f2a 262 _e_err_exit.func(eval);
6465356a
A
263 }
264#else
265 _e_err_exit.func(eval);
266#endif /* __BLOCKS__ */
267 }
e9ce8d39
A
268 exit(eval);
269}
270
9385eb3d
A
271__weak_reference(_warn, warn);
272
e9ce8d39 273void
9385eb3d 274_warn(const char *fmt, ...)
e9ce8d39
A
275{
276 va_list ap;
e9ce8d39 277 va_start(ap, fmt);
9385eb3d 278 vwarnc(errno, fmt, ap);
e9ce8d39
A
279 va_end(ap);
280}
281
282void
1f2f436a 283vwarn(const char *fmt, va_list ap)
e9ce8d39 284{
9385eb3d
A
285 vwarnc(errno, fmt, ap);
286}
287
288void
289warnc(int code, const char *fmt, ...)
290{
291 va_list ap;
292 va_start(ap, fmt);
293 vwarnc(code, fmt, ap);
294 va_end(ap);
295}
296
297void
1f2f436a 298vwarnc(int code, const char *fmt, va_list ap)
9385eb3d 299{
ad3c9f2a 300 if (_e_err_file == 0)
9385eb3d 301 err_set_file((FILE *)0);
ad3c9f2a 302 fprintf(_e_err_file, "%s: ", _getprogname());
e9ce8d39 303 if (fmt != NULL) {
ad3c9f2a
A
304 _e_visprintf(_e_err_file, fmt, ap);
305 fprintf(_e_err_file, ": ");
e9ce8d39 306 }
ad3c9f2a 307 fprintf(_e_err_file, "%s\n", strerror(code));
e9ce8d39
A
308}
309
310void
e9ce8d39 311warnx(const char *fmt, ...)
e9ce8d39
A
312{
313 va_list ap;
e9ce8d39 314 va_start(ap, fmt);
e9ce8d39
A
315 vwarnx(fmt, ap);
316 va_end(ap);
317}
318
319void
1f2f436a 320vwarnx(const char *fmt, va_list ap)
e9ce8d39 321{
ad3c9f2a 322 if (_e_err_file == 0)
9385eb3d 323 err_set_file((FILE *)0);
ad3c9f2a 324 fprintf(_e_err_file, "%s: ", _getprogname());
e9ce8d39 325 if (fmt != NULL)
ad3c9f2a
A
326 _e_visprintf(_e_err_file, fmt, ap);
327 fprintf(_e_err_file, "\n");
e9ce8d39 328}