#! /bin/sh # bash-login --- invoke bash when using /bin/sh as login shell # Copyright (C) 1996, 1999 Noah S. Friedman # Author: Noah Friedman # Created: 1996-10-11 # $Id: bash-login,v 1.13 2004/11/29 06:16:15 friedman Exp $ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, you can either send email to this # program's maintainer or write to: The Free Software Foundation, # Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA. # Commentary: # This script allows you to set your login shell to /bin/sh, but invoke # bash transparently on login. If bash can't be found, restart the bourne # shell. This script should either be `execed' from .profile or else # copied into it wholesale. One possible .profile logic is: # # case "${BASH_LOGIN_FAILED_P+set}:$LOGGED:$0" in # set:*:* | *:t:* ) : ;; # *:*:-sh | *:*:-*/sh ) # case "${SINIT_MACHTYPE-unset}" in # unset ) # hosttype=$HOME/etc/init/bin/hosttype # if test -f $hosttype; then # SINIT_MACHTYPE=`$hosttype` # export SINIT_MACHTYPE # fi ;; # esac # p=$HOME/bin/share/bash-login # if test -f "$p"; then # exec=exec # # If /bin/sh is bash 2.x, there is some lossage which prevents # # interactive shells from working correctly if we exec here. # case "$BASH_VERSION" in 2.* ) exec= ;; esac # $exec /bin/sh "$p" # exit $? # fi # ;; # esac # # This allows you to set your login shell to something safe in heterogenous # environments where bash may not exist, but you want to use it if it's # available. # Code: # Name by which this script was invoked. progname=`echo "$0" | sed -e 's/[^\/]*\///g'` # To prevent hairy quoting and escaping later. bq='`' eq="'" usage="Usage: $progname {options} Options are: -D, --debug Turn on shell debugging ($bq${bq}set -x$eq$eq). -h, --help You're looking at it. -L, --no-login Do not invoke bash as a login shell. -p, --print-path Print path of bash command that would be run. Print nothing if bash cannot be found. -S, --no-set-default-shell Do not change value of \$SHELL. -v, --verbose Be verbose. " # Initialize variables. # Don't use `unset' since old bourne shells don't have this command. # Instead, assign them an empty value. debug= verbose= printp= setshellp=t loginp=t # Usage: eval "$getopt"; value=$optarg # or optarg_optional=t; eval "$getopt"; value=$optarg # # This function automatically shifts the positional args as appropriate. # The argument to an option is optional if the variable `optarg_optional' # is non-empty. Otherwise, the argument is required and getopt will cause # the program to exit on an error. optarg_optional is reset to be empty # after every call to getopt. The argument (if any) is stored in the # variable `optarg'. # # Long option syntax is `--foo=bar' or `--foo bar'. # For optional args, you must use the `--foo=bar' long option syntax # if the argument starts with `-', otherwise the argument will be ignored # and treated as the next option. # # Note: because of broken bourne shells, using --foo=bar syntax can # actually screw the quoting of args that end with trailing newlines. # Specifically, most shells strip trailing newlines from substituted # output, regardless of quoting. getopt=' { optarg= case "$1" in --*=* ) optarg=`echo "$1" | sed -e "1s/^[^=]*=//"` ; shift ;; -* ) case "${2+set}:$optarg_optional" in set: ) optarg="$2" ; shift ; shift ;; set:?* ) case "$2" in -* ) shift ;; * ) optarg="$2"; shift; shift ;; esac ;; : ) option="$1" case "$option" in --*=* ) option=`echo "$option" | sed -e "1s/=.*//;q"` ;; esac echo "$progname: option $bq$option$eq requires argument." 1>&2 echo "$progname: use $bq--help$eq to list option syntax." 1>&2 exit 1 ;; * ) shift ;; esac ;; esac optarg_optional= }' # Parse command line arguments. # Make sure that all wildcarded options are long enough to be unambiguous. # It's a good idea to document the full long option name in each case. # Long options which take arguments will need a `*' appended to the # canonical name to match the value appended after the `=' character. while : ; do case $# in 0) break ;; esac case "$1" in -D | --debug | --d* ) debug=t shift ;; -h | --help | --h* ) echo "$usage" 1>&2 exit 0 ;; -L | --no-login | -no-l* ) loginp=nil shift ;; -p | --print-path | --p* ) printp=t shift ;; -S | --no-set-default-shell | --no-s* ) setshellp= shift ;; -v | --verbose | --v* ) verbose=t shift ;; -- ) # Stop option processing shift break ;; -? | --* ) case "$1" in --*=* ) arg=`echo "$1" | sed -e 's/=.*//'` ;; * ) arg="$1" ;; esac exec 1>&2 echo "$progname: unknown or ambiguous option $bq$arg$eq" echo "$progname: Use $bq--help$eq for a list of options." exit 1 ;; -??* ) # Split grouped single options into separate args and try again optarg="$1" shift set fnord `echo "x$optarg" | sed -e 's/^x-//;s/\(.\)/-\1 /g'` ${1+"$@"} shift ;; * ) break ;; esac done case "$debug" in t ) set -x ;; esac # Directories where bash may exist. # These should be specified in reverse order of preference. pathdirs=" /usr/sww/bin /usr/local/bin /usr/local/gnubin /usr/local/gnu/bin /tools/contrib/bin /tools/ns/bin /opt/gnu/bin /opt/local/bin /opt/lude/bin /usr/bin /bin $HOME/etc/arch/${SINIT_MACHTYPE-unknown}/bin " for d in $pathdirs; do case "$PATH" in "$d" | *":$d:"* | "$d:"* | *":$d" ) : ;; * ) PATH="$d:$PATH"; export PATH ;; esac done case "$printp" in t ) path=`echo "$PATH" | sed -e 's/^:/.:/;s/::/:.:/g;s/:$/:./;s/:/ /g'` for p in $path ; do if test -f "$p/bash" && { "$p/bash" -c : ; } 2> /dev/null; then echo "$p/bash" exit 0 fi done exit 1 ;; esac # Not printing; actually execute bash # The -norc option in the test is just to see if bash is really bash. # On one system, bash was a symlink to a v7 bourne shell! if { bash -norc -c : ; } 2> /dev/null ; then exec bash -norc -c ' oSHELL="$SHELL" case "'"$setshellp"'" in t ) export SHELL=`type -path bash` ;; esac execflag= case "'"$loginp"':$BASH_VERSION" in t:1.*) execflag="-" ;; t:* ) execflag="-l" ;; esac no_exit_on_failed_exec=t exec $execflag bash ${1+"$@"} export SHELL="$oSHELL" export BASH_LOGIN_FAILED_P=t exec $execflag $SHELL ${1+"$@"} ' ${1+"$@"} else exec /bin/sh ${1+"$@"} fi # bash-login ends here