From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 567 invoked from network); 7 Sep 2001 17:54:18 -0000 Received: from sunsite.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 7 Sep 2001 17:54:18 -0000 Received: (qmail 9873 invoked by alias); 7 Sep 2001 17:54:11 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 15747 Received: (qmail 9860 invoked from network); 7 Sep 2001 17:54:10 -0000 Date: Fri, 7 Sep 2001 19:35:50 +0100 From: Adam Spiers To: zsh workers mailing list Subject: Switching shell safely and efficiently Message-ID: <20010907193550.A5678@thelonious.new.ox.ac.uk> Reply-To: Adam Spiers Mail-Followup-To: zsh workers mailing list Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i X-Home-Page: http://www.new.ox.ac.uk/~adam/ X-OS: RedHat Linux Regarding switching shells if zsh isn't your login shell ... I spawn new shells often enough that a safety-check prompt as suggested in section 1.7 of the FAQ would be too annoying. Using exec is preferable, to avoid leaving loads of copies of bash lying around in the process table doing nothing, but for me, the exec has been known to fail (despite a -x check succeeding) due to library mismatches between our various machines in the office. So I wanted something that hit the sweet spot in the safety/efficiency trade-off, and I came up with the following. Feel free to criticise, but if enough people think it's ok, would it be worth including in Misc/, or mentioning in the FAQ? --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- # Adam's .switch_shell # # Try switch shell if we're interactive, aiming for safety, but # not so much that we end up hogging memory. # # $Id: .switch_shell,v 1.9 2001/09/07 18:34:01 adam Exp $ # # Usage: # # . /path/to/.switch_shell [-d] [ /path/to/new_shell [ ] # -d turns on debugging if [ "$1" = '-d' ]; then debug=yes shift fi if [ -n "$1" ]; then myshell="$1" shift else # Sensible default shell to switch to. myshell=`which zsh` fi myshell_args="$@" switch_shell_safely () { # we do this rather than exec() just in case $myshell fails to run. [ -n "$debug" ] && echo "Switching to $myshell safely ..." $myshell $myshell_args "$@" && exit } switch_shell_dangerously () { [ -n "$debug" ] && echo "Switching to $myshell dangerously ..." exec $myshell $myshell_args "$@" } switch_shell () { if [ ! -x $myshell ]; then [ -n "$debug" ] && echo "$myshell not executable; aborting switch." return fi if [ -n "$NO_SWITCH" ]; then [ -n "$debug" ] && echo 'Shell switching disabled by $NO_SWITCH; aborting.' return fi case "$SHLVL" in 1) # login shell, be careful switch_shell_safely "$@" ;; *) # other shell, be risky and save memory switch_shell_dangerously "$@" ;; esac } # only switch if we're interactive case "$-" in *i*) switch_shell "$@" ;; esac --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- Then you put something like [ -e ~/.switch_shell ] && . ~/.switch_shell in your .bashrc. Although I wrote it to be as portable as possible (how global is $SHLVL ?), one obvious disadvantage is that it won't work with any type of csh. You also need bash () { NO_SWITCH="yes" command bash "$@" } somewhere in your .zshrc if you're ever forc^Wrequired to invoke bash. Adam