summary refs log tree commit diff
path: root/src/redir.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/redir.c')
-rw-r--r--src/redir.c65
1 files changed, 35 insertions, 30 deletions
diff --git a/src/redir.c b/src/redir.c
index aab1585..9e0fae5 100644
--- a/src/redir.c
+++ b/src/redir.c
@@ -138,21 +138,10 @@ redirect(union node *redir, int flags)
 		if (fd == newfd)
 			continue;
 		if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
-			int i = fcntl(fd, F_DUPFD, 10);
-			if (i == -1) {
-				i = errno;
-				if (i != EBADF) {
-					const char *m = strerror(i);
-					close(newfd);
-					sh_error("%d: %s", fd, m);
-					/* NOTREACHED */
-				}
-			} else {
+			int i = savefd(fd);
+
+			if (i >= 0)
 				*p = i;
-				close(fd);
-			}
-		} else {
-			close(fd);
 		}
 #ifdef notyet
 		dupredirect(n, newfd, memory);
@@ -244,6 +233,7 @@ dupredirect(redir, f)
 #endif
 	{
 	int fd = redir->nfile.fd;
+	int err = 0;
 
 #ifdef notyet
 	memory[fd] = 0;
@@ -255,16 +245,24 @@ dupredirect(redir, f)
 				memory[fd] = 1;
 			else
 #endif
-				copyfd(redir->ndup.dupfd, fd);
+				if (dup2(f, fd) < 0) {
+					err = errno;
+					goto err;
+				}
+			return;
 		}
-		return;
-	}
+		f = fd;
+	} else if (dup2(f, fd) < 0)
+		err = errno;
+
+	close(f);
+	if (err < 0)
+		goto err;
 
-	if (f != fd) {
-		copyfd(f, fd);
-		close(f);
-	}
 	return;
+
+err:
+	sh_error("%d: %s", f, strerror(err));
 }
 
 
@@ -327,10 +325,8 @@ popredir(int drop)
 	rp = redirlist;
 	for (i = 0 ; i < 10 ; i++) {
 		if (rp->renamed[i] != EMPTY) {
-			if (!drop) {
-				close(i);
-				copyfd(rp->renamed[i], i);
-			}
+			if (!drop)
+				dup2(rp->renamed[i], i);
 			close(rp->renamed[i]);
 		}
 	}
@@ -372,17 +368,26 @@ clearredir(int drop)
 
 
 /*
- * Copy a file descriptor to be >= to.  Invokes sh_error on error.
+ * Move a file descriptor to > 10.  Invokes sh_error on error unless
+ * the original file dscriptor is not open.
  */
 
 int
-copyfd(int from, int to)
+savefd(int from)
 {
 	int newfd;
+	int err;
+
+	newfd = fcntl(from, F_DUPFD, 10);
+	err = newfd < 0 ? errno : 0;
+	if (err != EBADF) {
+		close(from);
+		if (err)
+			sh_error("%d: %s", from, strerror(err));
+		else
+			fcntl(newfd, F_SETFD, FD_CLOEXEC);
+	}
 
-	newfd = fcntl(from, F_DUPFD, to);
-	if (newfd < 0)
-		sh_error("%d: %s", from, strerror(errno));
 	return newfd;
 }