From eaf13e9eabfc0531d6e3dedc090f0f495c8139d4 Mon Sep 17 00:00:00 2001 From: Paul Ackersviller Date: Mon, 23 Apr 2007 04:20:22 +0000 Subject: Merge of 21049: Don't close process substitution file descriptors for external programmes --- Src/exec.c | 50 ++++++++++++++++++++++++++++++-------------------- Src/init.c | 4 ++-- Src/utils.c | 11 ++++++----- Src/zsh.h | 26 ++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 27 deletions(-) diff --git a/Src/exec.c b/Src/exec.c index d34de945a..7963dfc52 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -77,7 +77,7 @@ long lastval2; * by zclose. */ /**/ -char *fdtable; +unsigned char *fdtable; /* The allocated size of fdtable */ @@ -498,7 +498,11 @@ execute(UNUSED(Cmdnam cmdname), int dash, int defpath) } argv = makecline(args); - closem(3); + /* + * Note that we don't close fd's attached to process substitution + * here, which should be visible to external processes. + */ + closem(FDT_XTRACE); child_unblock(); if ((int) strlen(arg0) >= PATH_MAX) { zerr("command too long: %s", arg0, 0); @@ -1055,7 +1059,7 @@ execpline(Estate state, wordcode slcode, int how, int last1) mpipe(opipe); coprocin = ipipe[0]; coprocout = opipe[1]; - fdtable[coprocin] = fdtable[coprocout] = 0; + fdtable[coprocin] = fdtable[coprocout] = FDT_UNUSED; } /* This used to set list_pipe_pid=0 unconditionally, but in things * like `ls|if true; then sleep 20; cat; fi' where the sleep was @@ -1578,7 +1582,7 @@ addfd(int forked, int *save, struct multio **mfds, int fd1, int fd2, int rflag) mfds[fd1]->fds[mfds[fd1]->ct++] = movefd(fd2); } } - if (subsh_close >= 0 && !fdtable[subsh_close]) + if (subsh_close >= 0 && fdtable[subsh_close] == FDT_UNUSED) subsh_close = -1; } @@ -2140,7 +2144,7 @@ execcmd(Estate state, int input, int output, int how, int last1) read(synch[0], &dummy, 1); close(synch[0]); #ifdef PATH_DEV_FD - closem(2); + closem(FDT_PROC_SUBST); #endif if (how & Z_ASYNC) { lastpid = (zlong) pid; @@ -2205,7 +2209,7 @@ execcmd(Estate state, int input, int output, int how, int last1) if (!(xtrerr = fdopen(movefd(dup(fileno(stderr))), "w"))) xtrerr = stderr; else - fdtable[fileno(xtrerr)] = 3; + fdtable[fileno(xtrerr)] = FDT_XTRACE; } /* Add pipeline input/output to mnodes */ @@ -2295,7 +2299,7 @@ execcmd(Estate state, int input, int output, int how, int last1) if (fn->fd2 < 10) closemn(mfds, fn->fd2); if (fn->fd2 > 9 && - (fdtable[fn->fd2] || + (fdtable[fn->fd2] != FDT_UNUSED || fn->fd2 == coprocin || fn->fd2 == coprocout)) { fil = -1; @@ -2423,7 +2427,7 @@ execcmd(Estate state, int input, int output, int how, int last1) int i; for (i = 10; i <= max_zsh_fd; i++) - if (fdtable[i] > 1) + if (fdtable[i] >= FDT_PROC_SUBST) fdtable[i]++; #endif if (subsh_close >= 0) @@ -2433,17 +2437,17 @@ execcmd(Estate state, int input, int output, int how, int last1) execshfunc((Shfunc) hn, args); #ifdef PATH_DEV_FD for (i = 10; i <= max_zsh_fd; i++) - if (fdtable[i] > 1) - if (--(fdtable[i]) <= 2) + if (fdtable[i] >= FDT_PROC_SUBST) + if (--(fdtable[i]) <= FDT_PROC_SUBST) zclose(i); #endif } else { /* It's a builtin */ if (forked) - closem(1); + closem(FDT_INTERNAL); lastval = execbuiltin(args, (Builtin) hn); #ifdef PATH_DEV_FD - closem(2); + closem(FDT_PROC_SUBST); #endif fflush(stdout); if (save[1] == -2) { @@ -2487,7 +2491,7 @@ execcmd(Estate state, int input, int output, int how, int last1) if (errflag) _exit(1); } - closem(1); + closem(FDT_INTERNAL); if (coprocin) zclose(coprocin); if (coprocout) @@ -2721,7 +2725,12 @@ entersubsh(int how, int cl, int fake, int revertpgrp) forklevel = locallevel; } -/* close internal shell fds */ +/* + * Close internal shell fds. + * + * Close any that are marked as used if "how" is FDT_UNUSED, else + * close any with the value "how". + */ /**/ mod_export void @@ -2730,7 +2739,8 @@ closem(int how) int i; for (i = 10; i <= max_zsh_fd; i++) - if (fdtable[i] && (!how || fdtable[i] == how)) + if (fdtable[i] != FDT_UNUSED && + (how == FDT_UNUSED || fdtable[i] == how)) zclose(i); } @@ -2875,7 +2885,7 @@ getoutput(char *cmd, int qt) zclose(pipes[1]); retval = readoutput(pipes[0], qt); - fdtable[pipes[0]] = 0; + fdtable[pipes[0]] = FDT_UNUSED; waitforpid(pid); /* unblocks */ lastval = cmdoutval; return retval; @@ -3079,7 +3089,7 @@ getproc(char *cmd) addproc(pid, NULL, 1, &bgtime); return pnam; } - closem(0); + closem(FDT_UNUSED); fd = open(pnam, out ? O_WRONLY | O_NOCTTY : O_RDONLY | O_NOCTTY); if (fd == -1) { zerr("can't open %s: %e", pnam, errno); @@ -3104,7 +3114,7 @@ getproc(char *cmd) zclose(pipes[!out]); return NULL; } - fdtable[pipes[!out]] = 2; + fdtable[pipes[!out]] = FDT_PROC_SUBST; if (!out) { addproc(pid, NULL, 1, &bgtime); @@ -3113,7 +3123,7 @@ getproc(char *cmd) } entersubsh(Z_ASYNC, 1, 0, 0); redup(pipes[out], out); - closem(0); /* this closes pipes[!out] as well */ + closem(FDT_UNUSED); /* this closes pipes[!out] as well */ #endif /* PATH_DEV_FD */ cmdpush(CS_CMDSUBST); @@ -3157,7 +3167,7 @@ getpipe(char *cmd, int nullexec) } entersubsh(Z_ASYNC, 1, 0, 0); redup(pipes[out], out); - closem(0); /* this closes pipes[!out] as well */ + closem(FDT_UNUSED); /* this closes pipes[!out] as well */ cmdpush(CS_CMDSUBST); execode(prog, 0, 1); cmdpop(); diff --git a/Src/init.c b/Src/init.c index 58b390bfa..64c2fa041 100644 --- a/Src/init.c +++ b/Src/init.c @@ -1050,7 +1050,7 @@ source(char *s) freeeprog(prog); else { fclose(bshin); - fdtable[SHIN] = 0; + fdtable[SHIN] = FDT_UNUSED; SHIN = fd; /* the shell input fd */ bshin = obshin; /* file handle for buffered shell input */ } @@ -1250,7 +1250,7 @@ zsh_main(UNUSED(int argc), char **argv) } while (zsh_name); fdtable_size = zopenmax(); - fdtable = zshcalloc(fdtable_size); + fdtable = zshcalloc(fdtable_size*sizeof(*fdtable)); createoptiontable(); emulate(zsh_name, 1); /* initialises most options */ diff --git a/Src/utils.c b/Src/utils.c index e9a2e8784..66585f10e 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1078,10 +1078,11 @@ movefd(int fd) if(fd != -1) { if (fd > max_zsh_fd) { while (fd >= fdtable_size) - fdtable = zrealloc(fdtable, (fdtable_size *= 2)); + fdtable = zrealloc(fdtable, + (fdtable_size *= 2)*sizeof(*fdtable)); max_zsh_fd = fd; } - fdtable[fd] = 1; + fdtable[fd] = FDT_INTERNAL; } return fd; } @@ -1096,7 +1097,7 @@ redup(int x, int y) zclose(y); else if (x != y) { while (y >= fdtable_size) - fdtable = zrealloc(fdtable, (fdtable_size *= 2)); + fdtable = zrealloc(fdtable, (fdtable_size *= 2)*sizeof(*fdtable)); dup2(x, y); if ((fdtable[y] = fdtable[x]) && y > max_zsh_fd) max_zsh_fd = y; @@ -1111,8 +1112,8 @@ mod_export int zclose(int fd) { if (fd >= 0) { - fdtable[fd] = 0; - while (max_zsh_fd > 0 && !fdtable[max_zsh_fd]) + fdtable[fd] = FDT_UNUSED; + while (max_zsh_fd > 0 && fdtable[max_zsh_fd] == FDT_UNUSED) max_zsh_fd--; if (fd == coprocin) coprocin = -1; diff --git a/Src/zsh.h b/Src/zsh.h index cb2e0cbb2..813d96364 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -262,6 +262,32 @@ enum { #define IS_READFD(X) (((X)>=REDIR_READWRITE && (X)<=REDIR_MERGEIN) || (X)==REDIR_INPIPE) #define IS_REDIROP(X) ((X)>=OUTANG && (X)<=TRINANG) +/* + * Values for the fdtable array. They say under what circumstances + * the fd will be close. The fdtable is an unsigned char, so these are + * #define's rather than an enum. + */ +/* Entry not used. */ +#define FDT_UNUSED 0 +/* + * Entry used internally by the shell, should not be visible to other + * processes. + */ +#define FDT_INTERNAL 1 +/* + * Entry used by output from the XTRACE option. + */ +#define FDT_XTRACE 2 +#ifdef PATH_DEV_FD +/* + * Entry used by a process substition. + * The value will be incremented on entering a function and + * decremented on exit; we don't close entries greater than + * FDT_PROC_SUBST except when closing everything. + */ +#define FDT_PROC_SUBST 3 +#endif + /* Flags for input stack */ #define INP_FREE (1<<0) /* current buffer can be free'd */ #define INP_ALIAS (1<<1) /* expanding alias or history */ -- cgit 1.4.1