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:
parent
e4ac7437f9
commit
370f00cafc
69
bin/sh/sh.1
69
bin/sh/sh.1
|
@ -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
|
||||
|
|
23
bin/sh/var.c
23
bin/sh/var.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue