⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bcsh.sh

📁 linux下bash的源码
💻 SH
📖 第 1 页 / 共 2 页
字号:
# 1-Feb-86 09:37:35-MST,30567;000000000001# Return-Path: <unix-sources-request@BRL.ARPA># Received: from BRL-TGR.ARPA by SIMTEL20.ARPA with TCP; Sat 1 Feb 86 09:36:16-MST# Received: from usenet by TGR.BRL.ARPA id a002623; 1 Feb 86 9:33 EST# From: chris <chris@globetek.uucp># Newsgroups: net.sources# Subject: Improved Bcsh (Bourne Shell Cshell-Emulator)# Message-ID: <219@globetek.UUCP># Date: 30 Jan 86 17:34:26 GMT# To:       unix-sources@BRL-TGR.ARPA## This is a new, improved version of my Bourne shell cshell-emulator.# The code has been cleaned up quite a bit, and a couple of new features# added (now supports 'noclobber' and 'iclobber' variables).  A bug with# 'eval' that caused "illegal I/O" error messages on vanilla V7 shells has# also been fixed.# I have posted the program in its entirety because a context diff of the# old and new versions was longer than the new version...# --Chris#	Bcsh -- A Simple Cshell-Like Command Pre-Processor For The Bourne Shell##	"Copyright (c) Chris Robertson, December 1985"##	This software may be used for any purpose provided the original#	copyright notice and this notice are affixed thereto.  No warranties of#	any kind whatsoever are provided with this software, and it is hereby#	understood that the author is not liable for any damagages arising#	from the use of this software.##	Features Which the Cshell Does Not Have:#	----------------------------------------##	+  command history persists across bcsh sessions# 	+  global last-command editing via 'g^string1^string2^' syntax#	+  edit any command via $EDITOR or $VISUAL editors#	+  history file name, .bcshrc file name, alias file name, and number#	   of commands saved on termination can be set by environment variables#	+  prompt may evaluate commands, such as `pwd`, `date`, etc.#	+  the whole text of interactive 'for' and 'while' loops and 'if'#	   statements goes into the history list and may be re-run or edited#	+  multiple copies of commands and requests to see command history#	   are not added to the history list#	+  the history mechanism actually stores all commands entered in a#	   current session, not just $history of them.  This means that you#	   can increase $history on the fly and at once have a larger history.###	Synonyms:#	---------##	logout, exit, bye	write out history file and exit#	h, history		show current history list#	#	#	Aliases:#	--------##	alias NAME CMND		create an alias called NAME to run CMND#	unalias NAME		remove the alias NAME##	There are no 'current-session only' aliases -- all alias and unalias#	commands are permanent, and stored in the $aliasfile.##	If an alias contains positional variables -- $1, $2, $*, etc. -- any#	arguments following the alias name are considered to be values for#	those variables, and the alias is turned into a command of the form#	'set - arguments;alias'.  Otherwise, a simple substitution is performed#	for the alias and the rest of the command preserved.  The cshell#	convention of using '\!:n' in an alias to get bits of the current#	command is mercifully abandoned.##	Quotes are not necessary around the commands comprising an alias;#	in fact, any enclosing quotes are stripped when the alias is added#	to the file.##	A couple of typical aliases might be:##		goto	cd $1;pwd#		l	ls -F##	Note that aliasing something to "commands;logout" will not work -- if#	you want something to happen routinely on logout put it in the file#	specified by $logoutfile, default = $HOME/.blogout.###	Command Substitutions:#	----------------------##	!!			substitute last command from history list#	!!:N			substitute Nth element of last command from#				history list -- 0 = command name, 1 = 1st arg# 	!!:$			substitute last element of last command from#				history list# 	!!:*			substitute all arguments to last command#				from history list#	!NUMBER			substitute command NUMBER from the history list#	!NUMBER:N		as above, but substitute Nth element, where#				0 = command name, 1 = 1st arg, etc.# 	!NUMBER:$		as above, but substitute last element# 	!NUMBER:*		as above, but substitute all arguments#	!-NUMBER		substitute the command NUMBER lines from the#				end of the history list; 1 = last command#	!-NUMBER:N		as above, but substitute Nth element, where#				0 = command name, 1 = 1st arg, etc.# 	!-NUMBER:$		as above, but substitute last element# 	!-NUMBER:*		as above, but substitute all arguments#	!?STRING		substitute most-recent command from history list#				containing STRING -- STRING must be enclosed in#				braces if followed by any other characters#	!?STRING:N		as above, but substitute Nth element, where#				0 = command name, 1 = 1st arg, etc.# 	!?STRING:$		as above, but substitute last element	# 	!?STRING:*		as above, but substitute all arguments###	Command Editing:#	----------------##	CMND~e			edit CMND using $EDITOR, where CMND may be found#				using a history substitution#	CMND~v			edit CMND using $VISUAL, where CMND may be found#				using a history substitution# "	^string1^string2^	substitute string2 for string1 in last command"#				command and run it# "	g^string1^string2^	globally substitute string2 for string1 in  "#				last command and run it# 	!NUMBER:s/string1/string2/#				substitute string2 for string1 in#				command NUMBER and run it# 	!NUMBER:gs/string1/string2/#				globally substitute string2 for string1 in#				command NUMBER and run it# 	!?STRING:s/string1/string2/#				substitute string2 for string1 in last command#				containing STRING and run it# 	!?STRING:gs/string1/string2/#				globally substitute string2 for string1 in last#				command containing STRING and run it#	#	Any command which ends in the string ":p" is treated as a normal#	command until all substitutions have been completed.  The trailing#	":p" is then stripped, and the command is simply echoed and added to#	the history list instead of being executed.##	None of the other colon extensions of the cshell are supported.###	Shell Environment Variables:#	----------------------------##	EDITOR		editor used by ~e command, default = "ed"#	VISUAL		editor used by ~v command, default = "vi"#	MAIL		your system mailbox#	PAGER		paging program used by history command, default = "more"#	PS1		primary prompt#	PS2		secondary prompt#	history		number of commands in history list, default = 22#	histfile	file history list is saved in, default = $HOME/.bhistory#	savehist	number of commands remembered from last bcsh session#	aliasfile	file of aliased commands, default = $HOME/.baliases#	logoutfile	file of commands to be executed before termination#	inc_cmdno	yes/no -- keep track of command numbers or not#	noclobber	if set, existing files are not overwritten by '>'#	iclobber	if both noclobber and iclobber are set, the user is#			prompted for confirmation before existing files are#			overwritten by '>'##	Note:	if you are setting either noclobber or iclobber mid-session,#		set them to 'yes'###	Regular Shell Variables:#	------------------------##	Shell variables may be set via Bourne or cshell syntax, e.g., both#	"set foo=bar" and "foo=bar" set a variable called "foo" with the value#	"bar".  However, all variables are automatically set as environment#	variables, so there is no need to export them.  Conversely, there#	are NO local variables.  Sorry, folks.##	A cshell-style "setenv" command is turned into a regular "set" command.###	The Prompt:#	----------##	You may, if you wish, have a command executed in your prompt.  If#	the variable PS1 contains a dollar sign or a backquote, it is#	evaluated and the result used as the prompt, provided the evaluation#	did not produce a "not found" error message.  The two special cases#	of PS1 consisting solely of "$" or "$ " are handled correctly.  For#	example, to have the prompt contain the current directory followed#	by a space, enter:##		PS1=\'echo "`pwd` "\'##	You need the backslashed single quotes to prevent the command being#	evaluated by the variable-setting mechanism and the shell before it#	is assigned to PS1.##	To include the command number in your prompt, enter the command:##		PS1=\'echo "$cmdno "\'###	Shell Control-Flow Syntax:#	--------------------------##	'While', 'for', 'case', and 'if' commands entered in Bourne shell#	syntax are executed as normal.##	A valiant attempt is made to convert 'foreach' loops into 'for' loops,#	cshell-syntax 'while' loops into Bourne shell syntax, and 'switch'#	statements into 'case' statements.  I cannot guarantee to always get it#	right.  If you forget the 'do' in a 'while' or 'for' loop, or finish#	them with 'end' instead of 'done', this will be corrected.##	Note that cshell-to-Bourne control flow conversions do not take place#	if control is nested -- e.g., a 'foreach' inside a 'while' will fail.##	The simple-case cshell "if (condition) command" is turned into Bourne#	syntax.  Other 'if' statements are left alone apart from making the#	'then' a separate statement, because constructing a valid interactive#	cshell 'if' statement is essentially an exercise in frustration anyway.#	The cshell and Bourne shell have sufficiently different ideas about#	conditions that if is probably best to resign yourself to learning#	the Bourne shell conventions.##	Note that since most of the testing built-ins of the cshell are#	not available in the Bourne shell, a complex condition in a 'while'#	loop or an 'if' statement will probably fail.#	##	Bugs, Caveats, etc.:#	--------------------##	This is not a super-speedy program.  Be patient, especially on startup.##	To the best of my knowledge this program should work on ANY Bourne#	shell -- note that if your shell does not understand 'echo -n' you#	will have to re-set the values of '$n' and '$c'.##	This program may run out of stack space on a 16-bit machine where#	/bin/sh is not split-space.##	Mail checking is done every 10 commands if $MAIL is set in your#	environment.  For anything fancier, you will have to hack the code.##	Because commands are stuffed in a file before sh is invoked on them,#	error messages from failed commands are ugly.##	Failed history substitutions either give nothing at all, or a#	"not found" style of error message.##	A command history is kept whether you want it or not.  This may be#	perceived as a bug or a feature, depending on which side of bed you#	got out on.##	If you want a real backslash in a command, you will have to type two# 	of them  because the shell swallows the first backslash in the initial# 	command pickup.  This means that to include a non-history '!' in a#	command you need '\\!' -- a real wart, especially for net mail,#	but unavoidable.##	Commands containing an '@' will break all sorts of things.##	Very complex history substitutions may fail.##	File names containing numbers may break numeric history sustitutions.##	Commands containing bizzare sequences of characters may conflict#	with internal kludges.##	Aliasing something to "commands;logout" will not work -- if you#	want something to happen routinely on logout, put it in the file#	specified by $logoutfile, default = $HOME/.blogout.##	Please send all bug reports to ihnp4!utzoo!globetek!chris.#	Flames will be posted to net.general with 'Reply-to' set to your# '	path...  :-)							'####		************* VERY IMPORTANT NOTICE *************## If your shell supports # comments, then REPLACE all the colon 'comments'# with # comments.  If it does not, then REMOVE all the 'comment' lines from the# working copy of the file, as it will run MUCH faster -- the shell evaluates# lines starting with a colon but does not actually execute them, so you will# save the read-and-evaluate time by removing them.case "`echo -n foo`" in	-n*)		n=		c="\c"		;;	foo)		n=-n		c=		;;	*)		echo "Your 'echo' command is broken."		exit 1		;;esachistory=${history-22}savehist=${savehist-22}histfile=${histfile-$HOME/.bhistory}logoutfile=${logoutfile-$HOME/.blogout}EDITOR=${EDITOR-ed}VISUAL=${VISUAL-vi}PAGER=${PAGER-more}aliasfile=${aliasfile-$HOME/.baliases}# the alias file may contain 1 blank line, so a test -s will not workcase "`cat $aliasfile 2> /dev/null`" in	"")		doalias=no		;;	*)		doalias=yes		;;esacif test -s "${sourcefile-$HOME/.bcshrc}"	then	. ${sourcefile-$HOME/.bcshrc}fiif test -s "$histfile"	then	cmdno="`set - \`wc -l $histfile\`;echo $1`"	cmdno="`expr \"$cmdno\" + 1`"	lastcmd="`tail -1 $histfile`"	copy=false	ohist=$histfile	while test ! -w "$histfile"		do		echo "Cannot write to history file '$histfile'."		echo $n "Please enter a new history filename: $c"		read histfile		copy=true	done	if $copy		then		cp $ohist $histfile	fielse	cat /dev/null > $histfile	cmdno=1	lastcmd=fi# keep track of command number as the defaultinc_cmdno=${inc_cmdo-yes}# default prompts -- PS1 and PS2 may be SET but EMPTY, so '${PS1-% }' syntax# is not used herecase "$PS1" in	"")							PS1="% "		;;				esaccase "$PS2" in	"")							PS2="> "		;;				esacexport histfile savehist history aliasfile EDITOR VISUAL PAGER cmdno PS1 PS2case "$MAIL" in	"")		;;	*)		if [ -f $MAIL ]; then			mailsize=`set - \`wc -c $MAIL\`;echo $1`		else			mailsize=0		fi		;;esactrap ':' 2trap exit 3trap "tail -$savehist $histfile>/tmp/hist$$;uniq /tmp/hist$$ > $histfile;\rm -f /tmp/*$$;exit 0" 15getcmd=yesmailcheck=exclaim=echoit=mailprompt=while :do	run=yes	case "$mailprompt" in		"")			;;		*)			echo "$mailprompt"			;;	esac	case "$getcmd" in	yes)		: guess if the prompt should be evaluated or not		case "$PS1" in		\$|\$\ )			echo $n "$PS1$c"				;;		*\`*|*\$*)			tmp="`(eval $PS1) 2>&1`"			case "$tmp" in			*not\ found)							echo $n "$PS1$c"				;;						*)								echo $n "$tmp$c"				;;						esac			;;		*)			echo $n "$PS1$c"			;;		esac		read cmd || cmd="exit"		;;	*)	;;	esac	case "$MAIL" in	"")		;;	*)		: check for mail every 10 commands		case "$mailcheck" in		1111111111)			mailcheck=			if [ -f $MAIL ]; then				newsize="`set - \`wc -c $MAIL\`;echo $1`"			else				newsize=0			fi			if test "$newsize" -gt "$mailsize"; then				mailprompt="You have new mail"			else				mailprompt=			fi			mailsize=$newsize			;;		*)			mailcheck=1$mailcheck			;;		esac		;;	esac	hist=no	case "$cmd" in	"")		continue		;;	sh)		sh		run=no		;;	!!)		cmd=$lastcmd		echoit=yes		getcmd=no		continue		;;	*:p)		cmd="`expr \"$cmd\" : '\(.*\):p'` +~+p"		getcmd=no		continue		;;	foreach[\ \	]*)		while test "$line" != "end"; do			echo $n "$PS2$c"			read line			cmd="${cmd};$line"		done		echo "$cmd" > /tmp/bcsh$$		ed - /tmp/bcsh$$ << ++++		s/end/done/		s/foreach[ 	]\(.*\)(/for \1 in /		s/)//		s/;/;do /		w++++		;;	for[\ \	]*|while[\ \	]*)		# try to catch the most common cshell-to-Bourne-shell		# mistakes		echo $n "$PS2$c"		read line		case "$line" in		*do)			line="do :"			;;		*do*)			;;		*)			line="do $line"			;;		esac		cmd="${cmd};$line"		while test "$line" != "done" -a "$line" != "end"		do			echo $n "$PS2$c"			read line			case "$line" in			end)				line=done				;;			esac			cmd="${cmd};$line"		done		echo "$cmd" > /tmp/bcsh$$		;;	if[\ \	]*)		while test "$line" != "fi" -a "$line" != "endif"		do			echo $n "$PS2$c"			read line			case "$line" in			*[a-z]*then)				line="`expr \"$line\" : '\(.*\)then'`;then"				;;			endif)				line=fi				;;			esac			cmd="${cmd};$line"		done		echo "$cmd" > /tmp/bcsh$$		case "`grep then /tmp/bcsh$$`" in		"")			# fix 'if foo bar' cases			ed - /tmp/bcsh$$ << ++++			s/)/);then/			s/.*/;fi/			w++++			;;		esac		;;	case[\ \	]*)		while test "$line" != "esac"		do			echo $n "$PS2$c"			read line			cmd="${cmd}@$line"		done		cmd="`echo \"$cmd\" | tr '@' ' '`"		echo "$cmd" > /tmp/bcsh$$		;;	switch[\ \	]*)		while test "$line" != "endsw"		do			echo $n "$PS2$c"			read line			cmd="${cmd}@$line"		done		echo "$cmd" > /tmp/bcsh$$		ed - /tmp/bcsh$$ << '++++'		1,$s/@/\/g		g/switch.*(/s//case "/		s/)/" in/		1,$s/case[	 ]\(.*\):$/;;\	\1)/		2d		1,$s/endsw/;;\esac/		g/breaksw/s///		1,$s/default.*/;;\	*)/		w++++		cmd="`cat /tmp/bcsh$$`"		;;	*!*)		hist=yes		;;	esac	case "$hist" in	yes)		# deal with genuine exclamation marks, go back and parse again		case "$cmd" in		*\>![\ \	]*|*\\!*)			cmd="`echo \"$cmd\" | sed -e 's@\\!@REALEXCLAMATIONMARK@g'`"			exclaim=yes			getcmd=no			continue			;;		esac		# break command into elements, parse each one		tmp=		for i in $cmd		do			# find element with !, peel off stuff up to !			case "$i" in			!)				# most likely a typo for !!, so fix it				front=				$i=!!				;;			!!*)				front=

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -