ash: explain redirect code a bit

function                                             old     new   delta
redirect                                            1059    1054      -5
This commit is contained in:
Denis Vlasenko 2008-07-24 07:54:57 +00:00
parent 2dc240c0d6
commit 0b76964ae1

View File

@ -594,8 +594,8 @@ struct nfile {
struct ndup { struct ndup {
smallint type; smallint type;
union node *next; union node *next; /* must match nfile's layout */
int fd; int fd; /* must match nfile's layout */
int dupfd; int dupfd;
union node *vname; union node *vname;
}; };
@ -1634,12 +1634,6 @@ nextopt(const char *optstring)
* The parsefile structure pointed to by the global variable parsefile * The parsefile structure pointed to by the global variable parsefile
* contains information about the current file being read. * contains information about the current file being read.
*/ */
struct redirtab {
struct redirtab *next;
int renamed[10];
int nullredirs;
};
struct shparam { struct shparam {
int nparam; /* # of positional parameters (without $0) */ int nparam; /* # of positional parameters (without $0) */
#if ENABLE_ASH_GETOPTS #if ENABLE_ASH_GETOPTS
@ -1765,6 +1759,7 @@ static const struct {
#endif #endif
}; };
struct redirtab;
struct globals_var { struct globals_var {
struct shparam shellparam; /* $@ current positional parameters */ struct shparam shellparam; /* $@ current positional parameters */
@ -1777,7 +1772,7 @@ struct globals_var {
extern struct globals_var *const ash_ptr_to_globals_var; extern struct globals_var *const ash_ptr_to_globals_var;
#define G_var (*ash_ptr_to_globals_var) #define G_var (*ash_ptr_to_globals_var)
#define shellparam (G_var.shellparam ) #define shellparam (G_var.shellparam )
#define redirlist (G_var.redirlist ) //#define redirlist (G_var.redirlist )
#define g_nullredirs (G_var.g_nullredirs ) #define g_nullredirs (G_var.g_nullredirs )
#define preverrout_fd (G_var.preverrout_fd) #define preverrout_fd (G_var.preverrout_fd)
#define vartab (G_var.vartab ) #define vartab (G_var.vartab )
@ -4767,6 +4762,7 @@ openhere(union node *redir)
} }
} }
if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
/* child */
close(pip[0]); close(pip[0]);
signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
@ -4777,7 +4773,7 @@ openhere(union node *redir)
signal(SIGPIPE, SIG_DFL); signal(SIGPIPE, SIG_DFL);
if (redir->type == NHERE) if (redir->type == NHERE)
full_write(pip[1], redir->nhere.doc->narg.text, len); full_write(pip[1], redir->nhere.doc->narg.text, len);
else else /* NXHERE */
expandhere(redir->nhere.doc, pip[1]); expandhere(redir->nhere.doc, pip[1]);
_exit(EXIT_SUCCESS); _exit(EXIT_SUCCESS);
} }
@ -4832,10 +4828,10 @@ openredirect(union node *redir)
abort(); abort();
#endif #endif
/* Fall through to eliminate warning. */ /* Fall through to eliminate warning. */
case NTOFD: // case NTOFD:
case NFROMFD: // case NFROMFD:
f = -1; // f = -1;
break; // break;
case NHERE: case NHERE:
case NXHERE: case NXHERE:
f = openhere(redir); f = openhere(redir);
@ -4873,19 +4869,26 @@ dupredirect(union node *redir, int f)
{ {
int fd = redir->nfile.fd; int fd = redir->nfile.fd;
if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { if (f < 0) { /* redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD */
if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
copyfd(redir->ndup.dupfd, fd); copyfd(redir->ndup.dupfd, fd);
} }
return; return;
} }
if (f != fd) { if (f != fd) {
copyfd(f, fd); copyfd(f, fd);
close(f); close(f);
} }
} }
/**/
struct redirtab {
struct redirtab *next;
int renamed[10];
int nullredirs;
};
#define redirlist (G_var.redirlist )
/* /*
* Process a list of redirection commands. If the REDIR_PUSH flag is set, * Process a list of redirection commands. If the REDIR_PUSH flag is set,
* old file descriptors are stashed away so that the redirection can be * old file descriptors are stashed away so that the redirection can be
@ -4921,11 +4924,12 @@ redirect(union node *redir, int flags)
} }
do { do {
fd = redir->nfile.fd; fd = redir->nfile.fd;
if ((redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
&& redir->ndup.dupfd == fd) if (redir->ndup.dupfd == fd)
continue; /* redirect from/to same file descriptor */ continue; /* redirect from/to same file descriptor */
newfd = -1;
newfd = openredirect(redir); } else {
newfd = openredirect(redir); /* always >= 0 */
if (fd == newfd) { if (fd == newfd) {
/* Descriptor wasn't open before redirect. /* Descriptor wasn't open before redirect.
* Mark it for close in the future */ * Mark it for close in the future */
@ -4933,24 +4937,30 @@ redirect(union node *redir, int flags)
sv->renamed[fd] = CLOSED; sv->renamed[fd] = CLOSED;
continue; continue;
} }
}
if (sv && sv->renamed[fd] == EMPTY) { if (sv && sv->renamed[fd] == EMPTY) {
/* Copy old descriptor */
i = fcntl(fd, F_DUPFD, 10); i = fcntl(fd, F_DUPFD, 10);
if (i == -1) { if (i == -1) {
i = errno; i = errno;
if (i != EBADF) { if (i != EBADF) { /* strange error */
close(newfd); close(newfd);
errno = i; errno = i;
ash_msg_and_raise_error("%d: %m", fd); ash_msg_and_raise_error("%d: %m", fd);
/* NOTREACHED */ /* NOTREACHED */
} }
/* it is not open - ok */
} else { } else {
/* it is open, save its copy */
sv->renamed[fd] = i; sv->renamed[fd] = i;
close(fd); close(fd);
} }
} else { } else {
close(fd); close(fd);
} }
/* Here fd is closed */
/* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
/* else: move newfd to fd */
dupredirect(redir, newfd); dupredirect(redir, newfd);
} while ((redir = redir->nfile.next) != NULL); } while ((redir = redir->nfile.next) != NULL);
INT_ON; INT_ON;