___ _ __ _ _ / __\__| |__ / _\ |_ __ _ _ __| |_ _ _ _ __ / / / __| '_ \ \ \| __/ _` | '__| __| | | | '_ \ / /__\__ \ | | | _\ \ || (_| | | | |_| |_| | |_) | \____/___/_| |_| \__/\__\__,_|_| \__|\__,_| .__/ __ |_| / _\_ _ _ __ ___ _ __ ___ __ _ _ __ _ _ \ \| | | | '_ ` _ \| '_ ` _ \ / _` | '__| | | | _\ \ |_| | | | | | | | | | | | (_| | | | |_| | \__/\__,_|_| |_| |_|_| |_| |_|\__,_|_| \__, | |___/ This document contains a summarized guide to the startup process for the csh and tcsh unix shell. In this guide you will find:- INDEX 1) Sections executed on startup under various conditions INDEX 2) What should/could be perform in each startup section INDEX 3) T/csh setup requiring no ".login" file. INDEX 4) A solution to X Window environment initialization problem INDEX 5) Csh Startup modularization INDEX 6) Small tricks, aliases and other bit 'n' pieces INDEX 7) Disclamer: Csh Script Programming Considered Harmful -- Anthony Thyssen -- Paul Davey This file can be found on the WWW in my "Tower of Computational Sorcery" on the floor devoted to "Shell Scripts". http://www.ict.griffith.edu.au/~anthony/info/shell/ -- Anthony Thyssen ------------------------------------------------------------------------------ INDEX 1) Sections executed on startup under various conditions Assuming that the .cshrc file is divided into two sections depending on if the 'prompt' was defined by the shell program. * Interactive (prompt defined -- normal user session) * Non-Interactive (prompt undefined -- script or rsh initialization) EG: #echo "Executing .cshrc script" #----- non-interactive shell ----- if ( ! $?prompt ) then # test if non-interactive (script or remote) ... ... exit 0 endif #------- interactive shell -------- ... ... NOTE: The non-interactive section should be very small and fast, providing the minimal amount of setup required to work. The only thing which must be provided is the 'path', and posibility the "LD_LIBRARY_PATH". IE: the locations of the commands and any environment required to run those commands. In particular the X window system path and library settup should be performed so that you can remotely execute the various X window commands (like "xterm"), and file transfer programs (like "rsync", and "unison") easilly. For example... set path = (/usr/ucb /usr/bin /usr/local/bin /opt/bin /usr/X11/bin) setenv LD_LIBRARY_PATH '/opt/lib:/usr/X11/lib:/usr/lib' This division creates three possible sections that can be executed on startup, (two in .cshrc, and one in .login) and you may want to include a fourth section with regards to .logout (exit csh script). Here are all the situations that I can find and the parts in the above scheme which are are executed for that situation :- csh script with a -f option no sections performed at all csh script without -f option non-interactive .cshrc script only remote command (rsh/ssh) non-interactive .cshrc script only program shell escaped commands non-interactive .cshrc script only sub-shell (t/csh or plain xterm) interactive .cshrc only full login or xterm -ls interactive .cshrc and .login in that order (and .logout on exit). -- Anthony Thyssen (anthony@cit.gu.edu.au) ------------------------------------------------------------------------------ INDEX 2) What should/could be perform in each startup section Non-interactive .cshrc (scripts, remote and shell escaped commands) * set important (must have) environment variables if we are csh (tcsh sets "HOST" and "HOSTTYPE" automatically for you) * default path so the X11 commands can be found without a full path, as well as for t/csh scripts without the (-f) flag * small number of aliases for use in rsh, the Sun Open Window File Manager user menu, or within "vi" shell escapes. * set umask (for remote commands or they run with umask 0) Interactive .cshrc (All other Csh and Tcsh related stuff should be here) * set complete interactive path for normal usage. This could be in .login but is here because the non-interactive test normally does not exist. It also places both path definitions in the same file for easier handling. * csh/tcsh settings:- prompts, filec, cdpath, periodic(tcsh). * full alias list for user's usage. I actually place this in a .cshaliases file which I source. * the cd-prompt hack for csh IE :- alias cwdcmd 'set prompt="$cwd:t> "' alias cd 'chdir \!* && cwdcmd' Full session startup -- .login (stuff to be set up once only) See also INDEX 3 for incorperating this into .cshrc * complete (once only) environment variable initialization * determine where we are logged in from (say for printer selection) * start X window system if necessary and not running * terminal setup commands : umask, stty, mesg * specialized terminal type setup. For example:- + dialin, network, or unknowen terminal type correction for pc's, macs, and home computers (amiga) + xterm determine DISPLAY and terminal size on remote machines set the xterminal title (IE: to the current host name) * checks for mail, news and other login notifications * check on breakin / illegal account access/usage * login and startup messages Exiting full session -- .logout (script called on logout) Remember ".logout" is called only if the shell exits normally! This can lead to problems if your shell core dumps and then you have to deal with a "You are already logged in" message 'cos ".logout" didn't decrement a login count. * cleanup of account * closing messages * session summeries NOTE: You do not need to do all the above. I myself do most of them except for a couple which is not needed in my own setups. If you have anything to add to this list please let me know. -- Anthony Thyssen ------------------------------------------------------------------------------ INDEX 3) T/csh setup requiring no ".login" file. I recently ceased using ".login" for just about anything. It's handy for setting the environment once but since it is read after ".cshrc: you can not use any variables or aliases it may setup. I now detect a login (or rsh job) by the fact that the environment (actually just the environment variable ENVSET) is not set. EG: in .cshrc script (immediately after non-interactive checks) # IS THE ENVIRONMENT SET? if ( $?ENVSET == 0 ) setenv ENVSET -1 # ensure ENVSET is defined if ( $ENVSET != 1) then # is the environment set # ---- normal login section ---- # do environment setup and terminal checks here ... setenv ENVSET 1 endif # ENVSET != 1 -- Paul Davey (pd@x.co.uk) ------------------------------------------------------------------------------ INDEX 4) A solution to X Window environment initialization problem For X it is convenient to have several clients (especially a window manager) started at login and of course this can be done from scripts such as .xsession run from xdm. However clients started from .xsession do not inherit the users (carefully tailored) environment from .cshrc/.login. One way around this is to make .xsession a csh script which sources .cshrc and/or .login but this is not particularly fast, reliable or portable. My solution is to make .xsession set a environment flag (XLOGIN) to 1 and to start one xterm (with shell) only. Within .cshrc a new section starts initial clients when XLOGIN is 1 after the environment has been initialized. It then sets XLOGIN to 0 to prevent this happening again if the file is reread. This allows the environment to be set in one file without having to source .cshrc from a .xsession written in csh (can't source csh from sh). Of course if you are logging in and running startx or xinit from the command line this approach is not needed as the X session inherits the environment from the login shell; This method will however cope with that case as well (my .xinitrc is a link to .xsession). EG for .xsession script #!/bin/sh # .xsession file HOST="@`hostname`" xrdb $HOME/.Xdefaults XLOGIN=1 export XLOGIN exec xterm -ls -geometry 80x24+0-0 -T "LOGIN$HOST" -n "LOGIN$HOST" AND in the .cshrc script (after the environment setup (see above) ) if ( $?XLOGIN ) then unsetenv XLOGIN # set a local csh variable for this critical xterm (started .xsession) set ignoreeof # ---- start other X clients ---- # Should really check xconsole exists (and works) before this bit # wait for xconsole to fork before continuing xconsole -daemon -geom 700x100-0-0 csh -f << EOF >& /dev/console set verbose twm & xterm -name xterm-$HOST -geometry 80x45+0+0 & xclock -g 100x100-0+0 & xsetroot -fg red -bg black -mod 2 2 & EOF endif # XLOGIN -- Paul Davey (pd@x.co.uk) NOTE: I myself do not like this method, instead I opt'ed for sourcing a bourne shell script with the appropriate minimal environment required in the .xsession file. This requires a bourne shell environment setup (sourced from .xsession) as well as a csh environment setup (from .login). It works for me. --- Anthony Thyssen ------------------------------------------------------------------------------ INDEX 5) Csh Startup modularization You may find it useful to actually split sections of your .cshrc into separate files. These can be read in with the source command which reads and evaluates a file in the current shell, ie without forking a subshell. (It is the equivalent of the "." command in sh). Breaking the .cshrc file into smaller files to be sourced, has certain advantages. * Reading of the .cshrc programming stucture is easier * All the aliases and environment variables are defined in the one place For example: i) Define your aliases in ~/.cshaliases ii) In .cshrc give the command "source ~/.cshaliases" in the interactive section defined above. Some canidates for modurizations are .cshaliases defines all your csh aliases .cshenv environment variable definitions (sourced from .login) .cshlogin a .login replacement to call from .cshrc ? (see INDEX 3) .cshXstartup X window startup clients script (see INDEX 4) .cshprompt script to set the csh prompt according to current directory The above are only suggestions, the file names used for the sourced csh scripts can be anything you like, or even stored in a .csh sub-directory. Any sourcing of an external file will slow down evaluation, but only very slighly. -- Paul Davey & Anthony Thyssen ------------------------------------------------------------------------------ INDEX 6) Small tricks, aliases and other bit 'n' pieces This is a list of small 'tricks' that can be incorperated into your own .cshrc/.login startup files. i) Show only new MOTD (messages of the the day) on login if (-f /etc/motd ) then cmp -s /etc/motd ~/.hushlogin if ($status) tee ~/.hushlogin < /etc/motd endif ii) Changing the prompt to reflect the current directory alias setprompt 'set prompt = "`pwd` > "' alias cd 'chdir \!* && setprompt' alias pushd 'pushd \!* && setprompt' alias popd 'popd \!* && setprompt' setprompt iii) Searching for a particular process (given as argument) WARNING this is for a SunOS environment and may be different for other OS's. alias pf 'ps auxgww|awk '\''/(^| |\(|\/)\!:1( |\)|$)/'\''|cut -c1-15,36-99' iv) Multiline prompt alias setprompt 'set prompt="\\ ${hostname:h}:${cwd}\\ \! % "' v) Log remote (rsh) non-interactive commands executed in this account. add something like the following to your .cshrc (non-interactive part) if ( ! $?prompt ) then # Record the ineractive command being executed set column = "`ps ww1 | head -1`" # figure out column from ps header set column = `expr "$column" : '\(.*\)COMMAND' : '.*' + 1` ps ww$$ | tail -1 | cut -c${column}- >> ~/command.log exit endif vi) Csh Function Scripts. Scripts which are executed by the current shell as if internal This allows more complex setprompt scripts, and for scripts to change the prompt, set environment variables or change the current directory. # Csh function scripts alias function 'set argv=(\!*); shift; source \!:1' # Specific Csh function alias setprompt function ~/bin/scripts/setprompt # Directory of Csh functions (initialization) foreach i (~/bin/csh.functions/*) alias $i:t function $i end vii) File/Directory mailing Aliases Mail files, binaries, and directories to other people easily Usage: mailfile addresss file alias a alias a mailfile 'cat ~/lib/line-cut \!:2 ~/lib/line-cut |\\ /usr/ucb/mail -s "file \!:2" \!:1' a mailuu 'uuencode \!:2 \!:2 | cat ~/lib/line-cut - ~/lib/line-cut |\\ /usr/ucb/mail -s "file \!:2.uu" \!:1' a maildir 'tar cvf - "\!:2" | compress | uuencode "\!:2.tar.Z" |\\ cat ~/lib/line-cut - ~/lib/line-cut |\\ /usr/ucb/mail -s "file \!:2.tar.Z.uu" \!:1' # Multiple file "tar mail" # Usage: tarmail address "subject" file... a tarmail 'tar cvf - \!:3* | compress | uuencode tarmail.tar.Z |\\ cat ~anthony/lib/line-cut - ~anthony/lib/line-cut |\\ /usr/ucb/mail -s "\!:2" \!:1' -- miscellaneous sources ------------------------------------------------------------------------------ INDEX 7) Disclamer: Csh Script Programming Considered Harmful There are plenty of reasons not to use csh for script writing. See Csh Programming Considered Harmful ftp://convex.com/pub/csh.whynot http://www.cit.gu.edu.au/~anthony/info/shell/csh.whynot-1.7 also http://www.cit.gu.edu.au/~anthony/info/shell/csh.whynot.extra This file is an attempt to explain how to make it easier and more convenient to use it interactively. It does NOT provide a guide to using csh as a general script writing language, and the authors recommend that it not be used for that purpose. But why use csh interactively? The aliases and history list alone make it worthwhile, extra features such as file completion, tilde expansion, and job control make even more useful. The tcsh command line editing and other interactive enhancements make it one of the best interactive shells around. There are arguably 'better' shells avaliable that can be used, but I have found many of them lacking in some important aspect or, generally not installed on most systems. A delivered vanilla machine however, is almost certain to have csh. A ".cshrc" and ".login" setup can then be easily copied and is available immediately. Faced with the choice between plain sh and bad old csh I'll take csh any day. -- Paul Davey -- Anthony Thyssen ------------------------------------------------------------------------------