1 /* $OpenBSD: io.c,v 1.36 2018/01/16 22:52:32 jca Exp $ */
4 * shell buffered IO and formatted output
17 static int initio_done
;
20 * formatted output functions
24 /* A shell error occurred (eg, syntax error, etc.) */
26 errorf(const char *fmt
, ...)
30 shl_stdout_ok
= 0; /* debugging: note that stdout not valid */
32 if (fmt
!= NULL
&& *fmt
!= '\0') {
35 shf_vfprintf(shl_out
, fmt
, va
);
37 shf_putchar('\n', shl_out
);
43 /* like errorf(), but no unwind is done */
45 warningf(bool show_lineno
, const char *fmt
, ...)
49 error_prefix(show_lineno
);
51 shf_vfprintf(shl_out
, fmt
, va
);
53 shf_putchar('\n', shl_out
);
57 /* Used by built-in utilities to prefix shell and utility name to message
58 * (also unwinds environments for special builtins).
61 bi_errorf(const char *fmt
, ...)
65 shl_stdout_ok
= 0; /* debugging: note that stdout not valid */
67 if (fmt
!= NULL
&& *fmt
!= '\0') {
69 /* not set when main() calls parse_args() */
71 shf_fprintf(shl_out
, "%s: ", builtin_argv0
);
73 shf_vfprintf(shl_out
, fmt
, va
);
75 shf_putchar('\n', shl_out
);
78 /* POSIX special builtins and ksh special builtins cause
79 * non-interactive shells to exit.
80 * XXX odd use of KEEPASN; also may not want LERROR here
82 if ((builtin_flag
& SPEC_BI
) ||
83 (Flag(FPOSIX
) && (builtin_flag
& KEEPASN
))) {
90 internal_error_vwarn(const char *fmt
, va_list va
)
93 shf_fprintf(shl_out
, "internal error: ");
94 shf_vfprintf(shl_out
, fmt
, va
);
95 shf_putchar('\n', shl_out
);
99 /* Warn when something that shouldn't happen does */
101 internal_warningf(const char *fmt
, ...)
106 internal_error_vwarn(fmt
, va
);
110 /* Warn and unwind when something that shouldn't happen does */
112 internal_errorf(const char *fmt
, ...)
117 internal_error_vwarn(fmt
, va
);
122 /* used by error reporting functions to print "ksh: .kshrc[25]: " */
124 error_prefix(int fileline
)
126 /* Avoid foo: foo[2]: ... */
127 if (!fileline
|| !source
|| !source
->file
||
128 strcmp(source
->file
, kshname
) != 0)
129 shf_fprintf(shl_out
, "%s: ", kshname
+ (*kshname
== '-'));
130 if (fileline
&& source
&& source
->file
!= NULL
) {
131 shf_fprintf(shl_out
, "%s[%d]: ", source
->file
,
132 source
->errline
> 0 ? source
->errline
: source
->line
);
137 /* printf to shl_out (stderr) with flush */
139 shellf(const char *fmt
, ...)
143 if (!initio_done
) /* shl_out may not be set up yet... */
146 shf_vfprintf(shl_out
, fmt
, va
);
151 /* printf to shl_stdout (stdout) */
153 shprintf(const char *fmt
, ...)
158 internal_errorf("shl_stdout not valid");
160 shf_vfprintf(shl_stdout
, fmt
, va
);
165 static struct shf
*kshdebug_shf
;
171 shf_close(kshdebug_shf
);
172 kshdebug_shf
= shf_open("/tmp/ksh-debug.log",
173 O_WRONLY
|O_APPEND
|O_CREAT
, 0600, SHF_WR
|SHF_MAPHI
);
175 shf_fprintf(kshdebug_shf
, "\nNew shell[pid %d]\n", getpid());
176 shf_flush(kshdebug_shf
);
180 /* print to debugging log */
182 kshdebug_printf_(const char *fmt
, ...)
189 shf_fprintf(kshdebug_shf
, "[%d] ", getpid());
190 shf_vfprintf(kshdebug_shf
, fmt
, va
);
192 shf_flush(kshdebug_shf
);
196 kshdebug_dump_(const char *str
, const void *mem
, int nbytes
)
203 shf_fprintf(kshdebug_shf
, "[%d] %s:\n", getpid(), str
);
204 for (i
= 0; i
< nbytes
; i
+= nprow
) {
207 for (j
= 0; j
< nprow
&& i
+ j
< nbytes
; j
++) {
208 shf_fprintf(kshdebug_shf
, "%c%02x", c
,
209 ((const unsigned char *) mem
)[i
+ j
]);
212 shf_fprintf(kshdebug_shf
, "\n");
214 shf_flush(kshdebug_shf
);
216 #endif /* KSH_DEBUG */
218 /* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */
224 return fstat(fd
, &statb
) == 0 && !S_ISREG(statb
.st_mode
) ?
228 struct shf shf_iob
[3];
233 shf_fdopen(1, SHF_WR
, shl_stdout
); /* force buffer allocation */
234 shf_fdopen(2, SHF_WR
, shl_out
);
235 shf_fdopen(2, SHF_WR
, shl_spare
); /* force buffer allocation */
240 /* A dup2() with error checking */
242 ksh_dup2(int ofd
, int nfd
, int errok
)
244 int ret
= dup2(ofd
, nfd
);
246 if (ret
< 0 && errno
!= EBADF
&& !errok
)
247 errorf("too many files open in shell");
253 * move fd from user space (0<=fd<10) to shell space (fd>=10),
254 * set close-on-exec flag.
262 nfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, FDBASE
);
267 errorf("too many files open in shell");
271 fcntl(nfd
, F_SETFD
, FD_CLOEXEC
);
277 restfd(int fd
, int ofd
)
280 shf_flush(&shf_iob
[fd
]);
281 if (ofd
< 0) /* original fd closed */
283 else if (fd
!= ofd
) {
284 ksh_dup2(ofd
, fd
, true); /* XXX: what to do if this fails? */
295 errorf("can't create pipe - try again");
296 pv
[0] = savefd(lpv
[0]);
299 pv
[1] = savefd(lpv
[1]);
311 /* Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn
312 * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor.
315 check_fd(char *name
, int mode
, const char **emsgp
)
319 if (isdigit((unsigned char)name
[0]) && !name
[1]) {
321 if ((fl
= fcntl(fd
, F_GETFL
)) < 0) {
323 *emsgp
= "bad file descriptor";
327 /* X_OK is a kludge to disable this check for dups (x<&1):
328 * historical shells never did this check (XXX don't know what
331 if (!(mode
& X_OK
) && fl
!= O_RDWR
&&
332 (((mode
& R_OK
) && fl
!= O_RDONLY
) ||
333 ((mode
& W_OK
) && fl
!= O_WRONLY
))) {
335 *emsgp
= (fl
== O_WRONLY
) ?
336 "fd not open for reading" :
337 "fd not open for writing";
341 } else if (name
[0] == 'p' && !name
[1])
342 return coproc_getfd(mode
, emsgp
);
344 *emsgp
= "illegal file descriptor name";
348 /* Called once from main */
352 coproc
.read
= coproc
.readw
= coproc
.write
= -1;
357 /* Called by c_read() when eof is read - close fd if it is the co-process fd */
359 coproc_read_close(int fd
)
361 if (coproc
.read
>= 0 && fd
== coproc
.read
) {
362 coproc_readw_close(fd
);
368 /* Called by c_read() and by iosetup() to close the other side of the
369 * read pipe, so reads will actually terminate.
372 coproc_readw_close(int fd
)
374 if (coproc
.readw
>= 0 && coproc
.read
>= 0 && fd
== coproc
.read
) {
380 /* Called by c_print when a write to a fd fails with EPIPE and by iosetup
381 * when co-process input is dup'd
384 coproc_write_close(int fd
)
386 if (coproc
.write
>= 0 && fd
== coproc
.write
) {
392 /* Called to check for existence of/value of the co-process file descriptor.
393 * (Used by check_fd() and by c_read/c_print to deal with -p option).
396 coproc_getfd(int mode
, const char **emsgp
)
398 int fd
= (mode
& R_OK
) ? coproc
.read
: coproc
.write
;
403 *emsgp
= "no coprocess";
407 /* called to close file descriptors related to the coprocess (if any)
408 * Should be called with SIGCHLD blocked.
411 coproc_cleanup(int reuse
)
413 /* This to allow co-processes to share output pipe */
414 if (!reuse
|| coproc
.readw
< 0 || coproc
.read
< 0) {
415 if (coproc
.read
>= 0) {
419 if (coproc
.readw
>= 0) {
424 if (coproc
.write
>= 0) {
436 maketemp(Area
*ap
, Temp_type type
, struct temp
**tlist
)
444 dir
= tmpdir
? tmpdir
: "/tmp";
445 /* The 20 + 20 is a paranoid worst case for pid/inc */
446 len
= strlen(dir
) + 3 + 20 + 20 + 1;
447 tp
= alloc(sizeof(struct temp
) + len
, ap
);
448 tp
->name
= path
= (char *) &tp
[1];
451 shf_snprintf(path
, len
, "%s/shXXXXXXXX", dir
);
454 tp
->shf
= shf_fdopen(fd
, SHF_WR
, NULL
);