-
-
Notifications
You must be signed in to change notification settings - Fork 399
Description
Current behavior 😯
On Unix-like systems, /bin/sh is usually a POSIX-compatible shell, but POSIX does not require that anything at /bin/sh even exist. It requires that sh run a POSIX-compatible shell (so long as PATH has not been changed to a value that prevents this) and that the shell language that interprets commands in system() and popen() calls is POSIX-compatible. But sh need not resolve to /bin/sh.
Because a lot of software assumes /bin/sh is widespread, it usually does exist, even in systems that don't otherwise use traditional locations for executables (#1810). But some Unix-like operating systems have a Bourne-style but substantially POSIX-incompatible sh implementation as /bin/sh. If the system does not also provide a POSIX-compatible sh elsewhere, then there is probably nothing we can or should do about it. More likely on a system used today, though, is that a POSIX-compatible sh does also exist, at another location.
An informative (i.e. official but supplementary and non-binding) section of the POSIX standard on the sh command includes this recommendation:
Applications should note that the standard PATH to the shell cannot be assumed to be either /bin/sh or /usr/bin/sh, and should be determined by interrogation of the PATH returned by getconf PATH , ensuring that the returned pathname is an absolute pathname and not a shell built-in.
For example, to determine the location of the standard sh utility:
command -v shOn some implementations this might return:
/usr/xpg4/bin/sh
I think, though I am not sure, that in practice today this is mainly important on Solaris and illumos systems.
Solaris
On Solaris 11, /bin/sh is ksh93, which is POSIX-compatible.
In Solaris 10 and earlier, /bin/sh is a legacy Bourne shell implementation, as described in User Environment Feature Changes for Solaris 11.
Solaris 10 remains in extended support until January 2027.
illumos?
For now, I am having trouble finding definitive information about /bin/sh on illumos. It is a family of operating systems, and while I think /bin/sh is the same on all illumos distributions of the same version of illumos, I am not sure about that either. However, OmniOS is an illumos system. On my OmniOS r151050 virtual machine, /bin/sh is POSIX-compatible:
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 9 Jun 23 2024 /bin/sh -> i86/ksh93
So the issue doesn't affect my OmniOS system. I think there are older supported versions of OmniOS and of other illumos operating systems, and I haven't researched or examined /bin/sh in them.
Expected behavior 🤔
It may be that we cannot change the behavior in a way that produces an overall improvement:
- We could use
shinstead of/bin/sh. This moderately decreases consistency with Git, which I suspect should work this way but does not (described below). This would apply to cases where/bin/sh -c ...is used, not for scripts with shebangs, so there is no problem with using the wrong shell when/bin/shis actually called for. But having a shell command, such as the value ofcore.sshCommand, be interpreted differently for the same user on the same system in the same environment between Git and gitoxide seems like it might lead to strange problems. - We could use
shwhen present and fall back to/bin/sh. This has the same effect as just usingshon most systems, including the decreased consistency with Git and increased difficulty to users who want to configure nontrivial shell commands on systems with non-POSIX/bin/shthat are compatible with both Git and gitoxide. It might cover the case wherePATHis unset better than just usingsh, though. - Using
/bin/shfirst and falling back toshon a Unix-like system is probably the least worthwhile change, because I don't think any such systems without any/bin/share in common use.
We could do any of those just on systems that are known to have non-POSIX /bin/sh. Detecting the system makes things more complicated but probably not excessively so. The tradeoffs still apply on the affected systems, though.
If on some systems downstream builds of Git have a different shell, then that would be a compelling case for covering them separately. Otherwise it may not be worthwhile.
If this is not to be changed, then I think it is worth documenting in gix-command, and in gix_path::env::shell().
(Either a change to the behavior or the documentation seems like it would conflict with #1862 and #1864. I have no objection to such changes being made at any time and I can rebase to solve the conflict. But if I do them, I may wait until after those are done or to include them there.)
Git behavior
The prepare_shell_cmd function in Git calls git_shell_path to decide what shell to use to run commands of the form sh -c ...:
char *git_shell_path(void)
{
#ifndef GIT_WINDOWS_NATIVE
return xstrdup(SHELL_PATH);
#else
char *p = locate_in_PATH("sh");
convert_slashes(p);
return p;
#endif
}That is:
- On Windows, the Windows
locate_in_PATHfunction (which is a macro formingw_locate_in_PATHin another file, and not the Unix-specificlocate_in_PATHfunction in this same file) is called to do aPATHsearch, then\separators are changed to/. - On all systems, including all Unix-like systems (including Cygwin), the compile-time
SHELL_PATHconstant is used. This could in principle be set differently when compiling on different systems. But unless configured differently at compile-time, it is/bin/sh.
Steps to reproduce 🕹
This can be double-checked by examining the above references. It could be useful to show results of a simple experiment on a system that continues to be used in practice, in a default or otherwise common realistic configuration, wherein /bin/sh exists but is not a POSIX-compatible shell and a separate POSIX-compatible sh exists and is present in a bin or sbin directory listed ahead of /bin in the PATH. In particular, that could help verify any examples or details being considered for inclusion in docstrings. I currently have no such system, but I may be able to set one up at some point.