msh: do not run pipes where last command is a builtin

msh: code shrink and some renames for better readability
This commit is contained in:
Denis Vlasenko 2008-02-11 18:10:06 +00:00
parent fc21305892
commit a5f2cd30c9

View File

@ -2553,7 +2553,6 @@ static int execute(struct op *t, int *pin, int *pout, int act)
interactive = hinteractive; interactive = hinteractive;
if (i != -1) { if (i != -1) {
setval(lookup("!"), putn(i)); setval(lookup("!"), putn(i));
if (pin != NULL)
closepipe(pin); closepipe(pin);
if (interactive) { if (interactive) {
prs(putn(i)); prs(putn(i));
@ -2689,8 +2688,8 @@ static builtin_func_ptr inbuilt(const char *s)
static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
{ {
pid_t newpid; pid_t newpid;
int i, rv; int i;
builtin_func_ptr shcom = NULL; builtin_func_ptr bltin = NULL;
int f; int f;
const char *cp = NULL; const char *cp = NULL;
struct ioword **iopp; struct ioword **iopp;
@ -2711,7 +2710,7 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
(void) &pin; (void) &pin;
(void) &pout; (void) &pout;
(void) ℘ (void) ℘
(void) &shcom; (void) &bltin;
(void) &cp; (void) &cp;
(void) &resetsig; (void) &resetsig;
(void) &owp; (void) &owp;
@ -2724,7 +2723,6 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
owp = wp; owp = wp;
resetsig = 0; resetsig = 0;
rv = -1; /* system-detected error */
if (t->type == TCOM) { if (t->type == TCOM) {
while (*wp++ != NULL) while (*wp++ != NULL)
continue; continue;
@ -2745,17 +2743,17 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
return setstatus(0); return setstatus(0);
} }
if (cp != NULL) { if (cp != NULL) {
shcom = inbuilt(cp); bltin = inbuilt(cp);
} }
} }
t->words = wp; t->words = wp;
f = act; f = act;
DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom, DBGPRINTF(("FORKEXEC: bltin %p, f&FEXEC 0x%x, owp %p\n", bltin,
f & FEXEC, owp)); f & FEXEC, owp));
if (shcom == NULL && (f & FEXEC) == 0) { if (!bltin && (f & FEXEC) == 0) {
/* Save values in case the child process alters them */ /* Save values in case the child process alters them */
hpin = pin; hpin = pin;
hpout = pout; hpout = pout;
@ -2783,18 +2781,13 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
intr = hintr; intr = hintr;
brklist = hbrklist; brklist = hbrklist;
execflg = hexecflg; execflg = hexecflg;
/* moved up
if (i == -1)
return rv;
*/
if (pin != NULL)
closepipe(pin);
closepipe(pin);
return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0); return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0);
} }
/* Must be the child process, pid should be 0 */ /* Child */
DBGPRINTF(("FORKEXEC: child process, shcom=%p\n", shcom)); DBGPRINTF(("FORKEXEC: child process, bltin=%p\n", bltin));
if (interactive) { if (interactive) {
signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN);
@ -2808,13 +2801,18 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
execflg = 0; execflg = 0;
} }
if (owp != NULL) if (owp)
while ((cp = *owp++) != NULL && assign(cp, COPYV)) while ((cp = *owp++) != NULL && assign(cp, COPYV))
if (shcom == NULL) if (!bltin)
export(lookup(cp)); export(lookup(cp));
#ifdef COMPIPE #if 1
if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) { /* How to fix it:
* explicitly pass pin[0] and pout[1] to builtins
* instead of making them rely on fd 0/1,
* and do not xmove_fd(pin[0]/pout[1]) below if bltin != NULL.
*/
if ((pin || pout) && bltin && bltin != doexec) {
err("piping to/from shell builtins not yet done"); err("piping to/from shell builtins not yet done");
if (forked) if (forked)
_exit(-1); _exit(-1);
@ -2822,20 +2820,20 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
} }
#endif #endif
if (pin != NULL) { if (pin) {
xmove_fd(pin[0], 0); xmove_fd(pin[0], 0);
if (pin[1] != 0) if (pin[1] != 0)
close(pin[1]); close(pin[1]);
} }
if (pout != NULL) { if (pout) {
xmove_fd(pout[1], 1); xmove_fd(pout[1], 1);
if (pout[1] != 1) if (pout[0] > 1)
close(pout[0]); close(pout[0]);
} }
iopp = t->ioact; iopp = t->ioact;
if (iopp != NULL) { if (iopp) {
if (shcom != NULL && shcom != doexec) { if (bltin && bltin != doexec) {
prs(cp); prs(cp);
err(": cannot redirect shell command"); err(": cannot redirect shell command");
if (forked) if (forked)
@ -2844,17 +2842,25 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
} }
while (*iopp) while (*iopp)
if (iosetup(*iopp++, pin != NULL, pout != NULL)) { if (iosetup(*iopp++, pin != NULL, pout != NULL)) {
/* system-detected error */
if (forked) if (forked)
_exit(rv); _exit(-1);
return rv; return -1;
} }
} }
if (shcom) { if (bltin) {
i = setstatus((*shcom) (t)); i = setstatus(bltin(t));
if (forked) if (forked)
_exit(i); _exit(i);
DBGPRINTF(("FORKEXEC: returning i=%d\n", i)); DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
/* Builtins in pipes ("ls /dev/null | cd"):
* here "cd" (which is not a child) will return to main msh,
* and we will read from ls's output as if it is our next command!
* Result: "/dev/null: cannot execute"
* and then we reach EOF on stdin and exit.
* See above for possible way to fix this.
*/
return i; return i;
} }
@ -2882,7 +2888,7 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
leave(); leave();
/* NOTREACHED */ /* NOTREACHED */
_exit(1); return 0;
} }
/* /*
@ -3056,7 +3062,7 @@ static const char *rexecve(char *c, char **v, char **envp)
int i; int i;
const char *sp; const char *sp;
char *tp; char *tp;
int eacces = 0, asis = 0; int asis = 0;
char *name = c; char *name = c;
if (ENABLE_FEATURE_SH_STANDALONE) { if (ENABLE_FEATURE_SH_STANDALONE) {
@ -3104,10 +3110,6 @@ static const char *rexecve(char *c, char **v, char **envp)
case E2BIG: case E2BIG:
return "argument list too long"; return "argument list too long";
case EACCES:
eacces++;
break;
} }
} }
return errno == ENOENT ? "not found" : "cannot execute"; return errno == ENOENT ? "not found" : "cannot execute";
@ -3280,8 +3282,7 @@ static int doumask(struct op *t)
fputc('0' + ((i >> n) & 07), stderr); fputc('0' + ((i >> n) & 07), stderr);
fputc('\n', stderr); fputc('\n', stderr);
} else { } else {
/* huh??? '8','9' are not allowed! */ for (n = 0; *cp >= '0' && *cp <= '7'; cp++)
for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
n = n * 8 + (*cp - '0'); n = n * 8 + (*cp - '0');
umask(n); umask(n);
} }
@ -4618,7 +4619,6 @@ static int readc(void)
DBGPRINTF(("READC: leave()...\n")); DBGPRINTF(("READC: leave()...\n"));
leave(); leave();
/* NOTREACHED */ /* NOTREACHED */
return 0; return 0;
} }
@ -4629,7 +4629,6 @@ static void ioecho(char c)
write(2, &c, sizeof c); write(2, &c, sizeof c);
} }
static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *)) static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
{ {
DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, global_env.iop %p\n", argp, DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, global_env.iop %p\n", argp,
@ -4967,8 +4966,8 @@ static int openpipe(int *pv)
static void closepipe(int *pv) static void closepipe(int *pv)
{ {
if (pv != NULL) { if (pv != NULL) {
close(*pv++); close(pv[0]);
close(*pv); close(pv[1]);
} }
} }