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.
This commit is contained in:
kre 2019-02-14 11:15:24 +00:00
parent 2358f4548e
commit 727a664bee
3 changed files with 96 additions and 5 deletions

View File

@ -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

View File

@ -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 execution identity
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 name are reflected
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 otherwise would be.
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

View File

@ -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 char *);
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 */