1 /* $NetBSD: io.c,v 1.8 2004/07/07 19:20:09 mycroft Exp $ */
4 * shell buffered IO and formatted output
9 __RCSID("$NetBSD: io.c,v 1.8 2004/07/07 19:20:09 mycroft Exp $");
17 static int initio_done
;
20 * formatted output functions
24 /* A shell error occurred (eg, syntax error, etc.) */
26 #ifdef HAVE_PROTOTYPES
27 errorf(const char *fmt
, ...)
36 shl_stdout_ok
= 0; /* debugging: note that stdout not valid */
41 shf_vfprintf(shl_out
, fmt
, va
);
43 shf_putchar('\n', shl_out
);
49 /* like errorf(), but no unwind is done */
51 #ifdef HAVE_PROTOTYPES
52 warningf(int fileline
, const char *fmt
, ...)
54 warningf(fileline
, fmt
, va_alist
)
62 error_prefix(fileline
);
64 shf_vfprintf(shl_out
, fmt
, va
);
66 shf_putchar('\n', shl_out
);
70 /* Used by built-in utilities to prefix shell and utility name to message
71 * (also unwinds environments for special builtins).
74 #ifdef HAVE_PROTOTYPES
75 bi_errorf(const char *fmt
, ...)
77 bi_errorf(fmt
, va_alist
)
84 shl_stdout_ok
= 0; /* debugging: note that stdout not valid */
88 /* not set when main() calls parse_args() */
90 shf_fprintf(shl_out
, "%s: ", builtin_argv0
);
92 shf_vfprintf(shl_out
, fmt
, va
);
94 shf_putchar('\n', shl_out
);
97 /* POSIX special builtins and ksh special builtins cause
98 * non-interactive shells to exit.
99 * XXX odd use of KEEPASN; also may not want LERROR here
101 if ((builtin_flag
& SPEC_BI
)
102 || (Flag(FPOSIX
) && (builtin_flag
& KEEPASN
)))
104 builtin_argv0
= (char *) 0;
109 /* Called when something that shouldn't happen does */
111 #ifdef HAVE_PROTOTYPES
112 internal_errorf(int jump
, const char *fmt
, ...)
114 internal_errorf(jump
, fmt
, va_alist
)
123 shf_fprintf(shl_out
, "internal error: ");
124 SH_VA_START(va
, fmt
);
125 shf_vfprintf(shl_out
, fmt
, va
);
127 shf_putchar('\n', shl_out
);
133 /* used by error reporting functions to print "ksh: .kshrc[25]: " */
135 error_prefix(fileline
)
138 /* Avoid foo: foo[2]: ... */
139 if (!fileline
|| !source
|| !source
->file
140 || strcmp(source
->file
, kshname
) != 0)
141 shf_fprintf(shl_out
, "%s: ", kshname
+ (*kshname
== '-'));
142 if (fileline
&& source
&& source
->file
!= NULL
) {
143 shf_fprintf(shl_out
, "%s[%d]: ", source
->file
,
144 source
->errline
> 0 ? source
->errline
: source
->line
);
149 /* printf to shl_out (stderr) with flush */
151 #ifdef HAVE_PROTOTYPES
152 shellf(const char *fmt
, ...)
154 shellf(fmt
, va_alist
)
161 if (!initio_done
) /* shl_out may not be set up yet... */
163 SH_VA_START(va
, fmt
);
164 shf_vfprintf(shl_out
, fmt
, va
);
169 /* printf to shl_stdout (stdout) */
171 #ifdef HAVE_PROTOTYPES
172 shprintf(const char *fmt
, ...)
174 shprintf(fmt
, va_alist
)
182 internal_errorf(1, "shl_stdout not valid");
183 SH_VA_START(va
, fmt
);
184 shf_vfprintf(shl_stdout
, fmt
, va
);
189 static struct shf
*kshdebug_shf
;
195 shf_close(kshdebug_shf
);
196 kshdebug_shf
= shf_open("/tmp/ksh-debug.log",
197 O_WRONLY
|O_APPEND
|O_CREAT
, 0600,
200 shf_fprintf(kshdebug_shf
, "\nNew shell[pid %d]\n", getpid());
201 shf_flush(kshdebug_shf
);
205 /* print to debugging log */
207 # ifdef HAVE_PROTOTYPES
208 kshdebug_printf_(const char *fmt
, ...)
210 kshdebug_printf_(fmt
, va_alist
)
219 SH_VA_START(va
, fmt
);
220 shf_fprintf(kshdebug_shf
, "[%d] ", getpid());
221 shf_vfprintf(kshdebug_shf
, fmt
, va
);
223 shf_flush(kshdebug_shf
);
227 kshdebug_dump_(str
, mem
, nbytes
)
237 shf_fprintf(kshdebug_shf
, "[%d] %s:\n", getpid(), str
);
238 for (i
= 0; i
< nbytes
; i
+= nprow
) {
240 for (j
= 0; j
< nprow
&& i
+ j
< nbytes
; j
++) {
241 shf_fprintf(kshdebug_shf
, "%c%02x",
242 c
, ((const unsigned char *) mem
)[i
+ j
]);
245 shf_fprintf(kshdebug_shf
, "\n");
247 shf_flush(kshdebug_shf
);
249 #endif /* KSH_DEBUG */
251 /* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */
258 return fstat(fd
, &statb
) == 0 && !S_ISREG(statb
.st_mode
) ?
262 struct shf shf_iob
[3];
267 shf_fdopen(1, SHF_WR
, shl_stdout
); /* force buffer allocation */
268 shf_fdopen(2, SHF_WR
, shl_out
);
269 shf_fdopen(2, SHF_WR
, shl_spare
); /* force buffer allocation */
274 /* A dup2() with error checking */
276 ksh_dup2(ofd
, nfd
, errok
)
281 int ret
= dup2(ofd
, nfd
);
283 if (ret
< 0 && errno
!= EBADF
&& !errok
)
284 errorf("too many files open in shell");
287 /* Ultrix systems like to preserve the close-on-exec flag */
289 (void) fcntl(nfd
, F_SETFD
, 0);
290 #endif /* DUP2_BROKEN */
296 * move fd from user space (0<=fd<10) to shell space (fd>=10),
297 * set close-on-exec flag.
307 nfd
= ksh_dupbase(fd
, FDBASE
);
312 errorf("too many files open in shell");
327 shf_flush(&shf_iob
[fd
]);
328 if (ofd
< 0) /* original fd closed */
330 else if (fd
!= ofd
) {
331 ksh_dup2(ofd
, fd
, TRUE
); /* XXX: what to do if this fails? */
341 errorf("can't create pipe - try again");
342 pv
[0] = savefd(pv
[0], 0);
343 pv
[1] = savefd(pv
[1], 0);
354 /* Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn
355 * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor.
358 check_fd(name
, mode
, emsgp
)
365 if (isdigit((unsigned char)name
[0]) && !name
[1]) {
367 if ((fl
= fcntl(fd
= name
[0] - '0', F_GETFL
, 0)) < 0) {
369 *emsgp
= "bad file descriptor";
375 if (setmode(fd
, O_TEXT
) == -1) {
377 *emsgp
= "couldn't set write mode";
380 } else if (mode
== R_OK
)
381 if (setmode(fd
, O_BINARY
) == -1) {
383 *emsgp
= "couldn't set read mode";
387 /* X_OK is a kludge to disable this check for dups (x<&1):
388 * historical shells never did this check (XXX don't know what
391 if (!(mode
& X_OK
) && fl
!= O_RDWR
392 && (((mode
& R_OK
) && fl
!= O_RDONLY
)
393 || ((mode
& W_OK
) && fl
!= O_WRONLY
)))
396 *emsgp
= (fl
== O_WRONLY
) ?
397 "fd not open for reading"
398 : "fd not open for writing";
405 else if (name
[0] == 'p' && !name
[1])
406 return coproc_getfd(mode
, emsgp
);
409 *emsgp
= "illegal file descriptor name";
414 /* Called once from main */
418 coproc
.read
= coproc
.readw
= coproc
.write
= -1;
423 /* Called by c_read() when eof is read - close fd if it is the co-process fd */
425 coproc_read_close(fd
)
428 if (coproc
.read
>= 0 && fd
== coproc
.read
) {
429 coproc_readw_close(fd
);
435 /* Called by c_read() and by iosetup() to close the other side of the
436 * read pipe, so reads will actually terminate.
439 coproc_readw_close(fd
)
442 if (coproc
.readw
>= 0 && coproc
.read
>= 0 && fd
== coproc
.read
) {
448 /* Called by c_print when a write to a fd fails with EPIPE and by iosetup
449 * when co-process input is dup'd
452 coproc_write_close(fd
)
455 if (coproc
.write
>= 0 && fd
== coproc
.write
) {
461 /* Called to check for existence of/value of the co-process file descriptor.
462 * (Used by check_fd() and by c_read/c_print to deal with -p option).
465 coproc_getfd(mode
, emsgp
)
469 int fd
= (mode
& R_OK
) ? coproc
.read
: coproc
.write
;
474 *emsgp
= "no coprocess";
478 /* called to close file descriptors related to the coprocess (if any)
479 * Should be called with SIGCHLD blocked.
482 coproc_cleanup(reuse
)
485 /* This to allow co-processes to share output pipe */
486 if (!reuse
|| coproc
.readw
< 0 || coproc
.read
< 0) {
487 if (coproc
.read
>= 0) {
491 if (coproc
.readw
>= 0) {
496 if (coproc
.write
>= 0) {
509 maketemp(ap
, type
, tlist
)
515 static unsigned int inc
;
523 dir
= tmpdir
? tmpdir
: "/tmp";
524 /* The 20 + 20 is a paranoid worst case for pid/inc */
525 len
= strlen(dir
) + 3 + 20 + 20 + 1;
526 tp
= (struct temp
*) alloc(sizeof(struct temp
) + len
, ap
);
527 tp
->name
= pathx
= (char *) &tp
[1];
528 tp
->shf
= (struct shf
*) 0;
531 shf_snprintf(pathx
, len
, "%s/shXXXXXXXX", dir
);
534 tp
->shf
= shf_fdopen(fd
, SHF_WR
, (struct shf
*) 0);
537 /* Note that temp files need to fit 8.3 DOS limits */
538 shf_snprintf(pathx
, len
, "%s/sh%05u.%03x",
539 dir
, (unsigned) procpid
, inc
++);
540 /* Mode 0600 to be paranoid, O_TRUNC in case O_EXCL isn't
543 fd
= open(pathx
, O_RDWR
|O_CREAT
|O_EXCL
|O_TRUNC
, 0600);
545 tp
->shf
= shf_fdopen(fd
, SHF_WR
, (struct shf
*) 0);
556 /* Error must be printed by caller: don't know here if
557 * errorf() or bi_errorf() should be used.
561 #endif /* __NetBSD__ */