[comp.unix.questions] A csh question ...

ljz@fxgrp.UUCP (Lloyd Zusman) (05/21/88)

A question concerning csh:

Can anyone explain why .login gets sourced *after* .cshrc?  I am constantly
running into situations where I'd like .login to get sourced first, and I
cannot see any good reasons for why it should get sourced after .cshrc.

I end up doing things like the following hack to get around this:

    # This resides at the top of a hypothetical .cshrc file ...

    if (! ${?FIRST_TIME_THROUGH}) then
    	setenv FIRST_TIME_THROUGH
    	# do all sorts of startup stuff that I would prefer to put
    	# into .login if it were only sourced before .cshrc
    endif

    ...

Are there any csh's out there that do this differently, perhaps if some
command-line flag is set?

--
  Lloyd Zusman                          UUCP:   ...!ames!fxgrp!ljz
  Master Byte Software              Internet:   ljz%fx.com@ames.arc.nasa.gov
  Los Gatos, California               or try:   fxgrp!ljz@ames.arc.nasa.gov
  "We take things well in hand."

gandalf@csli.STANFORD.EDU (Juergen Wagner) (05/21/88)

In article <636@fxgrp.UUCP> ljz%fx.com@ames.arc.nasa.gov (Lloyd Zusman) writes:
>A question concerning csh:
>
>Can anyone explain why .login gets sourced *after* .cshrc?  I am constantly
>running into situations where I'd like .login to get sourced first, and I
>cannot see any good reasons for why it should get sourced after .cshrc.

I don't see why you would like to read .login first. Basically, .cshrc has
the job of setting up things you'd like to have in *every* csh. Typically,
you will have a unconditional section, and a section depending on the value
of $?prompt. Everything else should go into .login.

>I end up doing things like the following hack to get around this:
>
>    # This resides at the top of a hypothetical .cshrc file ...
>
>    if (! ${?FIRST_TIME_THROUGH}) then
>    	setenv FIRST_TIME_THROUGH
>    	# do all sorts of startup stuff that I would prefer to put
>    	# into .login if it were only sourced before .cshrc
>    endif

What makes you think something gets executed twice? The csh reads .cshrc,
i.e. sets up an environment suitable for your interactive needs, as well as
for mail or the Liszt LISP compiler who fire up cshs. Then, your .login
is source'd, thereby establishing all the things you need for a (now
definitely interactive) session, like biff, stty, tset, ... Since environment
variables are inherited from the parent's shell, you can set environment
variables once in .login.

So, I don't see any reason why you may want to have .login executed first.
Maybe you could elaborate your point a bit.

>Are there any csh's out there that do this differently, perhaps if some
>command-line flag is set?

As far as I can tell, all cshs do it this way (i.e. read .cshrc, then .login)
because it makes sense.


-- 
Juergen "Gandalf" Wagner,		   gandalf@csli.stanford.edu
Center for the Study of Language and Information (CSLI), Stanford CA

barnett@vdsvax.steinmetz.ge.com (Bruce G. Barnett) (05/21/88)

In article <636@fxgrp.UUCP> ljz%fx.com@ames.arc.nasa.gov (Lloyd Zusman) writes:
|Can anyone explain why .login gets sourced *after* .cshrc? 

Probably because it makes sense. How else to you specify a command to
execute automatically when you log in that changes your environment?

Examples: emacs, X windows, suntools, screen-based applications, etc.

I usually test for the value of prompt, user, and/or term in my .cshrc file.
This way I can distinguish between a script, rcp/rsh, rlogin or login.
This has always been sufficient for me.

What are you doing that requires the opposite?

(You can always do a 'source .my-login' in your .login file).
-- 
	Bruce G. Barnett 	<barnett@ge-crd.ARPA> <barnett@steinmetz.UUCP>
				uunet!steinmetz!barnett

gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/21/88)

In article <636@fxgrp.UUCP> ljz%fx.com@ames.arc.nasa.gov (Lloyd Zusman) writes:
>Can anyone explain why .login gets sourced *after* .cshrc?  I am constantly
>running into situations where I'd like .login to get sourced first, and I
>cannot see any good reasons for why it should get sourced after .cshrc.

You're right, and csh is wrong, but as you can imagine it cannot be
changed now.

>Are there any csh's out there that do this differently, perhaps if some
>command-line flag is set?

Not that I know of.  The BRL Bourne shell equivalent feature (ENV file)
does this right.

ljz@fxgrp.UUCP (Lloyd Zusman) (05/22/88)

In article <3990@csli.STANFORD.EDU> gandalf@csli.stanford.edu (Juergen Wagner) writes:
  In article <636@fxgrp.UUCP> ljz%fx.com@ames.arc.nasa.gov (Lloyd Zusman) writes:
  >Can anyone explain why .login gets sourced *after* .cshrc?  ...
  
  I don't see why you would like to read .login first. Basically, .cshrc has
  the job of setting up things you'd like to have in *every* csh. Typically,
  you will have a unconditional section, and a section depending on the value
  of $?prompt. Everything else should go into .login.
  
Perhaps I didn't make myself clear.  For those of you who didn't
understand my question, let me try again, this time giving a bit more
detail ...

The C shell has, among other things, local shell variables (assigned
via the 'set' command) and environment variables (assigned via
'setenv').  The environment variables get inherited by children, while
the shell variables don't.  The .cshrc file gets sourced every time
csh is invoked (unless it's invoked with the -f option or it is a
shell script whose first line is "#!/bin/csh -f"), while .login gets
invoked only when I start up, *after* the initial invocation of .cshrc.

Since environment variables are automatically inherited by children, I
tend to use them to hold information that I may wish to know about in
all my subshells.  For example, if I do a

    setenv HOSTNAME "`hostname`"

in my login shell, all subshells will inherit this value.  On the
other hand, if I do a

    set HOSTNAME = "`hostname`"

I would have to repeat this command every time I enter a subshell, if
the value of HOSTNAME is important to me.  In the former case, it would
be logical to put the 'setenv ...' into my .login, and in the latter case,
the 'set ...' should be in .cshrc.

I tend to use very few 'set' variables, because I wish to avoid the
overhead of sourcing a .cshrc with lots of commands.  I almost always
write my csh scripts with the first line set to "#!/bin/csh -f" so that
they will start up quickly.  For these two reasons, among others, I
tend to use lots of environment variables.

Now, I also set aliases, and this needs to be done in my .cshrc file,
since aliases aren't inherited by children.  Some of my aliases make
use of the environment variables I set.  But since my .login gets run
*after* my .cshrc, I can't put these 'setenv' calls in my .login.

I tend to do things like the following example to get around this:

    # .cshrc file (extremely oversimplified) ...

    if (! ${?HOSTNAME}) then
    	#
    	# I don't want to call `hostname` every time I go to a
    	# subshell, since hostname is an external program and takes up
    	# system overhead.  My host name shouldn't change during the
    	# course of a login session.  I want to use $HOSTNAME in some
    	# of my aliases and to determine certain paths through my
    	# .cshrc logic.  This same thinking applies to certain other
    	# environment variables I set.
    	#
    	setenv HOSTNAME "`hostname`"
    	# etc. ...
    endif

    # alias settings go here
    # etc. ...

It would be nice if I could put the stuff between 'if (! ${?HOSTNAME}) ...'
and 'endif' into my .login file, and if .login would get sourced
before .cshrc, but I know this is impossible.  This is what inspired
my original question.

  >I end up doing things like the following hack ...
  >
  >    # This resides at the top of a hypothetical .cshrc file ...
  >
  >    if (! ${?FIRST_TIME_THROUGH}) then
  >    	setenv FIRST_TIME_THROUGH
  >    	# do all sorts of startup stuff that I would prefer to put
  >    	# into .login if it were only sourced before .cshrc
  >    endif
  
  What makes you think something gets executed twice?  ...

If I didn't have the 'if (! ${?FIRST_TIME_THROUGH) ...' logic bracketing
the '#do all sorts of startup stuff' logic, this 'startup stuff' would
get executed every time I entered a subshell or ran a csh script that
didn't begin with "#!/bin/csh -f".  I don't want this to happen.

  >Are there any csh's out there that do this differently, perhaps if some
  >command-line flag is set?
  
  As far as I can tell, all cshs do it this way (i.e. read .cshrc, then .login)
  because it makes sense.
  
But it doesn't make that much sense to me, given my above arguments, which
is what prompted my query here in the first place.

I'm quite willing to continue to make use of the method I outlined above
to make up for the fact that .login doesn't get sourced first.  But I'd
like to know if there's something I'm missing that would explain why
csh was designed to do it the way it does?
--
  Lloyd Zusman                          UUCP:   ...!ames!fxgrp!ljz
  Master Byte Software              Internet:   ljz%fx.com@ames.arc.nasa.gov
  Los Gatos, California               or try:   fxgrp!ljz@ames.arc.nasa.gov
  "We take things well in hand."

gandalf@csli.STANFORD.EDU (Juergen Wagner) (05/22/88)

After my posting I have received a number of responses of the form 
	"I am doing ... in my .cshrc, and also ... in .login, and
	 for that I need .login executed before .cshrc."

I don't believe there is the need to run .login before .cshrc. .cshrc
is intended to initialize *EVERY* csh fired up (except those invoked with
-f option), so subsequent programs run well. There is a clear distinction
between things which are typically done in .cshrc and .login:

.cshrc:
	setting umask
	setting up some environment variables like USER/LOGNAME/...
		which are supposed to be there in every environment.
	setting a (probably preliminary path/cdpath)
	setting csh variables
	providing aliases
	setting a (probably also preliminary) prompt.

    Never put in something setting the terminal, doing biff, echoing
    some text, etc. Remember: .cshrc is run every time a csh is fired
    up (by mail, emacs, X windows, LISP compilers, Prolog, ...) and
    should be as simple as possible (for obvious reasons). The case in
    which an interactive shell is started, can be recognized by using
    $?prompt conditionals. Oh, yes, and of course, the .cshrc *CAN*
    contain aliases and ways to set the prompt in a terminal dependent
    way. You just must not call them there.

.login:
	set the terminal type and initialize the terminal
	set some globally defined environment variables like (EXINIT, EDITOR,
		VISUAL, EMACSLIB, EMACSLOADPATH, TEXLIB, ...) which should
		be accessible for all programs run interactively.

    You now may say "what if one needs these variables in a rsh, too". Well,
    in that case, execute a "source .login" before you actually run the
    desired program, and be sure your .login also does the $?prompt business.

    In my .login, all the machine/terminal/UNIX-version dependent things
    are done. This includes computing/fetching host/...-dependent values
    for some environment variables. Then, 

    If you'd like to set your prompt depending on the terminal type (e.g.
    highlight some portions of it with terminal-specific control sequences),
    why don't you do this here. I can't remember the last time when I've
    exchanged the terminal just before running a new csh, so I don't see
    a need to do this in a fashion requiring to execute .login first. Either
    you are running with $?prompt==1, i.e. you can set the terminal-specific
    prompt wherever you want to, or you have $?prompt==0 and you don't have
    a terminal at all.

Apologies for this message being so long but I have a final comment on my
.login. The last two steps in my .login are 
    o  source a location-dependent .login (location=institute or something
       similar), and
    o  read a host type dependent .login (host type is sun, vax, ...).
This allows me to have the same rc files on all machines I'm working on, even
if one is a Bobcat (HP-UX), one is a Sun 3, one is a Sun 4, another one is 
a VAX, ...

A small configuration database consisting of some attribute lists and a couple
of shell scripts provides this functionality, and I've been pretty happy with
it. Of course, this doesn't claim to be an ideal solution to all problems but
has been working fine.

I'd love to hear of instances where it is impossible or unreasonable (i.e.
requiring too much efforts) to get along with the .cshrc .login order of
execution.

All opinions expressed herein, even the most arbitrary, are defended by my
employer with religious fervor.

-- 
Juergen "Gandalf" Wagner,		   gandalf@csli.stanford.edu
Center for the Study of Language and Information (CSLI), Stanford CA

barnett@vdsvax.steinmetz.ge.com (Bruce G. Barnett) (05/23/88)

In article <655@fxgrp.UUCP> ljz%fx.com@ames.arc.nasa.gov (Lloyd Zusman) writes:

|I tend to use very few 'set' variables, because I wish to avoid the
|overhead of sourcing a .cshrc with lots of commands.  I almost always
|write my csh scripts with the first line set to "#!/bin/csh -f" so that
|they will start up quickly.  For these two reasons, among others, I
|tend to use lots of environment variables.

You are trying to avoid extra overhead, but i believe you are doing it
the wrong way. See below.

|But I'd
|like to know if there's something I'm missing that would explain why
|csh was designed to do it the way it does?

Usually people start up special applications in their .login file.
Emacs, X windows, suntools, ... In fact, when you want the user to 
run a special application, you just modify the .login file. Yet
anything in the .cshrc file is also executed.

There are also times when you may want to allow a remote shell or copy, but
no local login. Because .cshrc is sourced before .login, this is
possible. You can have remote users/scripts that only run non-interactive, etc.

But let's not start anything religious.

If I understand what you want to do, I suggest you make use of
site specific .cshrc files. e.g.

	if ( -e .my-cshrc && -o .my-cshrc ) source .my-cshrc

Yes, this does mean you have to maintain an extra file.
But you probably have to maintain some site dependancies somewhere.
Use m4(1) or make(1) if you wish.

I believe this will be much more efficient that what you are doing
for the following reasons:

	1. Sticking extra baggage in your environment variables
	   means that each process has to copy the entire environment
	   variable list for EACH PROCESS. This slows down each fork.
	   Not just scripts.

	2. Testing for the existance of a file should be faster than
	   executing a program. (Okay, if all of your systems use the
	   same NFS home directory, this wouldn't win. The file would
	   always be there.)

	3. Enclosing large lists of aliases in if/then blocks
	   still requires the shell to scan past them even if they
	   aren't going to use them. That is, the construct

		if ( $?prompt ) then
			# monster list of aliases
			...
		endif 
	
	   is inefficient if the shell is not interactive.
-- 
	Bruce G. Barnett 	<barnett@ge-crd.ARPA> <barnett@steinmetz.UUCP>
				uunet!steinmetz!barnett

rgsmeb@abcom.ATT.COM (Michel Behna) (05/23/88)

From article <636@fxgrp.UUCP>, by ljz@fxgrp.UUCP (Lloyd Zusman):
> A question concerning csh:
> 
> Can anyone explain why .login gets sourced *after* .cshrc?  I am constantly

Excuse me for asking a stupid question, but why don't you move the code from 
one to the other? Would that solve yopur problem?
-- 
Michel Behna	 rgsmeb@abcom.att.com	 |  ihnp4!{ncsc1,codas}!abcom!rgsmeb
" It is all right for man to make love, and it is all right for man to make
war, but he shouldn't try to do both at the same time."

ljz@fxgrp.UUCP (Lloyd Zusman) (05/26/88)

In article <2791@abcom.ATT.COM> rgsmeb@abcom.ATT.COM (Michel Behna) writes:
  From article <636@fxgrp.UUCP>, by ljz@fxgrp.UUCP (Lloyd Zusman):
  > Can anyone explain why .login gets sourced *after* .cshrc?  I am constantly
  
  Excuse me for asking a stupid question, but why don't you move the code from 
  one to the other? Would that solve yopur problem?

No, because .login only gets sourced when you first log in, but .cshrc
gets sourced whenever a shell is started up.  The latter can take place
more than once per login session, and it usually does.

Hence, different types of information are put into the two files.

It's not a stupid question.


--
  Lloyd Zusman                          UUCP:   ...!ames!fxgrp!ljz
  Master Byte Software              Internet:   ljz%fx.com@ames.arc.nasa.gov
  Los Gatos, California               or try:   fxgrp!ljz@ames.arc.nasa.gov
  "We take things well in hand."

strong@tc.fluke.COM (Norm Strong) (05/26/88)

In article <636@fxgrp.UUCP> ljz%fx.com@ames.arc.nasa.gov (Lloyd Zusman) writes:
}A question concerning csh:
}
}Can anyone explain why .login gets sourced *after* .cshrc?  I am constantly
}running into situations where I'd like .login to get sourced first, and I
}cannot see any good reasons for why it should get sourced after .cshrc.
}
Why not put the contents of your .login file in your .cshrc file?
-- 

Norm   (strong@tc.fluke.com)

dg@lakart.UUCP (David Goodenough) (05/31/88)

>In article <636@fxgrp.UUCP> ljz%fx.com@ames.arc.nasa.gov (Lloyd Zusman) writes:
>}A question concerning csh:
>}Can anyone explain why .login gets sourced *after* .cshrc?  I am constantly
>}running into situations where I'd like .login to get sourced first, and I
>}cannot see any good reasons for why it should get sourced after .cshrc.
>
And in article <3872@fluke.COM>, strong@tc.fluke.COM (Norm Strong) replies:
> Why not put the contents of your .login file in your .cshrc file?

The reason that I believe it is done is to allow such things as

unset ignoreeof		# in ~/.cshrc

and then

set ignoreeof		# in ~/.login

Now this means that in all your c-shells except your login shell will respect
a ^D to exit, but you explicitly have to say "logout" or "exit" to your
login shell to get it to go away i.e. hammering ^D will return you to your
login shell but will stop there. The basic notion is that you set your
environment with .cshrc, and thene make any login shell changes (and of course
login only commands) in your .login. Now if anyone knows different they will
doubtless speak up :-) :-)
-- 
	dg@lakart.UUCP - David Goodenough		+---+
							| +-+-+
	....... !harvard!adelie!cfisun!lakart!dg	+-+-+ |
						  	  +---+

gph@hpsemc.HP.COM (Troutfishing in America) (06/04/88)

Lloyd Zusman writes:

-->Are there any csh's out there that do this differently, perhaps if some
-->command-line flag is set?
----------

    Lloyd, 

    I think you have a very good point.  It's interesting that the new
    Korn shell, which I view as an improvement over csh, first executes
    .profile, and then executes .kshrc.   .kshrc is executed with each
    invocation of a ksh.

    This is exactly the scenario you want for your csh.

    I use ksh, and this way is quite satisfactory.