summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2013-02-03 15:54:57 +0000
committerjilles <jilles@FreeBSD.org>2013-02-03 15:54:57 +0000
commit6fa139d56eac8251b9a64c249c8e6fc8131f405c (patch)
tree798963ecfeaa133433ad99b27533d07fa1521c76
parentaa08976cf0559eb6c97a1886ea652e0f839759e5 (diff)
downloadFreeBSD-src-6fa139d56eac8251b9a64c249c8e6fc8131f405c.zip
FreeBSD-src-6fa139d56eac8251b9a64c249c8e6fc8131f405c.tar.gz
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.
-rw-r--r--bin/sh/eval.c35
-rw-r--r--bin/sh/expand.c13
-rw-r--r--bin/sh/expand.h1
-rw-r--r--bin/sh/nodetypes1
-rw-r--r--bin/sh/redir.c22
5 files changed, 48 insertions, 24 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 7817806..66ae40e 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -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;
}
}
}
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index d43cc35..107f798 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -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)
{
diff --git a/bin/sh/expand.h b/bin/sh/expand.h
index 8114e2b..8d44321 100644
--- a/bin/sh/expand.h
+++ b/bin/sh/expand.h
@@ -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 *);
diff --git a/bin/sh/nodetypes b/bin/sh/nodetypes
index ae4bc4a..5e70c64 100644
--- a/bin/sh/nodetypes
+++ b/bin/sh/nodetypes
@@ -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
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index 915b2fc..c11cb71 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -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:
OpenPOWER on IntegriCloud