A shell is started when you login, but it's also started by programs like make
, or when you run a shell script, or when you type :sh
to vi
, or when you create a new terminal window.
Originally, the shell read in ~/.profile
when you logged in or ran su
. This script would do things like announce whether you had new email, customize your erase and kill characters, and set and export the TERM and PATH variables. When started in almost any other context, the shell did not read ~/.profile
, because doing most of those things would be redundant. You were expected to have exported any important shell variables to the new shell.
The way the shell knew whether to read in ~/.profile
was to check whether the first character of argv[0]
, aka $0
, was '-'
.
Starting with csh
, aliases were introduced. Aliases weren't exported in the environment. csh
was designed to read in two different initialization scripts. ~/.login
was read only when a user logged in, and the cue to do this was if argv[0]
began with '-'
. ~/.cshrc
was read every time the shell was started. In general, one placed aliases in ~/.cshrc
and everything else in ~/.login
. csh
also supported ~/.logout
, which in most cases just cleared the screen and ran fortune
.
Other shells adopted these same features. ksh
would read in ~/.kshrc
, bash
would read in ~/.bashrc
, and those were where you'd place your alias definitions.
So, to make a long story short, the application that spawns a shell gets to decide whether it should be a "login shell", in which case there's that '-'
at the beginning, or a regular shell. In most cases, a shell that's going to be interactive is started as a login shell, and a shell meant just to run some commands, either as arguments or from a script, and then exit is a regular shell.
But it's all up to the whim of the application that starts the shell.