1*61e6c220Smpech /* $OpenBSD: io.c,v 1.10 2001/09/19 10:58:07 mpech Exp $ */ 27cb960a2Sdownsj 37cb960a2Sdownsj /* 47cb960a2Sdownsj * shell buffered IO and formatted output 57cb960a2Sdownsj */ 67cb960a2Sdownsj 77cb960a2Sdownsj #include <ctype.h> 87cb960a2Sdownsj #include "sh.h" 97cb960a2Sdownsj #include "ksh_stat.h" 107cb960a2Sdownsj 113b015934Smillert static int initio_done; 123b015934Smillert 137cb960a2Sdownsj /* 147cb960a2Sdownsj * formatted output functions 157cb960a2Sdownsj */ 167cb960a2Sdownsj 177cb960a2Sdownsj 18*61e6c220Smpech /* A shell error occurred (eg, syntax error, etc.) */ 197cb960a2Sdownsj void 207cb960a2Sdownsj #ifdef HAVE_PROTOTYPES 217cb960a2Sdownsj errorf(const char *fmt, ...) 227cb960a2Sdownsj #else 237cb960a2Sdownsj errorf(fmt, va_alist) 247cb960a2Sdownsj const char *fmt; 257cb960a2Sdownsj va_dcl 267cb960a2Sdownsj #endif 277cb960a2Sdownsj { 287cb960a2Sdownsj va_list va; 297cb960a2Sdownsj 307cb960a2Sdownsj shl_stdout_ok = 0; /* debugging: note that stdout not valid */ 317cb960a2Sdownsj exstat = 1; 327cb960a2Sdownsj if (*fmt) { 337cb960a2Sdownsj error_prefix(TRUE); 347cb960a2Sdownsj SH_VA_START(va, fmt); 357cb960a2Sdownsj shf_vfprintf(shl_out, fmt, va); 367cb960a2Sdownsj va_end(va); 377cb960a2Sdownsj shf_putchar('\n', shl_out); 387cb960a2Sdownsj } 397cb960a2Sdownsj shf_flush(shl_out); 407cb960a2Sdownsj unwind(LERROR); 417cb960a2Sdownsj } 427cb960a2Sdownsj 437cb960a2Sdownsj /* like errorf(), but no unwind is done */ 447cb960a2Sdownsj void 457cb960a2Sdownsj #ifdef HAVE_PROTOTYPES 467cb960a2Sdownsj warningf(int fileline, const char *fmt, ...) 477cb960a2Sdownsj #else 487cb960a2Sdownsj warningf(fileline, fmt, va_alist) 497cb960a2Sdownsj int fileline; 507cb960a2Sdownsj const char *fmt; 517cb960a2Sdownsj va_dcl 527cb960a2Sdownsj #endif 537cb960a2Sdownsj { 547cb960a2Sdownsj va_list va; 557cb960a2Sdownsj 567cb960a2Sdownsj error_prefix(fileline); 577cb960a2Sdownsj SH_VA_START(va, fmt); 587cb960a2Sdownsj shf_vfprintf(shl_out, fmt, va); 597cb960a2Sdownsj va_end(va); 607cb960a2Sdownsj shf_putchar('\n', shl_out); 617cb960a2Sdownsj shf_flush(shl_out); 627cb960a2Sdownsj } 637cb960a2Sdownsj 647cb960a2Sdownsj /* Used by built-in utilities to prefix shell and utility name to message 657cb960a2Sdownsj * (also unwinds environments for special builtins). 667cb960a2Sdownsj */ 677cb960a2Sdownsj void 687cb960a2Sdownsj #ifdef HAVE_PROTOTYPES 697cb960a2Sdownsj bi_errorf(const char *fmt, ...) 707cb960a2Sdownsj #else 717cb960a2Sdownsj bi_errorf(fmt, va_alist) 727cb960a2Sdownsj const char *fmt; 737cb960a2Sdownsj va_dcl 747cb960a2Sdownsj #endif 757cb960a2Sdownsj { 767cb960a2Sdownsj va_list va; 777cb960a2Sdownsj 787cb960a2Sdownsj shl_stdout_ok = 0; /* debugging: note that stdout not valid */ 797cb960a2Sdownsj exstat = 1; 807cb960a2Sdownsj if (*fmt) { 817cb960a2Sdownsj error_prefix(TRUE); 827cb960a2Sdownsj /* not set when main() calls parse_args() */ 837cb960a2Sdownsj if (builtin_argv0) 847cb960a2Sdownsj shf_fprintf(shl_out, "%s: ", builtin_argv0); 857cb960a2Sdownsj SH_VA_START(va, fmt); 867cb960a2Sdownsj shf_vfprintf(shl_out, fmt, va); 877cb960a2Sdownsj va_end(va); 887cb960a2Sdownsj shf_putchar('\n', shl_out); 897cb960a2Sdownsj } 907cb960a2Sdownsj shf_flush(shl_out); 917cb960a2Sdownsj /* POSIX special builtins and ksh special builtins cause 927cb960a2Sdownsj * non-interactive shells to exit. 937cb960a2Sdownsj * XXX odd use of KEEPASN; also may not want LERROR here 947cb960a2Sdownsj */ 957cb960a2Sdownsj if ((builtin_flag & SPEC_BI) 967cb960a2Sdownsj || (Flag(FPOSIX) && (builtin_flag & KEEPASN))) 977cb960a2Sdownsj { 984c69a2c1Skstailey builtin_argv0 = (char *) 0; 997cb960a2Sdownsj unwind(LERROR); 1007cb960a2Sdownsj } 1017cb960a2Sdownsj } 1027cb960a2Sdownsj 1037cb960a2Sdownsj /* Called when something that shouldn't happen does */ 1047cb960a2Sdownsj void 1057cb960a2Sdownsj #ifdef HAVE_PROTOTYPES 1067cb960a2Sdownsj internal_errorf(int jump, const char *fmt, ...) 1077cb960a2Sdownsj #else 1087cb960a2Sdownsj internal_errorf(jump, fmt, va_alist) 1097cb960a2Sdownsj int jump; 1107cb960a2Sdownsj const char *fmt; 1117cb960a2Sdownsj va_dcl 1127cb960a2Sdownsj #endif 1137cb960a2Sdownsj { 1147cb960a2Sdownsj va_list va; 1157cb960a2Sdownsj 1167cb960a2Sdownsj error_prefix(TRUE); 1177cb960a2Sdownsj shf_fprintf(shl_out, "internal error: "); 1187cb960a2Sdownsj SH_VA_START(va, fmt); 1197cb960a2Sdownsj shf_vfprintf(shl_out, fmt, va); 1207cb960a2Sdownsj va_end(va); 1217cb960a2Sdownsj shf_putchar('\n', shl_out); 1227cb960a2Sdownsj shf_flush(shl_out); 1237cb960a2Sdownsj if (jump) 1247cb960a2Sdownsj unwind(LERROR); 1257cb960a2Sdownsj } 1267cb960a2Sdownsj 1277cb960a2Sdownsj /* used by error reporting functions to print "ksh: .kshrc[25]: " */ 1287cb960a2Sdownsj void 1297cb960a2Sdownsj error_prefix(fileline) 1307cb960a2Sdownsj int fileline; 1317cb960a2Sdownsj { 1323b015934Smillert /* Avoid foo: foo[2]: ... */ 1333b015934Smillert if (!fileline || !source || !source->file 1343b015934Smillert || strcmp(source->file, kshname) != 0) 1357cb960a2Sdownsj shf_fprintf(shl_out, "%s: ", kshname + (*kshname == '-')); 1367cb960a2Sdownsj if (fileline && source && source->file != NULL) { 1377cb960a2Sdownsj shf_fprintf(shl_out, "%s[%d]: ", source->file, 1387cb960a2Sdownsj source->errline > 0 ? source->errline : source->line); 1397cb960a2Sdownsj source->errline = 0; 1407cb960a2Sdownsj } 1417cb960a2Sdownsj } 1427cb960a2Sdownsj 1437cb960a2Sdownsj /* printf to shl_out (stderr) with flush */ 1447cb960a2Sdownsj void 1457cb960a2Sdownsj #ifdef HAVE_PROTOTYPES 1467cb960a2Sdownsj shellf(const char *fmt, ...) 1477cb960a2Sdownsj #else 1487cb960a2Sdownsj shellf(fmt, va_alist) 1497cb960a2Sdownsj const char *fmt; 1507cb960a2Sdownsj va_dcl 1517cb960a2Sdownsj #endif 1527cb960a2Sdownsj { 1537cb960a2Sdownsj va_list va; 1547cb960a2Sdownsj 1553b015934Smillert if (!initio_done) /* shl_out may not be set up yet... */ 1563b015934Smillert return; 1577cb960a2Sdownsj SH_VA_START(va, fmt); 1587cb960a2Sdownsj shf_vfprintf(shl_out, fmt, va); 1597cb960a2Sdownsj va_end(va); 1607cb960a2Sdownsj shf_flush(shl_out); 1617cb960a2Sdownsj } 1627cb960a2Sdownsj 1637cb960a2Sdownsj /* printf to shl_stdout (stdout) */ 1647cb960a2Sdownsj void 1657cb960a2Sdownsj #ifdef HAVE_PROTOTYPES 1667cb960a2Sdownsj shprintf(const char *fmt, ...) 1677cb960a2Sdownsj #else 1687cb960a2Sdownsj shprintf(fmt, va_alist) 1697cb960a2Sdownsj const char *fmt; 1707cb960a2Sdownsj va_dcl 1717cb960a2Sdownsj #endif 1727cb960a2Sdownsj { 1737cb960a2Sdownsj va_list va; 1747cb960a2Sdownsj 1757cb960a2Sdownsj if (!shl_stdout_ok) 1767cb960a2Sdownsj internal_errorf(1, "shl_stdout not valid"); 1777cb960a2Sdownsj SH_VA_START(va, fmt); 1787cb960a2Sdownsj shf_vfprintf(shl_stdout, fmt, va); 1797cb960a2Sdownsj va_end(va); 1807cb960a2Sdownsj } 1817cb960a2Sdownsj 182945abdecSmillert #ifdef KSH_DEBUG 183945abdecSmillert static struct shf *kshdebug_shf; 184945abdecSmillert 185945abdecSmillert void 186945abdecSmillert kshdebug_init_() 187945abdecSmillert { 188945abdecSmillert if (kshdebug_shf) 189945abdecSmillert shf_close(kshdebug_shf); 190945abdecSmillert kshdebug_shf = shf_open("/tmp/ksh-debug.log", 191945abdecSmillert O_WRONLY|O_APPEND|O_CREAT, 0600, 192945abdecSmillert SHF_WR|SHF_MAPHI); 193945abdecSmillert if (kshdebug_shf) { 194945abdecSmillert shf_fprintf(kshdebug_shf, "\nNew shell[pid %d]\n", getpid()); 195945abdecSmillert shf_flush(kshdebug_shf); 196945abdecSmillert } 197945abdecSmillert } 198945abdecSmillert 199945abdecSmillert /* print to debugging log */ 200945abdecSmillert void 201945abdecSmillert # ifdef HAVE_PROTOTYPES 202945abdecSmillert kshdebug_printf_(const char *fmt, ...) 203945abdecSmillert # else 204945abdecSmillert kshdebug_printf_(fmt, va_alist) 205945abdecSmillert const char *fmt; 206945abdecSmillert va_dcl 207945abdecSmillert # endif 208945abdecSmillert { 209945abdecSmillert va_list va; 210945abdecSmillert 211945abdecSmillert if (!kshdebug_shf) 212945abdecSmillert return; 213945abdecSmillert SH_VA_START(va, fmt); 214945abdecSmillert shf_fprintf(kshdebug_shf, "[%d] ", getpid()); 215945abdecSmillert shf_vfprintf(kshdebug_shf, fmt, va); 216945abdecSmillert va_end(va); 217945abdecSmillert shf_flush(kshdebug_shf); 218945abdecSmillert } 219945abdecSmillert 220945abdecSmillert void 221945abdecSmillert kshdebug_dump_(str, mem, nbytes) 222945abdecSmillert const char *str; 223945abdecSmillert const void *mem; 224945abdecSmillert int nbytes; 225945abdecSmillert { 226945abdecSmillert int i, j; 227945abdecSmillert int nprow = 16; 228945abdecSmillert 229945abdecSmillert if (!kshdebug_shf) 230945abdecSmillert return; 231945abdecSmillert shf_fprintf(kshdebug_shf, "[%d] %s:\n", getpid(), str); 232945abdecSmillert for (i = 0; i < nbytes; i += nprow) { 233945abdecSmillert char c = '\t'; 234945abdecSmillert for (j = 0; j < nprow && i + j < nbytes; j++) { 235945abdecSmillert shf_fprintf(kshdebug_shf, "%c%02x", 236945abdecSmillert c, ((const unsigned char *) mem)[i + j]); 237945abdecSmillert c = ' '; 238945abdecSmillert } 239945abdecSmillert shf_fprintf(kshdebug_shf, "\n"); 240945abdecSmillert } 241945abdecSmillert shf_flush(kshdebug_shf); 242945abdecSmillert } 243945abdecSmillert #endif /* KSH_DEBUG */ 244945abdecSmillert 2457cb960a2Sdownsj /* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */ 2467cb960a2Sdownsj int 2477cb960a2Sdownsj can_seek(fd) 2487cb960a2Sdownsj int fd; 2497cb960a2Sdownsj { 2507cb960a2Sdownsj struct stat statb; 2517cb960a2Sdownsj 2527cb960a2Sdownsj return fstat(fd, &statb) == 0 && !S_ISREG(statb.st_mode) ? 2537cb960a2Sdownsj SHF_UNBUF : 0; 2547cb960a2Sdownsj } 2557cb960a2Sdownsj 2567cb960a2Sdownsj struct shf shf_iob[3]; 2577cb960a2Sdownsj 2587cb960a2Sdownsj void 2597cb960a2Sdownsj initio() 2607cb960a2Sdownsj { 2617cb960a2Sdownsj shf_fdopen(1, SHF_WR, shl_stdout); /* force buffer allocation */ 2627cb960a2Sdownsj shf_fdopen(2, SHF_WR, shl_out); 2637cb960a2Sdownsj shf_fdopen(2, SHF_WR, shl_spare); /* force buffer allocation */ 2643b015934Smillert initio_done = 1; 265945abdecSmillert kshdebug_init(); 2667cb960a2Sdownsj } 2677cb960a2Sdownsj 2687cb960a2Sdownsj /* A dup2() with error checking */ 2697cb960a2Sdownsj int 2707cb960a2Sdownsj ksh_dup2(ofd, nfd, errok) 2717cb960a2Sdownsj int ofd; 2727cb960a2Sdownsj int nfd; 2737cb960a2Sdownsj int errok; 2747cb960a2Sdownsj { 2757cb960a2Sdownsj int ret = dup2(ofd, nfd); 2767cb960a2Sdownsj 2777cb960a2Sdownsj if (ret < 0 && errno != EBADF && !errok) 2787cb960a2Sdownsj errorf("too many files open in shell"); 2797cb960a2Sdownsj 2807cb960a2Sdownsj #ifdef DUP2_BROKEN 2817cb960a2Sdownsj /* Ultrix systems like to preserve the close-on-exec flag */ 2827cb960a2Sdownsj if (ret >= 0) 2837cb960a2Sdownsj (void) fcntl(nfd, F_SETFD, 0); 2847cb960a2Sdownsj #endif /* DUP2_BROKEN */ 2857cb960a2Sdownsj 2867cb960a2Sdownsj return ret; 2877cb960a2Sdownsj } 2887cb960a2Sdownsj 2897cb960a2Sdownsj /* 2907cb960a2Sdownsj * move fd from user space (0<=fd<10) to shell space (fd>=10), 2917cb960a2Sdownsj * set close-on-exec flag. 2927cb960a2Sdownsj */ 2937cb960a2Sdownsj int 2947cb960a2Sdownsj savefd(fd, noclose) 2957cb960a2Sdownsj int fd; 2967cb960a2Sdownsj int noclose; 2977cb960a2Sdownsj { 2987cb960a2Sdownsj int nfd; 2997cb960a2Sdownsj 3007cb960a2Sdownsj if (fd < FDBASE) { 3017cb960a2Sdownsj nfd = ksh_dupbase(fd, FDBASE); 30218bbba6bSmillert if (nfd < 0) { 3037cb960a2Sdownsj if (errno == EBADF) 3047cb960a2Sdownsj return -1; 3057cb960a2Sdownsj else 3067cb960a2Sdownsj errorf("too many files open in shell"); 30718bbba6bSmillert } 3087cb960a2Sdownsj if (!noclose) 3097cb960a2Sdownsj close(fd); 3107cb960a2Sdownsj } else 3117cb960a2Sdownsj nfd = fd; 3127cb960a2Sdownsj fd_clexec(nfd); 3137cb960a2Sdownsj return nfd; 3147cb960a2Sdownsj } 3157cb960a2Sdownsj 3167cb960a2Sdownsj void 3177cb960a2Sdownsj restfd(fd, ofd) 3187cb960a2Sdownsj int fd, ofd; 3197cb960a2Sdownsj { 3207cb960a2Sdownsj if (fd == 2) 3217cb960a2Sdownsj shf_flush(&shf_iob[fd]); 3227cb960a2Sdownsj if (ofd < 0) /* original fd closed */ 3237cb960a2Sdownsj close(fd); 3247cb960a2Sdownsj else { 3257cb960a2Sdownsj ksh_dup2(ofd, fd, TRUE); /* XXX: what to do if this fails? */ 3267cb960a2Sdownsj close(ofd); 3277cb960a2Sdownsj } 3287cb960a2Sdownsj } 3297cb960a2Sdownsj 3307cb960a2Sdownsj void 3317cb960a2Sdownsj openpipe(pv) 3327cb960a2Sdownsj register int *pv; 3337cb960a2Sdownsj { 3347cb960a2Sdownsj if (pipe(pv) < 0) 3357cb960a2Sdownsj errorf("can't create pipe - try again"); 3367cb960a2Sdownsj pv[0] = savefd(pv[0], 0); 3377cb960a2Sdownsj pv[1] = savefd(pv[1], 0); 3387cb960a2Sdownsj } 3397cb960a2Sdownsj 3407cb960a2Sdownsj void 3417cb960a2Sdownsj closepipe(pv) 3427cb960a2Sdownsj register int *pv; 3437cb960a2Sdownsj { 3447cb960a2Sdownsj close(pv[0]); 3457cb960a2Sdownsj close(pv[1]); 3467cb960a2Sdownsj } 3477cb960a2Sdownsj 3487cb960a2Sdownsj /* Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn 3497cb960a2Sdownsj * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor. 3507cb960a2Sdownsj */ 3517cb960a2Sdownsj int 3527cb960a2Sdownsj check_fd(name, mode, emsgp) 3537cb960a2Sdownsj char *name; 3547cb960a2Sdownsj int mode; 3557cb960a2Sdownsj const char **emsgp; 3567cb960a2Sdownsj { 3577cb960a2Sdownsj int fd, fl; 3587cb960a2Sdownsj 3597cb960a2Sdownsj if (isdigit(name[0]) && !name[1]) { 3607cb960a2Sdownsj fd = name[0] - '0'; 3617cb960a2Sdownsj if ((fl = fcntl(fd = name[0] - '0', F_GETFL, 0)) < 0) { 3627cb960a2Sdownsj if (emsgp) 3637cb960a2Sdownsj *emsgp = "bad file descriptor"; 3647cb960a2Sdownsj return -1; 3657cb960a2Sdownsj } 3667cb960a2Sdownsj fl &= O_ACCMODE; 3677cb960a2Sdownsj #ifdef OS2 3687cb960a2Sdownsj if (mode == W_OK ) { 3697cb960a2Sdownsj if (setmode(fd, O_TEXT) == -1) { 3707cb960a2Sdownsj if (emsgp) 3717cb960a2Sdownsj *emsgp = "couldn't set write mode"; 3727cb960a2Sdownsj return -1; 3737cb960a2Sdownsj } 3747cb960a2Sdownsj } else if (mode == R_OK) 3757cb960a2Sdownsj if (setmode(fd, O_BINARY) == -1) { 3767cb960a2Sdownsj if (emsgp) 3777cb960a2Sdownsj *emsgp = "couldn't set read mode"; 3787cb960a2Sdownsj return -1; 3797cb960a2Sdownsj } 3807cb960a2Sdownsj #else /* OS2 */ 3817cb960a2Sdownsj /* X_OK is a kludge to disable this check for dups (x<&1): 3827cb960a2Sdownsj * historical shells never did this check (XXX don't know what 3837cb960a2Sdownsj * posix has to say). 3847cb960a2Sdownsj */ 3857cb960a2Sdownsj if (!(mode & X_OK) && fl != O_RDWR 3867cb960a2Sdownsj && (((mode & R_OK) && fl != O_RDONLY) 3877cb960a2Sdownsj || ((mode & W_OK) && fl != O_WRONLY))) 3887cb960a2Sdownsj { 3897cb960a2Sdownsj if (emsgp) 3907cb960a2Sdownsj *emsgp = (fl == O_WRONLY) ? 3917cb960a2Sdownsj "fd not open for reading" 3927cb960a2Sdownsj : "fd not open for writing"; 3937cb960a2Sdownsj return -1; 3947cb960a2Sdownsj } 3957cb960a2Sdownsj #endif /* OS2 */ 3967cb960a2Sdownsj return fd; 3977cb960a2Sdownsj } 3987cb960a2Sdownsj #ifdef KSH 3997cb960a2Sdownsj else if (name[0] == 'p' && !name[1]) 400dcacb757Sdownsj return coproc_getfd(mode, emsgp); 4017cb960a2Sdownsj #endif /* KSH */ 4027cb960a2Sdownsj if (emsgp) 4037cb960a2Sdownsj *emsgp = "illegal file descriptor name"; 4047cb960a2Sdownsj return -1; 4057cb960a2Sdownsj } 4067cb960a2Sdownsj 4077cb960a2Sdownsj #ifdef KSH 4087cb960a2Sdownsj /* Called once from main */ 4097cb960a2Sdownsj void 4107cb960a2Sdownsj coproc_init() 4117cb960a2Sdownsj { 4127cb960a2Sdownsj coproc.read = coproc.readw = coproc.write = -1; 413dcacb757Sdownsj coproc.njobs = 0; 414dcacb757Sdownsj coproc.id = 0; 4157cb960a2Sdownsj } 4167cb960a2Sdownsj 4177cb960a2Sdownsj /* Called by c_read() when eof is read - close fd if it is the co-process fd */ 4187cb960a2Sdownsj void 4197cb960a2Sdownsj coproc_read_close(fd) 4207cb960a2Sdownsj int fd; 4217cb960a2Sdownsj { 4227cb960a2Sdownsj if (coproc.read >= 0 && fd == coproc.read) { 423dcacb757Sdownsj coproc_readw_close(fd); 4247cb960a2Sdownsj close(coproc.read); 4257cb960a2Sdownsj coproc.read = -1; 4267cb960a2Sdownsj } 4277cb960a2Sdownsj } 4287cb960a2Sdownsj 4297cb960a2Sdownsj /* Called by c_read() and by iosetup() to close the other side of the 4307cb960a2Sdownsj * read pipe, so reads will actually terminate. 4317cb960a2Sdownsj */ 4327cb960a2Sdownsj void 4337cb960a2Sdownsj coproc_readw_close(fd) 4347cb960a2Sdownsj int fd; 4357cb960a2Sdownsj { 436dcacb757Sdownsj if (coproc.readw >= 0 && coproc.read >= 0 && fd == coproc.read) { 4377cb960a2Sdownsj close(coproc.readw); 4387cb960a2Sdownsj coproc.readw = -1; 4397cb960a2Sdownsj } 4407cb960a2Sdownsj } 4417cb960a2Sdownsj 4427cb960a2Sdownsj /* Called by c_print when a write to a fd fails with EPIPE and by iosetup 4437cb960a2Sdownsj * when co-process input is dup'd 4447cb960a2Sdownsj */ 4457cb960a2Sdownsj void 4467cb960a2Sdownsj coproc_write_close(fd) 4477cb960a2Sdownsj int fd; 4487cb960a2Sdownsj { 4497cb960a2Sdownsj if (coproc.write >= 0 && fd == coproc.write) { 4507cb960a2Sdownsj close(coproc.write); 4517cb960a2Sdownsj coproc.write = -1; 4527cb960a2Sdownsj } 4537cb960a2Sdownsj } 4547cb960a2Sdownsj 4557cb960a2Sdownsj /* Called to check for existance of/value of the co-process file descriptor. 4567cb960a2Sdownsj * (Used by check_fd() and by c_read/c_print to deal with -p option). 4577cb960a2Sdownsj */ 4587cb960a2Sdownsj int 459dcacb757Sdownsj coproc_getfd(mode, emsgp) 4607cb960a2Sdownsj int mode; 4617cb960a2Sdownsj const char **emsgp; 4627cb960a2Sdownsj { 4637cb960a2Sdownsj int fd = (mode & R_OK) ? coproc.read : coproc.write; 4647cb960a2Sdownsj 4657cb960a2Sdownsj if (fd >= 0) 4667cb960a2Sdownsj return fd; 4677cb960a2Sdownsj if (emsgp) 4687cb960a2Sdownsj *emsgp = "no coprocess"; 4697cb960a2Sdownsj return -1; 4707cb960a2Sdownsj } 4717cb960a2Sdownsj 472dcacb757Sdownsj /* called to close file descriptors related to the coprocess (if any) 473dcacb757Sdownsj * Should be called with SIGCHLD blocked. 474dcacb757Sdownsj */ 4757cb960a2Sdownsj void 476dcacb757Sdownsj coproc_cleanup(reuse) 4777cb960a2Sdownsj int reuse; 4787cb960a2Sdownsj { 4797cb960a2Sdownsj /* This to allow co-processes to share output pipe */ 4807cb960a2Sdownsj if (!reuse || coproc.readw < 0 || coproc.read < 0) { 4817cb960a2Sdownsj if (coproc.read >= 0) { 4827cb960a2Sdownsj close(coproc.read); 4837cb960a2Sdownsj coproc.read = -1; 4847cb960a2Sdownsj } 4857cb960a2Sdownsj if (coproc.readw >= 0) { 4867cb960a2Sdownsj close(coproc.readw); 4877cb960a2Sdownsj coproc.readw = -1; 4887cb960a2Sdownsj } 4897cb960a2Sdownsj } 4907cb960a2Sdownsj if (coproc.write >= 0) { 4917cb960a2Sdownsj close(coproc.write); 4927cb960a2Sdownsj coproc.write = -1; 4937cb960a2Sdownsj } 4947cb960a2Sdownsj } 4957cb960a2Sdownsj #endif /* KSH */ 4967cb960a2Sdownsj 497f00c5086Smillert 4987cb960a2Sdownsj /* 4997cb960a2Sdownsj * temporary files 5007cb960a2Sdownsj */ 5017cb960a2Sdownsj 5027cb960a2Sdownsj struct temp * 503f00c5086Smillert maketemp(ap, type, tlist) 5047cb960a2Sdownsj Area *ap; 505f00c5086Smillert Temp_type type; 506f00c5086Smillert struct temp **tlist; 5077cb960a2Sdownsj { 5087cb960a2Sdownsj static unsigned int inc; 5097cb960a2Sdownsj struct temp *tp; 5107cb960a2Sdownsj int len; 5117cb960a2Sdownsj int fd; 5127cb960a2Sdownsj char *path; 513f00c5086Smillert const char *dir; 5147cb960a2Sdownsj 515f00c5086Smillert dir = tmpdir ? tmpdir : "/tmp"; 5167cb960a2Sdownsj /* The 20 + 20 is a paranoid worst case for pid/inc */ 517f00c5086Smillert len = strlen(dir) + 3 + 20 + 20 + 1; 5187cb960a2Sdownsj tp = (struct temp *) alloc(sizeof(struct temp) + len, ap); 5197cb960a2Sdownsj tp->name = path = (char *) &tp[1]; 5204c69a2c1Skstailey tp->shf = (struct shf *) 0; 521f00c5086Smillert tp->type = type; 5224a5d53a7Smillert #ifdef __OpenBSD__ 5234a5d53a7Smillert shf_snprintf(path, len, "%s/shXXXXXXXX", dir); 5244a5d53a7Smillert fd = mkstemp(path); 5254a5d53a7Smillert if (fd >= 0) 5264a5d53a7Smillert tp->shf = shf_fdopen(fd, SHF_WR, (struct shf *) 0); 5274a5d53a7Smillert #else 5287cb960a2Sdownsj while (1) { 5297cb960a2Sdownsj /* Note that temp files need to fit 8.3 DOS limits */ 5307cb960a2Sdownsj shf_snprintf(path, len, "%s/sh%05u.%03x", 531f00c5086Smillert dir, (unsigned) procpid, inc++); 5327cb960a2Sdownsj /* Mode 0600 to be paranoid, O_TRUNC in case O_EXCL isn't 5337cb960a2Sdownsj * really there. 5347cb960a2Sdownsj */ 5357cb960a2Sdownsj fd = open(path, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600); 5367cb960a2Sdownsj if (fd >= 0) { 5374c69a2c1Skstailey tp->shf = shf_fdopen(fd, SHF_WR, (struct shf *) 0); 5387cb960a2Sdownsj break; 5397cb960a2Sdownsj } 5407cb960a2Sdownsj if (errno != EINTR 5417cb960a2Sdownsj #ifdef EEXIST 5427cb960a2Sdownsj && errno != EEXIST 5437cb960a2Sdownsj #endif /* EEXIST */ 5447cb960a2Sdownsj #ifdef EISDIR 5457cb960a2Sdownsj && errno != EISDIR 5467cb960a2Sdownsj #endif /* EISDIR */ 5477cb960a2Sdownsj ) 548f00c5086Smillert /* Error must be printed by caller: don't know here if 5497cb960a2Sdownsj * errorf() or bi_errorf() should be used. 5507cb960a2Sdownsj */ 5517cb960a2Sdownsj break; 5527cb960a2Sdownsj } 5534a5d53a7Smillert #endif /* __OpenBSD__ */ 5547cb960a2Sdownsj tp->pid = procpid; 555f00c5086Smillert 556f00c5086Smillert tp->next = *tlist; 557f00c5086Smillert *tlist = tp; 558f00c5086Smillert 5597cb960a2Sdownsj return tp; 5607cb960a2Sdownsj } 561