Alter a design botch when magic (self modifying) variables

were added to sh ... in other shells, setting such a variable
(for most of them) causes it to lose its special properties,
and act the same as any other variable.   I had assumed that
was just implementor laziness...   I was wrong.

From now on the NetBSD shell will act like the others, and if vars
like HOSTNAME (and SECONDS, etc) are used as variables in a script
or whatever, they will act just like normal variables (and unless
this happens when they have been made local, or as a variable-assignment
as a prefix to a command, the special properties they would have had
otherwise are lost for the remainder of the life of the (sub-)shell
in which the variables were set).

Importing a value from the environment counts as setting the
value for this purpose (so if HOSTNAME is set in the environment,
the value there will be the value $HOSTNAME expands to).

The two exceptions to this are LINENO and RANDOM.   RANDOM
needs to be able to be set to (re-)set its seed.  LINENO needs to
be able to be set (at least in the "local" command) to achieve
the desired functionality.   It is unlikely that any (sane) script
is going to want to use those two as normal vars however.

While here, fix a minor bug in popping local vars (fn return) that need
to notify the shell of changes in value (like PATH).

Change sh(1) to reflect this alteration.  Also add doc of the
(forgotten) magic var EUSER (which has been there since the others
were added), and add a few more vars (which are documented
in other places in sh(1) - like ENV) into the defined or used
variable list (as well as wherever else they appear).

XXX pullup -8
This commit is contained in:
kre 2018-12-04 14:03:30 +00:00
parent e4ac7437f9
commit 370f00cafc
3 changed files with 81 additions and 15 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: sh.1,v 1.210 2018/12/03 06:43:19 kre Exp $
.\" $NetBSD: sh.1,v 1.211 2018/12/04 14:03:30 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 May 3, 2018
.Dd December 4, 2018
.Dt SH 1
.\" everything except c o and s (keep them ordered)
.ds flags abCEeFfhIiLmnpquVvXx
@ -2995,6 +2995,21 @@ destination for
output (as of the time of the
.Ic local
command) will also be restored.
If any of the shell's magic variables
(those which return a value which may vary without
the variable being explicitly altered,
e.g.:
.Dv SECONDS
or
.Dv HOSTNAME )
are made local in a function,
they will lose their special properties when set
within the function, including by the
.Ic local
command itself
(if not to be set in the function, there is little point
in making a variable local)
but those properties will be restored when the function returns.
.Pp
It is an error to use
.Ic local
@ -3934,6 +3949,30 @@ above, which are documented further above in
If unset
.Dq $HOME/.editrc
is used.
.It Ev ENV
Names the file sourced at startup by the shell.
Unused by this shell after initialization,
but is usually passed through the environment to
descendant shells.
.It Ev EUSER
Set to the login name of the effective user id running the shell,
as returned by
.Bd -compact -literal -offset indent
getpwuid(geteuid())->pw_name
.Ed
.Po
See
.Xr getpwuid 3
and
.Xr geteuid 2
for more details.
.Pc
This is obtained each time
.Ev EUSER
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.
.It Ev HISTSIZE
The number of lines in the history buffer for the shell.
.It Ev HOME
@ -3952,8 +3991,7 @@ This is obtained each time
is expanded, so changes to the system's name are reflected
without further action.
If unset, it returns nothing.
Setting it does nothing except reverse the effect of an earlier
.Ic unset .
If set it loses its special properties, and is simply a variable.
.It Ev IFS
Input Field Separators.
This is normally set to
@ -4005,6 +4043,22 @@ The default search path for executables.
See the
.Sx Path Search
section above.
.It Ev POSIXLY_CORRECT
If set in the environment upon initialization of the shell,
then the shell option
.Ic posix
will be set.
.Po
See the description of the
.Ic set
command in the
.Sx Built-ins
section.
.Pc
After initialization it is unused by the shell,
but is usually passed through the environment to
descendant processes, including other instances of the shell,
which may interpret it in a similar way.
.It Ev PPID
The process identified of the parent process of the
current shell.
@ -4096,8 +4150,8 @@ assigned before
is first accessed after shell initialization.
.It Ev SECONDS
Returns the number of seconds since the current shell was started.
Attempts to set this variable are ignored.
If unset, it remains unset, and returns nothing, unless set again.
If set, it loses its special properties, and becomes a normal variable.
.It Ev START_TIME
Initialized by the shell to the number of seconds since the Epoch
(see
@ -4109,7 +4163,7 @@ represents the current time, if
.Ev START_TIME
has not been modified, and
.Ev SECONDS
is not unset.
has not been set or unset.
.It Ev TERM
The default terminal setting for the shell.
This is inherited by
@ -4131,8 +4185,7 @@ if set, or current local time if not, and returns the result.
If unset
.Ev ToD
returns nothing.
Setting it has no effect, other than to reverse the effect of an earlier
.Ic unset .
If set, it loses its special properties, and becomes a normal variable.
.It Ev ToD_FORMAT
Can be set to the
.Xr strftime 3

View File

@ -1,4 +1,4 @@
/* $NetBSD: var.c,v 1.71 2018/12/03 06:42:25 kre Exp $ */
/* $NetBSD: var.c,v 1.72 2018/12/04 14:03:30 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.71 2018/12/03 06:42:25 kre Exp $");
__RCSID("$NetBSD: var.c,v 1.72 2018/12/04 14:03:30 kre Exp $");
#endif
#endif /* not lint */
@ -170,7 +170,7 @@ const struct varinit varinit[] = {
#endif
{ &voptind, VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1",
{ .set_func= getoptsreset } },
{ &line_num, VSTRFIXED|VTEXTFIXED|VFUNCREF, "LINENO=1",
{ &line_num, VSTRFIXED|VTEXTFIXED|VFUNCREF|VSPECIAL, "LINENO=1",
{ .ref_func= get_lineno } },
#ifndef SMALL
{ &tod, VSTRFIXED|VTEXTFIXED|VFUNCREF, "ToD=",
@ -181,7 +181,7 @@ const struct varinit varinit[] = {
{ .ref_func= get_seconds } },
{ &euname, VSTRFIXED|VTEXTFIXED|VFUNCREF, "EUSER=",
{ .ref_func= get_euser } },
{ &random_num, VSTRFIXED|VTEXTFIXED|VFUNCREF, "RANDOM=",
{ &random_num, VSTRFIXED|VTEXTFIXED|VFUNCREF|VSPECIAL, "RANDOM=",
{ .ref_func= get_random } },
#endif
{ NULL, 0, NULL,
@ -479,6 +479,13 @@ setvareq(char *s, int flags)
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
ckfree(vp->text);
/*
* if we set a magic var, the magic dissipates,
* unless it is very special indeed.
*/
if (vp->rfunc && (vp->flags & (VFUNCREF|VSPECIAL)) == VFUNCREF)
vp->rfunc = NULL;
vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
if (flags & VNOEXPORT)
vp->flags &= ~VEXPORT;
@ -940,6 +947,7 @@ mklocal(const char *name, int flags)
char *p;
p = ckmalloc(sizeof_optlist);
lvp->text = memcpy(p, optlist, sizeof_optlist);
lvp->rfunc = NULL;
vp = NULL;
xtrace_clone(0);
} else {
@ -954,9 +962,11 @@ mklocal(const char *name, int flags)
vp = *vpp; /* the new variable */
lvp->text = NULL;
lvp->flags = VUNSET;
lvp->rfunc = NULL;
} else {
lvp->text = vp->text;
lvp->flags = vp->flags;
lvp->v_u = vp->v_u;
vp->flags |= VSTRFIXED|VTEXTFIXED;
if (flags & (VDOEXPORT | VUNSET))
vp->flags &= ~VNOEXPORT;
@ -1010,12 +1020,13 @@ poplocalvars(void)
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
(void)unsetvar(vp->text, 0);
} else {
if (vp->func && (vp->flags & (VNOFUNC|VFUNCREF)) == 0)
(*vp->func)(lvp->text + vp->name_len + 1);
if (lvp->func && (lvp->flags & (VNOFUNC|VFUNCREF)) == 0)
(*lvp->func)(lvp->text + vp->name_len + 1);
if ((vp->flags & VTEXTFIXED) == 0)
ckfree(vp->text);
vp->flags = lvp->flags;
vp->text = lvp->text;
vp->v_u = lvp->v_u;
}
ckfree(lvp);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: var.h,v 1.37 2018/12/03 06:42:25 kre Exp $ */
/* $NetBSD: var.h,v 1.38 2018/12/04 14:03:30 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 VSPECIAL 0x1000 /* magic properties not lost when 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) */
@ -76,6 +77,7 @@ struct localvar {
struct var *vp; /* the variable that was made local */
int flags; /* saved flags */
char *text; /* saved text */
union var_func_union v_u; /* saved function */
};