summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Src/exec.c50
-rw-r--r--Src/init.c4
-rw-r--r--Src/utils.c11
-rw-r--r--Src/zsh.h26
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 */