There are heuristics that can help you, but there is no fully reliable way.
Otheus shows how to use file descriptors. That's a nice heuristic, which works in most cases. However there are edge cases where it fails, and there's no way to detect failures.
Example: take the following script.
lsof -p$$ | sed 's/[0-9][0-9]*//'
Make two copies of the script, one called
foo, one called
bar. Now let's stress this a bit:
$ env -i PATH=/bin:/usr/bin perl -MPOSIX -e 'dup2(4, 11) or die $!; exec "dash", "foo", "bar"' 3<foo 4<bar </dev/null >foo.out
$ env -i PATH=/bin:/usr/bin perl -MPOSIX -e 'dup2(3, 10) or die $!; exec "dash", "bar", "foo"' 3<foo 4<bar </dev/null >bar.out
$ diff foo.out bar.out
< dash gilles 1w REG 0,24 99 10130024 /tmp/202954/foo.out
dash gilles 1w REG 0,24 99 10130022 /tmp/202954/bar.out
The only difference here is the file in which I logged the output.
Another case where this heuristic would fail is if the shell was invoked on standard input, or with
Another approach is to parse the shell's command line. On Linux, you can access it through
/proc. The arguments are null-delimited, which is hard to parse with portable shell tools (recent GNU tools make it easier), but it can be done. Portably, you need to call
ps to access the arguments, and there is no output format that is unambiguous:
ps -o args concatenates the arguments with spaces, and may be truncated.
Even on Linux, the problem you'll run into here is that the shell might have been invoked with options that your script isn't aware of, and one of these options might take an argument. For example, suppose you have a script called
1 and another script called
mksh -T 1 2
This invokes mksh on
/dev/tty1 and runs the script
zsh -T 1 2
This invokes zsh with the
cprecedences option and runs the script
1 with the argument
You need knowledge of individual shells to tell these apart. With this method, you can detect edge cases: if you see a nonstandard option, bail out.