Contents of /trunk/mkinitrd-magellan/klibc/usr/dash/output.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 7527 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 7527 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | /*- |
2 | * Copyright (c) 1991, 1993 |
3 | * The Regents of the University of California. All rights reserved. |
4 | * Copyright (c) 1997-2005 |
5 | * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved. |
6 | * |
7 | * This code is derived from software contributed to Berkeley by |
8 | * Kenneth Almquist. |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. Neither the name of the University nor the names of its contributors |
19 | * may be used to endorse or promote products derived from this software |
20 | * without specific prior written permission. |
21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. |
33 | */ |
34 | |
35 | /* |
36 | * Shell output routines. We use our own output routines because: |
37 | * When a builtin command is interrupted we have to discard |
38 | * any pending output. |
39 | * When a builtin command appears in back quotes, we want to |
40 | * save the output of the command in a region obtained |
41 | * via malloc, rather than doing a fork and reading the |
42 | * output of the command via a pipe. |
43 | * Our output routines may be smaller than the stdio routines. |
44 | */ |
45 | |
46 | #include <sys/types.h> /* quad_t */ |
47 | #include <sys/param.h> /* BSD4_4 */ |
48 | #include <sys/ioctl.h> |
49 | |
50 | #include <stdio.h> /* defines BUFSIZ */ |
51 | #include <string.h> |
52 | #include <unistd.h> |
53 | #include <stdlib.h> |
54 | #ifdef USE_GLIBC_STDIO |
55 | #include <fcntl.h> |
56 | #endif |
57 | #include <limits.h> |
58 | |
59 | #include "shell.h" |
60 | #include "syntax.h" |
61 | #include "output.h" |
62 | #include "memalloc.h" |
63 | #include "error.h" |
64 | #include "main.h" |
65 | #include "system.h" |
66 | |
67 | |
68 | #define OUTBUFSIZ BUFSIZ |
69 | #define MEM_OUT -3 /* output to dynamically allocated memory */ |
70 | |
71 | |
72 | #ifdef USE_GLIBC_STDIO |
73 | struct output output = { |
74 | stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 1, flags: 0 |
75 | }; |
76 | struct output errout = { |
77 | stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 2, flags: 0 |
78 | } |
79 | #ifdef notyet |
80 | struct output memout = { |
81 | stream: 0, nextc: 0, end: 0, buf: 0, bufsize: 0, fd: MEM_OUT, flags: 0 |
82 | }; |
83 | #endif |
84 | #else |
85 | struct output output = { |
86 | nextc: 0, end: 0, buf: 0, bufsize: OUTBUFSIZ, fd: 1, flags: 0 |
87 | }; |
88 | struct output errout = { |
89 | nextc: 0, end: 0, buf: 0, bufsize: 0, fd: 2, flags: 0 |
90 | }; |
91 | struct output preverrout; |
92 | #ifdef notyet |
93 | struct output memout = { |
94 | nextc: 0, end: 0, buf: 0, bufsize: 0, fd: MEM_OUT, flags: 0 |
95 | }; |
96 | #endif |
97 | #endif |
98 | struct output *out1 = &output; |
99 | struct output *out2 = &errout; |
100 | |
101 | |
102 | #ifndef USE_GLIBC_STDIO |
103 | static void __outstr(const char *, size_t, struct output *); |
104 | #endif |
105 | static int xvsnprintf(char *, size_t, const char *, va_list); |
106 | |
107 | |
108 | #ifdef mkinit |
109 | |
110 | INCLUDE "output.h" |
111 | INCLUDE "memalloc.h" |
112 | |
113 | INIT { |
114 | #ifdef USE_GLIBC_STDIO |
115 | initstreams(); |
116 | #endif |
117 | } |
118 | |
119 | RESET { |
120 | #ifdef notyet |
121 | out1 = &output; |
122 | out2 = &errout; |
123 | #ifdef USE_GLIBC_STDIO |
124 | if (memout.stream != NULL) |
125 | __closememout(); |
126 | #endif |
127 | if (memout.buf != NULL) { |
128 | ckfree(memout.buf); |
129 | memout.buf = NULL; |
130 | } |
131 | #endif |
132 | } |
133 | |
134 | #endif |
135 | |
136 | |
137 | #ifndef USE_GLIBC_STDIO |
138 | static void |
139 | __outstr(const char *p, size_t len, struct output *dest) |
140 | { |
141 | size_t bufsize; |
142 | size_t offset; |
143 | size_t nleft; |
144 | |
145 | nleft = dest->end - dest->nextc; |
146 | if (nleft >= len) { |
147 | buffered: |
148 | dest->nextc = mempcpy(dest->nextc, p, len); |
149 | return; |
150 | } |
151 | |
152 | bufsize = dest->bufsize; |
153 | if (!bufsize) { |
154 | ; |
155 | } else if (dest->buf == NULL) { |
156 | if (dest->fd == MEM_OUT && len > bufsize) { |
157 | bufsize = len; |
158 | } |
159 | offset = 0; |
160 | goto alloc; |
161 | } else if (dest->fd == MEM_OUT) { |
162 | offset = bufsize; |
163 | if (bufsize >= len) { |
164 | bufsize <<= 1; |
165 | } else { |
166 | bufsize += len; |
167 | } |
168 | if (bufsize < offset) |
169 | goto err; |
170 | alloc: |
171 | INTOFF; |
172 | dest->buf = ckrealloc(dest->buf, bufsize); |
173 | dest->bufsize = bufsize; |
174 | dest->end = dest->buf + bufsize; |
175 | dest->nextc = dest->buf + offset; |
176 | INTON; |
177 | } else { |
178 | flushout(dest); |
179 | } |
180 | |
181 | nleft = dest->end - dest->nextc; |
182 | if (nleft > len) |
183 | goto buffered; |
184 | |
185 | if ((xwrite(dest->fd, p, len))) { |
186 | err: |
187 | dest->flags |= OUTPUT_ERR; |
188 | } |
189 | } |
190 | #endif |
191 | |
192 | |
193 | void |
194 | outstr(const char *p, struct output *file) |
195 | { |
196 | #ifdef USE_GLIBC_STDIO |
197 | INTOFF; |
198 | fputs(p, file->stream); |
199 | INTON; |
200 | #else |
201 | size_t len; |
202 | |
203 | len = strlen(p); |
204 | __outstr(p, len, file); |
205 | #endif |
206 | } |
207 | |
208 | |
209 | #ifndef USE_GLIBC_STDIO |
210 | |
211 | |
212 | void |
213 | outcslow(int c, struct output *dest) |
214 | { |
215 | char buf = c; |
216 | __outstr(&buf, 1, dest); |
217 | } |
218 | #endif |
219 | |
220 | |
221 | void |
222 | flushall(void) |
223 | { |
224 | flushout(&output); |
225 | #ifdef FLUSHERR |
226 | flushout(&errout); |
227 | #endif |
228 | } |
229 | |
230 | |
231 | void |
232 | flushout(struct output *dest) |
233 | { |
234 | #ifdef USE_GLIBC_STDIO |
235 | INTOFF; |
236 | fflush(dest->stream); |
237 | INTON; |
238 | #else |
239 | size_t len; |
240 | |
241 | len = dest->nextc - dest->buf; |
242 | if (!len || dest->fd < 0) |
243 | return; |
244 | dest->nextc = dest->buf; |
245 | if ((xwrite(dest->fd, dest->buf, len))) |
246 | dest->flags |= OUTPUT_ERR; |
247 | #endif |
248 | } |
249 | |
250 | |
251 | void |
252 | outfmt(struct output *file, const char *fmt, ...) |
253 | { |
254 | va_list ap; |
255 | |
256 | va_start(ap, fmt); |
257 | doformat(file, fmt, ap); |
258 | va_end(ap); |
259 | } |
260 | |
261 | |
262 | void |
263 | out1fmt(const char *fmt, ...) |
264 | { |
265 | va_list ap; |
266 | |
267 | va_start(ap, fmt); |
268 | doformat(out1, fmt, ap); |
269 | va_end(ap); |
270 | } |
271 | |
272 | |
273 | int |
274 | fmtstr(char *outbuf, size_t length, const char *fmt, ...) |
275 | { |
276 | va_list ap; |
277 | int ret; |
278 | |
279 | va_start(ap, fmt); |
280 | ret = xvsnprintf(outbuf, length, fmt, ap); |
281 | va_end(ap); |
282 | return ret; |
283 | } |
284 | |
285 | |
286 | #ifndef USE_GLIBC_STDIO |
287 | void |
288 | doformat(struct output *dest, const char *f, va_list ap) |
289 | { |
290 | struct stackmark smark; |
291 | char *s; |
292 | int len, ret; |
293 | size_t size; |
294 | va_list ap2; |
295 | |
296 | va_copy(ap2, ap); |
297 | size = dest->end - dest->nextc; |
298 | len = xvsnprintf(dest->nextc, size, f, ap2); |
299 | va_end(ap2); |
300 | if (len < 0) { |
301 | dest->flags |= OUTPUT_ERR; |
302 | return; |
303 | } |
304 | if (len < size) { |
305 | dest->nextc += len; |
306 | return; |
307 | } |
308 | setstackmark(&smark); |
309 | s = stalloc((len >= stackblocksize() ? len : stackblocksize()) + 1); |
310 | ret = xvsnprintf(s, len + 1, f, ap); |
311 | if (ret == len) |
312 | __outstr(s, len, dest); |
313 | else |
314 | dest->flags |= OUTPUT_ERR; |
315 | popstackmark(&smark); |
316 | } |
317 | #endif |
318 | |
319 | |
320 | |
321 | /* |
322 | * Version of write which resumes after a signal is caught. |
323 | */ |
324 | |
325 | int |
326 | xwrite(int fd, const void *p, size_t n) |
327 | { |
328 | const char *buf = p; |
329 | |
330 | while (n) { |
331 | ssize_t i; |
332 | size_t m; |
333 | |
334 | m = n; |
335 | if (m > SSIZE_MAX) |
336 | m = SSIZE_MAX; |
337 | do { |
338 | i = write(fd, buf, m); |
339 | } while (i < 0 && errno == EINTR); |
340 | if (i < 0) |
341 | return -1; |
342 | buf += i; |
343 | n -= i; |
344 | } |
345 | return 0; |
346 | } |
347 | |
348 | |
349 | #ifdef notyet |
350 | #ifdef USE_GLIBC_STDIO |
351 | void initstreams() { |
352 | output.stream = stdout; |
353 | errout.stream = stderr; |
354 | } |
355 | |
356 | |
357 | void |
358 | openmemout(void) { |
359 | INTOFF; |
360 | memout.stream = open_memstream(&memout.buf, &memout.bufsize); |
361 | INTON; |
362 | } |
363 | |
364 | |
365 | int |
366 | __closememout(void) { |
367 | int error; |
368 | error = fclose(memout.stream); |
369 | memout.stream = NULL; |
370 | return error; |
371 | } |
372 | #endif |
373 | #endif |
374 | |
375 | |
376 | static int |
377 | xvsnprintf(char *outbuf, size_t length, const char *fmt, va_list ap) |
378 | { |
379 | int ret; |
380 | |
381 | INTOFF; |
382 | ret = vsnprintf(outbuf, length, fmt, ap); |
383 | INTON; |
384 | return ret; |
385 | } |