VirtualBox

source: kBuild/trunk/src/kash/output.c@ 1211

Last change on this file since 1211 was 1207, checked in by bird, 17 years ago

jobs and other stuff.

  • Property svn:eol-style set to native
File size: 10.3 KB
Line 
1/* $NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $ */
2
3/*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. 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#ifdef HAVE_SYS_CDEFS_H
36#include <sys/cdefs.h>
37#endif
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
41#else
42__RCSID("$NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $");
43#endif
44#endif /* not lint */
45
46/*
47 * Shell output routines. We use our own output routines because:
48 * When a builtin command is interrupted we have to discard
49 * any pending output.
50 * When a builtin command appears in back quotes, we want to
51 * save the output of the command in a region obtained
52 * via malloc, rather than doing a fork and reading the
53 * output of the command via a pipe.
54 * Our output routines may be smaller than the stdio routines.
55 */
56
57#include <sys/types.h> /* quad_t */
58#include <sys/param.h> /* BSD4_4 */
59#include <sys/ioctl.h>
60
61#include <stdio.h> /* defines BUFSIZ */
62#include <string.h>
63#include <errno.h>
64#include <unistd.h>
65#include <stdlib.h>
66
67#include "shell.h"
68#include "syntax.h"
69#include "output.h"
70#include "memalloc.h"
71#include "error.h"
72
73#include "shinstance.h"
74
75//#define OUTBUFSIZ BUFSIZ
76#define BLOCK_OUT -2 /* output to a fixed block of memory */
77//#define MEM_OUT -3 /* output to dynamically allocated memory */
78#define OUTPUT_ERR 01 /* error occurred on output */
79
80
81//struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
82//struct output errout = {NULL, 0, NULL, 100, 2, 0};
83//struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
84//struct output *out1 = &output;
85//struct output *out2 = &errout;
86
87
88
89#ifdef mkinit
90
91INCLUDE "output.h"
92INCLUDE "memalloc.h"
93
94RESET {
95 psh->out1 = &psh->output;
96 psh->out2 = &psh->errout;
97 if (psh->memout.buf != NULL) {
98 ckfree(psh->memout.buf);
99 psh->memout.buf = NULL;
100 }
101}
102
103#endif
104
105
106#ifdef notdef /* no longer used */
107/*
108 * Set up an output file to write to memory rather than a file.
109 */
110
111void
112open_mem(char *block, int length, struct output *file)
113{
114 file->nextc = block;
115 file->nleft = --length;
116 file->fd = BLOCK_OUT;
117 file->flags = 0;
118}
119#endif
120
121
122void
123out1str(shinstance *psh, const char *p)
124{
125 outstr(p, psh->out1);
126}
127
128
129void
130out2str(shinstance *psh, const char *p)
131{
132 outstr(p, psh->out2);
133}
134
135
136void
137outstr(const char *p, struct output *file)
138{
139 while (*p)
140 outc(*p++, file);
141 if (file == file->psh->out2)
142 flushout(file);
143}
144
145
146char out_junk[16];
147
148
149void
150emptyoutbuf(struct output *dest)
151{
152 int offset;
153 shinstance *psh = dest->psh;
154
155 if (dest->fd == BLOCK_OUT) {
156 dest->nextc = out_junk;
157 dest->nleft = sizeof out_junk;
158 dest->flags |= OUTPUT_ERR;
159 } else if (dest->buf == NULL) {
160 INTOFF;
161 dest->buf = ckmalloc(dest->bufsize);
162 dest->nextc = dest->buf;
163 dest->nleft = dest->bufsize;
164 INTON;
165 } else if (dest->fd == MEM_OUT) {
166 offset = dest->bufsize;
167 INTOFF;
168 dest->bufsize <<= 1;
169 dest->buf = ckrealloc(dest->buf, dest->bufsize);
170 dest->nleft = dest->bufsize - offset;
171 dest->nextc = dest->buf + offset;
172 INTON;
173 } else {
174 flushout(dest);
175 }
176 dest->nleft--;
177}
178
179
180void
181output_flushall(shinstance *psh)
182{
183 flushout(&psh->output);
184 flushout(&psh->errout);
185}
186
187
188void
189flushout(struct output *dest)
190{
191
192 if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
193 return;
194 if (xwrite(dest->psh, dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
195 dest->flags |= OUTPUT_ERR;
196 dest->nextc = dest->buf;
197 dest->nleft = dest->bufsize;
198}
199
200
201void
202freestdout(shinstance *psh)
203{
204 INTOFF;
205 if (psh->output.buf) {
206 ckfree(psh->output.buf);
207 psh->output.buf = NULL;
208 psh->output.nleft = 0;
209 }
210 INTON;
211}
212
213
214void
215outfmt(struct output *file, const char *fmt, ...)
216{
217 va_list ap;
218
219 va_start(ap, fmt);
220 doformat(file, fmt, ap);
221 va_end(ap);
222}
223
224
225void
226out1fmt(shinstance *psh, const char *fmt, ...)
227{
228 va_list ap;
229
230 va_start(ap, fmt);
231 doformat(psh->out1, fmt, ap);
232 va_end(ap);
233}
234
235void
236dprintf(shinstance *psh, const char *fmt, ...)
237{
238 va_list ap;
239
240 va_start(ap, fmt);
241 doformat(psh->out2, fmt, ap);
242 va_end(ap);
243 flushout(psh->out2);
244}
245
246void
247fmtstr(char *outbuf, size_t length, const char *fmt, ...)
248{
249 va_list ap;
250 struct output strout;
251
252 va_start(ap, fmt);
253 strout.nextc = outbuf;
254 strout.nleft = (int)length;
255 strout.fd = BLOCK_OUT;
256 strout.flags = 0;
257 strout.psh = NULL;
258 doformat(&strout, fmt, ap);
259 outc('\0', &strout);
260 if (strout.flags & OUTPUT_ERR)
261 outbuf[length - 1] = '\0';
262 va_end(ap);
263}
264
265/*
266 * Formatted output. This routine handles a subset of the printf formats:
267 * - Formats supported: d, u, o, p, X, s, and c.
268 * - The x format is also accepted but is treated like X.
269 * - The l, ll and q modifiers are accepted.
270 * - The - and # flags are accepted; # only works with the o format.
271 * - Width and precision may be specified with any format except c.
272 * - An * may be given for the width or precision.
273 * - The obsolete practice of preceding the width with a zero to get
274 * zero padding is not supported; use the precision field.
275 * - A % may be printed by writing %% in the format string.
276 */
277
278#define TEMPSIZE 24
279
280#ifdef BSD4_4
281#define HAVE_VASPRINTF 1
282#endif
283
284void
285doformat(struct output *dest, const char *f, va_list ap)
286{
287#if HAVE_VASPRINTF
288 char *s;
289
290 vasprintf(&s, f, ap);
291 outstr(s, dest);
292 free(s);
293#else /* !HAVE_VASPRINTF */
294 static const char digit[] = "0123456789ABCDEF";
295 char c;
296 char temp[TEMPSIZE];
297 int flushleft;
298 int sharp;
299 int width;
300 int prec;
301 int islong;
302 int isquad;
303 char *p;
304 int sign;
305#ifdef BSD4_4
306 quad_t l;
307 u_quad_t num;
308#else
309 long l;
310 unsigned long num;
311#endif
312 unsigned base;
313 int len;
314 int size;
315 int pad;
316
317 while ((c = *f++) != '\0') {
318 if (c != '%') {
319 outc(c, dest);
320 continue;
321 }
322 flushleft = 0;
323 sharp = 0;
324 width = 0;
325 prec = -1;
326 islong = 0;
327 isquad = 0;
328 for (;;) {
329 if (*f == '-')
330 flushleft++;
331 else if (*f == '#')
332 sharp++;
333 else
334 break;
335 f++;
336 }
337 if (*f == '*') {
338 width = va_arg(ap, int);
339 f++;
340 } else {
341 while (is_digit(*f)) {
342 width = 10 * width + digit_val(*f++);
343 }
344 }
345 if (*f == '.') {
346 if (*++f == '*') {
347 prec = va_arg(ap, int);
348 f++;
349 } else {
350 prec = 0;
351 while (is_digit(*f)) {
352 prec = 10 * prec + digit_val(*f++);
353 }
354 }
355 }
356 if (*f == 'l') {
357 f++;
358 if (*f == 'l') {
359 isquad++;
360 f++;
361 } else
362 islong++;
363 } else if (*f == 'q') {
364 isquad++;
365 f++;
366 }
367 switch (*f) {
368 case 'd':
369#ifdef BSD4_4
370 if (isquad)
371 l = va_arg(ap, quad_t);
372 else
373#endif
374 if (islong)
375 l = va_arg(ap, long);
376 else
377 l = va_arg(ap, int);
378 sign = 0;
379 num = l;
380 if (l < 0) {
381 num = -l;
382 sign = 1;
383 }
384 base = 10;
385 goto number;
386 case 'u':
387 base = 10;
388 goto uns_number;
389 case 'o':
390 base = 8;
391 goto uns_number;
392 case 'p':
393 outc('0', dest);
394 outc('x', dest);
395 /*FALLTHROUGH*/
396 case 'x':
397 /* we don't implement 'x'; treat like 'X' */
398 case 'X':
399 base = 16;
400uns_number: /* an unsigned number */
401 sign = 0;
402#ifdef BSD4_4
403 if (isquad)
404 num = va_arg(ap, u_quad_t);
405 else
406#endif
407 if (islong)
408 num = va_arg(ap, unsigned long);
409 else
410 num = va_arg(ap, unsigned int);
411number: /* process a number */
412 p = temp + TEMPSIZE - 1;
413 *p = '\0';
414 while (num) {
415 *--p = digit[num % base];
416 num /= base;
417 }
418 len = (int)((temp + TEMPSIZE - 1) - p);
419 if (prec < 0)
420 prec = 1;
421 if (sharp && *f == 'o' && prec <= len)
422 prec = len + 1;
423 pad = 0;
424 if (width) {
425 size = len;
426 if (size < prec)
427 size = prec;
428 size += sign;
429 pad = width - size;
430 if (flushleft == 0) {
431 while (--pad >= 0)
432 outc(' ', dest);
433 }
434 }
435 if (sign)
436 outc('-', dest);
437 prec -= len;
438 while (--prec >= 0)
439 outc('0', dest);
440 while (*p)
441 outc(*p++, dest);
442 while (--pad >= 0)
443 outc(' ', dest);
444 break;
445 case 's':
446 p = va_arg(ap, char *);
447 pad = 0;
448 if (width) {
449 len = (int)strlen(p);
450 if (prec >= 0 && len > prec)
451 len = prec;
452 pad = width - len;
453 if (flushleft == 0) {
454 while (--pad >= 0)
455 outc(' ', dest);
456 }
457 }
458 prec++;
459 while (--prec != 0 && *p)
460 outc(*p++, dest);
461 while (--pad >= 0)
462 outc(' ', dest);
463 break;
464 case 'c':
465 c = va_arg(ap, int);
466 outc(c, dest);
467 break;
468 default:
469 outc(*f, dest);
470 break;
471 }
472 f++;
473 }
474#endif /* !HAVE_VASPRINTF */
475}
476
477
478
479/*
480 * Version of write which resumes after a signal is caught.
481 */
482
483int
484xwrite(shinstance *psh, int fd, char *buf, size_t nbytes)
485{
486 int ntry;
487 long i;
488 size_t n;
489
490 n = nbytes;
491 ntry = 0;
492 for (;;) {
493 i = shfile_write(&psh->fdtab, fd, buf, n);
494 if (i > 0) {
495 if ((n -= i) <= 0)
496 return (int)nbytes;
497 buf += i;
498 ntry = 0;
499 } else if (i == 0) {
500 if (++ntry > 10)
501 return (int)(nbytes - n);
502 } else if (errno != EINTR) {
503 return -1;
504 }
505 }
506}
507
508
509#ifdef not_used
510/*
511 * Version of ioctl that retries after a signal is caught.
512 * XXX unused function
513 */
514
515int
516xioctl(shinstance *psh, int fd, unsigned long request, char *arg)
517{
518 int i;
519
520 while ((i = shfile_ioctl(&psh->fdtab, fd, request, arg)) == -1 && errno == EINTR);
521 return i;
522}
523#endif /* not_used */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette