Module Name:    src
Committed By:   kre
Date:           Mon Dec  3 06:42:25 UTC 2018

Modified Files:
        src/bin/sh: eval.c var.c var.h

Log Message:
Fix "export -x" (and its consequences) to behave as originally
intended (and as documented) rather than how it has been behaving
(which was not very rational.)   Since it is unlikely that anyone
is using this, the change should be mostly invisible.

While here, a couple of other minor cleanups:
        . One call of geteuid() is enough in choose_ps1()
        . Fix a typo in a comment
        . Improve appearance (whitspace changes) in find_var()


To generate a diff of this commit:
cvs rdiff -u -r1.166 -r1.167 src/bin/sh/eval.c
cvs rdiff -u -r1.70 -r1.71 src/bin/sh/var.c
cvs rdiff -u -r1.36 -r1.37 src/bin/sh/var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/sh/eval.c
diff -u src/bin/sh/eval.c:1.166 src/bin/sh/eval.c:1.167
--- src/bin/sh/eval.c:1.166	Mon Dec  3 06:40:26 2018
+++ src/bin/sh/eval.c	Mon Dec  3 06:42:25 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: eval.c,v 1.166 2018/12/03 06:40:26 kre Exp $	*/
+/*	$NetBSD: eval.c,v 1.167 2018/12/03 06:42:25 kre Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
 #else
-__RCSID("$NetBSD: eval.c,v 1.166 2018/12/03 06:40:26 kre Exp $");
+__RCSID("$NetBSD: eval.c,v 1.167 2018/12/03 06:42:25 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -1085,7 +1085,8 @@ evalcommand(union node *cmd, int flgs, s
 				}
 				savehandler = handler;
 				handler = &jmploc;
-				listmklocal(varlist.list, VEXPORT | VNOFUNC);
+				listmklocal(varlist.list,
+				    VDOEXPORT | VEXPORT | VNOFUNC);
 				forkchild(jp, cmd, mode, vforked);
 				break;
 			default:
@@ -1189,7 +1190,7 @@ evalcommand(union node *cmd, int flgs, s
 			    cmdentry.lineno, cmdentry.lno_frel?" (=1)":"",
 			    funclinebase));
 		}
-		listmklocal(varlist.list, VEXPORT);
+		listmklocal(varlist.list, VDOEXPORT | VEXPORT);
 		/* stop shell blowing its stack */
 		if (++funcnest > 1000)
 			error("too many nested function calls");
@@ -1317,7 +1318,7 @@ evalcommand(union node *cmd, int flgs, s
 		    (vforked ? REDIR_VFORK : 0) | REDIR_KEEP);
 		if (!vforked)
 			for (sp = varlist.list ; sp ; sp = sp->next)
-				setvareq(sp->text, VEXPORT|VSTACK);
+				setvareq(sp->text, VDOEXPORT|VEXPORT|VSTACK);
 		envp = environment();
 		shellexec(argv, envp, path, cmdentry.u.index, vforked);
 		break;
@@ -1579,7 +1580,7 @@ execcmd(int argc, char **argv)
 		mflag = 0;
 		optschanged();
 		for (sp = cmdenviron; sp; sp = sp->next)
-			setvareq(sp->text, VEXPORT|VSTACK);
+			setvareq(sp->text, VDOEXPORT|VEXPORT|VSTACK);
 		shellexec(argv + 1, environment(), pathval(), 0, 0);
 	}
 	return 0;

Index: src/bin/sh/var.c
diff -u src/bin/sh/var.c:1.70 src/bin/sh/var.c:1.71
--- src/bin/sh/var.c:1.70	Fri Jul 13 22:43:44 2018
+++ src/bin/sh/var.c	Mon Dec  3 06:42:25 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.70 2018/07/13 22:43:44 kre Exp $	*/
+/*	$NetBSD: var.c,v 1.71 2018/12/03 06:42:25 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: var.c,v 1.70 2018/07/13 22:43:44 kre Exp $");
+__RCSID("$NetBSD: var.c,v 1.71 2018/12/03 06:42:25 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -323,15 +323,17 @@ initvar(void)
 void
 choose_ps1(void)
 {
+	uid_t u = geteuid();
+
 	if ((vps1.flags & (VTEXTFIXED|VSTACK)) == 0)
 		free(vps1.text);
-	vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
+	vps1.text = strdup(u != 0 ? "PS1=$ " : "PS1=# ");
 	vps1.flags &= ~(VTEXTFIXED|VSTACK);
 
 	/*
 	 * Update PSc whenever we feel the need to update PS1
 	 */
-	setvarsafe("PSc", (geteuid() == 0 ? "#" : "$"), 0);
+	setvarsafe("PSc", (u == 0 ? "#" : "$"), 0);
 }
 
 /*
@@ -480,9 +482,11 @@ setvareq(char *s, int flags)
 		vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
 		if (flags & VNOEXPORT)
 			vp->flags &= ~VEXPORT;
+		if (flags & VDOEXPORT)
+			vp->flags &= ~VNOEXPORT;
 		if (vp->flags & VNOEXPORT)
 			flags &= ~VEXPORT;
-		vp->flags |= flags & ~VNOFUNC;
+		vp->flags |= flags & ~(VNOFUNC | VDOEXPORT);
 		vp->text = s;
 
 		/*
@@ -495,20 +499,22 @@ setvareq(char *s, int flags)
 		INTON;
 		return;
 	}
-	VTRACE(DBG_VARS, ("new\n"));
 	/* not found */
 	if (flags & VNOSET) {
+		VTRACE(DBG_VARS, ("new noset\n"));
 		if ((flags & (VTEXTFIXED|VSTACK)) == 0)
 			ckfree(s);
 		return;
 	}
 	vp = ckmalloc(sizeof (*vp));
-	vp->flags = flags & ~(VNOFUNC|VFUNCREF);
+	vp->flags = flags & ~(VNOFUNC|VFUNCREF|VDOEXPORT);
 	vp->text = s;
 	vp->name_len = nlen;
-	vp->next = *vpp;
 	vp->func = NULL;
+	vp->next = *vpp;
 	*vpp = vp;
+
+	VTRACE(DBG_VARS, ("new [%s] (%d) %#x\n", s, nlen, vp->flags));
 }
 
 
@@ -853,26 +859,32 @@ exportcmd(int argc, char **argv)
 
 	res = 0;
 	while ((name = *argptr++) != NULL) {
+		int len;
+
 		f = flag;
-		if ((p = strchr(name, '=')) != NULL) {
-			p++;
-		} else {
-			vp = find_var(name, NULL, NULL);
-			if (vp != NULL) {
-				if (nflg)
-					vp->flags &= ~flag;
-				else if (flag&VEXPORT && vp->flags&VNOEXPORT)
-					res = 1;
-				else {
-					vp->flags |= flag;
-					if (flag == VNOEXPORT)
-						vp->flags &= ~VEXPORT;
-				}
+
+		vp = find_var(name, NULL, &len);
+		p = name + len;
+		if (*p++ != '=')
+			p = NULL;
+
+		if (vp != NULL) {
+			if (nflg)
+				vp->flags &= ~flag;
+			else if (flag&VEXPORT && vp->flags&VNOEXPORT) {
+				sh_warnx("%.*s: not available for export",
+				    len, name);
+				res = 1;
+			} else {
+				vp->flags |= flag;
+				if (flag == VNOEXPORT)
+					vp->flags &= ~VEXPORT;
+			}
+			if (p == NULL)
 				continue;
-			} else
-				f |= VUNSET;
-		}
-		if (!nflg)
+		} 
+
+		if (!nflg || p != NULL)
 			setvar(name, p, f);
 	}
 	return res;
@@ -946,7 +958,10 @@ mklocal(const char *name, int flags)
 			lvp->text = vp->text;
 			lvp->flags = vp->flags;
 			vp->flags |= VSTRFIXED|VTEXTFIXED;
-			if (vp->flags & VNOEXPORT)
+			if (flags & (VDOEXPORT | VUNSET))
+				vp->flags &= ~VNOEXPORT;
+			if (vp->flags & VNOEXPORT &&
+			    (flags & (VEXPORT|VDOEXPORT|VUNSET)) == VEXPORT)
 				flags &= ~VEXPORT;
 			if (flags & (VNOEXPORT | VUNSET))
 				vp->flags &= ~VEXPORT;
@@ -986,7 +1001,7 @@ poplocalvars(void)
 	while ((lvp = localvars) != NULL) {
 		localvars = lvp->next;
 		vp = lvp->vp;
-		VTRACE(DBG_VARS, ("poplocalvar %s", vp ? vp->text : "-"));
+		VTRACE(DBG_VARS, ("poplocalvar %s\n", vp ? vp->text : "-"));
 		if (vp == NULL) {	/* $- saved */
 			memcpy(optlist, lvp->text, sizeof_optlist);
 			ckfree(lvp->text);
@@ -1124,7 +1139,7 @@ strequal(const char *p, const char *q)
  * Search for a variable.
  * 'name' may be terminated by '=' or a NUL.
  * vppp is set to the pointer to vp, or the list head if vp isn't found
- * lenp is set to the number of charactets in 'name'
+ * lenp is set to the number of characters in 'name'
  */
 
 STATIC struct var *
@@ -1138,10 +1153,11 @@ find_var(const char *name, struct var **
 	hashval = 0;
 	while (*p && *p != '=')
 		hashval = 2 * hashval + (unsigned char)*p++;
-	len = p - name;
 
+	len = p - name;
 	if (lenp)
 		*lenp = len;
+
 	vpp = &vartab[hashval % VTABSIZE];
 	if (vppp)
 		*vppp = vpp;

Index: src/bin/sh/var.h
diff -u src/bin/sh/var.h:1.36 src/bin/sh/var.h:1.37
--- src/bin/sh/var.h:1.36	Sat Oct 28 03:59:11 2017
+++ src/bin/sh/var.h	Mon Dec  3 06:42:25 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.h,v 1.36 2017/10/28 03:59:11 kre Exp $	*/
+/*	$NetBSD: var.h,v 1.37 2018/12/03 06:42:25 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -51,6 +51,7 @@
 #define VNOFUNC		0x0100	/* don't call the callback function */
 #define VFUNCREF	0x0200	/* the function is called on ref, not set */
 
+#define VDOEXPORT	0x2000	/* obey VEXPORT even if VNOEXPORT */
 #define VNOSET		0x4000	/* do not set variable - just readonly test */
 #define VNOERROR	0x8000	/* be quiet if set fails (no error msg) */
 

Reply via email to