There is no way to guarantee a SUS/POSIX shell
and environment. This is not a problem for
interactive use, as a user of some system can
manually bootstrap this environment, usually by
executing a POSIX shell and using
PATH=$(getconf PATH)
This is also not an issue when booting a computer;
the shell scripts that are used for that on most
POSIX (okay I really mean Unix/Linux) systems need
not be and in some cases aren't POSIX compliant.
A compliant environment can't be guaranteed until
a system is fully "up".
There remains one common case I would like to see
addressed: that of a shell script. Since the
"she-bang" line is not part of SUS (and I guess won't
be any time soon), the only reference is this excerpt
from the SUS "exec" function:
<quote>
... In the cases where the other members of the exec family
of functions would fail and set errno to [ENOEXEC], the
execlp() and execvp() functions shall execute a command
interpreter and the environment of the executed command shall
be as if the process invoked the sh utility using execl()
as follows:
execl(<shell path>, arg0, file, arg1, ..., (char *)0);
where <shell path> is an unspecified pathname for the
sh utility, ...
</quote>
To me this implies a POSIX/SUS shell but that isn't
always the case, say with Solaris in which "/bin/sh"
is not POSIX compliant but is the default shell
started. (Although OpenSolaris uses the Korn shell AFAIK).
Without endorsing a she-bang standard I think the SUS could
still include a way to get a script to run with a compliant
environment including a POSIX shell. Without any additional
support the best I can come up with so far is this:
<SSCCE>
PATH=$(getconf PATH)
tail -n +4 "$0" | sh -
exit
# Script starts here
printf 'Hello, World!\n'
</SSCCE>
(See <http://www.sscce.org/> for the meaning of SSCCE.)
This should work *providing* the default environment
includes a compliant version of getconf, but I'm
not proud of this code.
What I'd like to see is the execlp and execvp system
calls be enhanced to include something like this:
<quote>
... On any compliant system, a supplied process image file
pathname of ``/bin/SUS-POSIX'' shall execute a command
interpreter and the environment of the executed command
shall be as if the process invoked the sh utility using
execl() as follows ...
</quote>
The idea is that this pathname need not exist but a
simple and useful idea would be to have a (link to a)
compliant shell with that pathname. On systems without
such a filesystem the execlp and execvp would need to
start a POSIX shell and not some arbitrary shell, when
supplied with that string.
This would permit compliant systems work as always and
require no changes save for the addition of a symlink
to the filesystem. (``ln -s /bin/ksh /bin/SUS-POSIX'')
But on systems that do use a she-bang mechanism, you
could then force a compliant environment for a script
by:
<SSCCE>
#!/bin/SUS-POSIX -
PATH=$(getconf PATH)
printf 'I am running a POSIX shell and using SUS utilities!\n'
</SSCCE>
Note I really don't care what special pathname is used.
``/bin/SUS'' or something else might be nicer but I would
worry about the potential conflict with some real file
at such a pathname.
To have this guaranteed to work under a POSIX shell you
need one further change: getconf should behave as if it
were a built-in utility in a POSIX shell. It need not
be built-in, and on (say) a Solaris, Cygwin, Gnu/Linux
system there is only one getconf anyway; so such a requirement
is no burden and should require no changes. But, if
PATH were not set to use a SUS version of getconf, this
requirement would cause it to use that. (An example
implementation shows this to be trivial: have the shell
add an alias to the correct getconf if needed.)
I think this would be a useful way to allow portable
shell scripts while imposing minimal (or no) changes to
most current POSIX/SUS OSes, and should not cause any
backward compatibility issues.
It has been suggested to me that the special pathname
should include a version number, e.g. ``/bin/SUSv4-POSIX'',
but then you need the complication that without the
version number, the most recent version of the standard(s)
should apply. That way when SUSv6 breaks compatibility with
SUSv5 someday, a SUSv5 script would still work provided
such an environment was still available. I believe Solaris
does something like that with /usr/xpg[46]/bin directories.
I realize the reluctance of the Austin Group to put in
enhancements. I guess you see your goal as to document
and clarify existing practice, and to resolve ambiguities
and conflicts. But I also know occasionally enhancements
can be made, especially if they involve small but useful
changes.
--
Wayne Pollock
|