2 * Copyright (c) 1991 The Regents of the University of California.
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
38 static char sccsid
[] = "@(#)output.c 5.1 (Berkeley) 3/7/91";
42 * Shell output routines. We use our own output routines because:
43 * When a builtin command is interrupted we have to discard
45 * When a builtin command appears in back quotes, we want to
46 * save the output of the command in a region obtained
47 * via malloc, rather than doing a fork and reading the
48 * output of the command via a pipe.
49 * Our output routines may be smaller than the stdio routines.
52 #include <stdio.h> /* defines BUFSIZ */
66 #define OUTBUFSIZ BUFSIZ
67 #define BLOCK_OUT -2 /* output to a fixed block of memory */
68 #define MEM_OUT -3 /* output to dynamically allocated memory */
69 #define OUTPUT_ERR 01 /* error occurred on output */
72 struct output output
= {NULL
, 0, NULL
, OUTBUFSIZ
, 1, 0};
73 struct output errout
= {NULL
, 0, NULL
, 100, 2, 0};
74 struct output memout
= {NULL
, 0, NULL
, 0, MEM_OUT
, 0};
75 struct output
*out1
= &output
;
76 struct output
*out2
= &errout
;
88 if (memout
.buf
!= NULL
) {
97 #ifdef notdef /* no longer used */
99 * Set up an output file to write to memory rather than a file.
103 open_mem(block
, length
, file
)
106 register struct output
*file
;
109 file
->nleft
= --length
;
110 file
->fd
= BLOCK_OUT
;
135 register struct output
*file
;
147 register struct output
*dest
;
151 if (dest
->fd
== BLOCK_OUT
) {
152 dest
->nextc
= out_junk
;
153 dest
->nleft
= sizeof out_junk
;
154 dest
->flags
|= OUTPUT_ERR
;
155 } else if (dest
->buf
== NULL
) {
157 dest
->buf
= ckmalloc(dest
->bufsize
);
158 dest
->nextc
= dest
->buf
;
159 dest
->nleft
= dest
->bufsize
;
161 } else if (dest
->fd
== MEM_OUT
) {
162 offset
= dest
->bufsize
;
165 dest
->buf
= ckrealloc(dest
->buf
, dest
->bufsize
);
166 dest
->nleft
= dest
->bufsize
- offset
;
167 dest
->nextc
= dest
->buf
+ offset
;
185 register struct output
*dest
;
188 if (dest
->buf
== NULL
|| dest
->nextc
== dest
->buf
|| dest
->fd
< 0)
190 if (xwrite(dest
->fd
, dest
->buf
, dest
->nextc
- dest
->buf
) < 0)
191 dest
->flags
|= OUTPUT_ERR
;
192 dest
->nextc
= dest
->buf
;
193 dest
->nleft
= dest
->bufsize
;
211 outfmt(struct output
*file
, char *fmt
, ...) {
215 doformat(file
, fmt
, ap
);
221 out1fmt(char *fmt
, ...) {
225 doformat(out1
, fmt
, ap
);
231 fmtstr(char *outbuf
, int length
, char *fmt
, ...) {
233 struct output strout
;
236 strout
.nextc
= outbuf
;
237 strout
.nleft
= length
;
238 strout
.fd
= BLOCK_OUT
;
240 doformat(&strout
, fmt
, ap
);
242 if (strout
.flags
& OUTPUT_ERR
)
243 outbuf
[length
- 1] = '\0';
247 #else /* not __STDC__ */
254 register struct output
*file
;
258 file
= va_arg(ap
, struct output
*);
259 fmt
= va_arg(ap
, char *);
260 doformat(file
, fmt
, ap
);
273 fmt
= va_arg(ap
, char *);
274 doformat(out1
, fmt
, ap
);
284 struct output strout
;
285 register char *outbuf
;
290 outbuf
= va_arg(ap
, char *);
291 length
= va_arg(ap
, int);
292 fmt
= va_arg(ap
, char *);
293 strout
.nextc
= outbuf
;
294 strout
.nleft
= length
;
295 strout
.fd
= BLOCK_OUT
;
297 doformat(&strout
, fmt
, ap
);
299 if (strout
.flags
& OUTPUT_ERR
)
300 outbuf
[length
- 1] = '\0';
302 #endif /* __STDC__ */
306 * Formatted output. This routine handles a subset of the printf formats:
307 * - Formats supported: d, u, o, X, s, and c.
308 * - The x format is also accepted but is treated like X.
309 * - The l modifier is accepted.
310 * - The - and # flags are accepted; # only works with the o format.
311 * - Width and precision may be specified with any format except c.
312 * - An * may be given for the width or precision.
313 * - The obsolete practice of preceding the width with a zero to get
314 * zero padding is not supported; use the precision field.
315 * - A % may be printed by writing %% in the format string.
321 static const char digit
[17] = "0123456789ABCDEF";
323 static const char digit
[17] = "0123456789ABCDEF";
328 doformat(dest
, f
, ap
)
329 register struct output
*dest
;
330 register char *f
; /* format string */
349 while ((c
= *f
++) != '\0') {
369 width
= va_arg(ap
, int);
372 while (is_digit(*f
)) {
373 width
= 10 * width
+ digit_val(*f
++);
378 prec
= va_arg(ap
, int);
382 while (is_digit(*f
)) {
383 prec
= 10 * prec
+ digit_val(*f
++);
394 l
= va_arg(ap
, long);
412 /* we don't implement 'x'; treat like 'X' */
415 uns_number
: /* an unsigned number */
418 num
= va_arg(ap
, unsigned long);
420 num
= va_arg(ap
, unsigned int);
421 number
: /* process a number */
422 p
= temp
+ TEMPSIZE
- 1;
425 *--p
= digit
[num
% base
];
428 len
= (temp
+ TEMPSIZE
- 1) - p
;
431 if (sharp
&& *f
== 'o' && prec
<= len
)
440 if (flushleft
== 0) {
456 p
= va_arg(ap
, char *);
460 if (prec
>= 0 && len
> prec
)
463 if (flushleft
== 0) {
469 while (--prec
!= 0 && *p
)
489 * Version of write which resumes after a signal is caught.
493 xwrite(fd
, buf
, nbytes
)
505 i
= write(fd
, buf
, n
);
514 } else if (errno
!= EINTR
) {
522 * Version of ioctl that retries after a signal is caught.
526 xioctl(fd
, request
, arg
) {
529 while ((i
= ioctl(fd
, request
, arg
)) == -1 && errno
== EINTR
);