about summary refs log tree commit diff
path: root/Src/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/utils.c')
-rw-r--r--Src/utils.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/Src/utils.c b/Src/utils.c
index 221d10d5d..0168c8287 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1621,6 +1621,27 @@ adjustwinsize(int from)
     }
 }
 
+/*
+ * Ensure the fdtable is large enough for fd, and that the
+ * maximum fd is set appropriately.
+ */
+static void
+check_fd_table(int fd)
+{
+    if (fd <= max_zsh_fd)
+	return;
+
+    if (fd >= fdtable_size) {
+	int old_size = fdtable_size;
+	while (fd >= fdtable_size)
+	    fdtable = zrealloc(fdtable,
+			       (fdtable_size *= 2)*sizeof(*fdtable));
+	memset(fdtable + old_size, 0,
+	       (fdtable_size - old_size) * sizeof(*fdtable));
+    }
+    max_zsh_fd = fd;
+}
+
 /* Move a fd to a place >= 10 and mark the new fd in fdtable.  If the fd *
  * is already >= 10, it is not moved.  If it is invalid, -1 is returned. */
 
@@ -1644,12 +1665,7 @@ movefd(int fd)
 	fd = fe;
     }
     if(fd != -1) {
-	if (fd > max_zsh_fd) {
-	    while (fd >= fdtable_size)
-		fdtable = zrealloc(fdtable,
-				   (fdtable_size *= 2)*sizeof(*fdtable));
-	    max_zsh_fd = fd;
-	}
+	check_fd_table(fd);
 	fdtable[fd] = FDT_INTERNAL;
     }
     return fd;
@@ -1669,12 +1685,12 @@ redup(int x, int y)
     if(x < 0)
 	zclose(y);
     else if (x != y) {
-	while (y >= fdtable_size)
-	    fdtable = zrealloc(fdtable, (fdtable_size *= 2)*sizeof(*fdtable));
-	if (dup2(x, y) == -1)
+	if (dup2(x, y) == -1) {
 	    ret = -1;
-	if ((fdtable[y] = fdtable[x]) && y > max_zsh_fd)
-	    max_zsh_fd = y;
+	} else {
+	    check_fd_table(y);
+	    fdtable[y] = fdtable[x];
+	}
 	zclose(x);
     }