]>
Commit | Line | Data |
---|---|---|
34e8f829 A |
1 | --- err.c.orig 2009-05-12 11:21:55.000000000 -0700 |
2 | +++ err.c 2009-05-23 13:27:52.000000000 -0700 | |
3 | @@ -44,12 +44,105 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/err | |
224c7076 A |
4 | #include <stdio.h> |
5 | #include <stdlib.h> | |
6 | #include <string.h> | |
7 | +#include <vis.h> | |
8 | #include "un-namespace.h" | |
3d9156a7 | 9 | |
34e8f829 A |
10 | +#ifdef __BLOCKS__ |
11 | +#include <Block.h> | |
12 | +#endif /* __BLOCKS__ */ | |
3d9156a7 A |
13 | #include "libc_private.h" |
14 | ||
15 | -static FILE *err_file; /* file to use for error output */ | |
16 | -static void (*err_exit)(int); | |
34e8f829 A |
17 | +#define ERR_EXIT_UNDEF 0 |
18 | +#ifdef __BLOCKS__ | |
19 | +#define ERR_EXIT_BLOCK 1 | |
20 | +#endif /* __BLOCKS__ */ | |
21 | +#define ERR_EXIT_FUNC 2 | |
22 | +struct _e_err_exit { | |
23 | + unsigned int type; | |
24 | +#ifdef __BLOCKS__ | |
25 | + union { | |
26 | +#endif /* __BLOCKS__ */ | |
27 | + void (*func)(int); | |
28 | +#ifdef __BLOCKS__ | |
29 | + void (^block)(int); | |
30 | + }; | |
31 | +#endif /* __BLOCKS__ */ | |
32 | +}; | |
33 | + | |
3d9156a7 A |
34 | +#ifdef BUILDING_VARIANT |
35 | + | |
36 | +__private_extern__ FILE *_e_err_file; /* file to use for error output */ | |
34e8f829 | 37 | +__private_extern__ struct _e_err_exit _e_err_exit; |
224c7076 | 38 | +__private_extern__ void _e_visprintf(FILE * __restrict, const char * __restrict, va_list); |
3d9156a7 A |
39 | + |
40 | +#else /* !BUILDING_VARIANT */ | |
41 | + | |
42 | +__private_extern__ FILE *_e_err_file = NULL; /* file to use for error output */ | |
34e8f829 | 43 | +__private_extern__ struct _e_err_exit _e_err_exit = {ERR_EXIT_UNDEF}; |
224c7076 A |
44 | + |
45 | +/* | |
46 | + * zero means pass as is | |
47 | + * 255 means use \nnn (octal) | |
48 | + * otherwise use \x (x is value) | |
49 | + * (NUL isn't used) | |
50 | + */ | |
51 | +static unsigned char escape[256] = { | |
52 | + /* NUL SOH STX ETX EOT ENQ ACK BEL */ | |
53 | + 0 , 255, 255, 255, 255, 255, 255, 'a', | |
54 | + /* BS HT NL VT NP CR SO SI */ | |
55 | + 'b', 't', 'n', 'v', 'f', 'r', 255, 255, | |
56 | + /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ | |
57 | + 255, 255, 255, 255, 255, 255, 255, 255, | |
58 | + /* CAN EM SUB ESC FS GS RS US */ | |
59 | + 255, 255, 255, 255, 255, 255, 255, 255, | |
60 | + /* the rest are zero */ | |
61 | +}; | |
62 | + | |
63 | +/* | |
64 | + * Make characters visible. If we can't allocate enough | |
65 | + * memory, we fall back on vfprintf(). | |
66 | + */ | |
67 | +__private_extern__ void | |
68 | +_e_visprintf(FILE * __restrict stream, const char * __restrict format, va_list ap) | |
69 | +{ | |
70 | + int failed = 0; | |
71 | + char *str, *visstr; | |
72 | + va_list backup; | |
73 | + | |
74 | + va_copy(backup, ap); | |
75 | + vasprintf(&str, format, ap); | |
76 | + if (str != NULL) { | |
77 | + if ((visstr = malloc(4 * strlen(str) + 1)) != NULL) { | |
78 | + unsigned char *fp = (unsigned char *)str; | |
79 | + unsigned char *tp = (unsigned char *)visstr; | |
80 | + while(*fp) { | |
81 | + switch(escape[*fp]) { | |
82 | + case 0: | |
83 | + *tp++ = *fp; | |
84 | + break; | |
85 | + case 255: | |
86 | + sprintf(tp, "\\%03o", *fp); | |
87 | + tp += 4; | |
88 | + break; | |
89 | + default: | |
90 | + *tp++ = '\\'; | |
91 | + *tp++ = escape[*fp]; | |
92 | + break; | |
93 | + } | |
94 | + fp++; | |
95 | + } | |
96 | + *tp = 0; | |
97 | + fputs(visstr, stream); | |
98 | + free(visstr); | |
99 | + } else | |
100 | + failed = 1; | |
101 | + free(str); | |
102 | + } else | |
103 | + failed = 1; | |
104 | + if (failed) | |
105 | + vfprintf(stream, format, backup); | |
106 | + va_end(backup); | |
107 | +} | |
3d9156a7 A |
108 | |
109 | /* | |
110 | * This is declared to take a `void *' so that the caller is not required | |
34e8f829 | 111 | @@ -60,16 +153,27 @@ void |
3d9156a7 A |
112 | err_set_file(void *fp) |
113 | { | |
114 | if (fp) | |
115 | - err_file = fp; | |
116 | + _e_err_file = fp; | |
117 | else | |
118 | - err_file = stderr; | |
119 | + _e_err_file = stderr; | |
120 | } | |
121 | ||
122 | void | |
123 | err_set_exit(void (*ef)(int)) | |
124 | { | |
125 | - err_exit = ef; | |
34e8f829 A |
126 | + _e_err_exit.type = ERR_EXIT_FUNC; |
127 | + _e_err_exit.func = ef; | |
128 | +} | |
129 | + | |
130 | +#ifdef __BLOCKS__ | |
131 | +void | |
132 | +err_set_exit_b(void (^ef)(int)) | |
133 | +{ | |
134 | + _e_err_exit.type = ERR_EXIT_BLOCK; | |
135 | + _e_err_exit.block = Block_copy(ef); | |
3d9156a7 | 136 | } |
34e8f829 | 137 | +#endif /* __BLOCKS__ */ |
3d9156a7 A |
138 | +#endif /* !BUILDING_VARIANT */ |
139 | ||
140 | __weak_reference(_err, err); | |
141 | ||
34e8f829 | 142 | @@ -107,16 +211,21 @@ verrc(eval, code, fmt, ap) |
3d9156a7 A |
143 | const char *fmt; |
144 | va_list ap; | |
145 | { | |
146 | - if (err_file == 0) | |
147 | + if (_e_err_file == 0) | |
148 | err_set_file((FILE *)0); | |
149 | - fprintf(err_file, "%s: ", _getprogname()); | |
150 | + fprintf(_e_err_file, "%s: ", _getprogname()); | |
151 | if (fmt != NULL) { | |
152 | - vfprintf(err_file, fmt, ap); | |
153 | - fprintf(err_file, ": "); | |
224c7076 | 154 | + _e_visprintf(_e_err_file, fmt, ap); |
3d9156a7 A |
155 | + fprintf(_e_err_file, ": "); |
156 | } | |
157 | - fprintf(err_file, "%s\n", strerror(code)); | |
158 | - if (err_exit) | |
159 | - err_exit(eval); | |
160 | + fprintf(_e_err_file, "%s\n", strerror(code)); | |
34e8f829 A |
161 | + if (_e_err_exit.type) |
162 | +#ifdef __BLOCKS__ | |
163 | + if (_e_err_exit.type == ERR_EXIT_BLOCK) | |
164 | + _e_err_exit.block(eval); | |
165 | + else | |
166 | +#endif /* __BLOCKS__ */ | |
167 | + _e_err_exit.func(eval); | |
3d9156a7 A |
168 | exit(eval); |
169 | } | |
170 | ||
34e8f829 | 171 | @@ -135,14 +244,19 @@ verrx(eval, fmt, ap) |
3d9156a7 A |
172 | const char *fmt; |
173 | va_list ap; | |
174 | { | |
175 | - if (err_file == 0) | |
176 | + if (_e_err_file == 0) | |
177 | err_set_file((FILE *)0); | |
178 | - fprintf(err_file, "%s: ", _getprogname()); | |
179 | + fprintf(_e_err_file, "%s: ", _getprogname()); | |
180 | if (fmt != NULL) | |
181 | - vfprintf(err_file, fmt, ap); | |
182 | - fprintf(err_file, "\n"); | |
183 | - if (err_exit) | |
184 | - err_exit(eval); | |
224c7076 | 185 | + _e_visprintf(_e_err_file, fmt, ap); |
3d9156a7 | 186 | + fprintf(_e_err_file, "\n"); |
34e8f829 A |
187 | + if (_e_err_exit.type) |
188 | +#ifdef __BLOCKS__ | |
189 | + if (_e_err_exit.type == ERR_EXIT_BLOCK) | |
190 | + _e_err_exit.block(eval); | |
191 | + else | |
192 | +#endif /* __BLOCKS__ */ | |
193 | + _e_err_exit.func(eval); | |
3d9156a7 A |
194 | exit(eval); |
195 | } | |
196 | ||
34e8f829 | 197 | @@ -180,14 +294,14 @@ vwarnc(code, fmt, ap) |
3d9156a7 A |
198 | const char *fmt; |
199 | va_list ap; | |
200 | { | |
201 | - if (err_file == 0) | |
202 | + if (_e_err_file == 0) | |
203 | err_set_file((FILE *)0); | |
204 | - fprintf(err_file, "%s: ", _getprogname()); | |
205 | + fprintf(_e_err_file, "%s: ", _getprogname()); | |
206 | if (fmt != NULL) { | |
207 | - vfprintf(err_file, fmt, ap); | |
208 | - fprintf(err_file, ": "); | |
224c7076 | 209 | + _e_visprintf(_e_err_file, fmt, ap); |
3d9156a7 A |
210 | + fprintf(_e_err_file, ": "); |
211 | } | |
212 | - fprintf(err_file, "%s\n", strerror(code)); | |
213 | + fprintf(_e_err_file, "%s\n", strerror(code)); | |
214 | } | |
215 | ||
216 | void | |
34e8f829 | 217 | @@ -204,10 +318,10 @@ vwarnx(fmt, ap) |
3d9156a7 A |
218 | const char *fmt; |
219 | va_list ap; | |
220 | { | |
221 | - if (err_file == 0) | |
222 | + if (_e_err_file == 0) | |
223 | err_set_file((FILE *)0); | |
224 | - fprintf(err_file, "%s: ", _getprogname()); | |
225 | + fprintf(_e_err_file, "%s: ", _getprogname()); | |
226 | if (fmt != NULL) | |
227 | - vfprintf(err_file, fmt, ap); | |
228 | - fprintf(err_file, "\n"); | |
224c7076 | 229 | + _e_visprintf(_e_err_file, fmt, ap); |
3d9156a7 A |
230 | + fprintf(_e_err_file, "\n"); |
231 | } |