]>
git.saurik.com Git - apple/shell_cmds.git/blob - sh/output.c
2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
37 static char sccsid
[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD: head/bin/sh/output.c 326025 2017-11-20 19:49:47Z pfg $");
44 * Shell output routines. We use our own output routines because:
45 * When a builtin command is interrupted we have to discard
47 * When a builtin command appears in back quotes, we want to
48 * save the output of the command in a region obtained
49 * via malloc, rather than doing a fork and reading the
50 * output of the command via a pipe.
53 #include <stdio.h> /* defines BUFSIZ */
70 #define OUTBUFSIZ BUFSIZ
71 #define MEM_OUT -2 /* output to dynamically allocated memory */
72 #define OUTPUT_ERR 01 /* error occurred on output */
74 static int doformat_wr(void *, const char *, int);
76 struct output output
= {NULL
, NULL
, NULL
, OUTBUFSIZ
, 1, 0};
77 struct output errout
= {NULL
, NULL
, NULL
, 256, 2, 0};
78 struct output memout
= {NULL
, NULL
, NULL
, 64, MEM_OUT
, 0};
79 struct output
*out1
= &output
;
80 struct output
*out2
= &errout
;
83 outcslow(int c
, struct output
*file
)
89 out1str(const char *p
)
95 out1qstr(const char *p
)
101 out2str(const char *p
)
107 out2qstr(const char *p
)
113 outstr(const char *p
, struct output
*file
)
115 outbin(p
, strlen(p
), file
);
119 byteseq(int ch
, struct output
*file
)
124 seq
[1] = (ch
>> 6 & 0x3) + '0';
125 seq
[2] = (ch
>> 3 & 0x7) + '0';
126 seq
[3] = (ch
& 0x7) + '0';
127 outbin(seq
, 4, file
);
131 outdqstr(const char *p
, struct output
*file
)
138 memset(&mbs
, '\0', sizeof(mbs
));
141 while ((clen
= mbrtowc(&wc
, p
, end
- p
+ 1, &mbs
)) != 0) {
142 if (clen
== (size_t)-2) {
147 if (clen
== (size_t)-1) {
148 memset(&mbs
, '\0', sizeof(mbs
));
153 outcslow('\n', file
), p
++;
154 else if (wc
== L
'\r')
155 outstr("\\r", file
), p
++;
156 else if (wc
== L
'\t')
157 outstr("\\t", file
), p
++;
158 else if (!iswprint(wc
)) {
159 for (; clen
> 0; clen
--)
162 if (wc
== L
'\'' || wc
== L
'\\')
163 outcslow('\\', file
);
164 outbin(p
, clen
, file
);
168 outcslow('\'', file
);
171 /* Like outstr(), but quote for re-input into the shell. */
173 outqstr(const char *p
, struct output
*file
)
181 for (i
= 0; p
[i
] != '\0'; i
++) {
182 if ((p
[i
] > '\0' && p
[i
] < ' ' && p
[i
] != '\n') ||
183 (p
[i
] & 0x80) != 0 || p
[i
] == '\'') {
189 if (p
[strcspn(p
, "|&;<>()$`\\\" \n*?[~#=")] == '\0' ||
190 strcmp(p
, "[") == 0) {
195 outcslow('\'', file
);
197 outcslow('\'', file
);
201 outbin(const void *data
, size_t len
, struct output
*file
)
211 emptyoutbuf(struct output
*dest
)
215 if (dest
->buf
== NULL
) {
217 dest
->buf
= ckmalloc(dest
->bufsize
);
218 dest
->nextc
= dest
->buf
;
219 dest
->bufend
= dest
->buf
+ dest
->bufsize
;
221 } else if (dest
->fd
== MEM_OUT
) {
222 offset
= dest
->nextc
- dest
->buf
;
223 newsize
= dest
->bufsize
<< 1;
225 dest
->buf
= ckrealloc(dest
->buf
, newsize
);
226 dest
->bufsize
= newsize
;
227 dest
->bufend
= dest
->buf
+ newsize
;
228 dest
->nextc
= dest
->buf
+ offset
;
245 flushout(struct output
*dest
)
248 if (dest
->buf
== NULL
|| dest
->nextc
== dest
->buf
|| dest
->fd
< 0)
250 if (xwrite(dest
->fd
, dest
->buf
, dest
->nextc
- dest
->buf
) < 0)
251 dest
->flags
|= OUTPUT_ERR
;
252 dest
->nextc
= dest
->buf
;
259 output
.nextc
= output
.buf
;
264 outiserror(struct output
*file
)
266 return (file
->flags
& OUTPUT_ERR
);
271 outclearerror(struct output
*file
)
273 file
->flags
&= ~OUTPUT_ERR
;
278 outfmt(struct output
*file
, const char *fmt
, ...)
283 doformat(file
, fmt
, ap
);
289 out1fmt(const char *fmt
, ...)
294 doformat(out1
, fmt
, ap
);
299 out2fmt_flush(const char *fmt
, ...)
304 doformat(out2
, fmt
, ap
);
310 fmtstr(char *outbuf
, int length
, const char *fmt
, ...)
316 vsnprintf(outbuf
, length
, fmt
, ap
);
322 doformat_wr(void *cookie
, const char *buf
, int len
)
326 o
= (struct output
*)cookie
;
333 doformat(struct output
*dest
, const char *f
, va_list ap
)
337 if ((fp
= fwopen(dest
, doformat_wr
)) != NULL
) {
344 * Version of write which resumes after a signal is caught.
348 xwrite(int fd
, const char *buf
, int nbytes
)
357 i
= write(fd
, buf
, n
);
366 } else if (errno
!= EINTR
) {