Module Name:    src
Committed By:   kre
Date:           Thu Feb 14 11:15:24 UTC 2019

Modified Files:
        src/bin/sh: builtins.def sh.1 var.c

Log Message:
Add the "specialvar" built-in command.   Discussed (well, mentioned
anway) on tech-userlevel with no adverse response.

This allows the magic of vars like HOSTNAME SECONDS, ToD (etc) to be
restored should it be lost - perhaps by having a var of the same name
imported from the environment (which needs to remove the magic in case
a set of scripts are using the env to pass data, and the var name chosen
happens to be one of our magic ones).

No change to SMALL shells (or smaller) - none of the magic vars (except
LINENO, which is exempt from all of this) exist in those, hence such a
shell has no need for this command either.


To generate a diff of this commit:
cvs rdiff -u -r1.25 -r1.26 src/bin/sh/builtins.def
cvs rdiff -u -r1.219 -r1.220 src/bin/sh/sh.1
cvs rdiff -u -r1.77 -r1.78 src/bin/sh/var.c

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/builtins.def
diff -u src/bin/sh/builtins.def:1.25 src/bin/sh/builtins.def:1.26
--- src/bin/sh/builtins.def:1.25	Mon May 15 20:00:36 2017
+++ src/bin/sh/builtins.def	Thu Feb 14 11:15:24 2019
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#	$NetBSD: builtins.def,v 1.25 2017/05/15 20:00:36 kre Exp $
+#	$NetBSD: builtins.def,v 1.26 2019/02/14 11:15:24 kre Exp $
 #
 # Copyright (c) 1991, 1993
 #	The Regents of the University of California.  All rights reserved.
@@ -76,6 +76,9 @@ setcmd		-s set
 fdflagscmd	fdflags
 setvarcmd	setvar
 shiftcmd	-s shift
+#ifndef SMALL
+specialvarcmd	specialvar
+#endif
 timescmd	-s times
 trapcmd		-s trap
 truecmd		-s : -u true

Index: src/bin/sh/sh.1
diff -u src/bin/sh/sh.1:1.219 src/bin/sh/sh.1:1.220
--- src/bin/sh/sh.1:1.219	Mon Feb  4 12:18:36 2019
+++ src/bin/sh/sh.1	Thu Feb 14 11:15:24 2019
@@ -1,4 +1,4 @@
-.\"	$NetBSD: sh.1,v 1.219 2019/02/04 12:18:36 wiz Exp $
+.\"	$NetBSD: sh.1,v 1.220 2019/02/14 11:15:24 kre Exp $
 .\" Copyright (c) 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
 .\"
@@ -31,7 +31,7 @@
 .\"
 .\"	@(#)sh.1	8.6 (Berkeley) 5/4/95
 .\"
-.Dd February 4, 2019
+.Dd February 14, 2019
 .Dt SH 1
 .\" everything except c o and s (keep them ordered)
 .ds flags abCEeFfhIiLmnpquVvXx
@@ -3351,6 +3351,39 @@ positional parameters (
 .Dq Li $# )
 before the shift.
 .\"
+.It Ic specialvar Ar variable ...
+For each
+.Ar variable
+name given,
+if the variable named is one which,
+in this
+.Nm ,
+could be treated as a special variable,
+then cause that
+.Ar variable
+to be made special, undoing any effects of an earlier
+.Ic unset
+or assignment to the variable.
+If all
+.Ar variable Ns s
+given are recognized special variables in this
+.Nm
+the
+.Ic specialvar
+command will exit with status 0, otherwise 1.
+Invalid usage will result in an exit status of 2.
+.Pp
+Note that all variables capable of being special are created
+that way, this command is not required to cause that to happen.
+However should such a variable be imported from the environment,
+that will cause (for those special variables so designated)
+the special effects for that variable to be lost.
+Consequently, as the contents of the environment cannot be controlled,
+any script which desires to make use of the properties
+of most of the special variables should use this command,
+naming the variables required,
+to ensure that their special properties are available.
+.\"
 .It Ic times
 Prints two lines to standard output.
 Each line contains two accumulated time values, expressed
@@ -4093,6 +4126,9 @@ is expanded, so changes to the shell's e
 cause updates without further action.
 If unset, it returns nothing.
 If set it loses its special properties, and is simply a variable.
+See the
+.Ic specialvar
+built-in command for remedial action.
 .It Ev HISTSIZE
 The number of lines in the history buffer for the shell.
 .It Ev HOME
@@ -4112,6 +4148,9 @@ is expanded, so changes to the system's 
 without further action.
 If unset, it returns nothing.
 If set it loses its special properties, and is simply a variable.
+See the
+.Ic specialvar
+built-in command for remedial action.
 .It Ev IFS
 Input Field Separators.
 This is normally set to
@@ -4284,6 +4323,9 @@ not be as unpredictable as they otherwis
 Returns the number of seconds since the current shell was started.
 If unset, it remains unset, and returns nothing, unless set again.
 If set, it loses its special properties, and becomes a normal variable.
+See the
+.Ic specialvar
+built-in command for remedial action.
 .It Ev START_TIME
 Initialized by the shell to the number of seconds since the Epoch
 (see
@@ -4318,6 +4360,9 @@ If unset
 .Ev ToD
 returns nothing.
 If set, it loses its special properties, and becomes a normal variable.
+See the
+.Ic specialvar
+built-in command for remedial action.
 .It Ev ToD_FORMAT
 Can be set to the
 .Xr strftime 3

Index: src/bin/sh/var.c
diff -u src/bin/sh/var.c:1.77 src/bin/sh/var.c:1.78
--- src/bin/sh/var.c:1.77	Sat Feb  9 09:38:11 2019
+++ src/bin/sh/var.c	Thu Feb 14 11:15:24 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.77 2019/02/09 09:38:11 kre Exp $	*/
+/*	$NetBSD: var.c,v 1.78 2019/02/14 11:15:24 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.77 2019/02/09 09:38:11 kre Exp $");
+__RCSID("$NetBSD: var.c,v 1.78 2019/02/14 11:15:24 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -194,6 +194,7 @@ STATIC int strequal(const char *, const 
 STATIC struct var *find_var(const char *, struct var ***, int *);
 STATIC void showvar(struct var *, const char *, const char *, int);
 static void export_usage(const char *) __dead;
+STATIC int makespecial(const char *);
 
 /*
  * Initialize the varable symbol tables and import the environment
@@ -1616,4 +1617,46 @@ get_random(struct var *vp)
 #undef srandom
 }
 
+STATIC int
+makespecial(const char *name)
+{
+	const struct varinit *ip;
+	struct var *vp;
+
+	CTRACE(DBG_VARS, ("makespecial('%s') -> ", name));
+	for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
+		if (strequal(ip->text, name)) {
+			if (!(ip->flags & VFUNCREF)) {
+				CTRACE(DBG_VARS, ("+1\n"));
+				return 1;
+			}
+			INTOFF;
+			vp->flags &= ~VUNSET;
+			vp->v_u = ip->v_u;
+			INTON;
+			CTRACE(DBG_VARS, ("0\n"));
+			return 0;
+		}
+	}
+	CTRACE(DBG_VARS, ("1\n"));
+	return 1;
+}
+
+int
+specialvarcmd(int argc, char **argv)
+{
+	int res = 0;
+	char **ap;
+
+	(void) nextopt("");
+
+	if (!*argptr)
+		error("Usage: specialvar var...");
+
+	for (ap = argptr; *ap ; ap++)
+		res |= makespecial(*ap);
+
+	return res;
+}
+
 #endif /* SMALL */

Reply via email to