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.
This commit is contained in:
parent
de17cbcc7e
commit
4dc6bdd3e7
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user