[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


From: Robert Elz
Subject: Re: GROUPS
Date: Fri, 13 Aug 2021 05:25:54 +0700

    Date:        Wed, 11 Aug 2021 15:31:08 -0400
    From:        Chet Ramey <chet.ramey@case.edu>
    Message-ID:  <87b7cb49-444f-aa06-198d-57f4071a0309@case.edu>

  | I believe I'd rather have variables behave as they're documented. It's more
  | predictable.

I'm not sure I follow the logic that leads to that conclusion - variables
that simply ignore being set isn't what I'd call predictable.  Ones where
setting them has some effect (aside from storing the value) are understandable,
but (aside from read only vars, where an attempt to set is an error)
vars that don't allow writing are just something very odd.

  | Bash allows variables in the environment to override special
  | variables -- for example, UID and EUID --

I didn't know that, but that makes things even more confusing.

  | and I've gotten bug reports about that behavior for forever.

That's probably because it is unpredicable and weird - either an attempt
to set the var is ignored (or the var is read only and it is an error) or
they're allowed, possibly with the effect of removing any special properties
the variable has.   Works from the environment but not in the script makes no
sense to me at all.   Is this documented anywhere (in the man page)?
It certainly isn't in the section where each var is described, and we're
told that attempts to set the var are ignored.

Incidentally, while I was scanning (not really reading) the man page to see
if I could find anywhere this is documented (I didn't, but that doesn't mean
it isn't there) I noticed that in the section on the environment (section
heading "ENVIRONMENT") it mentions how the environment for an executed command
is formed, which is all fine as far as it goes, but it omits any mention of
"set -a" which probably would be worth including there in some form or other.
[This paragraph has nothing whatever to do with the rest of this thread...]

  | That's one of the problems here: the author never intended this script to
  | run in any shell other that Debian's dash.

That is possible perhaps, I don't know the author, or the script, but
being able to run on dash (which is a fairly minimalist POSIX compat sh)
generally means being able to run on any POSIX compat sh, we (people who
modify shells) generally expend much effort in trying to make sure that
the extensions we make to the shell don't break scripts written by people
who have no idea that the extension exists.

  | If they had, maybe they would have tested it on other shells,

Perhaps they did, I have no idea, without looking at it, I'm guessing
that if it worked in dash it would also work in other (modern) ash
derived shells, and probably bosh and yash, and most probably mksh as
well.   It's hard to tell about zsh and ksh93 as they have so many
extensions and variations.

  | The other problem is the OP assuming that posix mode would change it, when
  | posix mode means something else.

Sure, I agree with you there, there's no reason for posix mode to make
any difference to this.  I'm not sure he assumed it would change it
quite so much as hoped that it might (from my reading of what was said.)

  | It could have, but I'm not seeing a good enough reason to change it
  | 25-30 years in.

Not the ability to run more scripts that simply run everywhere else?

And given that changing it is benign to existing scripts that make use
of these vars (and completely irrelevant to those that don't).  That's
even more true than I thought it might be now I know of the way these
things work when in the environment - though because of that (and because
with it, it is trivially possible to subvert scripts which use any of
these vars simply by loading the environ with lots of junk) it gets a
bit more important to provide a way for a script to be sure it is getting
the enhanced version of a variable - scripts that know they want to use
GROUPS or UID (etc) in the way bash defines them can easily include a
command to make sure that always works - in the NetBSD sh, if we had these
vars, which we don't their description would be something like we have
for EUSER and SECONDS (which we do have)...

     EUSER      Set to the login name of the effective user id running the
                shell, as returned by
                (See getpwuid(3) and geteuid(2) for more details.) This is
                obtained each time 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.  See the
                specialvar built-in command for remedial action.

     SECONDS    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 specialvar built-in
                command for remedial action.

(there's also HOSTNAME which is just the same).   Like any other var,
these can be set in the script, in the environment, or in a startup file
(or any other .'d file).   A script that intends to use them is expected
to do something like
        if ! specialvar EUSER SECONDS
Assuming we don't call for help, after that has executed, both EUSER and
SECONDS will be magic, whatever was in the environment or startup files
(what happens after that is entirely governed by what the script does).
(If the script desires to know which var is missing from the shell, in
case we do call for help, it needs to test/enable them one at a time.)

     specialvar variable ...
            For each variable name given, if the variable named is one which,
            in this sh, could be treated as a special variable, then cause
            that variable to be made special, undoing any effects of an
            earlier unset or assignment to the variable.  If all variables
            given are recognized special variables in this sh the specialvar
            command will exit with status 0, otherwise 1.  Invalid usage will
            result in an exit status of 2.

            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.

The "for those special variables so designated" is because there are some
(like RANDOM and LINENO) which are more magic, and where the special properties
can never be removed (though they can be hidden if the variable is unset, but
setting it again resumes the magic variable (for RANDOM with a new seed - as
given if a numeric value was assigned, or from a kernel random number source
otherwise).   These are very rare, and only for var names known to be special
in many shells (LINENO is in POSIX so should be in every shell, though the
effects of unsetting or setting it aren't specified there, rather than don't
do that...)    (Of course, just like bash, we also have a bunch of vars, which
are just vars, except they're initialised to something particular when the
shell starts - some before environment processing, others after it (ie: the
environment cannot control them ... PPID, another POSIX var, is one like that,
though POSIX doesn't say anything about what happens if the sh finds PPID
in the environment).

  | The original implementation was read-only, but that caused bug reports
  | because trying to unset a readonly variable is a fatal error in posix
  | mode.

That would perhaps be better, at least then script writers would get an
obvious error, rather that simply having assignments ignored, and then
"wrong" values produced upon expansion.   Much safer - but even better is
to leave them writeable, but turn the magic off if written.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]