pushd/popd as ksh functions: possible in unix pc ksh?

Bruce Lilly bruce at balilly.UUCP
Sun Dec 30 00:20:30 AEST 1990


In article <1990Dec28.054110.13613 at shibaya.lonestar.org> afc at shibaya.lonestar.org (Augustine Cano) writes:
>
>I just typed in the pushd/popd functions found in "The Korn Shell" by Bolsky
>and Korn and guess what... they don't work!  Is this because of our ancient
>version?  Has anybody attempted this?  Does anybody have a working version
>of pushd/popd as ksh functions that work on our antiquated shell?

In addition to Thad's comments, I can offer the following which ``sort
of'' work (seems to be a minor problem after su'ing).  These are the
``dirs'', ``cd'', and ``mcd'' functions described in the same section as
``pushd'' and ``popd''.  The push and pop stuff is in-line.  I hope this
helps.  I've also included a function ``su'' which allows one to run a
shell as another user in a new window (using windy) -- with this, I only
run a single login window, as I can then run a new window (e.g. as root)
to do other things.

	unalias cd
	alias cd=_cd

	function _cd
	{
		typeset dir=$1
		integer n=0 type=4
		case $1 in
		-|-1|2) # cd -
			n=_push_top type=1
			;;
		-[1-9]|-[1-9][0-9])	# cd -n
			n=_push_top+${1#-}-1 type=2
			;;
		1)	# keep present directory
			print -r - "$PWD"
			return
			;;
		[2-9]|[1-9][0-9])	# cd n
			n=_push_top+${1}-2 type=2
			;;
		*)	if	((_push_top <= 0))
			then	type=3 n=_push_max
			fi
			;;
		esac
		if ((type<3))
		then	if ((n >= _push_max))
				then	print cd: Directory stack not that deep.
					return 1
				else	dir=${_push_stack[n]}
				fi
		fi
		case $dir in
		\~)	dir=$HOME
			;;
		\~/*)	dir=$HOME${dir#~}
				;;
		\~*)	dirleft=${dir%%/*}
			dirright=${dir##*/}
			if [ "$dirleft" = "$dirright" ]
			then
				dirright=
			else
				dirright=/$dirright
			fi
			username=${dirleft#~}
			userhome=`grep ^$username: /etc/passwd | cut -d: -f6 | sed -e "s,/$,,"`
			dir=$userhome$dirright
			unset dirright dirleft username userhome
			;;
		esac
		\cd "${dir:-$@}" > /dev/null || return 1
		dir=${OLDPWD#$HOME/}
		case $dir in
		$HOME)
			dir=\~
			;;
		/*)	;;
		*)	dir=\~/$dir;;
		esac
		case $type in
		1)	# swap first two elements
			_push_stack[_push_top=_push_top-1]=$dir
			;;
		2|3)	# put $dir on top and shift down by one until top
			integer i=_push_top
			for dir in "$dir" "${_push_stack[@]}"
			do ((i > n)) && break
				_push_stack[i]=$dir
				i=i+1
			done
			;;
		4)	# push name
			_push_stack[_push_top=_push_top-1]=$dir
			;;
		esac
			print -r - "$PWD"
	}

	function dirs
	{
		typeset dir=${PWD#$HOME/}
		case $dir in
		$HOME)
			dir=\~ ;;
		/*)	;;
		*)	dir=\~/$dir;;
		esac
		print -r - "$dir ${_push_stack[@]}"
	}

	function mcd
	{
		typeset dir="${PWD#$HOME/}"
		case $dir in
		~/*)	dir=$HOME${dir#~};;
		esac
		case $dir in
		$HOME)
			dir=\~
			;;
		/*)	;;
		*)	dir=\~/$dir;;
		esac
		OLDPS3=$PS3
		PS3='Select by number or enter a name: '
		select dir in "$dir" "${_push_stack[@]}"
		do	if	_cd $REPLY
			then	return
			fi
		done
		PS3=$OLDPS3
	}

	function su {
		if [ "$1" = "-" ]
		then
			# no problem - .profile will take care of things
			windy -b /bin/su $*
		else
			# need to make sure ksh is used
			# but can't simply force "-" because that will clear environment
			# need to take care of ENV and HISTFILE
			tempENV=$ENV
			tempHISTFILE=$HISTFILE
			tempHISTSIZE=$HISTSIZE
			tempHOME=$HOME
			tempMAIL=$MAIL
			tempMAILPATH=$MAILPATH
			if [ $# = 0 ]
			then
				# no args - root is default
				suuser=root
				suhome=""
			else
				# have some args - $1 must be user
				suuser=$1
				suhome=`grep "^${suuser}:" /etc/passwd | cut -d: -f6 | sed -e "s,/$,,"`
				shift
			fi
			ENV=${suhome}/.kshrc
			HISTFILE=${suhome}/.kshistory
			HISTSIZE=999
			HOME=${suhome:=/}
			unset MAIL
			MAILPATH=$MAILPATH:/usr/mail/$suuser:/usr/spool/uucppublic/$suuser
			windy -b /bin/su ${suuser} -c "exec /bin/ksh $*"
			ENV=$tempENV
			HISTFILE=$tempHISTFILE
			HISTSIZE=$tempHISTSIZE
			HOME=$tempHOME
			MAIL=$tempMAIL
			MAILPATH=$tempMAILPATH
			unset suuser suhome tempENV tempHISTFILE tempHISTSIZE tempHOME tempMAIL tempMAILPATH
		fi
	}

--
	Bruce Lilly		blilly!balilly!bruce at sonyd1.Broadcast.Sony.COM



More information about the Comp.sys.att mailing list