2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
41 static const char rcsid[] =
46 * Shell output routines. We use our own output routines because:
47 * When a builtin command is interrupted we have to discard
49 * When a builtin command appears in back quotes, we want to
50 * save the output of the command in a region obtained
51 * via malloc, rather than doing a fork and reading the
52 * output of the command via a pipe.
53 * Our output routines may be smaller than the stdio routines.
56 #include <sys/types.h> /* quad_t */
57 #include <sys/ioctl.h>
59 #include <stdio.h> /* defines BUFSIZ */
77 #define OUTBUFSIZ BUFSIZ
78 #define BLOCK_OUT -2 /* output to a fixed block of memory */
79 #define MEM_OUT -3 /* output to dynamically allocated memory */
80 #define OUTPUT_ERR 01 /* error occurred on output */
83 struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
84 struct output errout = {NULL, 0, NULL, 100, 2, 0};
85 struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
86 struct output *out1 = &output;
87 struct output *out2 = &errout;
99 if (memout.buf != NULL) {
108 #ifdef notdef /* no longer used */
110 * Set up an output file to write to memory rather than a file.
114 open_mem(block, length, file)
120 file->nleft = --length;
121 file->fd = BLOCK_OUT;
164 if (dest->fd == BLOCK_OUT) {
165 dest->nextc = out_junk;
166 dest->nleft = sizeof out_junk;
167 dest->flags |= OUTPUT_ERR;
168 } else if (dest->buf == NULL) {
170 dest->buf = ckmalloc(dest->bufsize);
171 dest->nextc = dest->buf;
172 dest->nleft = dest->bufsize;
174 } else if (dest->fd == MEM_OUT) {
175 offset = dest->bufsize;
178 dest->buf = ckrealloc(dest->buf, dest->bufsize);
179 dest->nleft = dest->bufsize - offset;
180 dest->nextc = dest->buf + offset;
201 if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
203 if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
204 dest->flags |= OUTPUT_ERR;
205 dest->nextc = dest->buf;
206 dest->nleft = dest->bufsize;
224 outfmt(struct output *file, char *fmt, ...) {
228 doformat(file, fmt, ap);
234 out1fmt(char *fmt, ...) {
238 doformat(out1, fmt, ap);
243 dprintf(char *fmt, ...) {
247 doformat(out2, fmt, ap);
253 fmtstr(char *outbuf, int length, char *fmt, ...) {
255 struct output strout;
258 strout.nextc = outbuf;
259 strout.nleft = length;
260 strout.fd = BLOCK_OUT;
262 doformat(&strout, fmt, ap);
264 if (strout.flags & OUTPUT_ERR)
265 outbuf[length - 1] = '\0';
268 #else /* not __STDC__ */
279 file = va_arg(ap, struct output *);
280 fmt = va_arg(ap, char *);
281 doformat(file, fmt, ap);
294 fmt = va_arg(ap, char *);
295 doformat(out1, fmt, ap);
307 fmt = va_arg(ap, char *);
308 doformat(out2, fmt, ap);
318 struct output strout;
324 outbuf = va_arg(ap, char *);
325 length = va_arg(ap, int);
326 fmt = va_arg(ap, char *);
327 strout.nextc = outbuf;
328 strout.nleft = length;
329 strout.fd = BLOCK_OUT;
331 doformat(&strout, fmt, ap);
333 if (strout.flags & OUTPUT_ERR)
334 outbuf[length - 1] = '\0';
336 #endif /* __STDC__ */
340 * Formatted output. This routine handles a subset of the printf formats:
341 * - Formats supported: d, u, o, X, s, and c.
342 * - The x format is also accepted but is treated like X.
343 * - The l and q modifiers are accepted.
344 * - The - and # flags are accepted; # only works with the o format.
345 * - Width and precision may be specified with any format except c.
346 * - An * may be given for the width or precision.
347 * - The obsolete practice of preceding the width with a zero to get
348 * zero padding is not supported; use the precision field.
349 * - A % may be printed by writing %% in the format string.
354 static const char digit[] = "0123456789ABCDEF";
358 doformat(dest, f, ap)
360 char *f; /* format string */
380 while ((c = *f++) != '\0') {
401 width = va_arg(ap, int);
404 while (is_digit(*f)) {
405 width = 10 * width + digit_val(*f++);
410 prec = va_arg(ap, int);
414 while (is_digit(*f)) {
415 prec = 10 * prec + digit_val(*f++);
422 } else if (*f == 'q') {
429 l = va_arg(ap, quad_t);
431 l = va_arg(ap, long);
449 /* we don't implement 'x'; treat like 'X' */
452 uns_number: /* an unsigned number */
455 num = va_arg(ap, u_quad_t);
457 num = va_arg(ap, unsigned long);
459 num = va_arg(ap, unsigned int);
460 number: /* process a number */
461 p = temp + TEMPSIZE - 1;
464 *--p = digit[num % base];
467 len = (temp + TEMPSIZE - 1) - p;
470 if (sharp && *f == 'o' && prec <= len)
479 if (flushleft == 0) {
495 p = va_arg(ap, char *);
499 if (prec >= 0 && len > prec)
502 if (flushleft == 0) {
508 while (--prec != 0 && *p)
528 * Version of write which resumes after a signal is caught.
532 xwrite(fd, buf, nbytes)
544 i = write(fd, buf, n);
553 } else if (errno != EINTR) {
561 * Version of ioctl that retries after a signal is caught.
562 * XXX unused function
566 xioctl(fd, request, arg)
568 unsigned long request;
573 while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);