Skip to content

Commit

Permalink
ash: [REDIR] Replace copyfd by savefd and use dup2 elsewhere
Browse files Browse the repository at this point in the history
Upstream commit:

    Date: Sat, 12 May 2007 18:00:57 +1000
    [REDIR] Replace copyfd by savefd and use dup2 elsewhere

    There are two kinds of users to copyfd, those that want to copy an fd to
    an exact value and those that want to move an fd to a value >= 10.  The
    former can simply use dup2 directly while the latter share a lot of common
    code that now constitutes savefd.

This does not change much, just reducing our divergence from dash code.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
  • Loading branch information
Denys Vlasenko committed Oct 26, 2016
1 parent 4135a75 commit 6477460
Showing 1 changed file with 31 additions and 27 deletions.
58 changes: 31 additions & 27 deletions shell/ash.c
Original file line number Diff line number Diff line change
Expand Up @@ -3760,12 +3760,12 @@ setjobctl(int on)
if (--fd < 0)
goto out;
}
/* fd is a tty at this point */
fd = fcntl(fd, F_DUPFD, 10);
if (ofd >= 0)
if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, dont */
close(ofd);
if (fd < 0)
goto out;
/* fd is a tty at this point */
goto out; /* F_DUPFD failed */
close_on_exec_on(fd);
while (1) { /* while we are in the background */
pgrp = tcgetpgrp(fd);
Expand Down Expand Up @@ -5181,26 +5181,31 @@ openredirect(union node *redir)
}

/*
* Copy a file descriptor to be >= to. Throws exception on error.
* Copy a file descriptor to be >= 10. Throws exception on error.
*/
/* 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 */
enum {
COPYFD_EXACT = (int)~(INT_MAX),
COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
};
static int
copyfd(int from, int to)
savefd(int from)
{
int newfd;
int err;

if (to & COPYFD_EXACT) {
to &= ~COPYFD_EXACT;
/*if (from != to)*/
newfd = dup2(from, to);
} else {
newfd = fcntl(from, F_DUPFD, to);
newfd = fcntl(from, F_DUPFD, 10);
err = newfd < 0 ? errno : 0;
if (err != EBADF) {
if (err)
ash_msg_and_raise_error("%d: %m", from);
close(from);
fcntl(newfd, F_SETFD, FD_CLOEXEC);
}

return newfd;
}
static int
dup2_or_raise(int from, int to)
{
int newfd;

newfd = (from != to) ? dup2(from, to) : to;
if (newfd < 0) {
/* Happens when source fd is not open: try "echo >&99" */
ash_msg_and_raise_error("%d: %m", from);
Expand All @@ -5218,6 +5223,9 @@ struct redirtab {
struct two_fd_t two_fd[];
};
#define redirlist (G_var.redirlist)
enum {
COPYFD_RESTORE = (int)~(INT_MAX),
};

static int
need_to_remember(struct redirtab *rp, int fd)
Expand Down Expand Up @@ -5391,10 +5399,10 @@ redirect(union node *redir, int flags)
if (fd != -1)
close(fd);
} else {
copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
dup2_or_raise(redir->ndup.dupfd, fd);
}
} else if (fd != newfd) { /* move newfd to fd */
copyfd(newfd, fd | COPYFD_EXACT);
dup2_or_raise(newfd, fd);
#if ENABLE_ASH_BASH_COMPAT
if (!(redir->nfile.type == NTO2 && fd == 2))
#endif
Expand Down Expand Up @@ -5440,7 +5448,7 @@ popredir(int drop, int restore)
if (!drop || (restore && (copy & COPYFD_RESTORE))) {
copy &= ~COPYFD_RESTORE;
/*close(fd);*/
copyfd(copy, fd | COPYFD_EXACT);
dup2_or_raise(copy, fd);
}
close(copy & ~COPYFD_RESTORE);
}
Expand Down Expand Up @@ -5894,7 +5902,7 @@ evalbackcmd(union node *n, struct backcmd *result)
close(pip[0]);
if (pip[1] != 1) {
/*close(1);*/
copyfd(pip[1], 1 | COPYFD_EXACT);
dup2_or_raise(pip[1], 1);
close(pip[1]);
}
/* TODO: eflag clearing makes the following not abort:
Expand Down Expand Up @@ -10204,7 +10212,6 @@ static int
setinputfile(const char *fname, int flags)
{
int fd;
int fd2;

INT_OFF;
fd = open(fname, O_RDONLY);
Expand All @@ -10214,11 +10221,8 @@ setinputfile(const char *fname, int flags)
exitstatus = 127;
ash_msg_and_raise_error("can't open '%s'", fname);
}
if (fd < 10) {
fd2 = copyfd(fd, 10);
close(fd);
fd = fd2;
}
if (fd < 10)
fd = savefd(fd);
setinputfd(fd, flags & INPUT_PUSH_FILE);
out:
INT_ON;
Expand Down

0 comments on commit 6477460

Please sign in to comment.