mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-02 10:01:11 +02:00
Merge of 21049: Don't close process substitution file descriptors for external programmes
This commit is contained in:
parent
f355b42e16
commit
eaf13e9eab
4 changed files with 64 additions and 27 deletions
50
Src/exec.c
50
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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
11
Src/utils.c
11
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;
|
||||
|
|
26
Src/zsh.h
26
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 */
|
||||
|
|
Loading…
Reference in a new issue