* if the source file descriptor is closed, EMPTY if there are no unused
* file descriptors left.
*/
+/* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
+ * old code was doing close(to) prior to copyfd() to achieve the same */
+#define COPYFD_EXACT ((int)~INT_MAX)
static int
copyfd(int from, int to)
{
int newfd;
- newfd = fcntl(from, F_DUPFD, to);
+ if (to & COPYFD_EXACT) {
+ to &= ~COPYFD_EXACT;
+ /*if (from != to)*/
+ newfd = dup2(from, to);
+ } else {
+ newfd = fcntl(from, F_DUPFD, to);
+ }
if (newfd < 0) {
if (errno == EMFILE)
return EMPTY;
/* Descriptor wasn't open before redirect.
* Mark it for close in the future */
if (need_to_remember(sv, fd)) {
- if (fd == 2)
- copied_fd2 = CLOSED; /// do we need this?
- sv->two_fd[sv_pos].orig = fd;
- sv->two_fd[sv_pos].copy = CLOSED;
- sv_pos++;
+ goto remember_to_close;
}
continue;
}
if (need_to_remember(sv, fd)) {
/* Copy old descriptor */
i = fcntl(fd, F_DUPFD, 10);
+/* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
+ * are closed in popredir() in the child, preventing them from leaking
+ * into child. (popredir() also cleans up the mess in case of failures)
+ */
if (i == -1) {
i = errno;
if (i != EBADF) {
ash_msg_and_raise_error("%d: %m", fd);
/* NOTREACHED */
}
- /* EBADF: it is not open - ok */
- } else {
- /* fd is open, save its copy */
-/* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
- * are closed in popredir() in the child, preventing them from leaking
- * into child. (popredir() also cleans up the mess in case of failures)
- */
- if (fd == 2)
- copied_fd2 = i;
- sv->two_fd[sv_pos].orig = fd;
- sv->two_fd[sv_pos].copy = i;
- sv_pos++;
- close(fd);
- }
- } else {
- close(fd);
+ /* EBADF: it is not open - good, remember to close it */
+ remember_to_close:
+ i = CLOSED;
+ } /* else: fd is open, save its copy */
+ if (fd == 2)
+ copied_fd2 = i;
+ sv->two_fd[sv_pos].orig = fd;
+ sv->two_fd[sv_pos].copy = i;
+ sv_pos++;
}
- /* At this point fd is closed */
if (newfd < 0) {
/* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
- if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
- copyfd(redir->ndup.dupfd, fd);
+ if (redir->ndup.dupfd < 0) { /* "NN>&-" */
+ close(fd);
+ } else {
+ copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
}
- } else { /* move newfd to fd */
- copyfd(newfd, fd);
+ } else if (fd != newfd) { /* move newfd to fd */
+ copyfd(newfd, fd | COPYFD_EXACT);
close(newfd);
}
} while ((redir = redir->nfile.next) != NULL);
}
if (rp->two_fd[i].copy != EMPTY) {
if (!drop) {
- close(fd);
- copyfd(rp->two_fd[i].copy, fd);
+ /*close(fd);*/
+ copyfd(rp->two_fd[i].copy, fd | COPYFD_EXACT);
}
close(rp->two_fd[i].copy);
}
struct jmploc jmploc;
SAVE_INT(saveint);
- err = setjmp(jmploc.loc) * 2;
+ /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
+ err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
if (!err) {
exception_handler = &jmploc;
redirect(redir, flags);
FORCE_INT_ON;
close(pip[0]);
if (pip[1] != 1) {
- close(1);
- copyfd(pip[1], 1);
+ /*close(1);*/
+ copyfd(pip[1], 1 | COPYFD_EXACT);
close(pip[1]);
}
eflag = 0;
len = out - (char *)stackblock();
out = stackblock();
if (eofmark == NULL) {
- if ((c == '>' || c == '<')
- && quotef == 0
- // && len <= 2 // THIS LIMITS fd to 1 char: N>file, but no NN>file!
- // && (*out == '\0' || isdigit(*out))
- ) {
+ if ((c == '>' || c == '<') && quotef == 0) {
int maxlen = 9 + 1; /* max 9 digit fd#: 999999999 */
char *np = out;
while (--maxlen && isdigit(*np))