Unix's special way of marking login shells goes back to V2 Unix (at least)

December 10, 2022

Many Unix shells have some command line argument that tells them that they are a login shell; for example, Bash has '-l' (also '--login'), and I think that '-l' has become the de facto standard. However, this argument is not how Unix programs like sshd and login actually tell your shell that it's a login shell; instead, for a long time, a login shell has a '-' as the first character of its program name, or to put it another way, argv[0][0] is '-'.

Recently I wound up wondering how far back this approach goes. The answer turns out to be more interesting than I expected, and what exactly is done has changed over time. First, as you might expect, this behavior is in V7 Unix, where login.c sticks a '-' on the front of your shell's name (and is confident that your /etc/passwd shell entry will never be more than 14 characters long). In V6 and V5, we have the C source for login (V6, V5), and both versions simply set argv[0] to '-'. I don't think we have user level source for V4 or V3, but it turns out that we do have assembly source for V2's login.s, and to my surprise, it is still following the same approach of having argv[0] be '-' (visible in the definitions of 'mshell' and 'shellp').

So this approach to marking login shells goes back to pretty much the dawn of Unix, and might even be in V1 (again, I don't think we have user level source for V1). Unix has been doing it this way since at least mid 1972, or fifty years now, and for incremental historical compatibility, your system is probably still doing it today.

(Even OpenBSD, the modern Unix I would most expect to have modernized how login shells are marked, has left this intact in their login source code.)

PS: To my surprise, as late as 4.3 BSD, login.c is still assuming that your /etc/passwd shell is 14 characters or less (or otherwise it will overflow a buffer). This finally gets fixed in 4.4 BSD. This is also not fixed in the System III login.c. I haven't looked at System V, since source for that is less readily accessible.


Comments on this page:

By rwoodsmall at 2022-12-10 23:39:51:

SVR4 has the same assumptions/code in a slightly modified form:

https://github.com/ryanwoodsmall/oldsysv/blob/master/sysvr4/svr4/cmd/login/login.c#L146

but basename() is used against the shell for the strcat():

https://github.com/ryanwoodsmall/oldsysv/blob/master/sysvr4/svr4/cmd/login/login.c#L936-L937

OpenSolaris has similar code of the same pedigree that appears to have diverged in ~1991 or so:

https://www.tuhs.org/cgi-bin/utree.pl?file=OpenSolaris_b135/cmd/login/login.c

to my surprise,

What would your original guess have been, and why?

By cks at 2022-12-11 23:05:28:

My guess would have been that the notion of a 'login shell' would only appear when the shell itself got a notion of an initialization file that was read (only) by the login shell. I wouldn't have expected such an initialization file in the very earliest Unix shell but I'd also have expected it to appear before V7, so I would have guessed somewhere around V5 or V6.

With that said, it's quite possible that in V2, login's hardcoded '-' for the shell's argv[0] was simply a matter of slightly simpler code, instead of something intended as a signal to the shell. When the shell turned out to need such a signal (much later on), login's existing expedient practice could have been (re)used to create it.

Written on 10 December 2022.
« Sometimes an Ubuntu package of a Python module is probably good enough
Prometheus Blackbox 0.23.0 has added a nice improvement to its DNS checks »

Page tools: View Source, View Normal, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sat Dec 10 21:53:14 2022
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.