sh: Reduce unnecessary forks with eval.
[dragonfly.git] / bin / sh / eval.c
index 8169d12..ecc53f4 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  * @(#)eval.c  8.9 (Berkeley) 6/8/95
- * $FreeBSD: src/bin/sh/eval.c,v 1.103 2011/04/25 20:54:12 jilles Exp $
+ * $FreeBSD: src/bin/sh/eval.c,v 1.110 2011/06/16 21:50:28 jilles Exp $
  */
 
 #include <sys/time.h>
@@ -141,7 +141,7 @@ evalcmd(int argc, char **argv)
                         STPUTC('\0', concat);
                         p = grabstackstr(concat);
                 }
-                evalstring(p, builtin_flags & EV_TESTED);
+                evalstring(p, builtin_flags);
         } else
                 exitstatus = 0;
         return exitstatus;
@@ -166,7 +166,7 @@ evalstring(char *s, int flags)
        setstackmark(&smark);
        setinputstring(s, 1);
        while ((n = parsecmd(0)) != NEOF) {
-               if (n != NULL) {
+               if (n != NULL && !nflag) {
                        if (flags_exit && preadateof())
                                evaltree(n, flags | EV_EXIT);
                        else
@@ -410,6 +410,7 @@ evalsubshell(union node *n, int flags)
        struct job *jp;
        int backgnd = (n->type == NBACKGND);
 
+       oexitstatus = exitstatus;
        expredir(n->nredir.redirect);
        if ((!backgnd && flags & EV_EXIT && !have_traps()) ||
            forkshell(jp = makejob(n, 1), n, backgnd) == 0) {
@@ -437,6 +438,7 @@ evalredir(union node *n, int flags)
        struct jmploc *savehandler;
        volatile int in_redirect = 1;
 
+       oexitstatus = exitstatus;
        expredir(n->nredir.redirect);
        savehandler = handler;
        if (setjmp(jmploc.loc)) {
@@ -479,7 +481,6 @@ expredir(union node *n)
        for (redir = n ; redir ; redir = redir->nfile.next) {
                struct arglist fn;
                fn.lastp = &fn.list;
-               oexitstatus = exitstatus;
                switch (redir->type) {
                case NFROM:
                case NTO:
@@ -554,7 +555,8 @@ evalpipe(union node *n)
                if (prevfd >= 0)
                        close(prevfd);
                prevfd = pip[0];
-               close(pip[1]);
+               if (pip[1] != -1)
+                       close(pip[1]);
        }
        INTON;
        if (n->npipe.backgnd == 0) {
@@ -571,14 +573,8 @@ evalpipe(union node *n)
 static int
 is_valid_fast_cmdsubst(union node *n)
 {
-       union node *argp;
 
-       if (n->type != NCMD)
-               return 0;
-       for (argp = n->ncmd.args ; argp ; argp = argp->narg.next)
-               if (expandhassideeffects(argp->narg.text))
-                       return 0;
-       return 1;
+       return (n->type == NCMD);
 }
 
 /*
@@ -596,6 +592,7 @@ evalbackcmd(union node *n, struct backcmd *result)
        struct stackmark smark;         /* unnecessary */
        struct jmploc jmploc;
        struct jmploc *savehandler;
+       struct localvar *savelocalvars;
 
        setstackmark(&smark);
        result->fd = -1;
@@ -608,12 +605,18 @@ evalbackcmd(union node *n, struct backcmd *result)
        }
        if (is_valid_fast_cmdsubst(n)) {
                exitstatus = oexitstatus;
+               savelocalvars = localvars;
+               localvars = NULL;
+               forcelocal++;
                savehandler = handler;
                if (setjmp(jmploc.loc)) {
                        if (exception == EXERROR || exception == EXEXEC)
                                exitstatus = 2;
                        else if (exception != 0) {
                                handler = savehandler;
+                               forcelocal--;
+                               poplocalvars();
+                               localvars = savelocalvars;
                                longjmp(handler->loc, 1);
                        }
                } else {
@@ -621,6 +624,9 @@ evalbackcmd(union node *n, struct backcmd *result)
                        evalcommand(n, EV_BACKCMD, result);
                }
                handler = savehandler;
+               forcelocal--;
+               poplocalvars();
+               localvars = savelocalvars;
        } else {
                exitstatus = 0;
                if (pipe(pip) < 0)
@@ -716,15 +722,9 @@ evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
        oexitstatus = exitstatus;
        exitstatus = 0;
        for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
-               char *p = argp->narg.text;
-               if (varflag && is_name(*p)) {
-                       do {
-                               p++;
-                       } while (is_in_name(*p));
-                       if (*p == '=') {
-                               expandarg(argp, &varlist, EXP_VARTILDE);
-                               continue;
-                       }
+               if (varflag && isassignment(argp->narg.text)) {
+                       expandarg(argp, &varlist, EXP_VARTILDE);
+                       continue;
                }
                expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
                varflag = 0;
@@ -752,8 +752,9 @@ evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
        /* Print the command if xflag is set. */
        if (xflag) {
                char sep = 0;
-               const char *p;
-               out2str(ps4val());
+               const char *p, *ps4;
+               ps4 = expandstr(ps4val());
+               out2str(ps4 != NULL ? ps4 : ps4val());
                for (sp = varlist.list ; sp ; sp = sp->next) {
                        if (sep != 0)
                                out2c(' ');
@@ -910,6 +911,7 @@ evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
                                dup2(pip[1], 1);
                                close(pip[1]);
                        }
+                       flags &= ~EV_BACKCMD;
                }
                flags |= EV_EXIT;
        }