1 /* $OpenBSD: io.c,v 1.36 2018/01/16 22:52:32 jca Exp $ */
4 * shell buffered IO and formatted output
18 static int initio_done
;
21 * formatted output functions
25 /* A shell error occurred (eg, syntax error, etc.) */
27 errorf(const char *fmt
, ...)
31 shl_stdout_ok
= 0; /* debugging: note that stdout not valid */
33 if (fmt
!= NULL
&& *fmt
!= '\0') {
36 shf_vfprintf(shl_out
, fmt
, va
);
38 shf_putchar('\n', shl_out
);
44 /* like errorf(), but no unwind is done */
46 warningf(bool show_lineno
, const char *fmt
, ...)
50 error_prefix(show_lineno
);
52 shf_vfprintf(shl_out
, fmt
, va
);
54 shf_putchar('\n', shl_out
);
58 /* Used by built-in utilities to prefix shell and utility name to message
59 * (also unwinds environments for special builtins).
62 bi_errorf(const char *fmt
, ...)
66 shl_stdout_ok
= 0; /* debugging: note that stdout not valid */
68 if (fmt
!= NULL
&& *fmt
!= '\0') {
70 /* not set when main() calls parse_args() */
72 shf_fprintf(shl_out
, "%s: ", builtin_argv0
);
74 shf_vfprintf(shl_out
, fmt
, va
);
76 shf_putchar('\n', shl_out
);
79 /* POSIX special builtins and ksh special builtins cause
80 * non-interactive shells to exit.
81 * XXX odd use of KEEPASN; also may not want LERROR here
83 if ((builtin_flag
& SPEC_BI
) ||
84 (Flag(FPOSIX
) && (builtin_flag
& KEEPASN
))) {
91 internal_error_vwarn(const char *fmt
, va_list va
)
94 shf_fprintf(shl_out
, "internal error: ");
95 shf_vfprintf(shl_out
, fmt
, va
);
96 shf_putchar('\n', shl_out
);
100 /* Warn when something that shouldn't happen does */
102 internal_warningf(const char *fmt
, ...)
107 internal_error_vwarn(fmt
, va
);
111 /* Warn and unwind when something that shouldn't happen does */
113 internal_errorf(const char *fmt
, ...)
118 internal_error_vwarn(fmt
, va
);
123 /* used by error reporting functions to print "ksh: .kshrc[25]: " */
125 error_prefix(int fileline
)
127 /* Avoid foo: foo[2]: ... */
128 if (!fileline
|| !source
|| !source
->file
||
129 strcmp(source
->file
, kshname
) != 0)
130 shf_fprintf(shl_out
, "%s: ", kshname
+ (*kshname
== '-'));
131 if (fileline
&& source
&& source
->file
!= NULL
) {
132 shf_fprintf(shl_out
, "%s[%d]: ", source
->file
,
133 source
->errline
> 0 ? source
->errline
: source
->line
);
138 /* printf to shl_out (stderr) with flush */
140 shellf(const char *fmt
, ...)
144 if (!initio_done
) /* shl_out may not be set up yet... */
147 shf_vfprintf(shl_out
, fmt
, va
);
152 /* printf to shl_stdout (stdout) */
154 shprintf(const char *fmt
, ...)
159 internal_errorf("shl_stdout not valid");
161 shf_vfprintf(shl_stdout
, fmt
, va
);
166 static struct shf
*kshdebug_shf
;
172 shf_close(kshdebug_shf
);
173 kshdebug_shf
= shf_open("/tmp/ksh-debug.log",
174 O_WRONLY
|O_APPEND
|O_CREAT
, 0600, SHF_WR
|SHF_MAPHI
);
176 shf_fprintf(kshdebug_shf
, "\nNew shell[pid %d]\n", getpid());
177 shf_flush(kshdebug_shf
);
181 /* print to debugging log */
183 kshdebug_printf_(const char *fmt
, ...)
190 shf_fprintf(kshdebug_shf
, "[%d] ", getpid());
191 shf_vfprintf(kshdebug_shf
, fmt
, va
);
193 shf_flush(kshdebug_shf
);
197 kshdebug_dump_(const char *str
, const void *mem
, int nbytes
)
204 shf_fprintf(kshdebug_shf
, "[%d] %s:\n", getpid(), str
);
205 for (i
= 0; i
< nbytes
; i
+= nprow
) {
208 for (j
= 0; j
< nprow
&& i
+ j
< nbytes
; j
++) {
209 shf_fprintf(kshdebug_shf
, "%c%02x", c
,
210 ((const unsigned char *) mem
)[i
+ j
]);
213 shf_fprintf(kshdebug_shf
, "\n");
215 shf_flush(kshdebug_shf
);
217 #endif /* KSH_DEBUG */
219 /* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */
225 return fstat(fd
, &statb
) == 0 && !S_ISREG(statb
.st_mode
) ?
229 struct shf shf_iob
[3];
234 shf_fdopen(1, SHF_WR
, shl_stdout
); /* force buffer allocation */
235 shf_fdopen(2, SHF_WR
, shl_out
);
236 shf_fdopen(2, SHF_WR
, shl_spare
); /* force buffer allocation */
241 /* A dup2() with error checking */
243 ksh_dup2(int ofd
, int nfd
, int errok
)
245 int ret
= dup2(ofd
, nfd
);
247 if (ret
< 0 && errno
!= EBADF
&& !errok
)
248 errorf("too many files open in shell");
254 * move fd from user space (0<=fd<10) to shell space (fd>=10),
255 * set close-on-exec flag.
263 nfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, FDBASE
);
268 errorf("too many files open in shell");
272 fcntl(nfd
, F_SETFD
, FD_CLOEXEC
);
278 restfd(int fd
, int ofd
)
281 shf_flush(&shf_iob
[fd
]);
282 if (ofd
< 0) /* original fd closed */
284 else if (fd
!= ofd
) {
285 ksh_dup2(ofd
, fd
, true); /* XXX: what to do if this fails? */
296 errorf("can't create pipe - try again");
297 pv
[0] = savefd(lpv
[0]);
300 pv
[1] = savefd(lpv
[1]);
312 /* Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn
313 * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor.
316 check_fd(char *name
, int mode
, const char **emsgp
)
320 if (isdigit((unsigned char)name
[0]) && !name
[1]) {
322 if ((fl
= fcntl(fd
, F_GETFL
)) < 0) {
324 *emsgp
= "bad file descriptor";
328 /* X_OK is a kludge to disable this check for dups (x<&1):
329 * historical shells never did this check (XXX don't know what
332 if (!(mode
& X_OK
) && fl
!= O_RDWR
&&
333 (((mode
& R_OK
) && fl
!= O_RDONLY
) ||
334 ((mode
& W_OK
) && fl
!= O_WRONLY
))) {
336 *emsgp
= (fl
== O_WRONLY
) ?
337 "fd not open for reading" :
338 "fd not open for writing";
342 } else if (name
[0] == 'p' && !name
[1])
343 return coproc_getfd(mode
, emsgp
);
345 *emsgp
= "illegal file descriptor name";
349 /* Called once from main */
353 coproc
.read
= coproc
.readw
= coproc
.write
= -1;
358 /* Called by c_read() when eof is read - close fd if it is the co-process fd */
360 coproc_read_close(int fd
)
362 if (coproc
.read
>= 0 && fd
== coproc
.read
) {
363 coproc_readw_close(fd
);
369 /* Called by c_read() and by iosetup() to close the other side of the
370 * read pipe, so reads will actually terminate.
373 coproc_readw_close(int fd
)
375 if (coproc
.readw
>= 0 && coproc
.read
>= 0 && fd
== coproc
.read
) {
381 /* Called by c_print when a write to a fd fails with EPIPE and by iosetup
382 * when co-process input is dup'd
385 coproc_write_close(int fd
)
387 if (coproc
.write
>= 0 && fd
== coproc
.write
) {
393 /* Called to check for existence of/value of the co-process file descriptor.
394 * (Used by check_fd() and by c_read/c_print to deal with -p option).
397 coproc_getfd(int mode
, const char **emsgp
)
399 int fd
= (mode
& R_OK
) ? coproc
.read
: coproc
.write
;
404 *emsgp
= "no coprocess";
408 /* called to close file descriptors related to the coprocess (if any)
409 * Should be called with SIGCHLD blocked.
412 coproc_cleanup(int reuse
)
414 /* This to allow co-processes to share output pipe */
415 if (!reuse
|| coproc
.readw
< 0 || coproc
.read
< 0) {
416 if (coproc
.read
>= 0) {
420 if (coproc
.readw
>= 0) {
425 if (coproc
.write
>= 0) {
437 maketemp(Area
*ap
, Temp_type type
, struct temp
**tlist
)
445 dir
= tmpdir
? tmpdir
: "/tmp";
446 /* The 20 + 20 is a paranoid worst case for pid/inc */
447 len
= strlen(dir
) + 3 + 20 + 20 + 1;
448 tp
= alloc(sizeof(struct temp
) + len
, ap
);
449 tp
->name
= path
= (char *) &tp
[1];
452 shf_snprintf(path
, len
, "%s/shXXXXXXXX", dir
);
455 tp
->shf
= shf_fdopen(fd
, SHF_WR
, NULL
);