]> git.saurik.com Git - apple/libc.git/blob - gen/FreeBSD/err.c
e6e03f628ffd0602629a270b3a8b0839afc36010
[apple/libc.git] / gen / FreeBSD / err.c
1 /*-
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.
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
30 #if defined(LIBC_SCCS) && !defined(lint)
31 static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
32 #endif /* LIBC_SCCS and not lint */
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD: src/lib/libc/gen/err.c,v 1.15 2008/04/03 20:36:44 imp Exp $");
35
36 #include "namespace.h"
37 #include <err.h>
38 #include <errno.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <vis.h>
44 #include "un-namespace.h"
45
46 #ifdef __BLOCKS__
47 #include <Block.h>
48 #endif /* __BLOCKS__ */
49 #include "libc_private.h"
50
51 #define ERR_EXIT_UNDEF 0
52 #ifdef __BLOCKS__
53 #define ERR_EXIT_BLOCK 1
54 #endif /* __BLOCKS__ */
55 #define ERR_EXIT_FUNC 2
56 struct _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 */
85 static unsigned char escape[256] = {
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 }
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 */
150 void
151 err_set_file(void *fp)
152 {
153 if (fp)
154 _e_err_file = fp;
155 else
156 _e_err_file = stderr;
157 }
158
159 void
160 err_set_exit(void (*ef)(int))
161 {
162 _e_err_exit.type = ERR_EXIT_FUNC;
163 _e_err_exit.func = ef;
164 }
165
166 #ifdef __BLOCKS__
167 void
168 err_set_exit_b(void (^ef)(int))
169 {
170 _e_err_exit.type = ERR_EXIT_BLOCK;
171 _e_err_exit.block = Block_copy(ef);
172 }
173 #endif /* __BLOCKS__ */
174 #endif /* !BUILDING_VARIANT */
175
176 __weak_reference(_err, err);
177
178 void
179 _err(int eval, const char *fmt, ...)
180 {
181 va_list ap;
182 va_start(ap, fmt);
183 verrc(eval, errno, fmt, ap);
184 va_end(ap);
185 }
186
187 void
188 verr(eval, fmt, ap)
189 int eval;
190 const char *fmt;
191 va_list ap;
192 {
193 verrc(eval, errno, fmt, ap);
194 }
195
196 void
197 errc(int eval, int code, const char *fmt, ...)
198 {
199 va_list ap;
200 va_start(ap, fmt);
201 verrc(eval, code, fmt, ap);
202 va_end(ap);
203 }
204
205 void
206 verrc(int eval, int code, const char *fmt, va_list ap)
207 {
208 if (_e_err_file == 0)
209 err_set_file((FILE *)0);
210 fprintf(_e_err_file, "%s: ", _getprogname());
211 if (fmt != NULL) {
212 _e_visprintf(_e_err_file, fmt, ap);
213 fprintf(_e_err_file, ": ");
214 }
215 fprintf(_e_err_file, "%s\n", strerror(code));
216 if (_e_err_exit.type)
217 #ifdef __BLOCKS__
218 if (_e_err_exit.type == ERR_EXIT_BLOCK)
219 _e_err_exit.block(eval);
220 else
221 #endif /* __BLOCKS__ */
222 _e_err_exit.func(eval);
223 exit(eval);
224 }
225
226 void
227 errx(int eval, const char *fmt, ...)
228 {
229 va_list ap;
230 va_start(ap, fmt);
231 verrx(eval, fmt, ap);
232 va_end(ap);
233 }
234
235 void
236 verrx(int eval, const char *fmt, va_list ap)
237 {
238 if (_e_err_file == 0)
239 err_set_file((FILE *)0);
240 fprintf(_e_err_file, "%s: ", _getprogname());
241 if (fmt != NULL)
242 _e_visprintf(_e_err_file, fmt, ap);
243 fprintf(_e_err_file, "\n");
244 if (_e_err_exit.type)
245 #ifdef __BLOCKS__
246 if (_e_err_exit.type == ERR_EXIT_BLOCK)
247 _e_err_exit.block(eval);
248 else
249 #endif /* __BLOCKS__ */
250 _e_err_exit.func(eval);
251 exit(eval);
252 }
253
254 __weak_reference(_warn, warn);
255
256 void
257 _warn(const char *fmt, ...)
258 {
259 va_list ap;
260 va_start(ap, fmt);
261 vwarnc(errno, fmt, ap);
262 va_end(ap);
263 }
264
265 void
266 vwarn(const char *fmt, va_list ap)
267 {
268 vwarnc(errno, fmt, ap);
269 }
270
271 void
272 warnc(int code, const char *fmt, ...)
273 {
274 va_list ap;
275 va_start(ap, fmt);
276 vwarnc(code, fmt, ap);
277 va_end(ap);
278 }
279
280 void
281 vwarnc(int code, const char *fmt, va_list ap)
282 {
283 if (_e_err_file == 0)
284 err_set_file((FILE *)0);
285 fprintf(_e_err_file, "%s: ", _getprogname());
286 if (fmt != NULL) {
287 _e_visprintf(_e_err_file, fmt, ap);
288 fprintf(_e_err_file, ": ");
289 }
290 fprintf(_e_err_file, "%s\n", strerror(code));
291 }
292
293 void
294 warnx(const char *fmt, ...)
295 {
296 va_list ap;
297 va_start(ap, fmt);
298 vwarnx(fmt, ap);
299 va_end(ap);
300 }
301
302 void
303 vwarnx(const char *fmt, va_list ap)
304 {
305 if (_e_err_file == 0)
306 err_set_file((FILE *)0);
307 fprintf(_e_err_file, "%s: ", _getprogname());
308 if (fmt != NULL)
309 _e_visprintf(_e_err_file, fmt, ap);
310 fprintf(_e_err_file, "\n");
311 }