summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/eval.c23
-rw-r--r--src/eval.h1
-rw-r--r--src/var.c45
-rw-r--r--src/var.h15
4 files changed, 42 insertions, 42 deletions
diff --git a/src/eval.c b/src/eval.c
index 8d2767c..a6981a9 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -77,7 +77,6 @@ static int funcnest;		/* depth of function calls */
 
 
 char *commandname;
-struct strlist *cmdenviron;
 int exitstatus;			/* exit status of last command */
 int back_exitstatus;		/* exit status of backquoted command */
 
@@ -704,6 +703,7 @@ evalcommand(union node *cmd, int flags)
 	/* First expand the arguments. */
 	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
 	setstackmark(&smark);
+	pushlocalvars();
 	back_exitstatus = 0;
 
 	cmdentry.cmdtype = CMDBUILTIN;
@@ -748,6 +748,8 @@ evalcommand(union node *cmd, int flags)
 		spp = varlist.lastp;
 		expandarg(argp, &varlist, EXP_VARTILDE);
 
+		mklocal((*spp)->text);
+
 		/*
 		 * Modify the command lookup path, if a PATH= assignment
 		 * is present
@@ -835,6 +837,7 @@ bail:
 			if (forkshell(jp, cmd, FORK_FG) != 0) {
 				exitstatus = waitforjob(jp);
 				INTON;
+				poplocalvars(0);
 				break;
 			}
 			FORCEINTON;
@@ -844,17 +847,9 @@ bail:
 		/* NOTREACHED */
 
 	case CMDBUILTIN:
-		cmdenviron = varlist.list;
-		if (cmdenviron) {
-			struct strlist *list = cmdenviron;
-			int i = VNOSET;
-			if (spclbltin > 0 || argc == 0) {
-				i = 0;
-				if (execcmd && argc > 1)
-					i = VEXPORT;
-			}
-			listsetvar(list, i);
-		}
+		poplocalvars(spclbltin > 0 || argc == 0);
+		if (execcmd && argc > 1)
+			listsetvar(varlist.list, VEXPORT);
 		if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
 			int status;
 			int i;
@@ -875,7 +870,7 @@ raise:
 		break;
 
 	case CMDFUNCTION:
-		listsetvar(varlist.list, 0);
+		poplocalvars(1);
 		if (evalfun(cmdentry.u.func, argc, argv, flags))
 			goto raise;
 		break;
@@ -949,7 +944,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
 	shellparam.optoff = -1;
 	pushlocalvars();
 	evaltree(&func->n, flags & EV_TESTED);
-	poplocalvars();
+	poplocalvars(0);
 funcdone:
 	INTOFF;
 	funcnest--;
diff --git a/src/eval.h b/src/eval.h
index e190b28..ac394e8 100644
--- a/src/eval.h
+++ b/src/eval.h
@@ -37,7 +37,6 @@
 extern char *commandname;	/* currently executing command */
 extern int exitstatus;		/* exit status of last command */
 extern int back_exitstatus;	/* exit status of backquoted command */
-extern struct strlist *cmdenviron;  /* environment for builtin command */
 
 
 struct backcmd {		/* result of evalbackcmd */
diff --git a/src/var.c b/src/var.c
index 12f2f6c..40bd3fd 100644
--- a/src/var.c
+++ b/src/var.c
@@ -44,7 +44,6 @@
 #include "output.h"
 #include "expand.h"
 #include "nodes.h"	/* for other headers */
-#include "eval.h"	/* defines cmdenviron */
 #include "exec.h"
 #include "syntax.h"
 #include "options.h"
@@ -104,7 +103,6 @@ struct var varinit[] = {
 
 STATIC struct var *vartab[VTABSIZE];
 
-STATIC void mklocal(char *);
 STATIC struct var **hashvar(const char *);
 STATIC int vpcmp(const void *, const void *);
 STATIC struct var **findvar(struct var **, const char *);
@@ -147,7 +145,7 @@ INIT {
 
 RESET {
 	while (localvar_stack)
-		poplocalvars();
+		poplocalvars(0);
 }
 #endif
 
@@ -339,24 +337,6 @@ intmax_t lookupvarint(const char *name)
 
 
 /*
- * Search the environment of a builtin command.
- */
-
-char *
-bltinlookup(const char *name)
-{
-	struct strlist *sp;
-
-	for (sp = cmdenviron ; sp ; sp = sp->next) {
-		if (varequal(sp->text, name))
-			return strchrnul(sp->text, '=') + 1;
-	}
-	return lookupvar(name);
-}
-
-
-
-/*
  * Generate a list of variables satisfying the given conditions.
  */
 
@@ -486,8 +466,7 @@ localcmd(int argc, char **argv)
  * "-" as a special case.
  */
 
-STATIC void
-mklocal(char *name)
+void mklocal(char *name)
 {
 	struct localvar *lvp;
 	struct var **vpp;
@@ -534,7 +513,7 @@ mklocal(char *name)
  */
 
 void
-poplocalvars(void)
+poplocalvars(int keep)
 {
 	struct localvar_list *ll;
 	struct localvar *lvp, *next;
@@ -551,7 +530,23 @@ poplocalvars(void)
 		next = lvp->next;
 		vp = lvp->vp;
 		TRACE(("poplocalvar %s", vp ? vp->text : "-"));
-		if (vp == NULL) {	/* $- saved */
+		if (keep) {
+			int bits = VSTRFIXED;
+
+			if (lvp->flags != VUNSET) {
+				if (vp->text == lvp->text)
+					bits |= VTEXTFIXED;
+				else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
+					ckfree(lvp->text);
+			}
+
+			vp->flags &= ~bits;
+			vp->flags |= (lvp->flags & bits);
+
+			if ((vp->flags &
+			     (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
+				unsetvar(vp->text);
+		} else if (vp == NULL) {	/* $- saved */
 			memcpy(optlist, lvp->text, sizeof(optlist));
 			ckfree(lvp->text);
 			optschanged();
diff --git a/src/var.h b/src/var.h
index 2bb82b1..ef6d583 100644
--- a/src/var.h
+++ b/src/var.h
@@ -133,14 +133,14 @@ struct strlist;
 void listsetvar(struct strlist *, int);
 char *lookupvar(const char *);
 intmax_t lookupvarint(const char *);
-char *bltinlookup(const char *);
 char **listvars(int, int, char ***);
 #define environment() listvars(VEXPORT, VUNSET, 0)
 int showvars(const char *, int, int);
 int exportcmd(int, char **);
 int localcmd(int, char **);
+void mklocal(char *);
 void pushlocalvars(void);
-void poplocalvars(void);
+void poplocalvars(int);
 int unsetcmd(int, char **);
 void unsetvar(const char *);
 int varcmp(const char *, const char *);
@@ -148,3 +148,14 @@ int varcmp(const char *, const char *);
 static inline int varequal(const char *a, const char *b) {
 	return !varcmp(a, b);
 }
+
+/*
+ * Search the environment of a builtin command.
+ */
+
+static inline char *bltinlookup(const char *name)
+{
+	return lookupvar(name);
+}
+
+