From 727a664beedf38a61f8cf5d4e14978b069676480 Mon Sep 17 00:00:00 2001 From: kre Date: Thu, 14 Feb 2019 11:15:24 +0000 Subject: [PATCH] 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. --- bin/sh/builtins.def | 5 ++++- bin/sh/sh.1 | 49 +++++++++++++++++++++++++++++++++++++++++++-- bin/sh/var.c | 47 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 96 insertions(+), 5 deletions(-) diff --git a/bin/sh/builtins.def b/bin/sh/builtins.def index d702707edd74..0a69f008816c 100644 --- a/bin/sh/builtins.def +++ b/bin/sh/builtins.def @@ -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 diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 832e0af0816f..6da76de7aafb 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -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 diff --git a/bin/sh/var.c b/bin/sh/var.c index 90549b9b76f3..b7d589f1463b 100644 --- a/bin/sh/var.c +++ b/bin/sh/var.c @@ -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 */