Author: jilles
Date: Sun Feb  3 15:54:57 2013
New Revision: 246288
URL: http://svnweb.freebsd.org/changeset/base/246288

Log:
  sh: Expand here documents in the current process.
  
  Expand here documents at the same point other redirections are expanded but
  use a non-fork subshell environment (like simple command substitutions) for
  compatibility. Substitition errors result in an empty here document like
  before.
  
  As a result, a fork is avoided for short (<4K) expanded here documents.
  
  Unexpanded here documents (with quoted end marker after <<) are not affected
  by this change. They already only forked when >4K.
  
  Side effects:
  * Order of expansion is slightly different.
  * Slow expansions are not executed in parallel with the redirected command.
  * A non-fork subshell environment is subtly different from a forked process.

Modified:
  head/bin/sh/eval.c
  head/bin/sh/expand.c
  head/bin/sh/expand.h
  head/bin/sh/nodetypes
  head/bin/sh/redir.c

Modified: head/bin/sh/eval.c
==============================================================================
--- head/bin/sh/eval.c  Sun Feb  3 15:23:28 2013        (r246287)
+++ head/bin/sh/eval.c  Sun Feb  3 15:54:57 2013        (r246288)
@@ -92,6 +92,7 @@ static void evalfor(union node *, int);
 static union node *evalcase(union node *);
 static void evalsubshell(union node *, int);
 static void evalredir(union node *, int);
+static void exphere(union node *, struct arglist *);
 static void expredir(union node *);
 static void evalpipe(union node *);
 static int is_valid_fast_cmdsubst(union node *n);
@@ -488,6 +489,37 @@ evalredir(union node *n, int flags)
 }
 
 
+static void
+exphere(union node *redir, struct arglist *fn)
+{
+       struct jmploc jmploc;
+       struct jmploc *savehandler;
+       struct localvar *savelocalvars;
+       int need_longjmp = 0;
+
+       redir->nhere.expdoc = nullstr;
+       savelocalvars = localvars;
+       localvars = NULL;
+       forcelocal++;
+       savehandler = handler;
+       if (setjmp(jmploc.loc))
+               need_longjmp = exception != EXERROR && exception != EXEXEC;
+       else {
+               handler = &jmploc;
+               expandarg(redir->nhere.doc, fn, 0);
+               redir->nhere.expdoc = fn->list->text;
+               INTOFF;
+       }
+       handler = savehandler;
+       forcelocal--;
+       poplocalvars();
+       localvars = savelocalvars;
+       if (need_longjmp)
+               longjmp(handler->loc, 1);
+       INTON;
+}
+
+
 /*
  * Compute the names of the files in a redirection list.
  */
@@ -516,6 +548,9 @@ expredir(union node *n)
                                fixredir(redir, fn.list->text, 1);
                        }
                        break;
+               case NXHERE:
+                       exphere(redir, &fn);
+                       break;
                }
        }
 }

Modified: head/bin/sh/expand.c
==============================================================================
--- head/bin/sh/expand.c        Sun Feb  3 15:23:28 2013        (r246287)
+++ head/bin/sh/expand.c        Sun Feb  3 15:54:57 2013        (r246288)
@@ -127,19 +127,6 @@ collate_range_cmp(wchar_t c1, wchar_t c2
        return (wcscoll(s1, s2));
 }
 
-/*
- * Expand shell variables and backquotes inside a here document.
- *     union node *arg         the document
- *     int fd;                 where to write the expanded version
- */
-
-void
-expandhere(union node *arg, int fd)
-{
-       expandarg(arg, (struct arglist *)NULL, 0);
-       xwrite(fd, stackblock(), expdest - stackblock());
-}
-
 static char *
 stputs_quotes(const char *data, const char *syntax, char *p)
 {

Modified: head/bin/sh/expand.h
==============================================================================
--- head/bin/sh/expand.h        Sun Feb  3 15:23:28 2013        (r246287)
+++ head/bin/sh/expand.h        Sun Feb  3 15:54:57 2013        (r246288)
@@ -57,7 +57,6 @@ struct arglist {
 
 
 union node;
-void expandhere(union node *, int);
 void expandarg(union node *, struct arglist *, int);
 void expari(int);
 void rmescapes(char *);

Modified: head/bin/sh/nodetypes
==============================================================================
--- head/bin/sh/nodetypes       Sun Feb  3 15:23:28 2013        (r246287)
+++ head/bin/sh/nodetypes       Sun Feb  3 15:54:57 2013        (r246288)
@@ -138,6 +138,7 @@ NXHERE nhere                        # fd<<!
        next      nodeptr               # next redirection in list
        fd        int                   # file descriptor being redirected
        doc       nodeptr               # input to command (NARG node)
+       expdoc    temp  char *expdoc    # actual document (for NXHERE)
 
 NNOT nnot                      # ! command  (actually pipeline)
        type    int

Modified: head/bin/sh/redir.c
==============================================================================
--- head/bin/sh/redir.c Sun Feb  3 15:23:28 2013        (r246287)
+++ head/bin/sh/redir.c Sun Feb  3 15:54:57 2013        (r246288)
@@ -251,18 +251,23 @@ movefd:
 static int
 openhere(union node *redir)
 {
+       char *p;
        int pip[2];
        int len = 0;
 
        if (pipe(pip) < 0)
                error("Pipe call failed: %s", strerror(errno));
-       if (redir->type == NHERE) {
-               len = strlen(redir->nhere.doc->narg.text);
-               if (len <= PIPESIZE) {
-                       xwrite(pip[1], redir->nhere.doc->narg.text, len);
-                       goto out;
-               }
+
+       if (redir->type == NXHERE)
+               p = redir->nhere.expdoc;
+       else
+               p = redir->nhere.doc->narg.text;
+       len = strlen(p);
+       if (len <= PIPESIZE) {
+               xwrite(pip[1], p, len);
+               goto out;
        }
+
        if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) 
{
                close(pip[0]);
                signal(SIGINT, SIG_IGN);
@@ -270,10 +275,7 @@ openhere(union node *redir)
                signal(SIGHUP, SIG_IGN);
                signal(SIGTSTP, SIG_IGN);
                signal(SIGPIPE, SIG_DFL);
-               if (redir->type == NHERE)
-                       xwrite(pip[1], redir->nhere.doc->narg.text, len);
-               else
-                       expandhere(redir->nhere.doc, pip[1]);
+               xwrite(pip[1], p, len);
                _exit(0);
        }
 out:
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to