I do not understand why `what /bin/sh` and `/bin/sh --version` do not agree on macOS Big Sur

On macOS Big Sur, I get

$ what /bin/sh
/bin/sh
    PROGRAM:sh  PROJECT:dash-11
    PROGRAM:sh  PROJECT:dash-11
$ /bin/sh --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20)
Copyright (C) 2007 Free Software Foundation, Inc.

It seems that /bin/sh is actually bash and not dash. Why is what saying differently?


Solution 1:

/bin/sh is a wrapper that forwards to another shell. If the link /private/var/select/sh is present, the shell pointed to by this link is started. Otherwise, one of fallbacks (bash, dash, or zsh) is executed.

So if your /private/var/select/sh points to /bin/bash, that's what eventually gets executed when you run /bin/sh --version.

See also man sh where this is described.

It seems this wrapper is indeed from the dash project (or at least Apple's version; couldn't find the source they're using), which is why what reports dash-11.

Solution 2:

When you run what, the program looks through the binary /bin/sh searching for a specific text pattern. This specific text pattern was put there by a source code revision control system named SCCS, that is used to keep track of changes to source code. The idea was that SCCS automatically updated a text string within the source code to contain a version marker that would then end up in the finished program. The what command could then be used to figure out which version of the source code that was used for building a specific binary.

Today, SCCS is considered ancient - being designed in the early 70s and not is not really used by anyone anymore (except perhaps for software archaeology). Therefore you can commonly find that programs that contain code dating back a long while might have such a text pattern inserted decades ago that hasn't been updated since or requires manual updating.

Basically you cannot really be sure that what outputs something that is actually "true".

In particular case it is so that sh is often a reduced version of a shell program (in comparison to for example a full blown bash shell). For example on the Mac I'm using right now, sh is 31 kB binary, where for example bash comes in at 609 kB and dash at 108 kB.

It is common to see that sh is a stripped down version of some other shell, or only a "bare-bones" shell. It is also common to see that other shells, such as for example bash offers a mode where they can be used to replace sh by simulating a simpler shell. In addition you can have a small, simple sh that calls out to a larger shell binary (like bash) when complexity is needed.

Earlier on macOS, sh was basically just bash run in compatibility mode. However, bash is a quite large program. On the other hand dash can also function as a simple sh shell, and is more light-weight. In order to get compatibility between versions, you can have dash simply respond to --version as bash would have done, behave like sh would have done - all while being a dash binary.