Detecting (or not) the use of -l and -c together in Bourne shells

Many Bourne shells go slightly beyond the POSIX sh specification to also support a '-l' option that makes the shell act as a 'login shell'. POSIX's omission of -l isn't only because it doesn't really talk about login shells at all, it's also because Unix has a special way of marking login shells that goes back very far in its history . The -l option isn't necessarily what login and sshd and so on use, it's something that you can use if you specifically want to get a login shell in an unusual circumstance.

Bourne shells also have a '-c <command string>' option that causes the shell to execute the command string rather than be interactive (this is a long standing option that is in POSIX). It may surprise you to hear that most or all Bourne shells that support -l also allow you to use -l and -c together. Basically all Bourne shells interpret this as first executing your .profile and so on, then executing the command string instead of going interactive. One use for this is to non-interactively run a command line in the context of your fully set up shell, with $PATH and other environment variables ready for use.

Now, suppose (not hypothetically) that you have some things in your .profile that you would like to not run in this situation. Perhaps they're unnecessary and expensive, or perhaps they cause problems in the rest of your environment if they're run outside the context of a genuine login shell. It would be nice for your .profile to be able to detect this. Unfortunately, as far as I know at the moment this is impossible in general.

If you're using Bash specifically (and /bin/sh is Bash), Bash will set ' $BASH_EXECUTION_STRING ' in this case when invoked as either 'bash -l -c ...' or 'sh -l -c'. As far as I know, this is the only common Bourne compatible shell that provides any way to detect this. I've been unable to find any other shell that provides any indicator of this, neither as environment variables nor as, for example setting ' $* ' or ' $0 ' to any special values.

(I checked Dash on Ubuntu LTS, which is their standard /bin/sh, the OpenBSD ksh (which is also /bin/sh), and FreeBSD /bin/sh (also a descendant of Kenneth Almquist's shell, like Dash. Fedora Linux uses Bash as /bin/sh.)

If you use Bash as your login shell but /bin/sh is something else (and things are specifically doing '/bin/sh -l -c ...'), you can rename your .profile to be .bash_profile , so it will only be read by Bash. If you have common setup stuff, you could put it in .profile and source that from your .bash_profile (although Bash has some complicated tangles around startup files , also ).

If what you really care about is running your .profile a second time inside a first session, you can set a marker environment variable at the end of your .profile and then have your .profile look to see if the environment variable is set. If it is, you can skip re-doing things. This doesn't help if some clever program is doing 'ssh yourhost sh -l -c ....' in order to run some command line with your full environment set up (or if a graphical login environment does this, partly because of the Unix shell initialization problem ). Under some circumstances you can detect this in your .profile because it won't be connected to a tty and you can check this with, for example, 'test -t 0'. Under other circumstances , you may have a tty despite being 'non interactive' in practice.

(It's possible that there is some generally available marker that I'm not aware of. If so, I'd be happy to hear about it.)