Magellan Linux

Contents of /trunk/mkinitrd-magellan/klibc/usr/dash/output.c

Parent Directory Parent Directory | Revision Log 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)
-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 }