bug-bash
[Top][All Lists]
Advanced

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

Re: "unset var" pops var off variable stack instead of unsetting it


From: Stephane Chazelas
Subject: Re: "unset var" pops var off variable stack instead of unsetting it
Date: Mon, 20 Mar 2017 09:50:10 +0000
User-agent: Mutt/1.5.24 (2015-08-30)

2017-03-20 12:30:09 +0900, 渡邊裕貴:
> It seems to me this matter is specific to the IFS variable (and possibly
> few others like CDPATH). Unsetting IFS restores the default field splitting
> behavior, but unsetting PATH does not restore the default command search
> path. As Peter suggests, you can locally re-define any variables you
> want and that should work in any situation.
[...]

Hi Yuki,

you seem to be concurring with me that unset is broken and that
the work around is to not use it.

Note that unsetting PATH generally *does* restore a default
command search path. However, on many systems, not everything
agrees on the default search path (for instance on my Debian
system, for execvp(), it's ":/bin:/usr/bin" (yes, current
directory first!), for bash and dash it seems to be only the
current directory (as if PATH was set to the empty string), for
yash it seems it's nothing, for mksh "/usr/bin:/bin", for ksh93
"/bin:/usr/bin"... behaviour left "implementation defined" by
POSIX) so unsetting PATH is not useful.

Now, there are many reasons one may want to use unset.

For instance, unsetting LC_* restores LANG, one may want to
unset LD_LIBRARY_PATH, GCONV_PATH, LOCPATH, PERL5LIB,
PYTHON_PATH... for security reasons or to get a consistent
behaviour. In POSIX sh language, unsetting a variable is the
only way to unexport it. Same for changing the type of a
variable to scalar in bash without declaring it local.
zsh/yash/mksh have "typeset -g" for that, but in bash typeset -g
affects the variable in the global scope instead of preventing
the restricting the scope in other shells.

unset is also commonly used to make sure variables /have a
default value of <unset>/ like in things like:

rmv() (
  unset OPTIND force interactive verbose
  while getopts :ivf o; do
    (f) force=1;;
    ...
  esac
  shift "$((OPTIND - 1))"
  exec rm ... ${force+"-f"} "$@"
)

Replacing the "unset force" with "force=" (and use
${force:+"-f"}) to work around the unset bug would not be enough
with bash/mksh as $force might have been defined as "integer" in
a parent scope. So one would need to use "typeset force=", or
just "typeset foo" which declares it with an <undef> value,
but that would make it no longer standard sh code (so that
function can no longer be used in sh scripts).

-- 
Stephane



reply via email to

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