2019-06-08 12:30:47 -0700, L A Walsh:
> On 2019/06/08 03:10, Stephane CHAZELAS wrote:
> > I beleive Joerg meant that we need a way to *ensure* that the
> > shell excludes "." and ".." from glob expansions.
> >
> > Otherwise:
> >
> > chmod a-x .*
> >
> > Could still be unsafe if we don't know the version of the
> > standard the shell is conforming to.
> >   
> Writing code like that seems to be inviting undefined
> behavior.
> 
> I'd always chmod a-x .[^.]*

.[^.]* is unspecified per POSIX and in Bourne-based (like bosh
-o posix) or ksh88-based shells (like /usr/xpg4/bin/sh (the
POSIX sh) of Solaris), would likely only match on .. (on
systems/filesystems where .. is returned in readdir(); [^.]
matches on either ^ or . there as allowed but not required by
POSIX).

Even if you meant .[!.]*, that would still be wrong as that
would miss files like ..foo. See the original bug description
for a closer equivalent to .* without . or ..

You're the third person in this thread (after me (.??* .[!.]*), 
Harald (and me: .??* .[!.]) to come up with a wrong one which is
just additional confirmation that there is a problem with the
current situation.

But here, even the correct .[!.]* ..?* variant would not be OK,
because even if there are hidden files, chmod could return with
an error and a non-zero exit status if either one of those two
globs are not matched. It would only be correct in
zsh +o banghist -o cshnullglob, but then in that shell you
wouldn't need it as chmod a-x .* works as expected.

To work around that, you'd need the (probably incorrect) 10
lines of code I came up with earlier:

set -- .[!.]
[ "$1" = '.[!.]' ] && shift
set -- .[?]'?*' .??* "$@"
if [ "$1$2" = '.[?]?*.??*' ]; then
  shift 2
else
  shift 1
fi
if [ "$#" -eq 0 ]; then
  echo >&2 No match
else
 chmod -- a-x "$@"
fi


> > That would mean chmod would not be run, but that means the
> > script would fail which is not better.
> >
> > Which is why we've argued here it was not really a solution to
> > the problem.
> >   
> Why look to shell options when you can protect yourself
> with fewer characters by using the right glob expression?

Note that, like most people in this thread, I'm not pushing for
this option, I was just trying to explain what I understood
the intention behind it was.

> That's true with anything that forces some new behavior different
> from what it was in the past, (which has, _unfortunately_, happened,
> despite belief to the contrary).  It basically 'kills' a command or
> features's usage as you can't rely on it being there and you can't
> rely on it not being there, which is thoughtless at best, and
> destructive if a random workaround is not done right or is broken
> (for which they would blame the script writer who wouldn't have
> had to do anything had it not been changed).
[...]

That's true as long as there are at least two implementations
that behave differently regardless of whether POSIX is involved.

That [^.] is a good example.

For instance, negating sets was always with [!x] in sh as ^ was
a pipe operator there. csh had | instead for piping so it could
use [^x] like in ed/grep regexps (and in there ! is used for
history expansion so could not be used anyway).

The Bourne shell switched to | for piping (as in newer versions
of ASCII, 0x5e rendering changed from ↑ to ^) and kept ^ for
backward compatibility with older sh so still couldn't use [^x].

ksh88 removed ^ as pipe operator, but still didn't support [^x].

Newer shells have added support for [^x] as an alias for [!x],
which is much better as it aligns with regexps.

POSIX allows it (leaves [^x] unspecified) but does not require
it. Once ksh88 dies away or maintainers of ksh88-based shells
eventually come around to adding it there, POSIX will be able to
mandate it without problem.

Here, ksh88 is only found on commercial Unices and commercial
Unices care about POSIX compliance. If POSIX had mandated [^x]
support in 1995 (or at a time most shells other than ksh88
supported it which I suspect was probably even sooner than that),
I'm pretty sure in 2019 we could have safely used [^.].

In bugid:1228, I'm asking POSIX to allow pathname expansion of
.* not to include . and .. even on systems where readdir()
returns them so shells can freely implement that better design,
like it did allow [^x] at some point, and if possible with a
future direction that states it may be mandated in a future
version to help make it happen sooner.

As soon as POSIX indicate they will allow it, and it seems
everybody is in agreement that it's a good idea, I'll contact
the maintainers of the FLOSS shells (I've already started
preparing patches).

-- 
Stephane

Reply via email to