about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2009-09-22 09:17:05 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2009-09-22 09:17:05 +0000
commit51409732d0e647661915fde0b15323005be7c9e8 (patch)
treedee1a7c103a59916c77fe7fac4aa8f9f2171a8ef
parent997eafdcad85e9a2c59db1141b404dd4c4bcb22d (diff)
downloadzsh-51409732d0e647661915fde0b15323005be7c9e8.tar.gz
zsh-51409732d0e647661915fde0b15323005be7c9e8.tar.xz
zsh-51409732d0e647661915fde0b15323005be7c9e8.zip
27284: better use of movefd()
-rw-r--r--ChangeLog9
-rw-r--r--Src/Modules/socket.c10
-rw-r--r--Src/Modules/tcp.c12
-rw-r--r--Src/Modules/zpty.c7
-rw-r--r--Src/exec.c21
-rw-r--r--Src/parse.c2
-rw-r--r--Src/utils.c23
7 files changed, 66 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 9e9e6d89a..944a5ab86 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-09-22  Peter Stephenson  <pws@csr.com>
+
+	* 27284: Src/exec.c, Src/parse.c, Src/utils.c,
+	Src/Modules/socket.c, Src/Modules/tcp.c, Src/Modules/zpty.c:
+	improve use of movefd() and restore closing of original fd
+	on failure pending further work.
+
 2009-09-21  Peter Stephenson  <p.w.stephenson@ntlworld.com>
 
 	* 27283: Src/exec.c, Src/utils.c: failure to dup fd accessed
@@ -12202,5 +12209,5 @@
 
 *****************************************************
 * This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.4785 $
+* $Revision: 1.4786 $
 *****************************************************
diff --git a/Src/Modules/socket.c b/Src/Modules/socket.c
index 469568a11..3f47636bc 100644
--- a/Src/Modules/socket.c
+++ b/Src/Modules/socket.c
@@ -120,13 +120,19 @@ bin_zsocket(char *nam, char **args, Options ops, UNUSED(int func))
 	}
 
 	if (targetfd) {
-	    redup(sfd, targetfd);
-	    sfd = targetfd;
+	    if (redup(sfd, targetfd) == -1)
+		sfd = -1;
+	    else
+		sfd = targetfd;
 	}
 	else {
 	    /* move the fd since no one will want to read from it */
 	    sfd = movefd(sfd);
 	}
+	if (sfd == -1) {
+	    zerrnam(nam, "cannot duplicate fd %d: %e", sfd, errno);
+	    return 1;
+	}
 
 	setiparam("REPLY", sfd);
 
diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c
index 2b9e9df18..2825cb978 100644
--- a/Src/Modules/tcp.c
+++ b/Src/Modules/tcp.c
@@ -446,14 +446,22 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
 	}
 
 	if (targetfd) {
-	    redup(sess->fd,targetfd);
-	    sess->fd = targetfd;
+	    if (redup(sess->fd,targetfd) == -1)
+		sess->fd = -1;
+	    else
+		sess->fd = targetfd;
 	}
 	else {
 	    /* move the fd since no one will want to read from it */
 	    sess->fd = movefd(sess->fd);
 	}
 
+	if (sess->fd == -1) {
+	    zwarnnam(nam, "cannot duplicate fd %d: %e", sess->fd, errno);
+	    tcp_close(sess);
+	    return 1;
+	}
+
 	setiparam("REPLY", sess->fd);
 
 	if (verbose)
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index 4899f8e2e..16bec2bc9 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -401,6 +401,12 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
 	zexit(lastval, 0);
     }
     master = movefd(master);
+    if (master == -1) {
+	zerrnam(nam, "cannot duplicate fd %d: %e", master, errno);
+	scriptname = oscriptname;
+	ineval = oineval;
+	return 1;
+    }
 
     p = (Ptycmd) zalloc(sizeof(*p));
 
@@ -423,6 +429,7 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
 
     scriptname = oscriptname;
     ineval = oineval;
+
     return 0;
 }
 
diff --git a/Src/exec.c b/Src/exec.c
index ca9cf0f4d..2263bd640 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1958,14 +1958,19 @@ addfd(int forked, int *save, struct multio **mfds, int fd1, int fd2, int rflag,
     if (varid) {
 	/* fd will be over 10, don't touch mfds */
 	fd1 = movefd(fd2);
-	fdtable[fd1] = FDT_EXTERNAL;
-	setiparam(varid, (zlong)fd1);
-	/*
-	 * If setting the parameter failed, close the fd else
-	 * it will leak.
-	 */
-	if (errflag)
-	    zclose(fd1);
+	if (fd1 == -1) {
+	    zerr("cannot moved fd %d: %e", fd2, errno);
+	    return;
+	} else {
+	    fdtable[fd1] = FDT_EXTERNAL;
+	    setiparam(varid, (zlong)fd1);
+	    /*
+	     * If setting the parameter failed, close the fd else
+	     * it will leak.
+	     */
+	    if (errflag)
+		zclose(fd1);
+	}
     } else if (!mfds[fd1] || unset(MULTIOS)) {
 	if(!mfds[fd1]) {		/* starting a new multio */
 	    mfds[fd1] = (struct multio *) zhalloc(sizeof(struct multio));
diff --git a/Src/parse.c b/Src/parse.c
index 105312f6e..7d736e4d3 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -3095,6 +3095,8 @@ load_dump_file(char *dump, struct stat *sbuf, int other, int len)
 	return;
 
     fd = movefd(fd);
+    if (fd == -1)
+	return;
 
     if ((addr = (Wordcode) mmap(NULL, mlen, PROT_READ, MAP_SHARED, fd, off)) ==
 	((Wordcode) -1)) {
diff --git a/Src/utils.c b/Src/utils.c
index a12914787..21a7b43f6 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1631,8 +1631,13 @@ movefd(int fd)
 #else
 	int fe = movefd(dup(fd));
 #endif
-	if (fe != -1)
-	    zclose(fd);
+	/*
+	 * To close or not to close if fe is -1?
+	 * If it is -1, we haven't moved the fd, so if we close
+	 * it we lose it; but we're probably not going to be able
+	 * to use it in situ anyway.  So probably better to avoid a leak.
+	 */
+	zclose(fd);
 	fd = fe;
     }
     if(fd != -1) {
@@ -1647,22 +1652,30 @@ movefd(int fd)
     return fd;
 }
 
-/* Move fd x to y.  If x == -1, fd y is closed. */
+/*
+ * Move fd x to y.  If x == -1, fd y is closed.
+ * Return 0 for success, -1 for failure.
+ */
 
 /**/
-mod_export void
+mod_export int
 redup(int x, int y)
 {
+    int ret = 0;
+
     if(x < 0)
 	zclose(y);
     else if (x != y) {
 	while (y >= fdtable_size)
 	    fdtable = zrealloc(fdtable, (fdtable_size *= 2)*sizeof(*fdtable));
-	dup2(x, y);
+	if (dup2(x, y) == -1)
+	    ret = -1;
 	if ((fdtable[y] = fdtable[x]) && y > max_zsh_fd)
 	    max_zsh_fd = y;
 	zclose(x);
     }
+
+    return ret;
 }
 
 /* Close the given fd, and clear it from fdtable. */