svn commit: r246288 - head/bin/sh

Jilles Tjoelker jilles at FreeBSD.org
Sun Feb 3 15:54:59 UTC 2013


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:


More information about the svn-src-head mailing list