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 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 static char sccsid
[] = "@(#)output.c 8.1 (Berkeley) 5/31/93";
38 * Shell output routines. We use our own output routines because:
39 * When a builtin command is interrupted we have to discard
41 * When a builtin command appears in back quotes, we want to
42 * save the output of the command in a region obtained
43 * via malloc, rather than doing a fork and reading the
44 * output of the command via a pipe.
45 * Our output routines may be smaller than the stdio routines.
48 #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
)
109 file
->nleft
= --length
;
110 file
->fd
= BLOCK_OUT
;
124 out1qstr(const char *p
)
131 out2str(const char *p
)
139 register const char *p
;
140 register struct output
*file
;
148 /* Like outstr(), but quote for re-input into the shell. */
150 outqstr(const char *p
, struct output
*file
)
154 if (p
[strcspn(p
, "|&;<>()$`\\\"'")] == '\0' && (!ifsset() ||
155 p
[strcspn(p
, ifsval())] == '\0')) {
161 while ((ch
= *p
++) != '\0') {
165 * Can't quote single quotes inside single quotes;
166 * close them, write escaped single quote, open again.
168 outstr("'\\''", file
);
187 if (dest
->fd
== BLOCK_OUT
) {
188 dest
->nextc
= out_junk
;
189 dest
->nleft
= sizeof out_junk
;
190 dest
->flags
|= OUTPUT_ERR
;
191 } else if (dest
->buf
== NULL
) {
193 dest
->buf
= ckmalloc(dest
->bufsize
);
194 dest
->nextc
= dest
->buf
;
195 dest
->nleft
= dest
->bufsize
;
197 } else if (dest
->fd
== MEM_OUT
) {
198 offset
= dest
->bufsize
;
201 dest
->buf
= ckrealloc(dest
->buf
, dest
->bufsize
);
202 dest
->nleft
= dest
->bufsize
- offset
;
203 dest
->nextc
= dest
->buf
+ offset
;
224 if (dest
->buf
== NULL
|| dest
->nextc
== dest
->buf
|| dest
->fd
< 0)
226 if (xwrite(dest
->fd
, dest
->buf
, dest
->nextc
- dest
->buf
) < 0)
227 dest
->flags
|= OUTPUT_ERR
;
228 dest
->nextc
= dest
->buf
;
229 dest
->nleft
= dest
->bufsize
;
247 outfmt(struct output
*file
, const char *fmt
, ...)
252 doformat(file
, fmt
, ap
);
258 out1fmt(const char *fmt
, ...)
263 doformat(out1
, fmt
, ap
);
268 dprintf(const char *fmt
, ...)
273 doformat(out2
, fmt
, ap
);
279 fmtstr(char *outbuf
, int length
, const char *fmt
, ...)
282 struct output strout
;
285 strout
.nextc
= outbuf
;
286 strout
.nleft
= length
;
287 strout
.fd
= BLOCK_OUT
;
289 doformat(&strout
, fmt
, ap
);
291 if (strout
.flags
& OUTPUT_ERR
)
292 outbuf
[length
- 1] = '\0';
296 #else /* not __STDC__ */
307 file
= va_arg(ap
, struct output
*);
308 fmt
= va_arg(ap
, char *);
309 doformat(file
, fmt
, ap
);
322 fmt
= va_arg(ap
, char *);
323 doformat(out1
, fmt
, ap
);
335 fmt
= va_arg(ap
, char *);
336 doformat(out2
, fmt
, ap
);
346 struct output strout
;
352 outbuf
= va_arg(ap
, char *);
353 length
= va_arg(ap
, int);
354 fmt
= va_arg(ap
, char *);
355 strout
.nextc
= outbuf
;
356 strout
.nleft
= length
;
357 strout
.fd
= BLOCK_OUT
;
359 doformat(&strout
, fmt
, ap
);
361 if (strout
.flags
& OUTPUT_ERR
)
362 outbuf
[length
- 1] = '\0';
364 #endif /* __STDC__ */
368 * Formatted output. This routine handles a subset of the printf formats:
369 * - Formats supported: d, u, o, X, s, and c.
370 * - The x format is also accepted but is treated like X.
371 * - The l modifier is accepted.
372 * - The - and # flags are accepted; # only works with the o format.
373 * - Width and precision may be specified with any format except c.
374 * - An * may be given for the width or precision.
375 * - The obsolete practice of preceding the width with a zero to get
376 * zero padding is not supported; use the precision field.
377 * - A % may be printed by writing %% in the format string.
383 static const char digit
[16] = "0123456789ABCDEF";
385 static const char digit
[17] = "0123456789ABCDEF";
390 doformat(struct output
*dest
, const char *f
, va_list ap
)
408 while ((c
= *f
++) != '\0') {
428 width
= va_arg(ap
, int);
431 while (is_digit(*f
)) {
432 width
= 10 * width
+ digit_val(*f
++);
437 prec
= va_arg(ap
, int);
441 while (is_digit(*f
)) {
442 prec
= 10 * prec
+ digit_val(*f
++);
453 l
= va_arg(ap
, long);
471 /* we don't implement 'x'; treat like 'X' */
474 uns_number
: /* an unsigned number */
477 num
= va_arg(ap
, unsigned long);
479 num
= va_arg(ap
, unsigned int);
480 number
: /* process a number */
481 p
= temp
+ TEMPSIZE
- 1;
484 *--p
= digit
[num
% base
];
487 len
= (temp
+ TEMPSIZE
- 1) - p
;
490 if (sharp
&& *f
== 'o' && prec
<= len
)
499 if (flushleft
== 0) {
515 p
= va_arg(ap
, char *);
519 if (prec
>= 0 && len
> prec
)
522 if (flushleft
== 0) {
528 while (--prec
!= 0 && *p
)
548 * Version of write which resumes after a signal is caught.
552 xwrite(fd
, buf
, nbytes
)
564 i
= write(fd
, buf
, n
);
573 } else if (errno
!= EINTR
) {
580 * $PchId: output.c,v 1.6 2006/05/22 12:46:03 philip Exp $