diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | Src/exec.c | 50 | ||||
-rw-r--r-- | Src/init.c | 4 | ||||
-rw-r--r-- | Src/utils.c | 11 | ||||
-rw-r--r-- | Src/zsh.h | 26 |
5 files changed, 71 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog index 22dce167a..86be43c70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2005-03-31 Peter Stephenson <pws@csr.com> + + * 21049: Src/exec.c, Src/init.c, Src/utils.c, Src/zsh.h: Don't + close file descriptors opened for process substitution when + executing external programmes in a shell function. Rewrite + the corresponding code to make it more transparent. + 2005-03-28 Wayne Davison <wayned@users.sourceforge.net> * unposted: Completion/Unix/Command/_rsync: Added --protocol. diff --git a/Src/exec.c b/Src/exec.c index 3c20f9352..1e5a2d0fd 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 */ @@ -496,7 +496,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); @@ -1053,7 +1057,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 @@ -1576,7 +1580,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; } @@ -2132,7 +2136,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; @@ -2196,7 +2200,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 */ @@ -2286,7 +2290,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; @@ -2414,7 +2418,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) @@ -2424,17 +2428,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) { @@ -2478,7 +2482,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) @@ -2711,7 +2715,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 @@ -2720,7 +2729,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); } @@ -2865,7 +2875,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; @@ -3069,7 +3079,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); @@ -3094,7 +3104,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); @@ -3103,7 +3113,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); @@ -3147,7 +3157,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 26f5fb06f..903df47cd 100644 --- a/Src/init.c +++ b/Src/init.c @@ -1048,7 +1048,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 */ } @@ -1252,7 +1252,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 936433a09..eb6edf719 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 0434fdb5e..b0ca94e09 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -254,6 +254,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 */ |