Avoid leaving unnecessary waiting shells in many forms of sh -c COMMAND. This change only affects strings passed to -c, when the -s option is not used. The approach is to read the first line of commands, then the second, and if it turns out there is no second line execute the first line with EV_EXIT. Otherwise execute the first and second line, then read and execute lines as long as they exist. A compound statement such as introduced by {, if, for or while counts as a single line of commands for this. Note that if the second line contains a syntactical error, the first line will not be executed, different from previously. (pdksh and zsh parse the entire -c string before executing it.) Example: sh -c 'ps lT' No longer shows a shell process waiting for ps to finish. diff --git a/eval.c b/eval.c --- a/eval.c +++ b/eval.c @@ -175,6 +175,44 @@ evalstring(char *s) } +/* + * Like evalstring(), but always exits. This is useful in avoiding shell + * processes just sitting around waiting for exit. + */ + +void +evalstring_exit(char *s) +{ + union node *n, *n2; + struct stackmark smark; + + setstackmark(&smark); + setinputstring(s, 1); + do + n = parsecmd(0); + while (n == NULL); + if (n != NEOF) { + do + n2 = parsecmd(0); + while (n2 == NULL); + if (n2 == NEOF) { + evaltree(n, EV_EXIT); + /*NOTREACHED*/ + } + evaltree(n, 0); + evaltree(n2, 0); + popstackmark(&smark); + while ((n = parsecmd(0)) != NEOF) { + if (n != NULL) + evaltree(n, 0); + popstackmark(&smark); + } + } + popfile(); + popstackmark(&smark); + exitshell(exitstatus); +} + /* * Evaluate a parse tree. The value is left in the global variable diff --git a/eval.h b/eval.h --- a/eval.h +++ b/eval.h @@ -47,6 +47,7 @@ struct backcmd { /* result of evalbackc int evalcmd(int, char **); void evalstring(char *); +void evalstring_exit(char *); union node; /* BLETCH for ansi C */ void evaltree(union node *, int); void evalbackcmd(union node *, struct backcmd *); diff --git a/main.c b/main.c --- a/main.c +++ b/main.c @@ -178,7 +178,10 @@ state2: state3: state = 4; if (minusc) { - evalstring(minusc); + if (sflag) + evalstring(minusc); + else + evalstring_exit(minusc); } if (sflag || minusc == NULL) { state4: /* XXX ??? - why isn't this before the "if" statement */