diff options
-rw-r--r-- | shell/ash.c | 58 |
1 files changed, 31 insertions, 27 deletions
diff --git a/shell/ash.c b/shell/ash.c index 647fc81b4..0490f7f7d 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -3760,12 +3760,12 @@ setjobctl(int on) | |||
3760 | if (--fd < 0) | 3760 | if (--fd < 0) |
3761 | goto out; | 3761 | goto out; |
3762 | } | 3762 | } |
3763 | /* fd is a tty at this point */ | ||
3763 | fd = fcntl(fd, F_DUPFD, 10); | 3764 | fd = fcntl(fd, F_DUPFD, 10); |
3764 | if (ofd >= 0) | 3765 | if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, dont */ |
3765 | close(ofd); | 3766 | close(ofd); |
3766 | if (fd < 0) | 3767 | if (fd < 0) |
3767 | goto out; | 3768 | goto out; /* F_DUPFD failed */ |
3768 | /* fd is a tty at this point */ | ||
3769 | close_on_exec_on(fd); | 3769 | close_on_exec_on(fd); |
3770 | while (1) { /* while we are in the background */ | 3770 | while (1) { /* while we are in the background */ |
3771 | pgrp = tcgetpgrp(fd); | 3771 | pgrp = tcgetpgrp(fd); |
@@ -5181,26 +5181,31 @@ openredirect(union node *redir) | |||
5181 | } | 5181 | } |
5182 | 5182 | ||
5183 | /* | 5183 | /* |
5184 | * Copy a file descriptor to be >= to. Throws exception on error. | 5184 | * Copy a file descriptor to be >= 10. Throws exception on error. |
5185 | */ | 5185 | */ |
5186 | /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD). | ||
5187 | * old code was doing close(to) prior to copyfd() to achieve the same */ | ||
5188 | enum { | ||
5189 | COPYFD_EXACT = (int)~(INT_MAX), | ||
5190 | COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1), | ||
5191 | }; | ||
5192 | static int | 5186 | static int |
5193 | copyfd(int from, int to) | 5187 | savefd(int from) |
5194 | { | 5188 | { |
5195 | int newfd; | 5189 | int newfd; |
5190 | int err; | ||
5196 | 5191 | ||
5197 | if (to & COPYFD_EXACT) { | 5192 | newfd = fcntl(from, F_DUPFD, 10); |
5198 | to &= ~COPYFD_EXACT; | 5193 | err = newfd < 0 ? errno : 0; |
5199 | /*if (from != to)*/ | 5194 | if (err != EBADF) { |
5200 | newfd = dup2(from, to); | 5195 | if (err) |
5201 | } else { | 5196 | ash_msg_and_raise_error("%d: %m", from); |
5202 | newfd = fcntl(from, F_DUPFD, to); | 5197 | close(from); |
5198 | fcntl(newfd, F_SETFD, FD_CLOEXEC); | ||
5203 | } | 5199 | } |
5200 | |||
5201 | return newfd; | ||
5202 | } | ||
5203 | static int | ||
5204 | dup2_or_raise(int from, int to) | ||
5205 | { | ||
5206 | int newfd; | ||
5207 | |||
5208 | newfd = (from != to) ? dup2(from, to) : to; | ||
5204 | if (newfd < 0) { | 5209 | if (newfd < 0) { |
5205 | /* Happens when source fd is not open: try "echo >&99" */ | 5210 | /* Happens when source fd is not open: try "echo >&99" */ |
5206 | ash_msg_and_raise_error("%d: %m", from); | 5211 | ash_msg_and_raise_error("%d: %m", from); |
@@ -5218,6 +5223,9 @@ struct redirtab { | |||
5218 | struct two_fd_t two_fd[]; | 5223 | struct two_fd_t two_fd[]; |
5219 | }; | 5224 | }; |
5220 | #define redirlist (G_var.redirlist) | 5225 | #define redirlist (G_var.redirlist) |
5226 | enum { | ||
5227 | COPYFD_RESTORE = (int)~(INT_MAX), | ||
5228 | }; | ||
5221 | 5229 | ||
5222 | static int | 5230 | static int |
5223 | need_to_remember(struct redirtab *rp, int fd) | 5231 | need_to_remember(struct redirtab *rp, int fd) |
@@ -5391,10 +5399,10 @@ redirect(union node *redir, int flags) | |||
5391 | if (fd != -1) | 5399 | if (fd != -1) |
5392 | close(fd); | 5400 | close(fd); |
5393 | } else { | 5401 | } else { |
5394 | copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT); | 5402 | dup2_or_raise(redir->ndup.dupfd, fd); |
5395 | } | 5403 | } |
5396 | } else if (fd != newfd) { /* move newfd to fd */ | 5404 | } else if (fd != newfd) { /* move newfd to fd */ |
5397 | copyfd(newfd, fd | COPYFD_EXACT); | 5405 | dup2_or_raise(newfd, fd); |
5398 | #if ENABLE_ASH_BASH_COMPAT | 5406 | #if ENABLE_ASH_BASH_COMPAT |
5399 | if (!(redir->nfile.type == NTO2 && fd == 2)) | 5407 | if (!(redir->nfile.type == NTO2 && fd == 2)) |
5400 | #endif | 5408 | #endif |
@@ -5440,7 +5448,7 @@ popredir(int drop, int restore) | |||
5440 | if (!drop || (restore && (copy & COPYFD_RESTORE))) { | 5448 | if (!drop || (restore && (copy & COPYFD_RESTORE))) { |
5441 | copy &= ~COPYFD_RESTORE; | 5449 | copy &= ~COPYFD_RESTORE; |
5442 | /*close(fd);*/ | 5450 | /*close(fd);*/ |
5443 | copyfd(copy, fd | COPYFD_EXACT); | 5451 | dup2_or_raise(copy, fd); |
5444 | } | 5452 | } |
5445 | close(copy & ~COPYFD_RESTORE); | 5453 | close(copy & ~COPYFD_RESTORE); |
5446 | } | 5454 | } |
@@ -5894,7 +5902,7 @@ evalbackcmd(union node *n, struct backcmd *result) | |||
5894 | close(pip[0]); | 5902 | close(pip[0]); |
5895 | if (pip[1] != 1) { | 5903 | if (pip[1] != 1) { |
5896 | /*close(1);*/ | 5904 | /*close(1);*/ |
5897 | copyfd(pip[1], 1 | COPYFD_EXACT); | 5905 | dup2_or_raise(pip[1], 1); |
5898 | close(pip[1]); | 5906 | close(pip[1]); |
5899 | } | 5907 | } |
5900 | /* TODO: eflag clearing makes the following not abort: | 5908 | /* TODO: eflag clearing makes the following not abort: |
@@ -10204,7 +10212,6 @@ static int | |||
10204 | setinputfile(const char *fname, int flags) | 10212 | setinputfile(const char *fname, int flags) |
10205 | { | 10213 | { |
10206 | int fd; | 10214 | int fd; |
10207 | int fd2; | ||
10208 | 10215 | ||
10209 | INT_OFF; | 10216 | INT_OFF; |
10210 | fd = open(fname, O_RDONLY); | 10217 | fd = open(fname, O_RDONLY); |
@@ -10214,11 +10221,8 @@ setinputfile(const char *fname, int flags) | |||
10214 | exitstatus = 127; | 10221 | exitstatus = 127; |
10215 | ash_msg_and_raise_error("can't open '%s'", fname); | 10222 | ash_msg_and_raise_error("can't open '%s'", fname); |
10216 | } | 10223 | } |
10217 | if (fd < 10) { | 10224 | if (fd < 10) |
10218 | fd2 = copyfd(fd, 10); | 10225 | fd = savefd(fd); |
10219 | close(fd); | ||
10220 | fd = fd2; | ||
10221 | } | ||
10222 | setinputfd(fd, flags & INPUT_PUSH_FILE); | 10226 | setinputfd(fd, flags & INPUT_PUSH_FILE); |
10223 | out: | 10227 | out: |
10224 | INT_ON; | 10228 | INT_ON; |