Imported from ../bash-2.0.tar.gz.
This commit is contained in:
		
					parent
					
						
							
								726f63884d
							
						
					
				
			
			
				commit
				
					
						ccc6cda312
					
				
			
		
					 502 changed files with 91988 additions and 69123 deletions
				
			
		|  | @ -1,22 +0,0 @@ | |||
| #! /bin/sh | ||||
| # | ||||
| # Convert Csh aliases to Bash aliases.  Adapted from a similar program | ||||
| # supplied with zsh. | ||||
| # | ||||
| # This is a quick script to convert csh aliases to Bash aliases/functions. | ||||
| # Pipe the output of csh's alias command through this; it will generate | ||||
| # a series of alias/function definitions on stdout, suitable for | ||||
| # processing by bash. | ||||
| # | ||||
| # This is not perfect, but it gets most common aliases; it should manage to | ||||
| # cut down a lot of the busy work. | ||||
| # | ||||
| sed -e 's/	(\(.*\))/	\1/' >/tmp/cz$$.1 | ||||
| grep ! /tmp/cz$$.1 >/tmp/cz$$.2 | ||||
| grep -v ! /tmp/cz$$.1 >/tmp/cz$$.3 | ||||
| sed -e "s/'/'"\\\\"''"/g -e 's/^\([^	]*\)	\(.*\)$/alias \1='"'\2'/" \ | ||||
| 	/tmp/cz$$.3 | ||||
| sed -e 's/![:#]*/$/g' -e 's/^\([^	]*\)	\(.*\)$/\1 () { \2 }/' /tmp/cz$$.2 | ||||
| rm /tmp/cz$$.? | ||||
| 
 | ||||
| exit 0 | ||||
							
								
								
									
										27
									
								
								examples/bashdb/PERMISSION
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								examples/bashdb/PERMISSION
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| From mikel@ora.com Tue Aug  1 12:13:20 1995 | ||||
| Flags: 10 | ||||
| Return-Path: mikel@ora.com | ||||
| Received: from ruby.ora.com (ruby.ora.com [198.112.208.25]) by odin.INS.CWRU.Edu with ESMTP (8.6.12+cwru/CWRU-2.1-ins) | ||||
| 	id MAA01565; Tue, 1 Aug 1995 12:13:18 -0400 (from mikel@ora.com for <chet@odin.INS.CWRU.Edu>) | ||||
| Received: (from fax@localhost) by ruby.ora.com (8.6.12/8.6.11) with UUCP id MAA23251; Tue, 1 Aug 1995 12:07:51 -0400 | ||||
| Received: by los.ora.com (4.1/Spike-2.1) | ||||
| 	id AA00672; Tue, 1 Aug 95 08:57:32 EDT | ||||
| Date: Tue, 1 Aug 95 08:57:32 EDT | ||||
| From: mikel@ora.com (Michael Loukides) | ||||
| Message-Id: <9508011257.AA00672@los.ora.com> | ||||
| Subject: Re: Ksh debugger from Rosenblatt's book [for bash] | ||||
| To: Chet Ramey <chet@odin.INS.CWRU.Edu> | ||||
| Cc: cmarie@ora.com, cam@iinet.com.au, brosenblatt@tm.com | ||||
| In-Reply-To: Chet Ramey <chet@odin.INS.CWRU.Edu>, Mon, 31 Jul 1995 16:22:48 -0400 | ||||
| 
 | ||||
|     I've modified a (modified) version of Bill Rosenblatt's ksh debugger | ||||
|     to work with bash-2.0.  Does ORA have any problem with me distributing | ||||
|     it with bash-2.0? | ||||
|      | ||||
| That's great! | ||||
| 
 | ||||
| Go ahead and circulate it; in fact, we should probably grab it and | ||||
| stick it in our ftp archive, and put a reference to it in the book. | ||||
| (Too late to actually discuss the thing, at least for this edition). | ||||
| ------- | ||||
| 
 | ||||
							
								
								
									
										8
									
								
								examples/bashdb/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								examples/bashdb/README
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| This is a modified version of the Korn Shell debugger from Bill | ||||
| Rosenblatt's `Learning the Korn Shell', published by O'Reilly | ||||
| and Associates (ISBN 1-56592-054-6). | ||||
| 
 | ||||
| The original `kshdb' is available for anonymous FTP with the URL | ||||
| 
 | ||||
| ftp://ftp.uu.net/published/oreilly/nutshell/ksh/ksh.tar.Z | ||||
| 
 | ||||
							
								
								
									
										29
									
								
								examples/bashdb/bashdb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								examples/bashdb/bashdb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | |||
| # kshdb - Korn Shell Debugger main file | ||||
| # adapted from 'Learning the Korn Shell' by Bill Rosenblatt (O'Reilly) | ||||
| # by Cigy Cyriac (cigy@felix.tulblr.unisys.com) | ||||
| # Main driver: constructs full script (with preamble) and runs it | ||||
| 
 | ||||
| echo 'Bourne-Again Shell Debugger version 0.1' | ||||
| 
 | ||||
| _pname=${0##*/} | ||||
| 
 | ||||
| [ $# -eq 0 ] && { | ||||
| 	echo "${_pname}: usage: ${_pname} <script_file>" | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| _guineapig=$1 | ||||
| 
 | ||||
| [ -r $_guineapig ] || { | ||||
| 	echo "${_pname}: cannot read $_guineapig." >&2 | ||||
| 	exit 1 | ||||
| } | ||||
| shift | ||||
| 
 | ||||
| _tmpdir=/tmp | ||||
| _libdir=. | ||||
| _dbgfile=$_tmpdir/bashdb$$		#temp file for script being debugged | ||||
| 
 | ||||
| cat $_libdir/bashdb.pre $_guineapig > $_dbgfile | ||||
| exec bash $_dbgfile $_guineapig $_tmpdir $_libdir "$@" | ||||
| # end of bashdb | ||||
							
								
								
									
										235
									
								
								examples/bashdb/bashdb.fns
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								examples/bashdb/bashdb.fns
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,235 @@ | |||
| # bashdb.fns - Bourne-Again Shell Debugger functions | ||||
| 
 | ||||
| _BUFSIZ=100 | ||||
| 
 | ||||
| # Here after each statement in script being debugged. | ||||
| # Handle single-step and breakpoints. | ||||
| _steptrap() { | ||||
| 	let _curline=$1-1		# no. of line that just ran | ||||
| 	let "$_curline < 1" && let _curline=1 | ||||
| 
 | ||||
| 	let "$_curline > $_firstline+$_BUFSIZ" && _readin $_curline | ||||
| 
 | ||||
| 	let " $_trace" && | ||||
| 		_msg "$PS4, line $_curline: ${_lines[$(($_curline-$_firstline+1))]}" | ||||
| 
 | ||||
| 	# if in step mode, decrement counter | ||||
| 	let " $_steps >= 0" && let _steps="$_steps - 1" | ||||
| 
 | ||||
| 	# first check if line num or string brkpt. reached | ||||
| 	if _at_linenumbp || _at_stringbp; then | ||||
| 		_msg "Reached breakpoint at line $_curline" | ||||
| 		_cmdloop		# enter debugger | ||||
| 
 | ||||
| 	# if not, check whether break condition exists and is true | ||||
| 	elif [ -n "$_brcond" ] && eval $_brcond; then | ||||
| 		_msg "Break condition $_brcond true at line $_curline" | ||||
| 		_cmdloop		# enter debugger | ||||
| 
 | ||||
| 	# next, check if step mode and no. of steps is up | ||||
| 	elif let "$_steps == 0"; then | ||||
| 		_msg "Stopped at line $_curline" | ||||
| 		_cmdloop		# enter debugger | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # Debugger command loop. | ||||
| # Here at start of debugger session, when brkpt. reached, or after single-step. | ||||
| _cmdloop() { | ||||
| 	local cmd args | ||||
| 
 | ||||
| # added support for default command (last one entered) | ||||
| 
 | ||||
| 	while read -e -p "bashdb> [$lastcmd $lastargs] " cmd args; do | ||||
| 		if [ -z "$cmd" ]; then | ||||
| 			cmd=$lastcmd | ||||
| 			args=$lastargs  | ||||
| 		fi | ||||
| 
 | ||||
| 		lastcmd="$cmd" | ||||
| 		lastargs=$args | ||||
| 
 | ||||
| # made commands to be debugger commands by default, no need for '*' prefix | ||||
| 
 | ||||
| 		case $cmd in | ||||
| 		bp ) _setbp $args ;;	#set brkpt at line num or string | ||||
| 
 | ||||
| 		bc ) _setbc $args ;;	# set break condition | ||||
| 
 | ||||
| 		cb ) _clearbp ;;	# clear all brkpts. | ||||
| 
 | ||||
| 		g ) return ;;		# start/resume execution | ||||
| 
 | ||||
| 		s ) let _steps=${args:-1}  | ||||
| 		    return ;;		# single-step N times(default 1) | ||||
| 
 | ||||
| 		x ) _xtrace ;;	# toggle execution trace | ||||
| 
 | ||||
| 		pr ) _print $args ;;	# print lines in file | ||||
| 
 | ||||
| 		\? | h | help ) _menu ;; # print command menu | ||||
| 
 | ||||
| 		hi ) history ;;		# show command history | ||||
| 
 | ||||
| 		q ) _cleanup; exit ;;		# quit | ||||
| 
 | ||||
| 		\! ) eval $args ;;	# run shell command | ||||
| 
 | ||||
| 		* ) _msg "Invalid command: $cmd" ; _menu ;; | ||||
| 		esac | ||||
| 	done | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # see if next line no. is a brkpt. | ||||
| _at_linenumbp() { | ||||
| 	if [ -z "${_linebp}" ]; then | ||||
| 		return 1 | ||||
| 	fi | ||||
| 	echo "${curline}" | egrep -s "(${linebp%\|})" >/dev/null 2>&1 | ||||
| 	return $? | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # search string brkpts to see if next line in script matches. | ||||
| _at_stringbp() { | ||||
| 	local l; | ||||
| 	if [ -z "$_stringbp" ]; then | ||||
| 		return 1; | ||||
| 	fi | ||||
| 	l=${_lines[$_curline-$_firstline+1]} | ||||
| 	echo "${l} | egrep -s "*(${stringbp%\|})*" >/dev/null 2>&1 | ||||
| 	return $? | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # print message to stderr | ||||
| _msg() { | ||||
| 	echo -e "$@" >&2 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # set brkpt(s) at given line numbers and/or strings | ||||
| # by appending lines to brkpt file | ||||
| _setbp() { | ||||
| 	declare -i n | ||||
| 	case "$1" in | ||||
| 	"")	_listbp ;; | ||||
| 	[0-9]*)	#number, set brkpt at that line | ||||
| 		n=$1 | ||||
| 		_linebp="${_linebp}$n|" | ||||
| 		_msg "Breakpoint at line " $1 | ||||
| 		;; | ||||
| 	*)	#string, set brkpt at next line w/string | ||||
| 		_stringbp="${_stringbp}$@|" | ||||
| 		_msg "Breakpoint at next line containing $@." | ||||
| 		;; | ||||
| 	esac | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # list brkpts and break condition. | ||||
| _listbp() { | ||||
| 	_msg "Breakpoints at lines:" | ||||
| 	_msg "$(echo $_linebp | tr '|' ' ')" | ||||
| 	_msg "Breakpoints at strings:" | ||||
| 	_msg "$(echo $_stringbp | tr '|' ' ')" | ||||
| 	_msg "Break on condition:" | ||||
| 	_msg "$_brcond" | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # set or clear break condition | ||||
| _setbc() { | ||||
| 	if [ -n "$@" ] ; then | ||||
| 		_brcond=$args | ||||
| 		_msg "Break when true: $_brcond" | ||||
| 	else | ||||
| 		_brcond= | ||||
| 		_msg "Break condition cleared" | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # clear all brkpts | ||||
| _clearbp() { | ||||
| 	_linebp= | ||||
| 	_stringbp= | ||||
| 	_msg "All breakpoints cleared" | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # toggle execution trace feature | ||||
| _xtrace() { | ||||
| 	let _trace="! $_trace" | ||||
| 
 | ||||
| 	_msg "Execution trace \c" | ||||
| 	let " $_trace" && _msg "on." || _msg "off." | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # print command menu | ||||
| _menu() { | ||||
| 
 | ||||
| # made commands to be debugger commands by default, no need for '*' prefix | ||||
| 
 | ||||
| 	_msg 'bashdb commands: | ||||
| 	bp N			set breakpoint at line N | ||||
| 	bp string		set breakpoint at next line containing "string" | ||||
| 	bp			list breakpoints and break condition | ||||
| 	bc string		set break condition to "string" | ||||
| 	bc			clear break condition | ||||
| 	cb			clear all breakpoints | ||||
| 	g			start/resume execution | ||||
| 	s [N]			execute N statements (default 1) | ||||
| 	x			toggle execution trace on/off (default on) | ||||
| 	pr [start|.] [cnt]	print "cnt" lines from line no. "start" | ||||
| 	?, h, help		print this menu | ||||
| 	hi			show command history	 | ||||
| 	q			quit | ||||
| 
 | ||||
| 	! cmd [args]		execute command "cmd" with "args" | ||||
| 
 | ||||
| 	default:		last command (in "[ ]" at the prompt) | ||||
| 
 | ||||
| 	Readline command line editing (emacs/vi mode) is available' | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # erase temp files before exiting | ||||
| _cleanup() { | ||||
| 	rm $_dbgfile 2>/dev/null | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # read $_BUFSIZ lines from $_guineapig into _lines array, starting from line $1 | ||||
| # save number of first line read in _firstline | ||||
| _readin() { | ||||
| 	declare -i _i=1			 | ||||
| 	let _firstline=$1 | ||||
| 
 | ||||
| 	SEDCMD="$_firstline,$(($_firstline+$_BUFSIZ))p" | ||||
| 
 | ||||
| 	sed -n "$SEDCMD" $_guineapig > /tmp/_script.$$ | ||||
| 	while read -r _lines[$_i]; do | ||||
| 		_i=_i+1 | ||||
| 	done  < /tmp/_script.$$ | ||||
| 	rm -f /tmp/_script.$$ 2>/dev/null | ||||
| } | ||||
| 
 | ||||
| _print() { | ||||
| 	typeset _start _cnt | ||||
| 
 | ||||
| 	if [ -z "$1" ] || [ "$1" = . ]; then | ||||
| 		_start=$_curline | ||||
| 	else | ||||
| 		_start=$1 | ||||
| 	fi | ||||
| 
 | ||||
| 	_cnt=${2:-9} | ||||
| 
 | ||||
| 	SEDCMD="$_start,$(($_start+$_cnt))p" | ||||
| 
 | ||||
| 	pr -tn $_guineapig | sed -n "$SEDCMD" | ||||
| } | ||||
							
								
								
									
										37
									
								
								examples/bashdb/bashdb.pre
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								examples/bashdb/bashdb.pre
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| # bashdb.pre - Bourne-Again Shell Debugger preamble file | ||||
| # prepended to script being ddebugged | ||||
| #arguments: | ||||
| # $1 = name of original guineapig script | ||||
| # $2 = dir where temp files are stored | ||||
| # $3 = dir where bashdb.pre and bashdb.fns are stored | ||||
| 
 | ||||
| # separate history file for bashdb | ||||
| HISTFILE=~/.bashdb_history | ||||
| set -o history | ||||
| set +H | ||||
| 
 | ||||
| # prompt for trace line | ||||
| PS4=$1 | ||||
| 
 | ||||
| _dbgfile=$0 | ||||
| _guineapig=$1 | ||||
| _tmpdir=$2 | ||||
| _libdir=$3 | ||||
| shift 3				#move user's args into place | ||||
| 
 | ||||
| . $_libdir/bashdb.fns		#read in the debugger functions | ||||
| 
 | ||||
| _linebp= | ||||
| _stringbp= | ||||
| let _trace=1			#init execution trace flag to on | ||||
| 
 | ||||
| #read guineapig file into _lines array | ||||
| _readin 1 | ||||
| 
 | ||||
| trap _cleanup EXIT		#erase files before exiting | ||||
| 
 | ||||
| let _steps=1			#no. of statements to run after setting trap | ||||
| #set LINENO, gets incremented to 1 | ||||
| LINENO=0 | ||||
| trap '_steptrap $LINENO' DEBUG | ||||
| : | ||||
|  | @ -29,7 +29,7 @@ | |||
| 
 | ||||
| aload() | ||||
| { | ||||
| 	eval $1 '() {  . '$2' ; '$1' "$@" ; return $?; }' | ||||
| 	eval $1 '() {  . '$2' ; '$1' "$@" ; return $? ; }' | ||||
| } | ||||
| 
 | ||||
| # | ||||
|  |  | |||
							
								
								
									
										192
									
								
								examples/functions/autoload.v2
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								examples/functions/autoload.v2
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,192 @@ | |||
| # | ||||
| # An almost ksh-compatible `autoload'.  A function declared as `autoload' will | ||||
| # be read in from a file the same name as the function found by searching the | ||||
| # $FPATH (which works the same as $PATH), then that definition will be run. | ||||
| # | ||||
| # To do this without source support, we define a dummy function that, when | ||||
| # executed, will load the file (thereby re-defining the function), then  | ||||
| # execute that newly-redefined function with the original arguments. | ||||
| # | ||||
| # It's not identical to ksh because ksh apparently does lazy evaluation | ||||
| # and looks for the file to load from only when the function is referenced. | ||||
| # This one requires that the file exist when the function is declared as | ||||
| # `autoload'. | ||||
| # | ||||
| # usage: autoload [-pu] [func ...] | ||||
| # | ||||
| # options: | ||||
| #	-p	print in a format that can be reused as input | ||||
| #	-u	unset each function and remove it from the autoload list | ||||
| # | ||||
| # The first cut of this was by Bill Trost, trost@reed.bitnet | ||||
| # | ||||
| # Chet Ramey | ||||
| # chet@ins.CWRU.Edu | ||||
| 
 | ||||
| unset _AUTOLOADS | ||||
| _aindex=0 | ||||
| 
 | ||||
| # | ||||
| # Declare a function ($1) to be autoloaded from a file ($2) when it is first | ||||
| # called.  This defines a `temporary' function that will `.' the file  | ||||
| # containg the real function definition, then execute that new definition with | ||||
| # the arguments given to this `fake' function.  The autoload function defined | ||||
| # by the file and the file itself *must* be named identically. | ||||
| # | ||||
| 
 | ||||
| _aload() | ||||
| { | ||||
| 	eval $1 '() {  . '$2' ; '$1' "$@" ; return $? ; }' | ||||
| 	_autoload_addlist "$1" | ||||
| } | ||||
| 
 | ||||
| _autoload_addlist() | ||||
| { | ||||
| 	local i=0 | ||||
| 
 | ||||
| 	while (( i < $_aindex )); do | ||||
| 		case "${_AUTOLOADS[i]}" in | ||||
| 		"$1")	return 1 ;; | ||||
| 		esac | ||||
| 		(( i += 1 )) | ||||
| 	done | ||||
| 	_AUTOLOADS[_aindex]="$1" | ||||
| 	(( _aindex += 1 )) | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| _autoload_dump() | ||||
| { | ||||
| 	local func | ||||
| 
 | ||||
| 	for func in ${_AUTOLOADS[@]}; do | ||||
| 		[ -n "$1" ] && echo -n "autoload " | ||||
| 		echo "$func" | ||||
| 	done | ||||
| } | ||||
| 
 | ||||
| # Remove $1 from the list of autoloaded functions | ||||
| _autoload_remove_one() | ||||
| { | ||||
| 	local i=0 nnl=0 | ||||
| 	local -a nlist | ||||
| 
 | ||||
| 	while (( i < _aindex )); do | ||||
| 		case "${_AUTOLOADS[i]}" in | ||||
| 		"$1")	;; | ||||
| 		*)	nlist[nnl]="${_AUTOLOADS[i]}" ; (( nnl += 1 ));; | ||||
| 		esac | ||||
| 		(( i += 1 )) | ||||
| 	done | ||||
| 	unset _AUTOLOADS _aindex | ||||
| 	eval _AUTOLOADS=( ${nlist[@]} ) | ||||
| 	_aindex=$nnl | ||||
| } | ||||
| 
 | ||||
| # Remove all function arguments from the list of autoloaded functions | ||||
| _autoload_remove() | ||||
| { | ||||
| 	local func i es=0 | ||||
| 	 | ||||
| 	# first unset the autoloaded functions | ||||
| 	for func; do | ||||
| 		i=0 | ||||
| 		while (( i < _aindex )); do | ||||
| 			case "${_AUTOLOADS[i]}" in | ||||
| 			"$func")	unset -f $func ; break ;; | ||||
| 			esac | ||||
| 			(( i += 1 )) | ||||
| 		done | ||||
| 		if (( i == _aindex )); then | ||||
| 			echo "autoload: $func: not an autoloaded function" >&2 | ||||
| 			es=1 | ||||
| 		fi | ||||
| 	done | ||||
| 
 | ||||
| 	# then rebuild the list of autoloaded functions | ||||
| 	for func ; do | ||||
| 		_autoload_remove_one "$func" | ||||
| 	done | ||||
| 
 | ||||
| 	return $es | ||||
| } | ||||
| 
 | ||||
| # | ||||
| # Search $FPATH for a file the same name as the function given as $1, and | ||||
| # autoload the function from that file.  There is no default $FPATH. | ||||
| # | ||||
| 
 | ||||
| autoload() | ||||
| { | ||||
| 	local -a fp | ||||
| 	local _autoload_unset nfp i | ||||
| 
 | ||||
| 	if (( $# == 0 )) ; then | ||||
| 		_autoload_dump | ||||
| 		return 0 | ||||
| 	fi | ||||
| 
 | ||||
| 	OPTIND=1 | ||||
| 	while getopts pu opt | ||||
| 	do | ||||
| 		case "$opt" in | ||||
| 		p)	_autoload_dump printable; return 0;; | ||||
| 		u)	_autoload_unset=y ;; | ||||
| 		*)	echo "autoload: usage: autoload [-pu] [function ...]" >&2 | ||||
| 			return 1 ;; | ||||
| 		esac | ||||
| 	done | ||||
| 
 | ||||
| 	shift $(( $OPTIND - 1 )) | ||||
| 
 | ||||
| 	if [ -n "$_autoload_unset" ]; then | ||||
| 		_autoload_remove "$@" | ||||
| 		return $? | ||||
| 	fi | ||||
| 
 | ||||
| 	# | ||||
| 	# If there is no $FPATH, there is no work to be done | ||||
| 	# | ||||
| 
 | ||||
| 	if [ -z "$FPATH" ] ; then | ||||
| 		echo "autoload: FPATH not set or null" >&2 | ||||
| 		return 1 | ||||
| 	fi | ||||
| 
 | ||||
| 	# | ||||
| 	# This treats FPATH exactly like PATH: a null field anywhere in the | ||||
| 	# FPATH is treated the same as the current directory. | ||||
| 	# | ||||
| 	# This turns $FPATH into an array, substituting `.' for `' | ||||
| 	# | ||||
| 	eval fp=( $( | ||||
| 			IFS=':' | ||||
| 			set -- ${FPATH} | ||||
| 			for p in "$@" ; do echo -n "${p:-.} "; done | ||||
| 		   ) | ||||
| 		) | ||||
| 
 | ||||
| 	nfp=${#fp[@]} | ||||
| 
 | ||||
| 	for FUNC ; do | ||||
| 		i=0; | ||||
| 		while (( i < nfp )) ; do | ||||
| 			if [ -f ${fp[i]}/$FUNC ] ; then | ||||
| 				break			# found it!  | ||||
| 			fi | ||||
| 			(( i += 1 )) | ||||
| 		done | ||||
| 
 | ||||
| 		if (( i == nfp )) ; then | ||||
| 			echo "autoload: $FUNC: autoload function not found" >&2 | ||||
| 			es=1 | ||||
| 			continue | ||||
| 		fi | ||||
| 
 | ||||
| #		echo auto-loading $FUNC from ${fp[i]}/$FUNC | ||||
| 		_aload $FUNC ${fp[i]}/$FUNC | ||||
| 		es=0 | ||||
| 	done | ||||
| 
 | ||||
| 	return $es | ||||
| } | ||||
|  | @ -1,27 +1,15 @@ | |||
| # C-shell compatabilty package. | ||||
| # setenv VAR VALUE | ||||
| function setenv () { | ||||
| function setenv () | ||||
| { | ||||
|   export $1="$2" | ||||
| } | ||||
| 
 | ||||
| function unsetenv () { | ||||
| function unsetenv () | ||||
| { | ||||
|   unset $1 | ||||
| } | ||||
| 
 | ||||
| function alias () { | ||||
|   local name=$1 | ||||
|   shift | ||||
|   local value="$*" | ||||
| 
 | ||||
|   if [ "$name" = "" ]; then | ||||
|     builtin alias | ||||
|   elif [ "$value" = "" ]; then | ||||
|     builtin alias $name | ||||
|   else | ||||
|     builtin alias $name="$value" | ||||
|   fi | ||||
| } | ||||
| 
 | ||||
| # Can't write foreach yet.  Need pattern matching, and a few extras. | ||||
| function foreach () { | ||||
| echo 'Can'\''t do `foreach'\'' yet.  Type "help for".' | ||||
|  | @ -31,6 +19,29 @@ echo 'Can'\''t do `foreach'\'' yet.  Type "help for".' | |||
| #set () { | ||||
| #} | ||||
| 
 | ||||
| chdir () { | ||||
|   builtin cd $* | ||||
|  } | ||||
| chdir () | ||||
| { | ||||
|   builtin cd "$@" | ||||
| } | ||||
| 
 | ||||
| # alias - convert csh alias commands to bash functions | ||||
| # from Mohit Aron <aron@cs.rice.edu> | ||||
| # posted to usenet as <4i5p17$bnu@larry.rice.edu> | ||||
| function alias () | ||||
| { | ||||
| 	if [ "x$2" = "x" ]  | ||||
| 	then | ||||
| 		declare -f $1 | ||||
| 	else | ||||
| 		echo $2 | egrep -s '(\!|#)' 2>/dev/null | ||||
| 		if [ $? -eq 0 ] | ||||
| 		then | ||||
| 			comm=$(echo $2 | sed  's/\\!\*/\"$\@\"/g | ||||
| 					       s/\\!:\([1-9]\)/\"$\1\"/g | ||||
| 				               s/#/\\#/g') | ||||
| 		else | ||||
| 			comm="$2 \"\$@\"" | ||||
| 		fi | ||||
| 		eval function $1 \(\) "{" command "$comm"  "; }" | ||||
| 	fi | ||||
| } | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ function check_exit_status () | |||
|     if [ ${status} -ne 0 -a ${status} != 128 ]; then | ||||
|        # If process exited by a signal, determine name of signal. | ||||
|        if [ ${status} -gt 128 ]; then | ||||
|           signal="$(builtin kill -l $[${status} - 128] 2>/dev/null)" | ||||
|           signal="$(builtin kill -l $((${status} - 128)) 2>/dev/null)" | ||||
| 	  if [ "$signal" ]; then signal="($signal)"; fi | ||||
|        fi | ||||
|        echo "[Exit ${status} ${signal}]" 1>&2 | ||||
|  |  | |||
							
								
								
									
										15
									
								
								examples/functions/inpath
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								examples/functions/inpath
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| inpath() | ||||
| { | ||||
| 	path=$(echo $PATH | sed 's/^:/.:/ | ||||
| 				s/::/:.:/g | ||||
| 				s/:$/:./ | ||||
| 				s/:/ /g') | ||||
| 
 | ||||
| 	for x in $path | ||||
| 	do | ||||
| 		[ -x $x/$1 ] && { PROG=$x/$1; break; } | ||||
| 	done | ||||
| 	[ -z "$PROG" ] | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										62
									
								
								examples/functions/keep
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								examples/functions/keep
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| # From: Seth Chaiklin <psykseth@aau.dk> | ||||
| # To: chet@ins.CWRU.Edu | ||||
| # Subject: bash functions (sorta) | ||||
| 
 | ||||
| # | ||||
| # keep: | ||||
| # usage: keep program | ||||
| # declare the a program should be "kept".  i.e. try to fg a stopped one | ||||
| # and only when that fails start a fresh program. | ||||
| # | ||||
| 
 | ||||
| keep() | ||||
| { | ||||
| 	case $# in | ||||
| 	1|2)	;; | ||||
| 	*) echo "usage: keep [alias] program" 1>&2 ; return 1;; | ||||
| 	esac | ||||
| 
 | ||||
| 	# progname | ||||
| 	pn=${1##*/} | ||||
| 
 | ||||
| 	# set up an alias for the kept program | ||||
| 	if [ $# = 1 ]; then | ||||
| 		alias "$pn=fg $1 2>/dev/null || $1" | ||||
| 	else | ||||
| 		alias "$1=fg $2 2>/dev/null || $2" | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| # | ||||
| # unkeep: | ||||
| # usage: unkeep program | ||||
| # unset the alias set up by the keep function | ||||
| # | ||||
| 
 | ||||
| unkeep() | ||||
| { | ||||
| 	if [ $# != 1 ]; then | ||||
| 		echo "usage: unkeep program" | ||||
| 		return 2 | ||||
| 	fi | ||||
| 
 | ||||
| 	# unset the alias for the kept program | ||||
| 	unalias "${1##*/}" | ||||
| } | ||||
| 
 | ||||
| # | ||||
| # kept: | ||||
| # lists all kept programs in 'alias: program' form | ||||
| # | ||||
| 
 | ||||
| kept() | ||||
| { | ||||
| 	alias | grep "fg.*2>" | sed "s/alias \(.*\)='fg.*||\(.*\)'$/\1:\2/" | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # some things that should be kept | ||||
| #keep /usr/local/bin/emacs | ||||
| #keep e ${EDITOR:-/usr/local/bin/emacs} | ||||
| #keep edit ${EDITOR:-/usr/local/bin/emacs} | ||||
| #keep /usr/local/bin/emm | ||||
|  | @ -39,13 +39,9 @@ whence() | |||
| 		return 1 | ||||
| 	fi | ||||
| 	case "$1" in | ||||
| 		-v) vflag=1 | ||||
| 		    shift 1 | ||||
| 		    ;; | ||||
| 		-*) echo "whence: bad option: $1" | ||||
| 		    return 1 | ||||
| 		    ;; | ||||
| 		 *) ;; | ||||
| 	-v) vflag=1 ; shift 1 ;; | ||||
| 	-*) echo "whence: bad option: $1" ; return 1 ;; | ||||
| 	 *) ;; | ||||
| 	esac | ||||
| 
 | ||||
| 	if [ "$#" = "0" ] ; then | ||||
|  | @ -63,15 +59,12 @@ whence() | |||
| 				echo $path | ||||
| 			else | ||||
| 				case "$cmd" in | ||||
| 					/*) echo "" | ||||
| 					    ;; | ||||
| 					 *) case "$(builtin type -type $cmd)" in | ||||
| 						"") echo "" | ||||
| 						    ;; | ||||
| 						 *) echo "$cmd" | ||||
| 						    ;; | ||||
| 					    esac | ||||
| 					    ;; | ||||
| 				/*) echo "" ;; | ||||
| 				 *) case "$(builtin type -type $cmd)" in | ||||
| 				    "") echo "" ;; | ||||
| 				    *) echo "$cmd" ;; | ||||
| 				    esac | ||||
| 				    ;; | ||||
| 				esac | ||||
| 			fi | ||||
| 		fi | ||||
|  | @ -117,7 +110,7 @@ cd() | |||
| #	-n	do not add trailing newline | ||||
| #	-p	no-op (no coprocesses) | ||||
| #	-r	no escapes | ||||
| #	-s	no-op (print to the history file) | ||||
| #	-s	print to the history file | ||||
| #	-u n	redirect output to fd n | ||||
| # | ||||
| 
 | ||||
|  | @ -131,20 +124,20 @@ print() | |||
| 	while getopts "Rnprsu:" c | ||||
| 	do | ||||
| 		case $c in | ||||
| 		R)	eflag= | ||||
| 			;; | ||||
| 		r)	eflag= | ||||
| 			;; | ||||
| 		n)	nflag=-n | ||||
| 			;; | ||||
| 		u)	fd=$OPTARG | ||||
| 			;; | ||||
| 		p|s)	;; | ||||
| 		R)	eflag= ;; | ||||
| 		r)	eflag= ;; | ||||
| 		n)	nflag=-n ;; | ||||
| 		s)	sflag=y ;; | ||||
| 		u)	fd=$OPTARG ;; | ||||
| 		p)	;; | ||||
| 		esac | ||||
| 	done | ||||
| 	shift $[ $OPTIND - 1 ] | ||||
| 
 | ||||
| 	builtin echo $eflag $nflag "$@" >&$fd | ||||
| 	case "$sflag" in | ||||
| 	y)	builtin history -s "$*" ;; | ||||
| 	*)	builtin echo $eflag $nflag "$@" >&$fd | ||||
| 	esac | ||||
| } | ||||
| 
 | ||||
| # substring function | ||||
|  |  | |||
							
								
								
									
										11
									
								
								examples/functions/login
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								examples/functions/login
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| # replace the `login' and `newgrp' builtins in old bourne shells | ||||
| 
 | ||||
| login() | ||||
| { | ||||
| 	exec login "$@" | ||||
| } | ||||
| 
 | ||||
| newgrp() | ||||
| { | ||||
| 	exec newgrp "$@" | ||||
| } | ||||
							
								
								
									
										26
									
								
								examples/functions/lowercase
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								examples/functions/lowercase
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from | ||||
| # @(#) lowercase.ksh 1.0 92/10/08 | ||||
| # 92/10/08 john h. dubois iii (john@armory.com) | ||||
| # | ||||
| # conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| lowercase() | ||||
| { | ||||
| for file; do | ||||
|     filename=${file##*/} | ||||
|     case "$filename" in | ||||
|     */*)    dirname=${file%/*} ;; | ||||
|     *) dirname=.;; | ||||
|     esac | ||||
|     nf=$(echo $filename | tr A-Z a-z) | ||||
|     newname="${dirname}/${nf}" | ||||
|     if [ "$nf" != "$filename" ]; then | ||||
| 	mv "$file" "$newname" | ||||
| 	echo "$0: $file -> $newname" | ||||
|     else | ||||
| 	echo "$0: $file not changed." | ||||
|     fi | ||||
| done | ||||
| } | ||||
							
								
								
									
										16
									
								
								examples/functions/mhfold
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								examples/functions/mhfold
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| # To: chet@ins.CWRU.Edu | ||||
| # Subject: Bash functions | ||||
| # From: Sandeep Mehta <sxm@philabs.Philips.Com> | ||||
| 
 | ||||
| # print MH folders, useful only because folders(1) doesn't print | ||||
| # mod date/times | ||||
| 
 | ||||
| mhfold() | ||||
| { | ||||
| 	list=`folders | tail +2 | awk '{print $1}'` | ||||
| 	/bin/ls -lag ~/Mail > /tmp/fold$$ | ||||
| 	for i in $list; do | ||||
| 		grep $i /tmp/fold$$ | ||||
| 	done | ||||
| 	/bin/rm -f /tmp/fold$$ | ||||
| } | ||||
							
								
								
									
										43
									
								
								examples/functions/repeat2
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								examples/functions/repeat2
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | |||
| # To: chet@ins.CWRU.Edu | ||||
| # Subject: Bash functions | ||||
| # From: Sandeep Mehta <sxm@philabs.Philips.Com> | ||||
| 
 | ||||
| ########################################## | ||||
| # | ||||
| # repeat - clone of C shell builtin `repeat' | ||||
| # | ||||
| # usage: repeat <count> <command> | ||||
| # | ||||
| # It has been tested inside other functions and in conditionals like  | ||||
| # if [ "`repeat <count> <command>`" ]; then COMMANDS [ else COMMANDS ] fi | ||||
| # Please send me fixes/enhancements. | ||||
| #  | ||||
| # Sandeep Mehta <sxm@philabs.Philips.Com> | ||||
| ########################################## | ||||
| repeat() | ||||
| { | ||||
| 	local rcount=$1 | ||||
| 
 | ||||
| 	if [ $# -le 1 ] || [ -z "$rcount" ]; then | ||||
| 		echo "usage: repeat <count> <command>" 1>&2 | ||||
| 		return 2 | ||||
| 	fi | ||||
| 
 | ||||
| 	shift | ||||
| 
 | ||||
| 	local acmd=("$@") | ||||
| 
 | ||||
| 	if [ $rcount -le 0 ]; then | ||||
| 		echo "count must be greater than 0" | ||||
| 		echo "usage: repeat <count> <command>" 1>&2 | ||||
| 		return 2 | ||||
| 	fi | ||||
| 
 | ||||
| 	st=0 | ||||
| 	while [ $rcount -gt 0 ]; do | ||||
| 		eval "${acmd[@]}" | ||||
| 		st=$? | ||||
| 		rcount=$((rcount - 1)) | ||||
| 	done | ||||
| 	return $st | ||||
| } | ||||
							
								
								
									
										29
									
								
								examples/functions/seq
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								examples/functions/seq
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | |||
| # Generate a sequence from m to n, m defaults to 1. | ||||
| 
 | ||||
| seq () | ||||
| { | ||||
| 	declare -i lo hi i	# makes local | ||||
| 	local _SEQ | ||||
| 
 | ||||
| 	case $# in | ||||
| 	1) seq 1 "$1" ; return $? ;; | ||||
| 	2) lo=$1 hi=$2 | ||||
| 	   i=$lo _SEQ="" | ||||
| 	   while let "i <= hi"; do | ||||
| 		_SEQ="${_SEQ}$i " | ||||
| 		let i+=1 | ||||
| 	   done | ||||
| 	   echo "${_SEQ# }" | ||||
| 	   return 0 ;; | ||||
| 	*) echo seq: usage: seq [low] high 1>&2 ; return 2 ;; | ||||
| 	esac | ||||
| } | ||||
| 
 | ||||
| # like the APL `iota' function (or at least how I remember it :-) | ||||
| iota() | ||||
| { | ||||
| 	case $# in | ||||
| 	1) seq 1 "$1"; return $?;; | ||||
| 	*) echo "iota: usage: iota high" 1>&2; return 2;; | ||||
| 	esac | ||||
| } | ||||
|  | @ -1,6 +1,6 @@ | |||
| shcat() | ||||
| { | ||||
| 	while read line | ||||
| 	while read -r line | ||||
| 	do | ||||
| 		echo "$line" | ||||
| 	done | ||||
|  |  | |||
							
								
								
									
										112
									
								
								examples/loadables/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								examples/loadables/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| #
 | ||||
| # Simple makefile for the sample loadable builtins
 | ||||
| #
 | ||||
| CC = cc | ||||
| 
 | ||||
| # SunOS 4
 | ||||
| PICFLAG = -pic | ||||
| # Some versions of gcc, esp. on NetBSD and FreeBSD
 | ||||
| #PICFLAG = -fpic
 | ||||
| # Linux -- could also be -fpic
 | ||||
| #PICFLAG = -fPIC
 | ||||
| # SunOS 5
 | ||||
| #PICFLAG = -K pic
 | ||||
| # SVR4, SVR4.2, Irix
 | ||||
| #PICFLAG = -K PIC
 | ||||
| # BSD/OS 2.1
 | ||||
| #PICFLAG =
 | ||||
| # AIX 4.2
 | ||||
| #PICFLAG = -K
 | ||||
| 
 | ||||
| # SunOS 4, BSD/OS 2.1, SVR4.2, SVR4, Linux, AIX 4.2, etc.
 | ||||
| LD = ld | ||||
| # SunOS 5, Linux
 | ||||
| #LD = cc
 | ||||
| 
 | ||||
| # SunOS 4
 | ||||
| LDOPT = -assert pure-text | ||||
| # OSF/1, Digital UNIX
 | ||||
| #LDOPT = -shared -soname $@ -expect_unresolved '*'
 | ||||
| # SunOS 5
 | ||||
| #LDOPT = -dy -z text -G -i -h $@
 | ||||
| # SVR4, SVR4.2
 | ||||
| #LDOPT = -dy -z text -G -h $@
 | ||||
| # NetBSD, FreeBSD -- might also need -r
 | ||||
| #LDOPT = -x -Bshareable
 | ||||
| # Linux
 | ||||
| #LDOPT = -shared
 | ||||
| # BSD/OS 2.1
 | ||||
| #LDOPT = -r
 | ||||
| # AIX 4.2
 | ||||
| #LDOPT = -bdynamic -bnoentry -bexpall -G
 | ||||
| 
 | ||||
| # other libraries to link the shared object against
 | ||||
| # BSD/OS 2.1
 | ||||
| #LDLIBS = -lc_s.2.1.0
 | ||||
| 
 | ||||
| srcdir = ../.. | ||||
| INC= -I$(srcdir) -I$(srcdir)/builtins -I$(srcdir)/lib | ||||
| 
 | ||||
| .c.o: | ||||
| 	$(CC) $(PICFLAG) $(CFLAGS) $(INC) -c -o $@ $< | ||||
| 
 | ||||
| all:	printf print truefalse sleep pushd finfo logname basename dirname \ | ||||
| 	tty pathchk tee head rmdir sprintf | ||||
| others:	necho getconf hello cat | ||||
| 
 | ||||
| printf:	printf.o | ||||
| 	$(LD) $(LDOPT) -o $@ printf.o $(LDLIBS) | ||||
| 
 | ||||
| sprintf: sprintf.o | ||||
| 	$(LD) $(LDOPT) -o $@ sprintf.o $(LDLIBS) | ||||
| 
 | ||||
| print:	print.o | ||||
| 	$(LD) $(LDOPT) -o $@ print.o $(LDLIBS) | ||||
| 
 | ||||
| necho:	necho.o | ||||
| 	$(LD) $(LDOPT) -o $@ necho.o $(LDLIBS) | ||||
| 
 | ||||
| getconf: getconf.o | ||||
| 	$(LD) $(LDOPT) -o $@ getconf.o $(LDLIBS) | ||||
| 
 | ||||
| hello:	hello.o | ||||
| 	$(LD) $(LDOPT) -o $@ hello.o $(LDLIBS) | ||||
| 
 | ||||
| truefalse: truefalse.o | ||||
| 	$(LD) $(LDOPT) -o $@ truefalse.o $(LDLIBS) | ||||
| 
 | ||||
| sleep:	sleep.o | ||||
| 	$(LD) $(LDOPT) -o $@ sleep.o $(LDLIBS) | ||||
| 
 | ||||
| pushd:	pushd.o | ||||
| 	$(LD) $(LDOPT) -o $@ pushd.o $(LDLIBS) | ||||
| 
 | ||||
| finfo:	finfo.o | ||||
| 	$(LD) $(LDOPT) -o $@ finfo.o $(LDLIBS) | ||||
| 
 | ||||
| cat:	cat.o | ||||
| 	$(LD) $(LDOPT) -o $@ cat.o $(LDLIBS) | ||||
| 
 | ||||
| logname:	logname.o | ||||
| 	$(LD) $(LDOPT) -o $@ logname.o $(LDLIBS) | ||||
| 
 | ||||
| basename:	basename.o | ||||
| 	$(LD) $(LDOPT) -o $@ basename.o $(LDLIBS) | ||||
| 
 | ||||
| dirname:	dirname.o | ||||
| 	$(LD) $(LDOPT) -o $@ dirname.o $(LDLIBS) | ||||
| 
 | ||||
| tty:	tty.o | ||||
| 	$(LD) $(LDOPT) -o $@ tty.o $(LDLIBS) | ||||
| 
 | ||||
| pathchk:	pathchk.o | ||||
| 	$(LD) $(LDOPT) -o $@ pathchk.o $(LDLIBS) | ||||
| 
 | ||||
| tee:	tee.o | ||||
| 	$(LD) $(LDOPT) -o $@ tee.o $(LDLIBS) | ||||
| 
 | ||||
| rmdir:	rmdir.o | ||||
| 	$(LD) $(LDOPT) -o $@ rmdir.o $(LDLIBS) | ||||
| 
 | ||||
| head:	head.o | ||||
| 	$(LD) $(LDOPT) -o $@ head.o $(LDLIBS) | ||||
							
								
								
									
										27
									
								
								examples/loadables/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								examples/loadables/README
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| Some examples of ready-to-dynamic-load builtins.  Most of the | ||||
| examples given are reimplementations of standard commands whose | ||||
| execution time is dominated by process startup time.  The | ||||
| exceptions are sleep, which allows you to sleep for fractions | ||||
| of a second, finfo, which provides access to the rest of the | ||||
| elements of the `stat' structure that `test' doesn't let you | ||||
| see, and pushd/popd/dirs, which allows you to compile them out | ||||
| of the shell. | ||||
| 
 | ||||
| All of the new builtins in ksh93 that bash didn't already have | ||||
| are included here, as is the ksh `print' builtin. | ||||
| 
 | ||||
| Compile with cc and whatever pic options you need (look in the | ||||
| Makefile for a few common settings) | ||||
| 
 | ||||
| load with ld and whatever shared object options you need (again, | ||||
| look in the Makefile) | ||||
| 
 | ||||
| then enable -f filename builtin-name | ||||
| 
 | ||||
| enable uses a simple reference-counting scheme to avoid unloading a | ||||
| shared object that implements more than one loadable builtin before | ||||
| all loadable builtins implemented in the object are removed. | ||||
| 
 | ||||
| Many of the details needed by builtin writers are found in hello.c, | ||||
| the canonical example.  There is no real `builtin writers' programming | ||||
| guide'. | ||||
							
								
								
									
										108
									
								
								examples/loadables/basename.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								examples/loadables/basename.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,108 @@ | |||
| /* basename - return nondirectory portion of pathname */ | ||||
| 
 | ||||
| /* See Makefile for compilation details. */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #if defined (HAVE_UNISTD_H) | ||||
| #  include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| 
 | ||||
| basename_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int slen, sufflen, off; | ||||
|   char *string, *suffix, *fn; | ||||
| 
 | ||||
|   if (list == 0) | ||||
|     { | ||||
|       builtin_usage (); | ||||
|       return (EX_USAGE); | ||||
|     } | ||||
| 
 | ||||
|   if (no_options (list)) | ||||
|     return (EX_USAGE); | ||||
| 
 | ||||
|   string = list->word->word; | ||||
|   suffix = (char *)NULL; | ||||
|   if (list->next) | ||||
|     { | ||||
|       list = list->next; | ||||
|       suffix = list->word->word; | ||||
|     } | ||||
| 
 | ||||
|   if (list->next) | ||||
|     { | ||||
|       builtin_usage (); | ||||
|       return (EX_USAGE); | ||||
|     } | ||||
| 
 | ||||
|   slen = strlen (string); | ||||
| 
 | ||||
|   /* Strip trailing slashes */ | ||||
|   while (slen > 0 && string[slen - 1] == '/') | ||||
|     slen--; | ||||
| 
 | ||||
|   /* (2) If string consists entirely of slash characters, string shall be
 | ||||
| 	 set to a single slash character.  In this case, skip steps (3) | ||||
| 	 through (5). */ | ||||
|   if (slen == 0) | ||||
|     { | ||||
|       fputs ("/\n", stdout); | ||||
|       return (EXECUTION_SUCCESS); | ||||
|     } | ||||
| 
 | ||||
|   /* (3) If there are any trailing slash characters in string, they
 | ||||
| 	 shall be removed. */ | ||||
|   string[slen] = '\0'; | ||||
| 
 | ||||
|   /* (4) If there are any slash characters remaining in string, the prefix
 | ||||
| 	 of string up to an including the last slash character in string | ||||
| 	 shall be removed. */ | ||||
|   while (--slen >= 0) | ||||
|     if (string[slen] == '/') | ||||
|       break; | ||||
| 
 | ||||
|   fn = string + slen + 1; | ||||
| 
 | ||||
|   /* (5) If the suffix operand is present, is not identical to the
 | ||||
| 	 characters remaining in string, and is identical to a suffix | ||||
| 	 of the characters remaining in string, the suffix suffix | ||||
| 	 shall be removed from string.  Otherwise, string shall not be | ||||
| 	 modified by this step. */ | ||||
|   if (suffix) | ||||
|     { | ||||
|       sufflen = strlen (suffix); | ||||
|       slen = strlen (fn); | ||||
|       if (sufflen < slen) | ||||
|         { | ||||
|           off = slen - sufflen; | ||||
|           if (strcmp (fn + off, suffix) == 0) | ||||
|             fn[off] = '\0'; | ||||
|         } | ||||
|     } | ||||
|   printf ("%s\n", fn); | ||||
|   return (EXECUTION_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| char *basename_doc[] = { | ||||
| 	"The STRING is converted to a filename corresponding to the last", | ||||
| 	"pathname component in STRING.  If the suffix string SUFFIX is", | ||||
| 	"supplied, it is removed.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| /* The standard structure describing a builtin command.  bash keeps an array
 | ||||
|    of these structures. */ | ||||
| struct builtin basename_struct = { | ||||
| 	"basename",		/* builtin name */ | ||||
| 	basename_builtin,	/* function implementing the builtin */ | ||||
| 	BUILTIN_ENABLED,	/* initial flags for builtin */ | ||||
| 	basename_doc,		/* array of long documentation strings. */ | ||||
| 	"basename string [suffix]",	/* usage synopsis */ | ||||
| 	0			/* reserved for internal use */ | ||||
| }; | ||||
							
								
								
									
										100
									
								
								examples/loadables/cat.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								examples/loadables/cat.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,100 @@ | |||
| /*
 | ||||
|  * cat replacement | ||||
|  * | ||||
|  * no options - the way cat was intended | ||||
|  */ | ||||
| 
 | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| 
 | ||||
| #ifndef errno | ||||
| extern int errno; | ||||
| #endif | ||||
| 
 | ||||
| extern char *strerror (); | ||||
| extern char **make_builtin_argv (); | ||||
| 
 | ||||
| static int | ||||
| fcopy(fd) | ||||
| int	fd; | ||||
| { | ||||
| 	char	buf[1024], *s; | ||||
| 	int	n, w, e; | ||||
| 
 | ||||
| 	while (n = read(fd, buf, sizeof (buf))) { | ||||
| 		w = write(1, buf, n); | ||||
| 		if (w != n) { | ||||
| 			e = errno; | ||||
| 			write(2, "cat: write error: ", 18); | ||||
| 			s = strerror(e); | ||||
| 			write(2, s, strlen(s)); | ||||
| 			write(2, "\n", 1); | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| cat_main (argc, argv) | ||||
| int	argc; | ||||
| char	**argv; | ||||
| { | ||||
| 	int	i, fd, r; | ||||
| 	char	*s; | ||||
| 
 | ||||
| 	if (argc == 1) | ||||
| 		return (fcopy(0)); | ||||
| 
 | ||||
| 	for (i = r = 1; i < argc; i++) { | ||||
| 		if (argv[i][0] == '-' && argv[i][1] == '\0') | ||||
| 			fd = 0; | ||||
| 		else { | ||||
| 			fd = open(argv[i], O_RDONLY, 0666); | ||||
| 			if (fd < 0) { | ||||
| 				s = strerror(errno); | ||||
| 				write(2, "cat: cannot open ", 17); | ||||
| 				write(2, argv[i], strlen(argv[i])); | ||||
| 				write(2, ": ", 2); | ||||
| 				write(2, s, strlen(s)); | ||||
| 				write(2, "\n", 1); | ||||
| 				continue; | ||||
| 			} | ||||
| 		} | ||||
| 		r = fcopy(fd); | ||||
| 		if (fd != 0) | ||||
| 			close(fd); | ||||
| 	} | ||||
| 	return (r); | ||||
| } | ||||
| 
 | ||||
| cat_builtin(list) | ||||
| WORD_LIST *list; | ||||
| { | ||||
| 	char	**v; | ||||
| 	int	c, r; | ||||
| 
 | ||||
| 	v = make_builtin_argv(list, &c); | ||||
| 	r = cat_main(c, v); | ||||
| 	free(v); | ||||
| 
 | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| char *cat_doc[] = { | ||||
| 	"Read each FILE and display it on the standard output.   If any", | ||||
| 	"FILE is `-' or if no FILE argument is given, the standard input", | ||||
| 	"is read.", | ||||
| 	(char *)0 | ||||
| }; | ||||
| 
 | ||||
| struct builtin cat_struct = { | ||||
| 	"cat", | ||||
| 	cat_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	cat_doc, | ||||
| 	"cat [-] [file ...]", | ||||
| 	0 | ||||
| }; | ||||
							
								
								
									
										95
									
								
								examples/loadables/dirname.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								examples/loadables/dirname.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,95 @@ | |||
| /* dirname - return directory portion of pathname */ | ||||
| 
 | ||||
| /* See Makefile for compilation details. */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #if defined (HAVE_UNISTD_H) | ||||
| #  include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| 
 | ||||
| dirname_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int slen; | ||||
|   char *string; | ||||
| 
 | ||||
|   if (list == 0 || list->next) | ||||
|     { | ||||
|       builtin_usage (); | ||||
|       return (EX_USAGE); | ||||
|     } | ||||
| 
 | ||||
|   if (no_options (list)) | ||||
|     return (EX_USAGE); | ||||
| 
 | ||||
|   string = list->word->word; | ||||
|   slen = strlen (string); | ||||
| 
 | ||||
|   /* Strip trailing slashes */ | ||||
|   while (slen > 0 && string[slen - 1] == '/') | ||||
|     slen--; | ||||
| 
 | ||||
|   /* (2) If string consists entirely of slash characters, string shall be
 | ||||
| 	 set to a single slash character.  In this case, skip steps (3) | ||||
| 	 through (8). */ | ||||
|   if (slen == 0) | ||||
|     { | ||||
|       fputs ("/\n", stdout); | ||||
|       return (EXECUTION_SUCCESS); | ||||
|     } | ||||
| 
 | ||||
|   /* (3) If there are any trailing slash characters in string, they
 | ||||
| 	 shall be removed. */ | ||||
|   string[slen] = '\0'; | ||||
| 
 | ||||
|   /* (4) If there are no slash characters remaining in string, string
 | ||||
| 	 shall be set to a single period character.  In this case, skip | ||||
| 	 steps (5) through (8). | ||||
| 
 | ||||
|      (5) If there are any trailing nonslash characters in string, | ||||
| 	 they shall be removed. */ | ||||
| 
 | ||||
|   while (--slen >= 0) | ||||
|     if (string[slen] == '/') | ||||
|       break; | ||||
| 
 | ||||
|   if (slen >= 0) | ||||
|     { | ||||
|       fputs (".\n", stdout); | ||||
|       return (EXECUTION_SUCCESS); | ||||
|     } | ||||
| 
 | ||||
|   /* (7) If there are any trailing slash characters in string, they
 | ||||
| 	 shall be removed. */ | ||||
|   while (--slen >= 0) | ||||
|     if (string[slen] != '/') | ||||
|       break; | ||||
|   string[++slen] = '\0'; | ||||
| 
 | ||||
|   /* (8) If the remaining string is empty, string shall be set to a single
 | ||||
| 	 slash character. */ | ||||
|   printf ("%s\n", (slen == 0) ? "/" : string); | ||||
|   return (EXECUTION_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| char *dirname_doc[] = { | ||||
| 	"The STRING is converted to the name of the directory containing",	 | ||||
| 	"the filename corresponding to the last pathname component in STRING.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| /* The standard structure describing a builtin command.  bash keeps an array
 | ||||
|    of these structures. */ | ||||
| struct builtin dirname_struct = { | ||||
| 	"dirname",		/* builtin name */ | ||||
| 	dirname_builtin,	/* function implementing the builtin */ | ||||
| 	BUILTIN_ENABLED,	/* initial flags for builtin */ | ||||
| 	dirname_doc,		/* array of long documentation strings. */ | ||||
| 	"dirname string",	/* usage synopsis */ | ||||
| 	0			/* reserved for internal use */ | ||||
| }; | ||||
							
								
								
									
										569
									
								
								examples/loadables/finfo.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										569
									
								
								examples/loadables/finfo.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,569 @@ | |||
| /*
 | ||||
|  * finfo - print file info | ||||
|  */ | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include "posixstat.h" | ||||
| #include <stdio.h> | ||||
| #include <pwd.h> | ||||
| #include <grp.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include "shell.h" | ||||
| #include "builtins.h" | ||||
| #include "common.h" | ||||
| 
 | ||||
| #ifndef errno | ||||
| extern int	errno; | ||||
| #endif | ||||
| 
 | ||||
| extern char	*strrchr(); | ||||
| extern char	**make_builtin_argv (); | ||||
| 
 | ||||
| static int	printst(); | ||||
| static int	printsome(); | ||||
| static int	printfinfo(); | ||||
| static int	finfo_main(); | ||||
| 
 | ||||
| extern int	sh_optind; | ||||
| extern char	*sh_optarg; | ||||
| extern char	*this_command_name; | ||||
| 
 | ||||
| static char	*prog; | ||||
| static int	pmask; | ||||
| 
 | ||||
| #define OPT_UID		0x00001 | ||||
| #define OPT_GID		0x00002 | ||||
| #define OPT_DEV		0x00004 | ||||
| #define OPT_INO		0x00008 | ||||
| #define OPT_PERM	0x00010 | ||||
| #define OPT_LNKNAM	0x00020 | ||||
| #define OPT_FID		0x00040 | ||||
| #define OPT_NLINK	0x00080 | ||||
| #define OPT_RDEV	0x00100 | ||||
| #define OPT_SIZE	0x00200 | ||||
| #define OPT_ATIME	0x00400 | ||||
| #define OPT_MTIME	0x00800 | ||||
| #define OPT_CTIME	0x01000 | ||||
| #define OPT_BLKSIZE	0x02000 | ||||
| #define OPT_BLKS	0x04000 | ||||
| #define OPT_FTYPE	0x08000 | ||||
| #define OPT_PMASK	0x10000 | ||||
| #define OPT_OPERM	0x20000 | ||||
| 
 | ||||
| #define OPT_ASCII	0x1000000 | ||||
| 
 | ||||
| #define OPTIONS		"acdgiflmnopsuACGMP:U" | ||||
| 
 | ||||
| static int | ||||
| octal(s) | ||||
| char	*s; | ||||
| { | ||||
| 	int	r; | ||||
| 
 | ||||
| 	r = *s - '0'; | ||||
| 	while (*++s >= '0' && *s <= '7') | ||||
| 		r = (r * 8) + (*s - '0'); | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| finfo_main(argc, argv) | ||||
| int	argc; | ||||
| char	**argv; | ||||
| { | ||||
| 	register int	i; | ||||
| 	int	mode, flags, opt; | ||||
| 
 | ||||
| 	sh_optind = 0;	/* XXX */ | ||||
| 	prog = base_pathname(argv[0]); | ||||
| 	if (argc == 1) { | ||||
| 		builtin_usage(); | ||||
| 		return(1); | ||||
| 	} | ||||
| 	flags = 0; | ||||
| 	while ((opt = sh_getopt(argc, argv, OPTIONS)) != EOF) { | ||||
| 		switch(opt) { | ||||
| 		case 'a': flags |= OPT_ATIME; break; | ||||
| 		case 'A': flags |= OPT_ATIME|OPT_ASCII; break; | ||||
| 		case 'c': flags |= OPT_CTIME; break; | ||||
| 		case 'C': flags |= OPT_CTIME|OPT_ASCII; break; | ||||
| 		case 'd': flags |= OPT_DEV; break; | ||||
| 		case 'i': flags |= OPT_INO; break; | ||||
| 		case 'f': flags |= OPT_FID; break; | ||||
| 		case 'g': flags |= OPT_GID; break; | ||||
| 		case 'G': flags |= OPT_GID|OPT_ASCII; break; | ||||
| 		case 'l': flags |= OPT_LNKNAM; break; | ||||
| 		case 'm': flags |= OPT_MTIME; break; | ||||
| 		case 'M': flags |= OPT_MTIME|OPT_ASCII; break; | ||||
| 		case 'n': flags |= OPT_NLINK; break; | ||||
| 		case 'o': flags |= OPT_OPERM; break; | ||||
| 		case 'p': flags |= OPT_PERM; break; | ||||
| 		case 'P': flags |= OPT_PMASK; pmask = octal(sh_optarg); break; | ||||
| 		case 's': flags |= OPT_SIZE; break; | ||||
| 		case 'u': flags |= OPT_UID; break; | ||||
| 		case 'U': flags |= OPT_UID|OPT_ASCII; break; | ||||
| 		default: builtin_usage (); return(1); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	argc -= sh_optind; | ||||
| 	argv += sh_optind; | ||||
| 
 | ||||
| 	if (argc == 0) { | ||||
| 		builtin_usage(); | ||||
| 		return(1); | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < argc; i++) | ||||
| 		opt = flags ? printsome (argv[i], flags) : printfinfo(argv[i]); | ||||
| 
 | ||||
| 	return(opt); | ||||
| } | ||||
| 
 | ||||
| static struct stat * | ||||
| getstat(f) | ||||
| char	*f; | ||||
| { | ||||
| 	static struct stat st; | ||||
| 	int	fd, r; | ||||
| 	long	lfd; | ||||
| 
 | ||||
| 	if (strncmp(f, "/dev/fd/", 8) == 0) { | ||||
| 		if (legal_number(f + 8, &lfd) == 0) { | ||||
| 			builtin_error("%s: invalid fd", f + 8); | ||||
| 			return ((struct stat *)0); | ||||
| 		} | ||||
| 		fd = lfd; | ||||
| 		r = fstat(fd, &st); | ||||
| 	} else | ||||
| 		r = stat(f, &st); | ||||
| 	if (r < 0) { | ||||
| 		builtin_error("%s: cannot stat: %s", f, strerror(errno)); | ||||
| 		return ((struct stat *)0); | ||||
| 	} | ||||
| 	return (&st); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| printfinfo(f) | ||||
| char	*f; | ||||
| { | ||||
| 	struct stat *st; | ||||
| 
 | ||||
| 	st = getstat(f); | ||||
| 	return (st ? printst(st) : 1); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| getperm(m) | ||||
| int	m; | ||||
| { | ||||
| 	return (m & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID)); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| perms(m) | ||||
| int	m; | ||||
| { | ||||
| 	char ubits[4], gbits[4], obits[4];	/* u=rwx,g=rwx,o=rwx */ | ||||
| 	int i; | ||||
| 
 | ||||
| 	i = 0; | ||||
| 	if (m & S_IRUSR) | ||||
| 		ubits[i++] = 'r'; | ||||
| 	if (m & S_IWUSR) | ||||
| 		ubits[i++] = 'w'; | ||||
| 	if (m & S_IXUSR) | ||||
| 		ubits[i++] = 'x'; | ||||
| 	ubits[i] = '\0'; | ||||
| 
 | ||||
| 	i = 0; | ||||
| 	if (m & S_IRGRP) | ||||
| 		gbits[i++] = 'r'; | ||||
| 	if (m & S_IWGRP) | ||||
| 		gbits[i++] = 'w'; | ||||
| 	if (m & S_IXGRP) | ||||
| 		gbits[i++] = 'x'; | ||||
| 	gbits[i] = '\0'; | ||||
| 
 | ||||
| 	i = 0; | ||||
| 	if (m & S_IROTH) | ||||
| 		obits[i++] = 'r'; | ||||
| 	if (m & S_IWOTH) | ||||
| 		obits[i++] = 'w'; | ||||
| 	if (m & S_IXOTH) | ||||
| 		obits[i++] = 'x'; | ||||
| 	obits[i] = '\0'; | ||||
| 
 | ||||
| 	printf ("u=%s,g=%s,o=%s", ubits, gbits, obits); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| printmode(mode) | ||||
| int	mode; | ||||
| { | ||||
| 	if (S_ISBLK(mode)) | ||||
| 		printf("S_IFBLK "); | ||||
| 	if (S_ISCHR(mode)) | ||||
| 		printf("S_IFCHR "); | ||||
| 	if (S_ISDIR(mode)) | ||||
| 		printf("S_IFDIR "); | ||||
| 	if (S_ISREG(mode)) | ||||
| 		printf("S_IFREG "); | ||||
| 	if (S_ISFIFO(mode)) | ||||
| 		printf("S_IFIFO "); | ||||
| 	if (S_ISLNK(mode)) | ||||
| 		printf("S_IFLNK "); | ||||
| 	if (S_ISSOCK(mode)) | ||||
| 		printf("S_IFSOCK "); | ||||
| 	perms(getperm(mode)); | ||||
| 	printf("\n"); | ||||
| } | ||||
| 
 | ||||
| static int	 | ||||
| printst(st) | ||||
| struct stat *st; | ||||
| { | ||||
| 	struct passwd	*pw; | ||||
| 	struct group	*gr; | ||||
| 	char	*owner; | ||||
| 
 | ||||
| 	printf("Device (major/minor): %d (%d/%d)\n", (int) (st->st_dev & 0xFF), | ||||
| 						     (int) major (st->st_dev), | ||||
| 						     (int) minor (st->st_dev)); | ||||
| 	printf("Inode: %d\n", (int) st->st_ino); | ||||
| 	printf("Mode: (%o) ", (int) st->st_mode); | ||||
| 	printmode((int) st->st_mode); | ||||
| 	printf("Link count: %d\n", (int) st->st_nlink); | ||||
| 	pw = getpwuid(st->st_uid); | ||||
| 	owner = pw ? pw->pw_name : "unknown"; | ||||
| 	printf("Uid of owner: %d (%s)\n", (int) st->st_uid, owner); | ||||
| 	gr = getgrgid(st->st_gid); | ||||
| 	owner = gr ? gr->gr_name : "unknown"; | ||||
| 	printf("Gid of owner: %d (%s)\n", (int) st->st_gid, owner); | ||||
| 	printf("Device type: %d\n", (int) st->st_rdev); | ||||
| 	printf("File size: %ld\n", (long) st->st_size); | ||||
| 	printf("File last access time: %s", ctime (&st->st_atime)); | ||||
| 	printf("File last modify time: %s", ctime (&st->st_mtime)); | ||||
| 	printf("File last status change time: %s", ctime (&st->st_ctime)); | ||||
| 	fflush(stdout); | ||||
| 	return(0); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| printsome(f, flags) | ||||
| char	*f; | ||||
| int	flags; | ||||
| { | ||||
| 	struct stat *st; | ||||
| 	struct passwd *pw; | ||||
| 	struct group *gr; | ||||
| 	int	p; | ||||
| 	char	*b; | ||||
| 
 | ||||
| 	st = getstat(f); | ||||
| 	if (st == NULL) | ||||
| 		return (1); | ||||
| 
 | ||||
| 	/* Print requested info */ | ||||
| 	if (flags & OPT_ATIME) { | ||||
| 		if (flags & OPT_ASCII) | ||||
| 			printf("%s", ctime(&st->st_atime)); | ||||
| 		else | ||||
| 			printf("%ld\n", st->st_atime); | ||||
| 	} else if (flags & OPT_MTIME) { | ||||
| 		if (flags & OPT_ASCII) | ||||
| 			printf("%s", ctime(&st->st_mtime)); | ||||
| 		else | ||||
| 			printf("%ld\n", st->st_mtime); | ||||
| 	} else if (flags & OPT_CTIME) { | ||||
| 		if (flags & OPT_ASCII) | ||||
| 			printf("%s", ctime(&st->st_ctime)); | ||||
| 		else | ||||
| 			printf("%ld\n", st->st_ctime); | ||||
| 	} else if (flags & OPT_DEV) | ||||
| 		printf("%d\n", st->st_dev); | ||||
| 	else if (flags & OPT_INO) | ||||
| 		printf("%d\n", st->st_ino); | ||||
| 	else if (flags & OPT_FID) | ||||
| 		printf("%d:%ld\n", st->st_dev, st->st_ino); | ||||
| 	else if (flags & OPT_NLINK) | ||||
| 		printf("%d\n", st->st_nlink); | ||||
| 	else if (flags & OPT_LNKNAM) { | ||||
| #ifdef S_ISLNK | ||||
| 		b = xmalloc(4096); | ||||
| 		p = readlink(f, b, 4096); | ||||
| 		if (p >= 0 && p < 4096) | ||||
| 			b[p] = '\0'; | ||||
| 		else { | ||||
| 			p = errno; | ||||
| 			strcpy(b, prog); | ||||
| 			strcat(b, ": "); | ||||
| 			strcat(b, strerror(p)); | ||||
| 		} | ||||
| 		printf("%s\n", b); | ||||
| 		free(b); | ||||
| #else | ||||
| 		printf("%s\n", f); | ||||
| #endif | ||||
| 	} else if (flags & OPT_PERM) { | ||||
| 		perms(st->st_mode); | ||||
| 		printf("\n"); | ||||
| 	} else if (flags & OPT_OPERM) | ||||
| 		printf("%o\n", getperm(st->st_mode)); | ||||
| 	else if (flags & OPT_PMASK) | ||||
| 		printf("%o\n", getperm(st->st_mode) & pmask); | ||||
| 	else if (flags & OPT_UID) { | ||||
| 		pw = getpwuid(st->st_uid); | ||||
| 		if (flags & OPT_ASCII) | ||||
| 			printf("%s\n", pw ? pw->pw_name : "unknown"); | ||||
| 		else | ||||
| 			printf("%d\n", st->st_uid); | ||||
| 	} else if (flags & OPT_GID) { | ||||
| 		gr = getgrgid(st->st_gid); | ||||
| 		if (flags & OPT_ASCII) | ||||
| 			printf("%s\n", gr ? gr->gr_name : "unknown"); | ||||
| 		else | ||||
| 			printf("%d\n", st->st_gid); | ||||
| 	} else if (flags & OPT_SIZE) | ||||
| 		printf("%ld\n", st->st_size); | ||||
| 
 | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| #ifndef NOBUILTIN | ||||
| finfo_builtin(list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int c, r; | ||||
|   char **v; | ||||
|   WORD_LIST *l; | ||||
| 
 | ||||
|   v = make_builtin_argv (list, &c); | ||||
|   r = finfo_main (c, v); | ||||
|   free (v); | ||||
| 
 | ||||
|   return r; | ||||
| } | ||||
| 
 | ||||
| static char *finfo_doc[] = { | ||||
|   "Display information about each FILE.  Only single operators should", | ||||
|   "be supplied.  If no options are supplied, a summary of the info", | ||||
|   "available about each FILE is printed.  If FILE is of the form", | ||||
|   "/dev/fd/XX, file descriptor XX is described.  Operators, if supplied,", | ||||
|   "have the following meanings:", | ||||
|   "", | ||||
|   "	-a	last file access time", | ||||
|   "	-A	last file access time in ctime format", | ||||
|   "	-c	last file status change time", | ||||
|   "	-C	last file status change time in ctime format", | ||||
|   "	-m	last file modification time", | ||||
|   "	-M	last file modification time in ctime format", | ||||
|   "	-d	device", | ||||
|   "	-i	inode", | ||||
|   "	-f	composite file identifier (device:inode)", | ||||
|   "	-g	gid of owner", | ||||
|   "	-G	group name of owner", | ||||
|   "	-l	name of file pointed to by symlink", | ||||
|   "	-n	link count", | ||||
|   "	-o	permissions in octal", | ||||
|   "	-p	permissions in ascii", | ||||
|   "	-P mask permissions ANDed with MASK (like with umask)", | ||||
|   "	-s	file size in bytes", | ||||
|   "	-u	uid of owner", | ||||
|   "	-U	user name of owner", | ||||
|   (char *)0 | ||||
| }; | ||||
| 
 | ||||
| struct builtin finfo_struct = { | ||||
| 	"finfo", | ||||
| 	finfo_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	finfo_doc, | ||||
| 	"finfo [-acdgiflmnopsuACGMPU] file [file...]", | ||||
| 	0 | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef NOBUILTIN | ||||
| #if defined (PREFER_STDARG) | ||||
| #  include <stdarg.h> | ||||
| #else | ||||
| #  if defined (PREFER_VARARGS) | ||||
| #    include <varargs.h> | ||||
| #  endif | ||||
| #endif | ||||
| 
 | ||||
| char *this_command_name; | ||||
| 
 | ||||
| main(argc, argv) | ||||
| int	argc; | ||||
| char	**argv; | ||||
| { | ||||
| 	this_command_name = argv[0]; | ||||
| 	exit(finfo_main(argc, argv)); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| builtin_usage() | ||||
| { | ||||
| 	fprintf(stderr, "%s: usage: %s [-%s] [file ...]\n", prog, OPTIONS); | ||||
| } | ||||
| 
 | ||||
| #ifndef HAVE_STRERROR | ||||
| char * | ||||
| strerror(e) | ||||
| int	e; | ||||
| { | ||||
| 	static char	ebuf[40]; | ||||
| 	extern int	sys_nerr; | ||||
| 	extern char	*sys_errlist[]; | ||||
| 
 | ||||
| 	if (e < 0 || e > sys_nerr) { | ||||
| 		sprintf(ebuf,"Unknown error code %d", e); | ||||
| 		return (&ebuf[0]); | ||||
| 	} | ||||
| 	return (sys_errlist[e]); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| char * | ||||
| xmalloc(s) | ||||
| size_t	s; | ||||
| { | ||||
| 	char	*ret; | ||||
| 	extern char *malloc(); | ||||
| 
 | ||||
| 	ret = malloc(s); | ||||
| 	if (ret) | ||||
| 		return (ret); | ||||
| 	fprintf(stderr, "%s: cannot malloc %d bytes\n", prog, s); | ||||
| 	exit(1); | ||||
| } | ||||
| 
 | ||||
| char * | ||||
| base_pathname(p) | ||||
| char	*p; | ||||
| { | ||||
| 	char	*t; | ||||
| 
 | ||||
| 	if (t = strrchr(p, '/')) | ||||
| 		return(++t); | ||||
| 	return(p); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| legal_number (string, result) | ||||
|      char *string; | ||||
|      long *result; | ||||
| { | ||||
|   int sign; | ||||
|   long value; | ||||
| 
 | ||||
|   sign = 1; | ||||
|   value = 0; | ||||
| 
 | ||||
|   if (result) | ||||
|     *result = 0; | ||||
| 
 | ||||
|   /* Skip leading whitespace characters. */ | ||||
|   while (whitespace (*string)) | ||||
|     string++; | ||||
| 
 | ||||
|   if (!*string) | ||||
|     return (0); | ||||
| 
 | ||||
|   /* We allow leading `-' or `+'. */ | ||||
|   if (*string == '-' || *string == '+') | ||||
|     { | ||||
|       if (!digit (string[1])) | ||||
|         return (0); | ||||
| 
 | ||||
|       if (*string == '-') | ||||
|         sign = -1; | ||||
| 
 | ||||
|       string++; | ||||
|     } | ||||
| 
 | ||||
|   while (digit (*string)) | ||||
|     { | ||||
|       if (result) | ||||
|         value = (value * 10) + digit_value (*string); | ||||
|       string++; | ||||
|     } | ||||
| 
 | ||||
|   /* Skip trailing whitespace, if any. */ | ||||
|   while (whitespace (*string)) | ||||
|     string++; | ||||
| 
 | ||||
|   /* Error if not at end of string. */ | ||||
|   if (*string) | ||||
|     return (0); | ||||
| 
 | ||||
|   if (result) | ||||
|     *result = value * sign; | ||||
| 
 | ||||
|   return (1); | ||||
| } | ||||
| 
 | ||||
| int sh_optind; | ||||
| char *sh_optarg; | ||||
| int sh_opterr; | ||||
| 
 | ||||
| extern int optind; | ||||
| extern char *optarg; | ||||
| 
 | ||||
| int | ||||
| sh_getopt(c, v, o) | ||||
| int	c; | ||||
| char	**v, *o; | ||||
| { | ||||
| 	int	r; | ||||
| 
 | ||||
| 	r = getopt(c, v, o); | ||||
| 	sh_optind = optind; | ||||
| 	sh_optarg = optarg; | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| #if defined (USE_VARARGS) | ||||
| void | ||||
| #if defined (PREFER_STDARG) | ||||
| builtin_error (const char *format, ...) | ||||
| #else | ||||
| builtin_error (format, va_alist) | ||||
|      const char *format; | ||||
|      va_dcl | ||||
| #endif | ||||
| { | ||||
|   va_list args; | ||||
| 
 | ||||
|   if (this_command_name && *this_command_name) | ||||
|     fprintf (stderr, "%s: ", this_command_name); | ||||
| 
 | ||||
| #if defined (PREFER_STDARG) | ||||
|   va_start (args, format); | ||||
| #else | ||||
|   va_start (args); | ||||
| #endif | ||||
| 
 | ||||
|   vfprintf (stderr, format, args); | ||||
|   va_end (args); | ||||
|   fprintf (stderr, "\n"); | ||||
| } | ||||
| #else | ||||
| void | ||||
| builtin_error (format, arg1, arg2, arg3, arg4, arg5) | ||||
|      char *format, *arg1, *arg2, *arg3, *arg4, *arg5; | ||||
| { | ||||
|   if (this_command_name && *this_command_name) | ||||
|     fprintf (stderr, "%s: ", this_command_name); | ||||
| 
 | ||||
|   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); | ||||
|   fprintf (stderr, "\n"); | ||||
|   fflush (stderr); | ||||
| } | ||||
| #endif /* !USE_VARARGS */ | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										272
									
								
								examples/loadables/getconf.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								examples/loadables/getconf.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,272 @@ | |||
| /*
 | ||||
|  * Copyright (c) 1994 Winning Strategies, Inc. | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer. | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer in the | ||||
|  *    documentation and/or other materials provided with the distribution. | ||||
|  * 3. All advertising materials mentioning features or use of this software | ||||
|  *    must display the following acknowledgement: | ||||
|  *      This product includes software developed by Winning Strategies, Inc. | ||||
|  * 4. The name of the author may not be used to endorse or promote products | ||||
|  *    derived from this software without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||||
|  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||
|  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * POSIX.2 getconf utility | ||||
|  * | ||||
|  * Written by: | ||||
|  *	J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef lint | ||||
| static char rcsid[] = "$Id: getconf.c,v 1.2 1994/05/10 00:04:12 jtc Exp $"; | ||||
| #endif /* not lint */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <limits.h> | ||||
| #include <locale.h> | ||||
| #include <unistd.h> | ||||
| #include <errno.h> | ||||
| #include "bashansi.h" | ||||
| #include "shell.h" | ||||
| #include "builtins.h" | ||||
| #include "stdc.h" | ||||
| 
 | ||||
| 
 | ||||
| struct conf_variable | ||||
| { | ||||
|   const char *name; | ||||
|   enum { SYSCONF, CONFSTR, PATHCONF, CONSTANT } type; | ||||
|   long value; | ||||
| }; | ||||
| 
 | ||||
| /* BSD/OS does not define this; use Posix.2 recommended minimum value. */ | ||||
| #ifndef _POSIX2_COLL_WEIGHTS_MAX | ||||
| #define _POSIX2_COLL_WEIGHTS_MAX 2 | ||||
| #endif | ||||
| 
 | ||||
| static const struct conf_variable conf_table[] = | ||||
| { | ||||
|   { "PATH",			CONFSTR,	_CS_PATH		}, | ||||
| 
 | ||||
|   /* Utility Limit Minimum Values */ | ||||
|   { "POSIX2_BC_BASE_MAX",	CONSTANT,	_POSIX2_BC_BASE_MAX	}, | ||||
|   { "POSIX2_BC_DIM_MAX",	CONSTANT,	_POSIX2_BC_DIM_MAX	}, | ||||
|   { "POSIX2_BC_SCALE_MAX",	CONSTANT,	_POSIX2_BC_SCALE_MAX	}, | ||||
|   { "POSIX2_BC_STRING_MAX",	CONSTANT,	_POSIX2_BC_STRING_MAX	}, | ||||
|   { "POSIX2_COLL_WEIGHTS_MAX",	CONSTANT,	_POSIX2_COLL_WEIGHTS_MAX }, | ||||
|   { "POSIX2_EXPR_NEST_MAX",	CONSTANT,	_POSIX2_EXPR_NEST_MAX	}, | ||||
|   { "POSIX2_LINE_MAX",		CONSTANT,	_POSIX2_LINE_MAX	}, | ||||
|   { "POSIX2_RE_DUP_MAX",	CONSTANT,	_POSIX2_RE_DUP_MAX	}, | ||||
|   { "POSIX2_VERSION",		CONSTANT,	_POSIX2_VERSION		}, | ||||
| 
 | ||||
|   /* POSIX.1 Minimum Values */ | ||||
|   { "_POSIX_ARG_MAX",		CONSTANT,	_POSIX_ARG_MAX		}, | ||||
|   { "_POSIX_CHILD_MAX",		CONSTANT,	_POSIX_CHILD_MAX	}, | ||||
|   { "_POSIX_LINK_MAX",		CONSTANT,	_POSIX_LINK_MAX		}, | ||||
|   { "_POSIX_MAX_CANON",		CONSTANT,	_POSIX_MAX_CANON	}, | ||||
|   { "_POSIX_MAX_INPUT",		CONSTANT,	_POSIX_MAX_INPUT	}, | ||||
|   { "_POSIX_NAME_MAX",		CONSTANT,	_POSIX_NAME_MAX		}, | ||||
|   { "_POSIX_NGROUPS_MAX",	CONSTANT,	_POSIX_NGROUPS_MAX	}, | ||||
|   { "_POSIX_OPEN_MAX",		CONSTANT,	_POSIX_OPEN_MAX		}, | ||||
|   { "_POSIX_PATH_MAX",		CONSTANT,	_POSIX_PIPE_BUF		}, | ||||
|   { "_POSIX_PIPE_BUF",		CONSTANT,	_POSIX_PIPE_BUF		}, | ||||
|   { "_POSIX_SSIZE_MAX",		CONSTANT,	_POSIX_SSIZE_MAX	}, | ||||
|   { "_POSIX_STREAM_MAX",	CONSTANT,	_POSIX_STREAM_MAX	}, | ||||
|   { "_POSIX_TZNAME_MAX",	CONSTANT,	_POSIX_TZNAME_MAX	}, | ||||
| 
 | ||||
|   /* Symbolic Utility Limits */ | ||||
|   { "BC_BASE_MAX",		SYSCONF,	_SC_BC_BASE_MAX		}, | ||||
|   { "BC_DIM_MAX",		SYSCONF,	_SC_BC_DIM_MAX		}, | ||||
|   { "BC_SCALE_MAX",		SYSCONF,	_SC_BC_SCALE_MAX	}, | ||||
|   { "BC_STRING_MAX",		SYSCONF,	_SC_BC_STRING_MAX	}, | ||||
|   { "COLL_WEIGHTS_MAX",		SYSCONF,	_SC_COLL_WEIGHTS_MAX	}, | ||||
|   { "EXPR_NEST_MAX",		SYSCONF,	_SC_EXPR_NEST_MAX	}, | ||||
|   { "LINE_MAX",			SYSCONF,	_SC_LINE_MAX		}, | ||||
|   { "RE_DUP_MAX",		SYSCONF,	_SC_RE_DUP_MAX		}, | ||||
| 
 | ||||
|   /* Optional Facility Configuration Values */ | ||||
|   { "POSIX2_C_BIND",		SYSCONF,	_SC_2_C_BIND		}, | ||||
|   { "POSIX2_C_DEV",		SYSCONF,	_SC_2_C_DEV		}, | ||||
|   { "POSIX2_CHAR_TERM",		SYSCONF,	_SC_2_CHAR_TERM		}, | ||||
|   { "POSIX2_FORT_DEV",		SYSCONF,	_SC_2_FORT_DEV		}, | ||||
|   { "POSIX2_FORT_RUN",		SYSCONF,	_SC_2_FORT_RUN		}, | ||||
|   { "POSIX2_LOCALEDEF",		SYSCONF,	_SC_2_LOCALEDEF		}, | ||||
|   { "POSIX2_SW_DEV",		SYSCONF,	_SC_2_SW_DEV		}, | ||||
|   { "POSIX2_UPE",		SYSCONF,	_SC_2_UPE		}, | ||||
| 
 | ||||
|   /* POSIX.1 Configurable System Variables */ | ||||
|   { "ARG_MAX",			SYSCONF,	_SC_ARG_MAX 		}, | ||||
|   { "CHILD_MAX",		SYSCONF,	_SC_CHILD_MAX		}, | ||||
|   { "CLK_TCK",			SYSCONF,	_SC_CLK_TCK		}, | ||||
|   { "NGROUPS_MAX",		SYSCONF,	_SC_NGROUPS_MAX		}, | ||||
|   { "OPEN_MAX",			SYSCONF,	_SC_OPEN_MAX		}, | ||||
|   { "STREAM_MAX",		SYSCONF,	_SC_STREAM_MAX		}, | ||||
|   { "TZNAME_MAX",		SYSCONF,	_SC_TZNAME_MAX		}, | ||||
|   { "_POSIX_JOB_CONTROL",	SYSCONF,	_SC_JOB_CONTROL 	}, | ||||
|   { "_POSIX_SAVED_IDS",		SYSCONF,	_SC_SAVED_IDS		}, | ||||
|   { "_POSIX_VERSION",		SYSCONF,	_SC_VERSION		}, | ||||
| 
 | ||||
|   { "LINK_MAX",			PATHCONF,	_PC_LINK_MAX		}, | ||||
|   { "MAX_CANON",		PATHCONF,	_PC_MAX_CANON		}, | ||||
|   { "MAX_INPUT",		PATHCONF,	_PC_MAX_INPUT		}, | ||||
|   { "NAME_MAX",			PATHCONF,	_PC_NAME_MAX		}, | ||||
|   { "PATH_MAX",			PATHCONF,	_PC_PATH_MAX		}, | ||||
|   { "PIPE_BUF",			PATHCONF,	_PC_PIPE_BUF		}, | ||||
|   { "_POSIX_CHOWN_RESTRICTED",	PATHCONF,	_PC_CHOWN_RESTRICTED	}, | ||||
|   { "_POSIX_NO_TRUNC",		PATHCONF,	_PC_NO_TRUNC		}, | ||||
|   { "_POSIX_VDISABLE",		PATHCONF,	_PC_VDISABLE		}, | ||||
| 
 | ||||
|   { NULL } | ||||
| }; | ||||
| 
 | ||||
| extern char *this_command_name; | ||||
| extern char *xmalloc (); | ||||
| extern char **make_builtin_argv (); | ||||
| static int getconf_main (); | ||||
| 
 | ||||
| int | ||||
| getconf_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int c, r; | ||||
|   char **v; | ||||
|   WORD_LIST *l; | ||||
| 
 | ||||
|   v = make_builtin_argv (list, &c); | ||||
|   r = getconf_main (c, v); | ||||
|   free (v); | ||||
| 
 | ||||
|   return r; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| getconf_main(argc, argv) | ||||
| 	int argc; | ||||
| 	char **argv; | ||||
| { | ||||
| 	int ch; | ||||
| 	const struct conf_variable *cp; | ||||
| 
 | ||||
| 	long val; | ||||
| 	size_t slen; | ||||
| 	char *sval; | ||||
| 
 | ||||
| 	setlocale(LC_ALL, ""); | ||||
| 
 | ||||
| 	while ((ch = getopt(argc, argv, "")) != -1) { | ||||
| 		switch (ch) { | ||||
| 		case '?': | ||||
| 		default: | ||||
| 			builtin_usage(); | ||||
| 			return(EX_USAGE); | ||||
| 			/* NOTREACHED */ | ||||
| 		} | ||||
| 	} | ||||
| 	argc -= optind; | ||||
| 	argv += optind; | ||||
| 
 | ||||
| 	if (argc < 1 || argc > 2) { | ||||
| 		builtin_usage(); | ||||
| 		return(EX_USAGE); | ||||
| 		/* NOTREACHED */ | ||||
| 	} | ||||
| 
 | ||||
| 	for (cp = conf_table; cp->name != NULL; cp++) { | ||||
| 		if (strcmp(*argv, cp->name) == 0) | ||||
| 			break; | ||||
| 	} | ||||
| 	if (cp->name == NULL) { | ||||
| 		builtin_error ("%s: unknown variable", *argv); | ||||
| 		return (EXECUTION_FAILURE); | ||||
| 	} | ||||
| 
 | ||||
| 	if (cp->type == PATHCONF) { | ||||
| 		if (argc != 2) { | ||||
| 			builtin_usage(); | ||||
| 			return(EX_USAGE); | ||||
| 		} | ||||
| 	} else { | ||||
| 		if (argc != 1) { | ||||
| 			builtin_usage(); | ||||
| 			return(EX_USAGE); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	switch (cp->type) { | ||||
| 	case CONSTANT: | ||||
| 		printf("%ld\n", cp->value); | ||||
| 		break; | ||||
| 
 | ||||
| 	case CONFSTR: | ||||
| 		slen = confstr (cp->value, (char *) 0, (size_t) 0); | ||||
| 
 | ||||
| 		sval = xmalloc(slen); | ||||
| 
 | ||||
| 		confstr(cp->value, sval, slen); | ||||
| 		printf("%s\n", sval); | ||||
| 		break; | ||||
| 
 | ||||
| 	case SYSCONF: | ||||
| 		errno = 0; | ||||
| 		if ((val = sysconf(cp->value)) == -1) { | ||||
| 			if (errno != 0) { | ||||
| 				builtin_error ("%s", strerror (errno)); | ||||
| 				return (EXECUTION_FAILURE); | ||||
| 			} | ||||
| 
 | ||||
| 			printf ("undefined\n"); | ||||
| 		} else { | ||||
| 			printf("%ld\n", val); | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	case PATHCONF: | ||||
| 		errno = 0; | ||||
| 		if ((val = pathconf(argv[1], cp->value)) == -1) { | ||||
| 			if (errno != 0) { | ||||
| 				builtin_error ("%s: %s", argv[1], strerror (errno)); | ||||
| 				return (EXECUTION_FAILURE); | ||||
| 			} | ||||
| 
 | ||||
| 			printf ("undefined\n"); | ||||
| 		} else { | ||||
| 			printf ("%ld\n", val); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return (ferror(stdout) ? EXECUTION_FAILURE : EXECUTION_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| static char *getconf_doc[] = { | ||||
| 	"getconf writes the current value of a configurable system limit or", | ||||
| 	"option variable to the standard output.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| struct builtin getconf_struct = { | ||||
| 	"getconf", | ||||
| 	getconf_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	getconf_doc, | ||||
| 	"getconf sysvar or getconf pathvar pathname", | ||||
| 	0 | ||||
| }; | ||||
							
								
								
									
										143
									
								
								examples/loadables/head.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								examples/loadables/head.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,143 @@ | |||
| /* head - copy first part of files. */ | ||||
| 
 | ||||
| /* See Makefile for compilation details. */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include "bashtypes.h" | ||||
| #include "posixstat.h" | ||||
| #include "filecntl.h" | ||||
| 
 | ||||
| #if defined (HAVE_UNISTD_H) | ||||
| #  include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "bashansi.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
| #include <ctype.h> | ||||
| 
 | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| #include "bashgetopt.h" | ||||
| 
 | ||||
| #if !defined (errno) | ||||
| extern int errno; | ||||
| #endif | ||||
| 
 | ||||
| static void | ||||
| munge_list (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   WORD_LIST *l, *nl; | ||||
|   WORD_DESC *wd; | ||||
|   char *arg; | ||||
| 
 | ||||
|   for (l = list; l; l = l->next) | ||||
|     { | ||||
|       arg = l->word->word; | ||||
|       if (arg[0] != '-' || arg[1] == '-' || (isdigit(arg[1]) == 0)) | ||||
|         return; | ||||
|       /* We have -[0-9]* */ | ||||
|       wd = make_bare_word (arg+1); | ||||
|       nl = make_word_list (wd, l->next); | ||||
|       l->word->word[1] = 'n'; | ||||
|       l->word->word[2] = '\0'; | ||||
|       l->next = nl; | ||||
|       l = nl;	/* skip over new argument */ | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| file_head (fp, cnt) | ||||
|      FILE *fp; | ||||
|      int cnt; | ||||
| { | ||||
|   int ch; | ||||
| 
 | ||||
|   while (cnt--) | ||||
|     { | ||||
|       while ((ch = getc (fp)) != EOF) | ||||
| 	{ | ||||
| 	  if (putchar (ch) == EOF) | ||||
| 	    { | ||||
| 	      builtin_error ("write error: %s", strerror (errno)); | ||||
| 	      return EXECUTION_FAILURE; | ||||
| 	    } | ||||
| 	  if (ch == '\n') | ||||
| 	    break; | ||||
| 	} | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| head_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int nline, opt, rval; | ||||
|   WORD_LIST *l; | ||||
|   FILE *fp; | ||||
| 
 | ||||
|   char *t; | ||||
| 
 | ||||
|   munge_list (list);	/* change -num into -n num */ | ||||
| 
 | ||||
|   reset_internal_getopt (); | ||||
|   nline = 10; | ||||
|   while ((opt = internal_getopt (list, "n:")) != -1) | ||||
|     { | ||||
|       switch (opt) | ||||
| 	{ | ||||
| 	case 'n': | ||||
| 	  nline = atoi (list_optarg); | ||||
| 	  if (nline <= 0) | ||||
| 	    { | ||||
| 	      builtin_error ("bad line count: %s", list_optarg); | ||||
| 	      return (EX_USAGE); | ||||
| 	    } | ||||
| 	  break; | ||||
| 	default: | ||||
| 	  builtin_usage (); | ||||
| 	  return (EX_USAGE); | ||||
| 	} | ||||
|     } | ||||
|   list = loptend; | ||||
| 
 | ||||
|   if (list == 0) | ||||
|     return (file_head (stdin, nline)); | ||||
| 
 | ||||
|   for (rval = EXECUTION_SUCCESS, opt = 1, l = list; l; l = l->next) | ||||
|     { | ||||
|       fp = fopen (l->word->word, "r"); | ||||
|       if (fp == NULL) | ||||
| 	{ | ||||
| 	  builtin_error ("%s: %s", l->word->word, strerror (errno)); | ||||
| 	  continue; | ||||
| 	} | ||||
|       if (list->next)	/* more than one file */ | ||||
| 	{ | ||||
| 	  printf ("%s==> %s <==\n", opt ? "" : "\n", l->word->word); | ||||
| 	  opt = 0; | ||||
| 	} | ||||
|       rval = file_head (fp, nline); | ||||
|       fclose (fp); | ||||
|     } | ||||
|     | ||||
|   return (rval); | ||||
| } | ||||
| 
 | ||||
| char *head_doc[] = { | ||||
| 	"Copy the first N lines from the input files to the standard output.", | ||||
| 	"N is supplied as an argument to the `-n' option.  If N is not given,", | ||||
| 	"the first ten lines are copied.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| struct builtin head_struct = { | ||||
| 	"head",			/* builtin name */ | ||||
| 	head_builtin,		/* function implementing the builtin */ | ||||
| 	BUILTIN_ENABLED,	/* initial flags for builtin */ | ||||
| 	head_doc,		/* array of long documentation strings. */ | ||||
| 	"head [-n num] [file ...]", /* usage synopsis; becomes short_doc */ | ||||
| 	0			/* reserved for internal use */ | ||||
| }; | ||||
							
								
								
									
										59
									
								
								examples/loadables/hello.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								examples/loadables/hello.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| /* Sample builtin to be dynamically loaded with enable -f and create a new
 | ||||
|    builtin. */ | ||||
| 
 | ||||
| /* See Makefile for compilation details. */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #if defined (HAVE_UNISTD_H) | ||||
| #  include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| 
 | ||||
| /* A builtin `xxx' is normally implemented with an `xxx_builtin' function.
 | ||||
|    If you're converting a command that uses the normal Unix argc/argv | ||||
|    calling convention, use argv = word_list_to_argv (list, &argc) and call | ||||
|    the original `main' something like `xxx_main'.  Look at cat.c for an | ||||
|    example. | ||||
| 
 | ||||
|    Builtins should use internal_getopt to parse options.  It is the same as | ||||
|    getopt(3), but it takes a WORD_LIST *.  Look at print.c for an example | ||||
|    of its use. | ||||
| 
 | ||||
|    If the builtin takes no options, call no_options(list) before doing | ||||
|    anything else.  If it returns a non-zero value, your builtin should | ||||
|    immediately return EX_USAGE.  Look at logname.c for an example. | ||||
| 
 | ||||
|    A builtin command returns EXECUTION_SUCCESS for success and | ||||
|    EXECUTION_FAILURE to indicate failure. */ | ||||
| hello_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   printf("hello world\n"); | ||||
|   fflush (stdout); | ||||
|   return (EXECUTION_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /* An array of strings forming the `long' documentation for a builtin xxx,
 | ||||
|    which is printed by `help xxx'.  It must end with a NULL. */ | ||||
| char *hello_doc[] = { | ||||
| 	"this is the long doc for the sample hello builtin", | ||||
| 	"which is a bare-bones echo", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| /* The standard structure describing a builtin command.  bash keeps an array
 | ||||
|    of these structures.  The flags must include BUILTIN_ENABLED so the | ||||
|    builtin can be used. */ | ||||
| struct builtin hello_struct = { | ||||
| 	"hello",		/* builtin name */ | ||||
| 	hello_builtin,		/* function implementing the builtin */ | ||||
| 	BUILTIN_ENABLED,	/* initial flags for builtin */ | ||||
| 	hello_doc,		/* array of long documentation strings. */ | ||||
| 	"hello [args]",		/* usage synopsis; becomes short_doc */ | ||||
| 	0			/* reserved for internal use */ | ||||
| }; | ||||
| 	 | ||||
							
								
								
									
										52
									
								
								examples/loadables/logname.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								examples/loadables/logname.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,52 @@ | |||
| /* logname - print login name of current user */ | ||||
| 
 | ||||
| #include <config.h> | ||||
| 
 | ||||
| #if defined (HAVE_UNISTD_H) | ||||
| #  include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| 
 | ||||
| #if !defined (errno) | ||||
| extern int errno; | ||||
| #endif | ||||
| 
 | ||||
| logname_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   char *np; | ||||
| 
 | ||||
|   if (no_options (list)) | ||||
|     return (EX_USAGE); | ||||
| 
 | ||||
|   np = getlogin (); | ||||
|   if (np == 0) | ||||
|     { | ||||
|       builtin_error ("cannot find username: %s", strerror (errno)); | ||||
|       return (EXECUTION_FAILURE); | ||||
|     } | ||||
|   printf ("%s\n", np); | ||||
|   return (EXECUTION_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| char *logname_doc[] = { | ||||
| 	"write the current user's login name to the standard output", | ||||
| 	"and exit.  logname ignores the LOGNAME and USER variables.", | ||||
| 	"logname ignores any non-option arguments.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 	 | ||||
| struct builtin logname_struct = { | ||||
| 	"logname", | ||||
| 	logname_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	logname_doc, | ||||
| 	"logname", | ||||
| 	0 | ||||
| }; | ||||
| 	 | ||||
							
								
								
									
										33
									
								
								examples/loadables/necho.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								examples/loadables/necho.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| /* necho - echo without options or argument interpretation */ | ||||
| 
 | ||||
| /* Sample builtin to be dynamically loaded with enable -f and replace an
 | ||||
|    existing builtin. */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| 
 | ||||
| necho_builtin (list) | ||||
| WORD_LIST *list; | ||||
| { | ||||
| 	print_word_list (list, " "); | ||||
| 	printf("\n"); | ||||
| 	fflush (stdout); | ||||
| 	return (EXECUTION_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| char *necho_doc[] = { | ||||
| 	"Print the arguments to the standard ouput separated", | ||||
| 	"by space characters and terminated with a newline.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 	 | ||||
| struct builtin echo_struct = { | ||||
| 	"echo", | ||||
| 	necho_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	necho_doc, | ||||
| 	"echo [args]", | ||||
| 	0 | ||||
| }; | ||||
| 	 | ||||
							
								
								
									
										359
									
								
								examples/loadables/pathchk.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										359
									
								
								examples/loadables/pathchk.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,359 @@ | |||
| /* pathchk - check pathnames for validity and portability */ | ||||
| 
 | ||||
| /* Usage: pathchk [-p] path ...
 | ||||
| 
 | ||||
|    For each PATH, print a message if any of these conditions are false: | ||||
|    * all existing leading directories in PATH have search (execute) permission | ||||
|    * strlen (PATH) <= PATH_MAX | ||||
|    * strlen (each_directory_in_PATH) <= NAME_MAX | ||||
| 
 | ||||
|    Exit status: | ||||
|    0			All PATH names passed all of the tests. | ||||
|    1			An error occurred. | ||||
| 
 | ||||
|    Options: | ||||
|    -p			Instead of performing length checks on the | ||||
| 			underlying filesystem, test the length of the | ||||
| 			pathname and its components against the POSIX.1 | ||||
| 			minimum limits for portability, _POSIX_NAME_MAX | ||||
| 			and _POSIX_PATH_MAX in 2.9.2.  Also check that | ||||
| 			the pathname contains no character not in the | ||||
| 			portable filename character set. */ | ||||
| 
 | ||||
| /* See Makefile for compilation details. */ | ||||
| 
 | ||||
| #include <config.h> | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include "posixstat.h" | ||||
| 
 | ||||
| #if defined (HAVE_UNISTD_H) | ||||
| #  include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #if defined (HAVE_LIMITS_H) | ||||
| #  include <limits.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "bashansi.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| #include "stdc.h" | ||||
| #include "bashgetopt.h" | ||||
| #include "maxpath.h" | ||||
| 
 | ||||
| #if !defined (errno) | ||||
| extern int errno; | ||||
| #endif | ||||
| 
 | ||||
| #if !defined (_POSIX_PATH_MAX) | ||||
| #  define _POSIX_PATH_MAX 255 | ||||
| #endif | ||||
| #if !defined (_POSIX_NAME_MAX) | ||||
| #  define _POSIX_NAME_MAX 14 | ||||
| #endif | ||||
| 
 | ||||
| /* How do we get PATH_MAX? */ | ||||
| #if defined (_POSIX_VERSION) && !defined (PATH_MAX) | ||||
| #  define PATH_MAX_FOR(p) pathconf ((p), _PC_PATH_MAX) | ||||
| #endif | ||||
| 
 | ||||
| /* How do we get NAME_MAX? */ | ||||
| #if defined (_POSIX_VERSION) && !defined (NAME_MAX) | ||||
| #  define NAME_MAX_FOR(p) pathconf ((p), _PC_NAME_MAX) | ||||
| #endif | ||||
| 
 | ||||
| #if !defined (PATH_MAX_FOR) | ||||
| #  define PATH_MAX_FOR(p)	PATH_MAX | ||||
| #endif | ||||
| 
 | ||||
| #if !defined (NAME_MAX_FOR) | ||||
| #  define NAME_MAX_FOR(p)	NAME_MAX | ||||
| #endif | ||||
| 
 | ||||
| extern char *strerror (); | ||||
| 
 | ||||
| static int validate_path (); | ||||
| 
 | ||||
| pathchk_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int retval, pflag, opt; | ||||
| 
 | ||||
|   reset_internal_getopt (); | ||||
|   while ((opt = internal_getopt (list, "p")) != -1) | ||||
|     { | ||||
|       switch (opt) | ||||
| 	{ | ||||
| 	case 'p': | ||||
| 	  pflag = 1; | ||||
| 	  break; | ||||
| 	default: | ||||
| 	  builtin_usage (); | ||||
| 	  return (EX_USAGE); | ||||
| 	} | ||||
|     } | ||||
|   list = loptend; | ||||
| 
 | ||||
|   if (list == 0) | ||||
|     { | ||||
|       builtin_usage (); | ||||
|       return (EX_USAGE); | ||||
|     } | ||||
| 
 | ||||
|   for (retval = 0; list; list = list->next) | ||||
|     retval |= validate_path (list->word->word, pflag); | ||||
| 
 | ||||
|   return (retval ? EXECUTION_FAILURE : EXECUTION_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| char *pathchk_doc[] = { | ||||
| 	"Check each pathname argument for validity (i.e., it may be used to", | ||||
| 	"create or access a file without casuing syntax errors) and portability", | ||||
| 	"(i.e., no filename truncation will result).  If the `-p' option is", | ||||
| 	"supplied, more extensive portability checks are performed.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| /* The standard structure describing a builtin command.  bash keeps an array
 | ||||
|    of these structures. */ | ||||
| struct builtin pathchk_struct = { | ||||
| 	"pathchk",		/* builtin name */ | ||||
| 	pathchk_builtin,	/* function implementing the builtin */ | ||||
| 	BUILTIN_ENABLED,	/* initial flags for builtin */ | ||||
| 	pathchk_doc,		/* array of long documentation strings. */ | ||||
| 	"pathchk [-p] pathname ...",	/* usage synopsis */ | ||||
| 	0			/* reserved for internal use */ | ||||
| }; | ||||
| 
 | ||||
| /* The remainder of this file is stolen shamelessly from `pathchk.c' in
 | ||||
|    the sh-utils-1.12 distribution, by  | ||||
| 
 | ||||
|    David MacKenzie <djm@gnu.ai.mit.edu> | ||||
|    and Jim Meyering <meyering@cs.utexas.edu> */ | ||||
| 
 | ||||
| /* Each element is nonzero if the corresponding ASCII character is
 | ||||
|    in the POSIX portable character set, and zero if it is not. | ||||
|    In addition, the entry for `/' is nonzero to simplify checking. */ | ||||
| static char const portable_chars[256] = | ||||
| { | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-15 */ | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-31 */ | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, /* 32-47 */ | ||||
|   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 48-63 */ | ||||
|   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64-79 */ | ||||
|   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 80-95 */ | ||||
|   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 96-111 */ | ||||
|   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 112-127 */ | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  | ||||
|   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||||
| }; | ||||
| 
 | ||||
| /* If PATH contains only portable characters, return 1, else 0.  */ | ||||
| 
 | ||||
| static int | ||||
| portable_chars_only (path) | ||||
|      const char *path; | ||||
| { | ||||
|   const char *p; | ||||
| 
 | ||||
|   for (p = path; *p; ++p) | ||||
|     if (portable_chars[(const unsigned char) *p] == 0) | ||||
|       { | ||||
| 	error (0, 0, "path `%s' contains nonportable character `%c'", | ||||
| 	       path, *p); | ||||
| 	return 0; | ||||
|       } | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| /* On some systems, stat can return EINTR.  */ | ||||
| 
 | ||||
| #ifndef EINTR | ||||
| # define SAFE_STAT(name, buf) stat (name, buf) | ||||
| #else | ||||
| # define SAFE_STAT(name, buf) safe_stat (name, buf) | ||||
| static inline int | ||||
| safe_stat (name, buf) | ||||
|      const char *name; | ||||
|      struct stat *buf; | ||||
| { | ||||
|   int ret; | ||||
| 
 | ||||
|   do | ||||
|     ret = stat (name, buf); | ||||
|   while (ret < 0 && errno == EINTR); | ||||
| 
 | ||||
|   return ret; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /* Return 1 if PATH is a usable leading directory, 0 if not,
 | ||||
|    2 if it doesn't exist.  */ | ||||
| 
 | ||||
| static int | ||||
| dir_ok (path) | ||||
|      const char *path; | ||||
| { | ||||
|   struct stat stats; | ||||
| 
 | ||||
|   if (SAFE_STAT (path, &stats)) | ||||
|     return 2; | ||||
| 
 | ||||
|   if (!S_ISDIR (stats.st_mode)) | ||||
|     { | ||||
|       error (0, 0, "`%s' is not a directory", path); | ||||
|       return 0; | ||||
|     } | ||||
| 
 | ||||
|   /* Use access to test for search permission because
 | ||||
|      testing permission bits of st_mode can lose with new | ||||
|      access control mechanisms.  Of course, access loses if you're | ||||
|      running setuid. */ | ||||
|   if (access (path, X_OK) != 0) | ||||
|     { | ||||
|       if (errno == EACCES) | ||||
| 	builtin_error ("directory `%s' is not searchable", path); | ||||
|       else | ||||
| 	builtin_error ("%s: %s", path, strerror (errno)); | ||||
|       return 0; | ||||
|     } | ||||
| 
 | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| static char * | ||||
| xstrdup (s) | ||||
|      char *s; | ||||
| { | ||||
|   return (savestring (s)); | ||||
| } | ||||
| 
 | ||||
| /* Make sure that
 | ||||
|    strlen (PATH) <= PATH_MAX | ||||
|    && strlen (each-existing-directory-in-PATH) <= NAME_MAX | ||||
| 
 | ||||
|    If PORTABILITY is nonzero, compare against _POSIX_PATH_MAX and | ||||
|    _POSIX_NAME_MAX instead, and make sure that PATH contains no | ||||
|    characters not in the POSIX portable filename character set, which | ||||
|    consists of A-Z, a-z, 0-9, ., _, -. | ||||
| 
 | ||||
|    Make sure that all leading directories along PATH that exist have | ||||
|    `x' permission. | ||||
| 
 | ||||
|    Return 0 if all of these tests are successful, 1 if any fail. */ | ||||
| 
 | ||||
| static int | ||||
| validate_path (path, portability) | ||||
|      char *path; | ||||
|      int portability; | ||||
| { | ||||
|   int path_max; | ||||
|   int last_elem;		/* Nonzero if checking last element of path. */ | ||||
|   int exists;			/* 2 if the path element exists.  */ | ||||
|   char *slash; | ||||
|   char *parent;			/* Last existing leading directory so far.  */ | ||||
| 
 | ||||
|   if (portability && !portable_chars_only (path)) | ||||
|     return 1; | ||||
| 
 | ||||
|   if (*path == '\0') | ||||
|     return 0; | ||||
| 
 | ||||
| #ifdef lint | ||||
|   /* Suppress `used before initialized' warning.  */ | ||||
|   exists = 0; | ||||
| #endif | ||||
| 
 | ||||
|   /* Figure out the parent of the first element in PATH.  */ | ||||
|   parent = xstrdup (*path == '/' ? "/" : "."); | ||||
| 
 | ||||
|   slash = path; | ||||
|   last_elem = 0; | ||||
|   while (1) | ||||
|     { | ||||
|       int name_max; | ||||
|       int length;		/* Length of partial path being checked. */ | ||||
|       char *start;		/* Start of path element being checked. */ | ||||
| 
 | ||||
|       /* Find the end of this element of the path.
 | ||||
| 	 Then chop off the rest of the path after this element. */ | ||||
|       while (*slash == '/') | ||||
| 	slash++; | ||||
|       start = slash; | ||||
|       slash = strchr (slash, '/'); | ||||
|       if (slash != NULL) | ||||
| 	*slash = '\0'; | ||||
|       else | ||||
| 	{ | ||||
| 	  last_elem = 1; | ||||
| 	  slash = strchr (start, '\0'); | ||||
| 	} | ||||
| 
 | ||||
|       if (!last_elem) | ||||
| 	{ | ||||
| 	  exists = dir_ok (path); | ||||
| 	  if (dir_ok == 0) | ||||
| 	    { | ||||
| 	      free (parent); | ||||
| 	      return 1; | ||||
| 	    } | ||||
| 	} | ||||
| 
 | ||||
|       length = slash - start; | ||||
|       /* Since we know that `parent' is a directory, it's ok to call
 | ||||
| 	 pathconf with it as the argument.  (If `parent' isn't a directory | ||||
| 	 or doesn't exist, the behavior of pathconf is undefined.) | ||||
| 	 But if `parent' is a directory and is on a remote file system, | ||||
| 	 it's likely that pathconf can't give us a reasonable value | ||||
| 	 and will return -1.  (NFS and tempfs are not POSIX . . .) | ||||
| 	 In that case, we have no choice but to assume the pessimal | ||||
| 	 POSIX minimums.  */ | ||||
|       name_max = portability ? _POSIX_NAME_MAX : NAME_MAX_FOR (parent); | ||||
|       if (name_max < 0) | ||||
| 	name_max = _POSIX_NAME_MAX; | ||||
|       if (length > name_max) | ||||
| 	{ | ||||
| 	  error (0, 0, "name `%s' has length %d; exceeds limit of %d", | ||||
| 		 start, length, name_max); | ||||
| 	  free (parent); | ||||
| 	  return 1; | ||||
| 	} | ||||
| 
 | ||||
|       if (last_elem) | ||||
| 	break; | ||||
| 
 | ||||
|       if (exists == 1) | ||||
| 	{ | ||||
| 	  free (parent); | ||||
| 	  parent = xstrdup (path); | ||||
| 	} | ||||
| 
 | ||||
|       *slash++ = '/'; | ||||
|     } | ||||
| 
 | ||||
|   /* `parent' is now the last existing leading directory in the whole path,
 | ||||
|      so it's ok to call pathconf with it as the argument.  */ | ||||
|   path_max = portability ? _POSIX_PATH_MAX : PATH_MAX_FOR (parent); | ||||
|   if (path_max < 0) | ||||
|     path_max = _POSIX_PATH_MAX; | ||||
|   free (parent); | ||||
|   if (strlen (path) > path_max) | ||||
|     { | ||||
|       error (0, 0, "path `%s' has length %d; exceeds limit of %d", | ||||
| 	     path, strlen (path), path_max); | ||||
|       return 1; | ||||
|     } | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										553
									
								
								examples/loadables/print.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										553
									
								
								examples/loadables/print.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,553 @@ | |||
| /*
 | ||||
|  * Copyright (c) 1989, 1993 | ||||
|  *	The Regents of the University of California.  All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer. | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer in the | ||||
|  *    documentation and/or other materials provided with the distribution. | ||||
|  * 3. All advertising materials mentioning features or use of this software | ||||
|  *    must display the following acknowledgement: | ||||
|  *	This product includes software developed by the University of | ||||
|  *	California, Berkeley and its contributors. | ||||
|  * 4. Neither the name of the University nor the names of its contributors | ||||
|  *    may be used to endorse or promote products derived from this software | ||||
|  *    without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||||
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
|  * SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #include "bashansi.h" | ||||
| #include "shell.h" | ||||
| #include "builtins.h" | ||||
| #include "stdc.h" | ||||
| #include "bashgetopt.h" | ||||
| 
 | ||||
| #if !defined (errno) | ||||
| extern int errno; | ||||
| #endif | ||||
| 
 | ||||
| #define PF(f, func) { \ | ||||
| 	if (fieldwidth) \ | ||||
| 		if (precision) \ | ||||
| 			(void)fprintf(ofp, f, fieldwidth, precision, func); \ | ||||
| 		else \ | ||||
| 			(void)fprintf(ofp, f, fieldwidth, func); \ | ||||
| 	else if (precision) \ | ||||
| 		(void)fprintf(ofp, f, precision, func); \ | ||||
| 	else \ | ||||
| 		(void)fprintf(ofp, f, func); \ | ||||
| } | ||||
| 
 | ||||
| static int	 asciicode __P((void)); | ||||
| static void	 escape __P((char *)); | ||||
| static int	 getchr __P((void)); | ||||
| static double	 getdouble __P((void)); | ||||
| static int	 getint __P((int *)); | ||||
| static int	 getlong __P((long *)); | ||||
| static char	*getstr __P((void)); | ||||
| static char	*mklong __P((char *, int)); | ||||
| static void	 usage __P((void)); | ||||
| 
 | ||||
| static char **gargv; | ||||
| 
 | ||||
| int print_builtin (); | ||||
| static int printf_main (); | ||||
| static int printargs (); | ||||
| 
 | ||||
| static FILE *ofp; | ||||
| 
 | ||||
| extern char *ansicstr (); | ||||
| extern char *single_quote (); | ||||
| extern char **make_builtin_argv (); | ||||
| 
 | ||||
| extern char *this_command_name; | ||||
| 
 | ||||
| extern int optind; | ||||
| 
 | ||||
| static char *print_doc[] = { | ||||
|   "Output the arguments.  The -f option means to use the argument as a", | ||||
|   "format string as would be supplied to printf(1).  The rest of the", | ||||
|   "options are as in ksh.", | ||||
|   (char *)NULL | ||||
| }; | ||||
| 
 | ||||
| struct builtin print_struct = { | ||||
| 	"print", | ||||
| 	print_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	print_doc, | ||||
| 	"print [-Rnprs] [-u unit] [-f format] [arguments]", | ||||
| 	(char *)0 | ||||
| }; | ||||
| 
 | ||||
| #ifndef ISOPTION | ||||
| #define ISOPTION(s, c)	(s[0] == '-' && s[2] == '\0' && s[1] == c) | ||||
| #endif | ||||
| 
 | ||||
| int | ||||
| print_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int c, r, nflag, raw, ofd, sflag; | ||||
|   char **v, *pfmt, *arg; | ||||
|   WORD_LIST *l; | ||||
| 
 | ||||
|   nflag = raw = sflag = 0; | ||||
|   ofd = 1; | ||||
|   pfmt = 0; | ||||
| 
 | ||||
|   reset_internal_getopt (); | ||||
|   while ((c = internal_getopt (list, "Rnprsu:f:")) != -1) | ||||
|     { | ||||
|       switch (c) | ||||
| 	{ | ||||
| 	case 'R': | ||||
| 	  raw = 2; | ||||
| 	  loptend = lcurrent; | ||||
| 	  if (loptend && ISOPTION (loptend->word->word, 'n')) | ||||
| 	    { | ||||
| 	      loptend = loptend->next; | ||||
| 	      nflag = 1; | ||||
| 	    } | ||||
| 	  goto opt_end; | ||||
| 	case 'r': | ||||
| 	  raw = 1; | ||||
| 	  break; | ||||
| 	case 'n': | ||||
| 	  nflag = 1; | ||||
| 	  break; | ||||
| 	case 's': | ||||
| 	  sflag = 1; | ||||
| 	  break; | ||||
| 	case 'p': | ||||
| 	  break;	/* NOP */ | ||||
| 	case 'u': | ||||
| 	  if (all_digits (list_optarg)) | ||||
| 	    ofd = atoi (list_optarg); | ||||
| 	  else | ||||
| 	    { | ||||
| 	      for (l = list; l->next && l->next != lcurrent; l = l->next); | ||||
| 	      lcurrent = loptend = l; | ||||
| 	      goto opt_end; | ||||
| 	    } | ||||
| 	  break; | ||||
| 	case 'f': | ||||
| 	  pfmt = list_optarg; | ||||
| 	  break; | ||||
| 	default: | ||||
| 	  builtin_usage (); | ||||
| 	  return (EX_USAGE); | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
| opt_end: | ||||
|   list = loptend; | ||||
| 
 | ||||
|   ofp = (ofd == 1) ? stdout : fdopen (dup (ofd), "w"); | ||||
| 
 | ||||
|   if (pfmt) | ||||
|     { | ||||
|       v = word_list_to_argv (list, 0, 2, &c); | ||||
|       v[0] = this_command_name; | ||||
|       v[1] = pfmt; | ||||
|       r = printf_main (c, v); | ||||
|       free (v); | ||||
|       return r; | ||||
|     } | ||||
| 
 | ||||
|   if (raw) | ||||
|     { | ||||
|       for (l = list; l; l = l->next) | ||||
| 	{ | ||||
| 	  fprintf (ofp, "%s", l->word->word); | ||||
| 	  if (l->next) | ||||
| 	    fprintf (ofp, " "); | ||||
| 	} | ||||
|       if (nflag == 0) | ||||
| 	fprintf (ofp, "\n"); | ||||
|       fflush (ofp); | ||||
|       return (0);	 | ||||
|     } | ||||
|          | ||||
|   r = printargs (list, ofp); | ||||
|   if (r && nflag == 0) | ||||
|     fprintf (ofp, "\n"); | ||||
|   if (ofd != 1) | ||||
|     fclose (ofp); | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| static int printargs (list, ofp) | ||||
|      WORD_LIST *list; | ||||
|      FILE *ofp; | ||||
| { | ||||
|   WORD_LIST *l; | ||||
|   char *ostr; | ||||
|   int sawc; | ||||
| 
 | ||||
|   for (sawc = 0, l = list; l; l = l->next) | ||||
|     { | ||||
|       ostr = ansicstr (l->word->word, strlen (l->word->word), &sawc); | ||||
|       fprintf (ofp, "%s", ostr); | ||||
|       free (ostr); | ||||
|       if (sawc) | ||||
|         return (0); | ||||
|       if (l->next) | ||||
|         fprintf (ofp, " "); | ||||
|     } | ||||
|   return (1); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| printf_main(argc, argv) | ||||
| 	int argc; | ||||
| 	char *argv[]; | ||||
| { | ||||
| 	static char *skip1, *skip2; | ||||
| 	int ch, end, fieldwidth, precision; | ||||
| 	char convch, nextch, *format, *fmt, *start; | ||||
| 
 | ||||
| 	while ((ch = getopt(argc, argv, "")) != EOF) | ||||
| 		switch (ch) { | ||||
| 		case '?': | ||||
| 		default: | ||||
| 			usage(); | ||||
| 			return (1); | ||||
| 		} | ||||
| 	argc -= optind; | ||||
| 	argv += optind; | ||||
| 
 | ||||
| 	if (argc < 1) { | ||||
| 		usage(); | ||||
| 		return (1); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Basic algorithm is to scan the format string for conversion | ||||
| 	 * specifications -- once one is found, find out if the field | ||||
| 	 * width or precision is a '*'; if it is, gather up value.  Note, | ||||
| 	 * format strings are reused as necessary to use up the provided | ||||
| 	 * arguments, arguments of zero/null string are provided to use | ||||
| 	 * up the format string. | ||||
| 	 */ | ||||
| 	skip1 = "#-+ 0"; | ||||
| 	skip2 = "*0123456789"; | ||||
| 
 | ||||
| 	escape(fmt = format = *argv);		/* backslash interpretation */ | ||||
| 	gargv = ++argv; | ||||
| 	for (;;) { | ||||
| 		end = 0; | ||||
| 		/* find next format specification */ | ||||
| next:		for (start = fmt;; ++fmt) { | ||||
| 			if (!*fmt) { | ||||
| 				/* avoid infinite loop */ | ||||
| 				if (end == 1) { | ||||
| 					warnx("missing format character", | ||||
| 					    NULL, NULL); | ||||
| 					return (1); | ||||
| 				} | ||||
| 				end = 1; | ||||
| 				if (fmt > start) | ||||
| 					(void)printf("%s", start); | ||||
| 				if (!*gargv) | ||||
| 					return (0); | ||||
| 				fmt = format; | ||||
| 				goto next; | ||||
| 			} | ||||
| 			/* %% prints a % */ | ||||
| 			if (*fmt == '%') { | ||||
| 				if (*++fmt != '%') | ||||
| 					break; | ||||
| 				*fmt++ = '\0'; | ||||
| 				(void)printf("%s", start); | ||||
| 				goto next; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		/* skip to field width */ | ||||
| 		for (; strchr(skip1, *fmt); ++fmt); | ||||
| 		if (*fmt == '*') { | ||||
| 			if (getint(&fieldwidth)) | ||||
| 				return (1); | ||||
| 		} else | ||||
| 			fieldwidth = 0; | ||||
| 
 | ||||
| 		/* skip to possible '.', get following precision */ | ||||
| 		for (; strchr(skip2, *fmt); ++fmt); | ||||
| 		if (*fmt == '.') | ||||
| 			++fmt; | ||||
| 		if (*fmt == '*') { | ||||
| 			if (getint(&precision)) | ||||
| 				return (1); | ||||
| 		} else | ||||
| 			precision = 0; | ||||
| 
 | ||||
| 		/* skip to conversion char */ | ||||
| 		for (; strchr(skip2, *fmt); ++fmt); | ||||
| 		if (!*fmt) { | ||||
| 			warnx("missing format character", NULL, NULL); | ||||
| 			return (1); | ||||
| 		} | ||||
| 
 | ||||
| 		convch = *fmt; | ||||
| 		nextch = *++fmt; | ||||
| 		*fmt = '\0'; | ||||
| 		switch(convch) { | ||||
| 		case 'c': { | ||||
| 			char p; | ||||
| 
 | ||||
| 			p = getchr(); | ||||
| 			PF(start, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 's': { | ||||
| 			char *p; | ||||
| 
 | ||||
| 			p = getstr(); | ||||
| 			PF(start, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'b': {		/* expand escapes in argument */ | ||||
| 			char *p; | ||||
| 
 | ||||
| 			p = getstr(); | ||||
| 			escape(p); | ||||
| 			PF(start, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'q': {		/* print with shell single quoting */ | ||||
| 			char *p, *p2; | ||||
| 
 | ||||
| 			p = getstr(); | ||||
| 			p2 = single_quote(p); | ||||
| 			PF(start, p2); | ||||
| 			free(p2); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { | ||||
| 			long p; | ||||
| 			char *f; | ||||
| 			 | ||||
| 			if ((f = mklong(start, convch)) == NULL) | ||||
| 				return (1); | ||||
| 			if (getlong(&p)) | ||||
| 				return (1); | ||||
| 			PF(f, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'e': case 'E': case 'f': case 'g': case 'G': { | ||||
| 			double p; | ||||
| 
 | ||||
| 			p = getdouble(); | ||||
| 			PF(start, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		default: | ||||
| 			warnx("illegal format character", NULL, NULL); | ||||
| 			return (1); | ||||
| 		} | ||||
| 		*fmt = nextch; | ||||
| 	} | ||||
| 	/* NOTREACHED */ | ||||
| } | ||||
| 
 | ||||
| static char * | ||||
| mklong(str, ch) | ||||
| 	char *str; | ||||
| 	int ch; | ||||
| { | ||||
| 	static char copy[64]; | ||||
| 	int len; | ||||
| 
 | ||||
| 	len = strlen(str) + 2; | ||||
| 	memmove(copy, str, len - 3); | ||||
| 	copy[len - 3] = 'l'; | ||||
| 	copy[len - 2] = ch; | ||||
| 	copy[len - 1] = '\0'; | ||||
| 	return (copy); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| escape(fmt) | ||||
| 	register char *fmt; | ||||
| { | ||||
| 	register char *store; | ||||
| 	register int value, c; | ||||
| 
 | ||||
| 	for (store = fmt; c = *fmt; ++fmt, ++store) { | ||||
| 		if (c != '\\') { | ||||
| 			*store = c; | ||||
| 			continue; | ||||
| 		} | ||||
| 		switch (*++fmt) { | ||||
| 		case '\0':		/* EOS, user error */ | ||||
| 			*store = '\\'; | ||||
| 			*++store = '\0'; | ||||
| 			return; | ||||
| 		case '\\':		/* backslash */ | ||||
| 		case '\'':		/* single quote */ | ||||
| 			*store = *fmt; | ||||
| 			break; | ||||
| 		case 'a':		/* bell/alert */ | ||||
| 			*store = '\7'; | ||||
| 			break; | ||||
| 		case 'b':		/* backspace */ | ||||
| 			*store = '\b'; | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 			return; | ||||
| 		case 'e': | ||||
| 		case 'E': | ||||
| 			*store = '\033'; | ||||
| 			break; | ||||
| 		case 'f':		/* form-feed */ | ||||
| 			*store = '\f'; | ||||
| 			break; | ||||
| 		case 'n':		/* newline */ | ||||
| 			*store = '\n'; | ||||
| 			break; | ||||
| 		case 'r':		/* carriage-return */ | ||||
| 			*store = '\r'; | ||||
| 			break; | ||||
| 		case 't':		/* horizontal tab */ | ||||
| 			*store = '\t'; | ||||
| 			break; | ||||
| 		case 'v':		/* vertical tab */ | ||||
| 			*store = '\13'; | ||||
| 			break; | ||||
| 					/* octal constant */ | ||||
| 		case '0': case '1': case '2': case '3': | ||||
| 		case '4': case '5': case '6': case '7': | ||||
| 			for (c = 3, value = 0; | ||||
| 			    c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) { | ||||
| 				value <<= 3; | ||||
| 				value += *fmt - '0'; | ||||
| 			} | ||||
| 			--fmt; | ||||
| 			*store = value; | ||||
| 			break; | ||||
| 		default: | ||||
| 			*store = *fmt; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	*store = '\0'; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| getchr() | ||||
| { | ||||
| 	if (!*gargv) | ||||
| 		return ('\0'); | ||||
| 	return ((int)**gargv++); | ||||
| } | ||||
| 
 | ||||
| static char * | ||||
| getstr() | ||||
| { | ||||
| 	if (!*gargv) | ||||
| 		return (""); | ||||
| 	return (*gargv++); | ||||
| } | ||||
| 
 | ||||
| static char *Number = "+-.0123456789"; | ||||
| static int | ||||
| getint(ip) | ||||
| 	int *ip; | ||||
| { | ||||
| 	long val; | ||||
| 
 | ||||
| 	if (getlong(&val)) | ||||
| 		return (1); | ||||
| 	if (val > INT_MAX) { | ||||
| 		warnx("%s: %s", *gargv, strerror(ERANGE)); | ||||
| 		return (1); | ||||
| 	} | ||||
| 	*ip = val; | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| getlong(lp) | ||||
| 	long *lp; | ||||
| { | ||||
| 	long val; | ||||
| 	char *ep; | ||||
| 
 | ||||
| 	if (!*gargv) { | ||||
| 		*lp = 0; | ||||
| 		return (0); | ||||
| 	} | ||||
| 	if (strchr(Number, **gargv)) { | ||||
| 		errno = 0; | ||||
| 		val = strtol(*gargv, &ep, 0); | ||||
| 		if (*ep != '\0') { | ||||
| 			warnx("%s: illegal number", *gargv, NULL); | ||||
| 			return (1); | ||||
| 		} | ||||
| 		if (errno == ERANGE) | ||||
| 			if (val == LONG_MAX) { | ||||
| 				warnx("%s: %s", *gargv, strerror(ERANGE)); | ||||
| 				return (1); | ||||
| 			} | ||||
| 			if (val == LONG_MIN) { | ||||
| 				warnx("%s: %s", *gargv, strerror(ERANGE)); | ||||
| 				return (1); | ||||
| 			} | ||||
| 			 | ||||
| 		*lp = val; | ||||
| 		++gargv; | ||||
| 		return (0); | ||||
| 	} | ||||
| 	*lp =  (long)asciicode(); | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| static double | ||||
| getdouble() | ||||
| { | ||||
| 	if (!*gargv) | ||||
| 		return ((double)0); | ||||
| 	if (strchr(Number, **gargv)) | ||||
| 		return (atof(*gargv++)); | ||||
| 	return ((double)asciicode()); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| asciicode() | ||||
| { | ||||
| 	register int ch; | ||||
| 
 | ||||
| 	ch = **gargv; | ||||
| 	if (ch == '\'' || ch == '"') | ||||
| 		ch = (*gargv)[1]; | ||||
| 	++gargv; | ||||
| 	return (ch); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| usage() | ||||
| { | ||||
| 	(void)fprintf(stderr, "usage: print [-Rnprs] [-u unit] [-f format] [arg ...]\n"); | ||||
| } | ||||
							
								
								
									
										460
									
								
								examples/loadables/printf.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										460
									
								
								examples/loadables/printf.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,460 @@ | |||
| /*
 | ||||
|  * Copyright (c) 1989, 1993 | ||||
|  *	The Regents of the University of California.  All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer. | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer in the | ||||
|  *    documentation and/or other materials provided with the distribution. | ||||
|  * 3. All advertising materials mentioning features or use of this software | ||||
|  *    must display the following acknowledgement: | ||||
|  *	This product includes software developed by the University of | ||||
|  *	California, Berkeley and its contributors. | ||||
|  * 4. Neither the name of the University nor the names of its contributors | ||||
|  *    may be used to endorse or promote products derived from this software | ||||
|  *    without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||||
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
|  * SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #if !defined(BUILTIN) && !defined(SHELL) | ||||
| #ifndef lint | ||||
| static char copyright[] = | ||||
| "@(#) Copyright (c) 1989, 1993\n\
 | ||||
| 	The Regents of the University of California.  All rights reserved.\n"; | ||||
| #endif /* not lint */ | ||||
| #endif | ||||
| 
 | ||||
| #ifndef lint | ||||
| static char sccsid[] = "@(#)printf.c	8.1 (Berkeley) 7/20/93"; | ||||
| #endif /* not lint */ | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #include "bashansi.h" | ||||
| #include "shell.h" | ||||
| #include "builtins.h" | ||||
| #include "stdc.h" | ||||
| 
 | ||||
| #if !defined (errno) | ||||
| extern int errno; | ||||
| #endif | ||||
| 
 | ||||
| #define PF(f, func) { \ | ||||
| 	if (fieldwidth) \ | ||||
| 		if (precision) \ | ||||
| 			(void)printf(f, fieldwidth, precision, func); \ | ||||
| 		else \ | ||||
| 			(void)printf(f, fieldwidth, func); \ | ||||
| 	else if (precision) \ | ||||
| 		(void)printf(f, precision, func); \ | ||||
| 	else \ | ||||
| 		(void)printf(f, func); \ | ||||
| } | ||||
| 
 | ||||
| static int	 asciicode __P((void)); | ||||
| static void	 escape __P((char *)); | ||||
| static int	 getchr __P((void)); | ||||
| static double	 getdouble __P((void)); | ||||
| static int	 getint __P((int *)); | ||||
| static int	 getlong __P((long *)); | ||||
| static char	*getstr __P((void)); | ||||
| static char	*mklong __P((char *, int)); | ||||
| static void	 usage __P((void)); | ||||
| 
 | ||||
| static char **gargv; | ||||
| 
 | ||||
| int printf_builtin (); | ||||
| static int printf_main (); | ||||
| extern char *this_command_name; | ||||
| extern char *single_quote (); | ||||
| extern char **make_builtin_argv (); | ||||
| 
 | ||||
| static char *printf_doc[] = { | ||||
|   "printf formats and prints its arguments, after the first, under control", | ||||
|   "of the format. The format is a character string which contains three", | ||||
|   "types of objects: plain characters, which are simply copied to standard", | ||||
|   "output, character escape sequences which are converted and copied to the", | ||||
|   "standard output, and format specifications, each of which causes printing", | ||||
|   "of the next successive argument.  In addition to the standard printf(1)", | ||||
|   "formats, %%b means to expand escapes in the corresponding argument, and", | ||||
|   "%%q means to quote the argument in a way that can be reused as shell input.", | ||||
|   (char *)NULL | ||||
| }; | ||||
| 
 | ||||
| struct builtin printf_struct = { | ||||
| 	"printf", | ||||
| 	printf_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	printf_doc, | ||||
| 	"printf format [arguments]", | ||||
| 	(char *)0 | ||||
| }; | ||||
| 
 | ||||
| int | ||||
| printf_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int c, r; | ||||
|   char **v; | ||||
|   WORD_LIST *l; | ||||
| 
 | ||||
|   v = make_builtin_argv (list, &c); | ||||
|   r = printf_main (c, v); | ||||
|   free (v); | ||||
|   fflush(stdout); | ||||
| 
 | ||||
|   return r; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| printf_main(argc, argv) | ||||
| 	int argc; | ||||
| 	char *argv[]; | ||||
| { | ||||
| 	extern int optind; | ||||
| 	static char *skip1, *skip2; | ||||
| 	int ch, end, fieldwidth, precision; | ||||
| 	char convch, nextch, *format, *fmt, *start; | ||||
| 
 | ||||
| 	while ((ch = getopt(argc, argv, "")) != EOF) | ||||
| 		switch (ch) { | ||||
| 		case '?': | ||||
| 		default: | ||||
| 			usage(); | ||||
| 			return (1); | ||||
| 		} | ||||
| 	argc -= optind; | ||||
| 	argv += optind; | ||||
| 
 | ||||
| 	if (argc < 1) { | ||||
| 		usage(); | ||||
| 		return (1); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Basic algorithm is to scan the format string for conversion | ||||
| 	 * specifications -- once one is found, find out if the field | ||||
| 	 * width or precision is a '*'; if it is, gather up value.  Note, | ||||
| 	 * format strings are reused as necessary to use up the provided | ||||
| 	 * arguments, arguments of zero/null string are provided to use | ||||
| 	 * up the format string. | ||||
| 	 */ | ||||
| 	skip1 = "#-+ 0"; | ||||
| 	skip2 = "*0123456789"; | ||||
| 
 | ||||
| 	escape(fmt = format = *argv);		/* backslash interpretation */ | ||||
| 	gargv = ++argv; | ||||
| 	for (;;) { | ||||
| 		end = 0; | ||||
| 		/* find next format specification */ | ||||
| next:		for (start = fmt;; ++fmt) { | ||||
| 			if (!*fmt) { | ||||
| 				/* avoid infinite loop */ | ||||
| 				if (end == 1) { | ||||
| 					warnx("missing format character", | ||||
| 					    NULL, NULL); | ||||
| 					return (1); | ||||
| 				} | ||||
| 				end = 1; | ||||
| 				if (fmt > start) | ||||
| 					(void)printf("%s", start); | ||||
| 				if (!*gargv) | ||||
| 					return (0); | ||||
| 				fmt = format; | ||||
| 				goto next; | ||||
| 			} | ||||
| 			/* %% prints a % */ | ||||
| 			if (*fmt == '%') { | ||||
| 				if (*++fmt != '%') | ||||
| 					break; | ||||
| 				*fmt++ = '\0'; | ||||
| 				(void)printf("%s", start); | ||||
| 				goto next; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		/* skip to field width */ | ||||
| 		for (; strchr(skip1, *fmt); ++fmt); | ||||
| 		if (*fmt == '*') { | ||||
| 			if (getint(&fieldwidth)) | ||||
| 				return (1); | ||||
| 		} else | ||||
| 			fieldwidth = 0; | ||||
| 
 | ||||
| 		/* skip to possible '.', get following precision */ | ||||
| 		for (; strchr(skip2, *fmt); ++fmt); | ||||
| 		if (*fmt == '.') | ||||
| 			++fmt; | ||||
| 		if (*fmt == '*') { | ||||
| 			if (getint(&precision)) | ||||
| 				return (1); | ||||
| 		} else | ||||
| 			precision = 0; | ||||
| 
 | ||||
| 		/* skip to conversion char */ | ||||
| 		for (; strchr(skip2, *fmt); ++fmt); | ||||
| 		if (!*fmt) { | ||||
| 			warnx("missing format character", NULL, NULL); | ||||
| 			return (1); | ||||
| 		} | ||||
| 
 | ||||
| 		convch = *fmt; | ||||
| 		nextch = *++fmt; | ||||
| 		*fmt = '\0'; | ||||
| 		switch(convch) { | ||||
| 		case 'c': { | ||||
| 			char p; | ||||
| 
 | ||||
| 			p = getchr(); | ||||
| 			PF(start, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 's': { | ||||
| 			char *p; | ||||
| 
 | ||||
| 			p = getstr(); | ||||
| 			PF(start, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'b': {		/* expand escapes in argument */ | ||||
| 			char *p; | ||||
| 
 | ||||
| 			p = getstr(); | ||||
| 			escape(p); | ||||
| 			PF("%s", p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'q': {		/* print with shell single quoting */ | ||||
| 			char *p, *p2; | ||||
| 
 | ||||
| 			p = getstr(); | ||||
| 			p2 = single_quote(p); | ||||
| 			PF("%s", p2); | ||||
| 			free(p2); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { | ||||
| 			long p; | ||||
| 			char *f; | ||||
| 			 | ||||
| 			if ((f = mklong(start, convch)) == NULL) | ||||
| 				return (1); | ||||
| 			if (getlong(&p)) | ||||
| 				return (1); | ||||
| 			PF(f, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'e': case 'E': case 'f': case 'g': case 'G': { | ||||
| 			double p; | ||||
| 
 | ||||
| 			p = getdouble(); | ||||
| 			PF(start, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		default: | ||||
| 			warnx("illegal format character", NULL, NULL); | ||||
| 			return (1); | ||||
| 		} | ||||
| 		*fmt = nextch; | ||||
| 	} | ||||
| 	/* NOTREACHED */ | ||||
| } | ||||
| 
 | ||||
| static char * | ||||
| mklong(str, ch) | ||||
| 	char *str; | ||||
| 	int ch; | ||||
| { | ||||
| 	static char copy[64]; | ||||
| 	int len; | ||||
| 
 | ||||
| 	len = strlen(str) + 2; | ||||
| 	memmove(copy, str, len - 3); | ||||
| 	copy[len - 3] = 'l'; | ||||
| 	copy[len - 2] = ch; | ||||
| 	copy[len - 1] = '\0'; | ||||
| 	return (copy); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| escape(fmt) | ||||
| 	register char *fmt; | ||||
| { | ||||
| 	register char *store; | ||||
| 	register int value, c; | ||||
| 
 | ||||
| 	for (store = fmt; c = *fmt; ++fmt, ++store) { | ||||
| 		if (c != '\\') { | ||||
| 			*store = c; | ||||
| 			continue; | ||||
| 		} | ||||
| 		switch (*++fmt) { | ||||
| 		case '\0':		/* EOS, user error */ | ||||
| 			*store = '\\'; | ||||
| 			*++store = '\0'; | ||||
| 			return; | ||||
| 		case '\\':		/* backslash */ | ||||
| 		case '\'':		/* single quote */ | ||||
| 			*store = *fmt; | ||||
| 			break; | ||||
| 		case 'a':		/* bell/alert */ | ||||
| 			*store = '\7'; | ||||
| 			break; | ||||
| 		case 'b':		/* backspace */ | ||||
| 			*store = '\b'; | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 			return; | ||||
| 		case 'e': | ||||
| 		case 'E': | ||||
| 			*store = '\033'; | ||||
| 			break; | ||||
| 		case 'f':		/* form-feed */ | ||||
| 			*store = '\f'; | ||||
| 			break; | ||||
| 		case 'n':		/* newline */ | ||||
| 			*store = '\n'; | ||||
| 			break; | ||||
| 		case 'r':		/* carriage-return */ | ||||
| 			*store = '\r'; | ||||
| 			break; | ||||
| 		case 't':		/* horizontal tab */ | ||||
| 			*store = '\t'; | ||||
| 			break; | ||||
| 		case 'v':		/* vertical tab */ | ||||
| 			*store = '\13'; | ||||
| 			break; | ||||
| 					/* octal constant */ | ||||
| 		case '0': case '1': case '2': case '3': | ||||
| 		case '4': case '5': case '6': case '7': | ||||
| 			for (c = 3, value = 0; | ||||
| 			    c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) { | ||||
| 				value <<= 3; | ||||
| 				value += *fmt - '0'; | ||||
| 			} | ||||
| 			--fmt; | ||||
| 			*store = value; | ||||
| 			break; | ||||
| 		default: | ||||
| 			*store = *fmt; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	*store = '\0'; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| getchr() | ||||
| { | ||||
| 	if (!*gargv) | ||||
| 		return ('\0'); | ||||
| 	return ((int)**gargv++); | ||||
| } | ||||
| 
 | ||||
| static char * | ||||
| getstr() | ||||
| { | ||||
| 	if (!*gargv) | ||||
| 		return (""); | ||||
| 	return (*gargv++); | ||||
| } | ||||
| 
 | ||||
| static char *Number = "+-.0123456789"; | ||||
| static int | ||||
| getint(ip) | ||||
| 	int *ip; | ||||
| { | ||||
| 	long val; | ||||
| 
 | ||||
| 	if (getlong(&val)) | ||||
| 		return (1); | ||||
| 	if (val > INT_MAX) { | ||||
| 		warnx("%s: %s", *gargv, strerror(ERANGE)); | ||||
| 		return (1); | ||||
| 	} | ||||
| 	*ip = val; | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| getlong(lp) | ||||
| 	long *lp; | ||||
| { | ||||
| 	long val; | ||||
| 	char *ep; | ||||
| 
 | ||||
| 	if (!*gargv) { | ||||
| 		*lp = 0; | ||||
| 		return (0); | ||||
| 	} | ||||
| 	if (strchr(Number, **gargv)) { | ||||
| 		errno = 0; | ||||
| 		val = strtol(*gargv, &ep, 0); | ||||
| 		if (*ep != '\0') { | ||||
| 			warnx("%s: illegal number", *gargv, NULL); | ||||
| 			return (1); | ||||
| 		} | ||||
| 		if (errno == ERANGE) | ||||
| 			if (val == LONG_MAX) { | ||||
| 				warnx("%s: %s", *gargv, strerror(ERANGE)); | ||||
| 				return (1); | ||||
| 			} | ||||
| 			if (val == LONG_MIN) { | ||||
| 				warnx("%s: %s", *gargv, strerror(ERANGE)); | ||||
| 				return (1); | ||||
| 			} | ||||
| 			 | ||||
| 		*lp = val; | ||||
| 		++gargv; | ||||
| 		return (0); | ||||
| 	} | ||||
| 	*lp =  (long)asciicode(); | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| static double | ||||
| getdouble() | ||||
| { | ||||
| 	if (!*gargv) | ||||
| 		return ((double)0); | ||||
| 	if (strchr(Number, **gargv)) | ||||
| 		return (atof(*gargv++)); | ||||
| 	return ((double)asciicode()); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| asciicode() | ||||
| { | ||||
| 	register int ch; | ||||
| 
 | ||||
| 	ch = **gargv; | ||||
| 	if (ch == '\'' || ch == '"') | ||||
| 		ch = (*gargv)[1]; | ||||
| 	++gargv; | ||||
| 	return (ch); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| usage() | ||||
| { | ||||
| 	(void)fprintf(stderr, "usage: printf format [arg ...]\n"); | ||||
| } | ||||
							
								
								
									
										601
									
								
								examples/loadables/pushd.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										601
									
								
								examples/loadables/pushd.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,601 @@ | |||
| /* pushd.c, created from pushd.def. */ | ||||
| #include <config.h> | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <sys/param.h> | ||||
| 
 | ||||
| #if defined (HAVE_UNISTD_H) | ||||
| #  include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "bashansi.h" | ||||
| 
 | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include <tilde/tilde.h> | ||||
| 
 | ||||
| #include "shell.h" | ||||
| #include "builtins.h" | ||||
| #include "maxpath.h" | ||||
| #include "common.h" | ||||
| 
 | ||||
| #if !defined (errno) | ||||
| extern int errno; | ||||
| #endif /* !errno */ | ||||
| 
 | ||||
| static char *m_badarg = "%s: bad argument"; | ||||
| 
 | ||||
| /* The list of remembered directories. */ | ||||
| static char **pushd_directory_list = (char **)NULL; | ||||
| 
 | ||||
| /* Number of existing slots in this list. */ | ||||
| static int directory_list_size; | ||||
| 
 | ||||
| /* Offset to the end of the list. */ | ||||
| static int directory_list_offset; | ||||
| 
 | ||||
| static void pushd_error (); | ||||
| static void clear_directory_stack (); | ||||
| static int cd_to_string (); | ||||
| static int change_to_temp (); | ||||
| static int get_dirstack_index (); | ||||
| static void add_dirstack_element (); | ||||
| 
 | ||||
| #define NOCD		0x01 | ||||
| #define ROTATE		0x02 | ||||
| #define LONGFORM	0x04 | ||||
| #define CLEARSTAK	0x08 | ||||
| 
 | ||||
| int | ||||
| pushd_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   char *temp, *current_directory, *top; | ||||
|   int j, flags; | ||||
|   long num; | ||||
|   char direction; | ||||
| 
 | ||||
|   /* If there is no argument list then switch current and
 | ||||
|      top of list. */ | ||||
|   if (list == 0) | ||||
|     { | ||||
|       if (directory_list_offset == 0) | ||||
| 	{ | ||||
| 	  builtin_error ("no other directory"); | ||||
| 	  return (EXECUTION_FAILURE); | ||||
| 	} | ||||
| 
 | ||||
|       current_directory = get_working_directory ("pushd"); | ||||
|       if (current_directory == 0) | ||||
| 	return (EXECUTION_FAILURE); | ||||
| 
 | ||||
|       j = directory_list_offset - 1; | ||||
|       temp = pushd_directory_list[j]; | ||||
|       pushd_directory_list[j] = current_directory; | ||||
|       j = change_to_temp (temp); | ||||
|       free (temp); | ||||
|       return j; | ||||
|     } | ||||
| 
 | ||||
|   for (flags = 0; list; list = list->next) | ||||
|     { | ||||
|       if (ISOPTION (list->word->word, 'n')) | ||||
| 	{ | ||||
| 	  flags |= NOCD; | ||||
| 	} | ||||
|       else if (ISOPTION (list->word->word, '-')) | ||||
|         { | ||||
|           list = list->next; | ||||
|           break; | ||||
|         } | ||||
|       else if (list->word->word[0] == '-' && list->word->word[1] == '\0') | ||||
| 	/* Let `pushd -' work like it used to. */ | ||||
| 	break; | ||||
|       else if (((direction = list->word->word[0]) == '+') || direction == '-') | ||||
| 	{ | ||||
| 	  if (legal_number (list->word->word + 1, &num) == 0) | ||||
| 	    { | ||||
| 	      builtin_error (m_badarg, list->word->word); | ||||
| 	      builtin_usage (); | ||||
| 	      return (EXECUTION_FAILURE); | ||||
| 	    } | ||||
| 
 | ||||
| 	  if (direction == '-') | ||||
| 	    num = directory_list_offset - num; | ||||
| 
 | ||||
| 	  if (num > directory_list_offset || num < 0) | ||||
| 	    { | ||||
| 	      pushd_error (directory_list_offset, list->word->word); | ||||
| 	      return (EXECUTION_FAILURE); | ||||
| 	    } | ||||
| 	  flags |= ROTATE; | ||||
| 	} | ||||
|       else if (*list->word->word == '-') | ||||
| 	{ | ||||
| 	  bad_option (list->word->word); | ||||
| 	  builtin_usage (); | ||||
| 	  return (EXECUTION_FAILURE); | ||||
| 	} | ||||
|       else | ||||
| 	break; | ||||
|     } | ||||
| 
 | ||||
|   if (flags & ROTATE) | ||||
|     { | ||||
|       /* Rotate the stack num times.  Remember, the current
 | ||||
| 	 directory acts like it is part of the stack. */ | ||||
|       temp = get_working_directory ("pushd"); | ||||
| 
 | ||||
|       if (num == 0) | ||||
| 	{ | ||||
| 	  j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS; | ||||
| 	  free (temp); | ||||
| 	  return j; | ||||
| 	} | ||||
| 
 | ||||
|       do | ||||
| 	{ | ||||
| 	  top = pushd_directory_list[directory_list_offset - 1]; | ||||
| 
 | ||||
| 	  for (j = directory_list_offset - 2; j > -1; j--) | ||||
| 	    pushd_directory_list[j + 1] = pushd_directory_list[j]; | ||||
| 
 | ||||
| 	  pushd_directory_list[j + 1] = temp; | ||||
| 
 | ||||
| 	  temp = top; | ||||
| 	  num--; | ||||
| 	} | ||||
|       while (num); | ||||
| 
 | ||||
|       j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS; | ||||
|       free (temp); | ||||
|       return j; | ||||
|     } | ||||
| 
 | ||||
|   if (list == 0) | ||||
|     return (EXECUTION_SUCCESS); | ||||
| 
 | ||||
|   /* Change to the directory in list->word->word.  Save the current
 | ||||
|      directory on the top of the stack. */ | ||||
|   current_directory = get_working_directory ("pushd"); | ||||
|   if (current_directory == 0) | ||||
|     return (EXECUTION_FAILURE); | ||||
| 
 | ||||
|   j = ((flags & NOCD) == 0) ? cd_builtin (list) : EXECUTION_SUCCESS; | ||||
|   if (j == EXECUTION_SUCCESS) | ||||
|     { | ||||
|       add_dirstack_element ((flags & NOCD) ? savestring (list->word->word) : current_directory); | ||||
|       dirs_builtin ((WORD_LIST *)NULL); | ||||
|       return (EXECUTION_SUCCESS); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       free (current_directory); | ||||
|       return (EXECUTION_FAILURE); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Pop the directory stack, and then change to the new top of the stack.
 | ||||
|    If LIST is non-null it should consist of a word +N or -N, which says | ||||
|    what element to delete from the stack.  The default is the top one. */ | ||||
| int | ||||
| popd_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   register int i; | ||||
|   long which; | ||||
|   int flags; | ||||
|   char direction; | ||||
| 
 | ||||
|   for (flags = 0, which = 0L, direction = '+'; list; list = list->next) | ||||
|     { | ||||
|       if (ISOPTION (list->word->word, 'n')) | ||||
|         { | ||||
|           flags |= NOCD; | ||||
|         } | ||||
|       else if (ISOPTION (list->word->word, '-')) | ||||
|         { | ||||
|           list = list->next; | ||||
|           break; | ||||
|         } | ||||
|       else if (((direction = list->word->word[0]) == '+') || direction == '-') | ||||
| 	{ | ||||
| 	  if (legal_number (list->word->word + 1, &which) == 0) | ||||
| 	    { | ||||
| 	      builtin_error (m_badarg, list->word->word); | ||||
| 	      builtin_usage (); | ||||
| 	      return (EXECUTION_FAILURE); | ||||
| 	    } | ||||
| 	} | ||||
|       else if (*list->word->word == '-') | ||||
| 	{ | ||||
| 	  bad_option (list->word->word); | ||||
| 	  builtin_usage (); | ||||
| 	  return (EXECUTION_FAILURE); | ||||
| 	} | ||||
|       else | ||||
| 	break; | ||||
|     } | ||||
| 
 | ||||
|   if (which > directory_list_offset || (directory_list_offset == 0 && which == 0)) | ||||
|     { | ||||
|       pushd_error (directory_list_offset, list ? list->word->word : ""); | ||||
|       return (EXECUTION_FAILURE); | ||||
|     } | ||||
| 
 | ||||
|   /* Handle case of no specification, or top of stack specification. */ | ||||
|   if ((direction == '+' && which == 0) || | ||||
|       (direction == '-' && which == directory_list_offset)) | ||||
|     { | ||||
|       i = ((flags & NOCD) == 0) ? cd_to_string (pushd_directory_list[directory_list_offset - 1]) | ||||
|       			        : EXECUTION_SUCCESS; | ||||
|       if (i != EXECUTION_SUCCESS) | ||||
| 	return (i); | ||||
|       free (pushd_directory_list[--directory_list_offset]); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* Since an offset other than the top directory was specified,
 | ||||
| 	 remove that directory from the list and shift the remainder | ||||
| 	 of the list into place. */ | ||||
|       i = (direction == '+') ? directory_list_offset - which : which; | ||||
|       free (pushd_directory_list[i]); | ||||
|       directory_list_offset--; | ||||
| 
 | ||||
|       /* Shift the remainder of the list into place. */ | ||||
|       for (; i < directory_list_offset; i++) | ||||
| 	pushd_directory_list[i] = pushd_directory_list[i + 1]; | ||||
|     } | ||||
| 
 | ||||
|   dirs_builtin ((WORD_LIST *)NULL); | ||||
|   return (EXECUTION_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| /* Print the current list of directories on the directory stack. */ | ||||
| int | ||||
| dirs_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int flags, desired_index, index_flag, vflag; | ||||
|   long i; | ||||
|   char *temp, *w; | ||||
| 
 | ||||
|   for (flags = vflag = index_flag = 0, desired_index = -1, w = ""; list; list = list->next) | ||||
|     { | ||||
|       if (ISOPTION (list->word->word, 'l')) | ||||
| 	{ | ||||
| 	  flags |= LONGFORM; | ||||
| 	} | ||||
|       else if (ISOPTION (list->word->word, 'c')) | ||||
| 	{ | ||||
| 	  flags |= CLEARSTAK; | ||||
| 	} | ||||
|       else if (ISOPTION (list->word->word, 'v')) | ||||
| 	{ | ||||
| 	  vflag |= 2; | ||||
| 	} | ||||
|       else if (ISOPTION (list->word->word, 'p')) | ||||
| 	{ | ||||
| 	  vflag |= 1; | ||||
| 	} | ||||
|       else if (ISOPTION (list->word->word, '-')) | ||||
|         { | ||||
|           list = list->next; | ||||
|           break; | ||||
|         } | ||||
|       else if (*list->word->word == '+' || *list->word->word == '-') | ||||
|         { | ||||
|           int sign; | ||||
|           if (legal_number (w = list->word->word + 1, &i) == 0) | ||||
| 	    { | ||||
| 	      builtin_error (m_badarg, list->word->word); | ||||
| 	      builtin_usage (); | ||||
| 	      return (EXECUTION_FAILURE); | ||||
| 	    } | ||||
| 	  sign = (*list->word->word == '+') ? 1 : -1; | ||||
| 	  desired_index = get_dirstack_index (i, sign, &index_flag); | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  bad_option (list->word->word); | ||||
| 	  builtin_usage (); | ||||
| 	  return (EXECUTION_FAILURE); | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|   if (flags & CLEARSTAK) | ||||
|     { | ||||
|       clear_directory_stack (); | ||||
|       return (EXECUTION_SUCCESS); | ||||
|     } | ||||
| 
 | ||||
|   if (index_flag && (desired_index < 0 || desired_index > directory_list_offset)) | ||||
|     { | ||||
|       pushd_error (directory_list_offset, w); | ||||
|       return (EXECUTION_FAILURE); | ||||
|     } | ||||
| 
 | ||||
| #define DIRSTACK_FORMAT(temp) \ | ||||
|   (flags & LONGFORM) ? temp : polite_directory_format (temp) | ||||
| 
 | ||||
|   /* The first directory printed is always the current working directory. */ | ||||
|   if (index_flag == 0 || (index_flag == 1 && desired_index == 0)) | ||||
|     { | ||||
|       temp = get_working_directory ("dirs"); | ||||
|       if (temp == 0) | ||||
| 	temp = savestring ("<no current directory>"); | ||||
|       if (vflag & 2) | ||||
| 	printf ("%2d  %s", 0, DIRSTACK_FORMAT (temp)); | ||||
|       else | ||||
| 	printf ("%s", DIRSTACK_FORMAT (temp)); | ||||
|       free (temp); | ||||
|       if (index_flag) | ||||
| 	{ | ||||
| 	  putchar ('\n'); | ||||
| 	  return EXECUTION_SUCCESS; | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
| #define DIRSTACK_ENTRY(i) \ | ||||
|   (flags & LONGFORM) ? pushd_directory_list[i] \ | ||||
| 		     : polite_directory_format (pushd_directory_list[i]) | ||||
| 
 | ||||
|   /* Now print the requested directory stack entries. */ | ||||
|   if (index_flag) | ||||
|     { | ||||
|       if (vflag & 2) | ||||
| 	printf ("%2d  %s", directory_list_offset - desired_index, | ||||
| 			   DIRSTACK_ENTRY (desired_index)); | ||||
|       else | ||||
| 	printf ("%s", DIRSTACK_ENTRY (desired_index)); | ||||
|     } | ||||
|   else | ||||
|     for (i = directory_list_offset - 1; i >= 0; i--) | ||||
|       if (vflag >= 2) | ||||
| 	printf ("\n%2d  %s", directory_list_offset - (int)i, DIRSTACK_ENTRY (i)); | ||||
|       else | ||||
| 	printf ("%s%s", (vflag & 1) ? "\n" : " ", DIRSTACK_ENTRY (i)); | ||||
| 
 | ||||
|   putchar ('\n'); | ||||
|   fflush (stdout); | ||||
|   return (EXECUTION_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| pushd_error (offset, arg) | ||||
|      int offset; | ||||
|      char *arg; | ||||
| { | ||||
|   if (offset == 0) | ||||
|     builtin_error ("directory stack empty"); | ||||
|   else if (arg) | ||||
|     builtin_error ("%s: bad directory stack index", arg); | ||||
|   else | ||||
|     builtin_error ("bad directory stack index"); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| clear_directory_stack () | ||||
| { | ||||
|   register int i; | ||||
| 
 | ||||
|   for (i = 0; i < directory_list_offset; i++) | ||||
|     free (pushd_directory_list[i]); | ||||
|   directory_list_offset = 0; | ||||
| } | ||||
| 
 | ||||
| /* Switch to the directory in NAME.  This uses the cd_builtin to do the work,
 | ||||
|    so if the result is EXECUTION_FAILURE then an error message has already | ||||
|    been printed. */ | ||||
| static int | ||||
| cd_to_string (name) | ||||
|      char *name; | ||||
| { | ||||
|   WORD_LIST *tlist; | ||||
|   int result; | ||||
| 
 | ||||
|   tlist = make_word_list (make_word (name), NULL); | ||||
|   result = cd_builtin (tlist); | ||||
|   dispose_words (tlist); | ||||
|   return (result); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| change_to_temp (temp) | ||||
|      char *temp; | ||||
| { | ||||
|   int tt; | ||||
| 
 | ||||
|   tt = temp ? cd_to_string (temp) : EXECUTION_FAILURE; | ||||
| 
 | ||||
|   if (tt == EXECUTION_SUCCESS) | ||||
|     dirs_builtin ((WORD_LIST *)NULL); | ||||
| 
 | ||||
|   return (tt); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| add_dirstack_element (dir) | ||||
|      char *dir; | ||||
| { | ||||
|   int j; | ||||
| 
 | ||||
|   if (directory_list_offset == directory_list_size) | ||||
|     { | ||||
|       j = (directory_list_size += 10) * sizeof (char *); | ||||
|       pushd_directory_list = (char **)xrealloc (pushd_directory_list, j); | ||||
|     } | ||||
|   pushd_directory_list[directory_list_offset++] = dir; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| get_dirstack_index (ind, sign, indexp) | ||||
|      int ind, sign, *indexp; | ||||
| { | ||||
|   if (indexp) | ||||
|     *indexp = sign > 0 ? 1 : 2; | ||||
| 
 | ||||
|   /* dirs +0 prints the current working directory. */ | ||||
|   /* dirs -0 prints last element in directory stack */ | ||||
|   if (ind == 0 && sign > 0) | ||||
|     return 0; | ||||
|   else if (ind == directory_list_offset) | ||||
|     { | ||||
|       if (indexp) | ||||
| 	*indexp = sign > 0 ? 2 : 1; | ||||
|       return 0; | ||||
|     } | ||||
|   else | ||||
|     return (sign > 0 ? directory_list_offset - ind : ind); | ||||
| } | ||||
| 
 | ||||
| char * | ||||
| get_dirstack_element (ind, sign) | ||||
|      int ind, sign; | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   i = get_dirstack_index (ind, sign, (int *)NULL); | ||||
|   return (i < 0 || i > directory_list_offset) ? (char *)NULL | ||||
| 					      : pushd_directory_list[i]; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| set_dirstack_element (ind, sign, value) | ||||
|      int ind, sign; | ||||
|      char *value; | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   i = get_dirstack_index (ind, sign, (int *)NULL); | ||||
|   if (ind == 0 || i < 0 || i > directory_list_offset) | ||||
|     return; | ||||
|   free (pushd_directory_list[i]); | ||||
|   pushd_directory_list[i] = savestring (value); | ||||
| } | ||||
| 
 | ||||
| WORD_LIST * | ||||
| get_directory_stack () | ||||
| { | ||||
|   register int i; | ||||
|   WORD_LIST *ret; | ||||
|   char *d, *t; | ||||
| 
 | ||||
|   for (ret = (WORD_LIST *)NULL, i = 0; i < directory_list_offset; i++) | ||||
|     { | ||||
|       d = polite_directory_format (pushd_directory_list[i]); | ||||
|       ret = make_word_list (make_word (d), ret); | ||||
|     } | ||||
|   /* Now the current directory. */ | ||||
|   d = get_working_directory ("dirstack"); | ||||
|   i = 0;	/* sentinel to decide whether or not to free d */ | ||||
|   if (d == 0) | ||||
|     d = "."; | ||||
|   else | ||||
|     { | ||||
|       t = polite_directory_format (d); | ||||
|       /* polite_directory_format sometimes returns its argument unchanged.
 | ||||
| 	 If it does not, we can free d right away.  If it does, we need to | ||||
| 	 mark d to be deleted later. */ | ||||
|       if (t != d) | ||||
| 	{ | ||||
| 	  free (d); | ||||
| 	  d = t; | ||||
| 	} | ||||
|       else /* t == d, so d is what we want */ | ||||
| 	i = 1; | ||||
|     } | ||||
|   ret = make_word_list (make_word (d), ret); | ||||
|   if (i) | ||||
|     free (d); | ||||
|   return ret;	/* was (REVERSE_LIST (ret, (WORD_LIST *)); */ | ||||
| } | ||||
| 
 | ||||
| static char *dirs_doc[] = { | ||||
|   "Display the list of currently remembered directories.  Directories", | ||||
|   "find their way onto the list with the `pushd' command; you can get", | ||||
|   "back up through the list with the `popd' command.", | ||||
|   "", | ||||
|   "The -l flag specifies that `dirs' should not print shorthand versions", | ||||
|   "of directories which are relative to your home directory.  This means", | ||||
|   "that `~/bin' might be displayed as `/homes/bfox/bin'.  The -v flag", | ||||
|   "causes `dirs' to print the directory stack with one entry per line,", | ||||
|   "prepending the directory name with its position in the stack.  The -p", | ||||
|   "flag does the same thing, but the stack position is not prepended.", | ||||
|   "The -c flag clears the directory stack by deleting all of the elements.", | ||||
|   "", | ||||
|   "+N   displays the Nth entry counting from the left of the list shown by", | ||||
|   "     dirs when invoked without options, starting with zero.", | ||||
|   "", | ||||
|   "-N   displays the Nth entry counting from the right of the list shown by", | ||||
|   "     dirs when invoked without options, starting with zero.", | ||||
|   (char *)NULL | ||||
| }; | ||||
| 
 | ||||
| static char *pushd_doc[] = { | ||||
|   "Adds a directory to the top of the directory stack, or rotates", | ||||
|   "the stack, making the new top of the stack the current working", | ||||
|   "directory.  With no arguments, exchanges the top two directories.", | ||||
|   "", | ||||
|   "+N   Rotates the stack so that the Nth directory (counting", | ||||
|   "     from the left of the list shown by `dirs') is at the top.", | ||||
|   "", | ||||
|   "-N   Rotates the stack so that the Nth directory (counting", | ||||
|   "     from the right) is at the top.", | ||||
|   "", | ||||
|   "-n   suppress the normal change of directory when adding directories", | ||||
|   "     to the stack, so only the stack is manipulated.", | ||||
|   "", | ||||
|   "dir  adds DIR to the directory stack at the top, making it the", | ||||
|   "     new current working directory.", | ||||
|   "", | ||||
|   "You can see the directory stack with the `dirs' command.", | ||||
|   (char *)NULL | ||||
| }; | ||||
| 
 | ||||
| static char *popd_doc[] = { | ||||
|   "Removes entries from the directory stack.  With no arguments,", | ||||
|   "removes the top directory from the stack, and cd's to the new", | ||||
|   "top directory.", | ||||
|   "", | ||||
|   "+N   removes the Nth entry counting from the left of the list", | ||||
|   "     shown by `dirs', starting with zero.  For example: `popd +0'", | ||||
|   "     removes the first directory, `popd +1' the second.",    | ||||
|   "", | ||||
|   "-N   removes the Nth entry counting from the right of the list", | ||||
|   "     shown by `dirs', starting with zero.  For example: `popd -0'", | ||||
|   "     removes the last directory, `popd -1' the next to last.", | ||||
|   "", | ||||
|   "-n   suppress the normal change of directory when removing directories", | ||||
|   "     from the stack, so only the stack is manipulated.", | ||||
|   "", | ||||
|   "You can see the directory stack with the `dirs' command.", | ||||
|   (char *)NULL | ||||
| }; | ||||
| 
 | ||||
| struct builtin pushd_struct = { | ||||
| 	"pushd", | ||||
| 	pushd_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	pushd_doc, | ||||
| 	"pushd [+N | -N] [-n] [dir]", | ||||
| 	0 | ||||
| }; | ||||
| 
 | ||||
| struct builtin popd_struct = { | ||||
| 	"popd", | ||||
| 	popd_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	popd_doc, | ||||
| 	"popd [+N | -N] [-n]", | ||||
| 	0 | ||||
| }; | ||||
| 
 | ||||
| struct builtin dirs_struct = { | ||||
| 	"dirs", | ||||
| 	dirs_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	dirs_doc, | ||||
| 	"dirs [-clpv] [+N] [-N]", | ||||
| 	0 | ||||
| }; | ||||
							
								
								
									
										50
									
								
								examples/loadables/rmdir.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								examples/loadables/rmdir.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| /* rmdir - remove directory */ | ||||
| 
 | ||||
| /* See Makefile for compilation details. */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| 
 | ||||
| #if !defined (errno) | ||||
| extern int errno; | ||||
| #endif | ||||
| 
 | ||||
| rmdir_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int rval; | ||||
|   WORD_LIST *l; | ||||
| 
 | ||||
|   if (no_options (list)) | ||||
|     return (EX_USAGE); | ||||
| 
 | ||||
|   for (rval = EXECUTION_SUCCESS, l = list; l; l = l->next) | ||||
|     if (rmdir (l->word->word) < 0) | ||||
|       { | ||||
| 	builtin_error ("%s: %s", l->word->word, strerror (errno)); | ||||
| 	rval = EXECUTION_FAILURE; | ||||
|       } | ||||
| 
 | ||||
|   return rval; | ||||
| } | ||||
| 
 | ||||
| char *rmdir_doc[] = { | ||||
| 	"rmdir removes the directory entry specified by each argument,", | ||||
| 	"provided the directory is empty.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| /* The standard structure describing a builtin command.  bash keeps an array
 | ||||
|    of these structures. */ | ||||
| struct builtin rmdir_struct = { | ||||
| 	"rmdir",		/* builtin name */ | ||||
| 	rmdir_builtin,		/* function implementing the builtin */ | ||||
| 	BUILTIN_ENABLED,	/* initial flags for builtin */ | ||||
| 	rmdir_doc,		/* array of long documentation strings. */ | ||||
| 	"rmdir directory ...",	/* usage synopsis; becomes short_doc */ | ||||
| 	0			/* reserved for internal use */ | ||||
| }; | ||||
							
								
								
									
										150
									
								
								examples/loadables/sleep.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								examples/loadables/sleep.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,150 @@ | |||
| /*
 | ||||
|  * sleep -- sleep for fractions of a second | ||||
|  * | ||||
|  * usage: sleep seconds[.fraction] | ||||
|  */ | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include "bashtypes.h" | ||||
| 
 | ||||
| #if defined (TIME_WITH_SYS_TIME) | ||||
| #  include <sys/time.h> | ||||
| #  include <time.h> | ||||
| #else | ||||
| #  if defined (HAVE_SYS_TIME_H) | ||||
| #    include <sys/time.h> | ||||
| #  else | ||||
| #    include <time.h> | ||||
| #  endif | ||||
| #endif | ||||
| 
 | ||||
| #if defined (HAVE_UNISTD_H) | ||||
| #include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #include "shell.h" | ||||
| #include "builtins.h" | ||||
| 
 | ||||
| #define RETURN(x) \ | ||||
| 	do { \ | ||||
| 		if (sp) *sp = sec; \ | ||||
| 		if (usp) *usp = usec; \ | ||||
| 		return (x); \ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) | ||||
| static int | ||||
| fsleep(sec, usec) | ||||
| long	sec, usec; | ||||
| { | ||||
| 	struct timeval tv; | ||||
| 
 | ||||
| 	tv.tv_sec = sec; | ||||
| 	tv.tv_usec = usec; | ||||
| 
 | ||||
| 	return select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv); | ||||
| } | ||||
| #else /* !HAVE_TIMEVAL || !HAVE_SELECT */ | ||||
| static int | ||||
| fsleep(sec, usec) | ||||
| long	sec, usec; | ||||
| { | ||||
| 	if (usec >= 500000)	/* round */ | ||||
| 		sec++; | ||||
| 	return (sleep(sec)); | ||||
| } | ||||
| #endif /* !HAVE_TIMEVAL || !HAVE_SELECT */ | ||||
| 
 | ||||
| /*
 | ||||
|  * An incredibly simplistic floating point converter. | ||||
|  */ | ||||
| static int | ||||
| convert(s, sp, usp) | ||||
| char	*s; | ||||
| long	*sp, *usp; | ||||
| { | ||||
| 	int n; | ||||
| 	long sec, usec; | ||||
| 	char	*p; | ||||
| 
 | ||||
| 	sec = usec = 0; | ||||
| 
 | ||||
| #define DECIMAL	'.' | ||||
| 
 | ||||
| 	for (p = s; p && *p; p++) { | ||||
| 		if (*p == DECIMAL)		/* decimal point */ | ||||
| 			break; | ||||
| 		if (isdigit(*p) == 0) | ||||
| 			RETURN(0); | ||||
| 		sec = (sec * 10) + (*p - '0'); | ||||
| 	} | ||||
| 
 | ||||
| 	if (*p == 0) | ||||
| 		RETURN(1); | ||||
| 
 | ||||
| 	if (*p == DECIMAL) | ||||
| 		p++; | ||||
| 
 | ||||
| 	/* Look for up to six digits past a decimal point. */ | ||||
| 	for (n = 0; n < 6 && p[n]; n++) { | ||||
| 		if (isdigit(p[n]) == 0) | ||||
| 			RETURN(0); | ||||
| 		usec = (usec * 10) + (p[n] - '0'); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Now convert to millionths */ | ||||
| 	if (n == 1) | ||||
| 		usec *= 100000; | ||||
| 	else if (n == 2) | ||||
| 		usec *= 10000; | ||||
| 	else if (n == 3) | ||||
| 		usec *= 1000; | ||||
| 	else if (n == 4) | ||||
| 		usec *= 100; | ||||
| 	else if (n == 5) | ||||
| 		usec *= 10; | ||||
| 	else if (n == 6 && p[6] && isdigit(p[6]) && p[6] >= '5')	 | ||||
| 		usec++;			/* round up 1 */ | ||||
| 	RETURN(1); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| sleep_builtin (list) | ||||
| WORD_LIST	*list; | ||||
| { | ||||
| 	long	sec, usec; | ||||
| 
 | ||||
| 	if (list == 0) { | ||||
| 		builtin_usage(); | ||||
| 		return(EX_USAGE); | ||||
| 	} | ||||
| 
 | ||||
| 	if (*list->word->word == '-' || list->next) { | ||||
| 		builtin_usage (); | ||||
| 		return (EX_USAGE); | ||||
| 	} | ||||
| 
 | ||||
|     	if (convert(list->word->word, &sec, &usec)) { | ||||
| 		fsleep(sec, usec); | ||||
| 		return(EXECUTION_SUCCESS); | ||||
|     	} | ||||
| 
 | ||||
| 	builtin_error("%s: bad sleep interval", list->word->word); | ||||
| 	return (EXECUTION_FAILURE); | ||||
| } | ||||
| 
 | ||||
| static char *sleep_doc[] = { | ||||
| 	"sleep suspends execution for a minimum of SECONDS[.FRACTION] seconds.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| struct builtin sleep_struct = { | ||||
| 	"sleep", | ||||
| 	sleep_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	sleep_doc, | ||||
| 	"sleep seconds[.fraction]", | ||||
| 	0 | ||||
| }; | ||||
							
								
								
									
										514
									
								
								examples/loadables/sprintf.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										514
									
								
								examples/loadables/sprintf.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,514 @@ | |||
| /*
 | ||||
|  * Copyright (c) 1989, 1993 | ||||
|  *	The Regents of the University of California.  All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer. | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer in the | ||||
|  *    documentation and/or other materials provided with the distribution. | ||||
|  * 3. All advertising materials mentioning features or use of this software | ||||
|  *    must display the following acknowledgement: | ||||
|  *	This product includes software developed by the University of | ||||
|  *	California, Berkeley and its contributors. | ||||
|  * 4. Neither the name of the University nor the names of its contributors | ||||
|  *    may be used to endorse or promote products derived from this software | ||||
|  *    without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||||
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
|  * SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #if !defined(BUILTIN) && !defined(SHELL) | ||||
| #ifndef lint | ||||
| static char copyright[] = | ||||
| "@(#) Copyright (c) 1989, 1993\n\
 | ||||
| 	The Regents of the University of California.  All rights reserved.\n"; | ||||
| #endif /* not lint */ | ||||
| #endif | ||||
| 
 | ||||
| #ifndef lint | ||||
| static char sccsid[] = "@(#)printf.c	8.1 (Berkeley) 7/20/93"; | ||||
| #endif /* not lint */ | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #include "bashansi.h" | ||||
| #include "shell.h" | ||||
| #include "builtins.h" | ||||
| #include "stdc.h" | ||||
| 
 | ||||
| #if !defined (errno) | ||||
| extern int errno; | ||||
| #endif | ||||
| 
 | ||||
| static char	sbuf[1024]; | ||||
| static int	sblen; | ||||
| 
 | ||||
| /* Gee, I wish sprintf could be reliably counted upon to return the
 | ||||
|    number of characters written :-( */ | ||||
| #define PF(f, func) \ | ||||
| do { \ | ||||
| 	if (fieldwidth) \ | ||||
| 		if (precision) \ | ||||
| 			sprintf(sbuf, f, fieldwidth, precision, func); \ | ||||
| 		else \ | ||||
| 			sprintf(sbuf, f, fieldwidth, func); \ | ||||
| 	else if (precision) \ | ||||
| 		sprintf(sbuf, f, precision, func); \ | ||||
| 	else \ | ||||
| 		sprintf(sbuf, f, func); \ | ||||
| 	spaddstr (sbuf, strlen (sbuf)); \ | ||||
| } while (0) | ||||
| 
 | ||||
| static int	 asciicode __P((void)); | ||||
| static void	 escape __P((char *)); | ||||
| static int	 getchr __P((void)); | ||||
| static double	 getdouble __P((void)); | ||||
| static int	 getint __P((int *)); | ||||
| static int	 getlong __P((long *)); | ||||
| static char	*getstr __P((void)); | ||||
| static char	*mklong __P((char *, int)); | ||||
| static void	 usage __P((void)); | ||||
| 
 | ||||
| static char **gargv; | ||||
| 
 | ||||
| static char *outstr; | ||||
| static int outsize; | ||||
| static int outind; | ||||
| 
 | ||||
| int sprintf_builtin (); | ||||
| static int sprintf_main (); | ||||
| static void spaddstr (); | ||||
| 
 | ||||
| extern char *this_command_name; | ||||
| extern char *single_quote (); | ||||
| extern char **make_builtin_argv (); | ||||
| 
 | ||||
| static char *sprintf_doc[] = { | ||||
|   "sprintf formats and outputs its arguments, after the second, under control", | ||||
|   "of the format and assigns the result to the variable named by its first", | ||||
|   "argument. The format is a character string which contains three types", | ||||
|   "of objects: plain characters, which are simply copied to the output string,", | ||||
|   "character escape sequences which are converted and copied to the output", | ||||
|   "string, and format specifications, each of which causes printing of the", | ||||
|   "next successive argument.  In addition to the standard sprintf(3) formats,", | ||||
|   "%b means to expand escapes in the corresponding argument, and %q means", | ||||
|   "to quote the argument in a way that can be reused as shell input.  Each", | ||||
|   "one of the format specifications must not expand to more than 1024", | ||||
|   "characters, though there is no limit on the total size of the output", | ||||
|   "string.", | ||||
|   (char *)NULL | ||||
| }; | ||||
| 
 | ||||
| struct builtin sprintf_struct = { | ||||
| 	"sprintf", | ||||
| 	sprintf_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	sprintf_doc, | ||||
| 	"sprintf var format [arguments]", | ||||
| 	(char *)0 | ||||
| }; | ||||
| 
 | ||||
| int | ||||
| sprintf_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int c, r; | ||||
|   char **v, *varname; | ||||
|   WORD_LIST *l; | ||||
|   SHELL_VAR *var; | ||||
| 
 | ||||
|   if (list == 0) | ||||
|     { | ||||
|       builtin_usage (); | ||||
|       return (EXECUTION_FAILURE); | ||||
|     } | ||||
| 
 | ||||
|   varname = list->word->word; | ||||
|   list = list->next; | ||||
| 
 | ||||
|   if (legal_identifier (varname) == 0) | ||||
|     { | ||||
|       builtin_error ("%s: not a legal variable name", varname); | ||||
|       return (EXECUTION_FAILURE); | ||||
|     } | ||||
| 
 | ||||
|   outind = 0; | ||||
|   if (outstr == 0) | ||||
|     outstr = xmalloc (outsize = 64); | ||||
|   outstr[0] = '\0'; | ||||
| 
 | ||||
|   v = make_builtin_argv (list, &c); | ||||
|   r = sprintf_main (c, v); | ||||
|   free (v); | ||||
| 
 | ||||
|   var = bind_variable (varname, outstr); | ||||
|   if (readonly_p (var)) | ||||
|     { | ||||
|       builtin_error ("%s: readonly variable", varname); | ||||
|       return (EXECUTION_FAILURE); | ||||
|     } | ||||
| 
 | ||||
|   return r; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| spaddstr(str, len) | ||||
|      char *str; | ||||
|      int len; | ||||
| { | ||||
|   RESIZE_MALLOCED_BUFFER (outstr, outind, len, outsize, 64); | ||||
|   strcpy (outstr + outind, str); | ||||
|   outind += len; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| sprintf_main(argc, argv) | ||||
| 	int argc; | ||||
| 	char *argv[]; | ||||
| { | ||||
| 	extern int optind; | ||||
| 	static char *skip1, *skip2; | ||||
| 	int ch, end, fieldwidth, precision; | ||||
| 	char convch, nextch, *format, *fmt, *start; | ||||
| 
 | ||||
| 	while ((ch = getopt(argc, argv, "")) != EOF) | ||||
| 		switch (ch) { | ||||
| 		case '?': | ||||
| 		default: | ||||
| 			usage(); | ||||
| 			return (1); | ||||
| 		} | ||||
| 	argc -= optind; | ||||
| 	argv += optind; | ||||
| 
 | ||||
| 	if (argc < 1) { | ||||
| 		usage(); | ||||
| 		return (1); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Basic algorithm is to scan the format string for conversion | ||||
| 	 * specifications -- once one is found, find out if the field | ||||
| 	 * width or precision is a '*'; if it is, gather up value.  Note, | ||||
| 	 * format strings are reused as necessary to use up the provided | ||||
| 	 * arguments, arguments of zero/null string are provided to use | ||||
| 	 * up the format string. | ||||
| 	 */ | ||||
| 	skip1 = "#-+ 0"; | ||||
| 	skip2 = "*0123456789"; | ||||
| 
 | ||||
| 	escape(fmt = format = *argv);		/* backslash interpretation */ | ||||
| 	gargv = ++argv; | ||||
| 	for (;;) { | ||||
| 		end = 0; | ||||
| 		/* find next format specification */ | ||||
| next:		for (start = fmt;; ++fmt) { | ||||
| 			if (!*fmt) { | ||||
| 				/* avoid infinite loop */ | ||||
| 				if (end == 1) { | ||||
| 					warnx("missing format character", | ||||
| 					    NULL, NULL); | ||||
| 					return (1); | ||||
| 				} | ||||
| 				end = 1; | ||||
| 				if (fmt > start) | ||||
| 					(void)printf("%s", start); | ||||
| 				if (!*gargv) | ||||
| 					return (0); | ||||
| 				fmt = format; | ||||
| 				goto next; | ||||
| 			} | ||||
| 			/* %% prints a % */ | ||||
| 			if (*fmt == '%') { | ||||
| 				if (*++fmt != '%') | ||||
| 					break; | ||||
| 				*fmt++ = '\0'; | ||||
| 				(void)printf("%s", start); | ||||
| 				goto next; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		/* skip to field width */ | ||||
| 		for (; strchr(skip1, *fmt); ++fmt); | ||||
| 		if (*fmt == '*') { | ||||
| 			if (getint(&fieldwidth)) | ||||
| 				return (1); | ||||
| 		} else | ||||
| 			fieldwidth = 0; | ||||
| 
 | ||||
| 		/* skip to possible '.', get following precision */ | ||||
| 		for (; strchr(skip2, *fmt); ++fmt); | ||||
| 		if (*fmt == '.') | ||||
| 			++fmt; | ||||
| 		if (*fmt == '*') { | ||||
| 			if (getint(&precision)) | ||||
| 				return (1); | ||||
| 		} else | ||||
| 			precision = 0; | ||||
| 
 | ||||
| 		/* skip to conversion char */ | ||||
| 		for (; strchr(skip2, *fmt); ++fmt); | ||||
| 		if (!*fmt) { | ||||
| 			warnx("missing format character", NULL, NULL); | ||||
| 			return (1); | ||||
| 		} | ||||
| 
 | ||||
| 		convch = *fmt; | ||||
| 		nextch = *++fmt; | ||||
| 		*fmt = '\0'; | ||||
| 		switch(convch) { | ||||
| 		case 'c': { | ||||
| 			char p; | ||||
| 
 | ||||
| 			p = getchr(); | ||||
| 			PF(start, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 's': { | ||||
| 			char *p; | ||||
| 
 | ||||
| 			p = getstr(); | ||||
| 			PF(start, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'b': {		/* expand escapes in argument */ | ||||
| 			char *p; | ||||
| 
 | ||||
| 			p = getstr(); | ||||
| 			escape(p); | ||||
| 			PF("%s", p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'q': {		/* print with shell single quoting */ | ||||
| 			char *p, *p2; | ||||
| 
 | ||||
| 			p = getstr(); | ||||
| 			p2 = single_quote(p); | ||||
| 			PF("%s", p2); | ||||
| 			free(p2); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { | ||||
| 			long p; | ||||
| 			char *f; | ||||
| 			 | ||||
| 			if ((f = mklong(start, convch)) == NULL) | ||||
| 				return (1); | ||||
| 			if (getlong(&p)) | ||||
| 				return (1); | ||||
| 			PF(f, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		case 'e': case 'E': case 'f': case 'g': case 'G': { | ||||
| 			double p; | ||||
| 
 | ||||
| 			p = getdouble(); | ||||
| 			PF(start, p); | ||||
| 			break; | ||||
| 		} | ||||
| 		default: | ||||
| 			warnx("illegal format character", NULL, NULL); | ||||
| 			return (1); | ||||
| 		} | ||||
| 		*fmt = nextch; | ||||
| 	} | ||||
| 	/* NOTREACHED */ | ||||
| } | ||||
| 
 | ||||
| static char * | ||||
| mklong(str, ch) | ||||
| 	char *str; | ||||
| 	int ch; | ||||
| { | ||||
| 	static char copy[64]; | ||||
| 	int len; | ||||
| 
 | ||||
| 	len = strlen(str) + 2; | ||||
| 	memmove(copy, str, len - 3); | ||||
| 	copy[len - 3] = 'l'; | ||||
| 	copy[len - 2] = ch; | ||||
| 	copy[len - 1] = '\0'; | ||||
| 	return (copy); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| escape(fmt) | ||||
| 	register char *fmt; | ||||
| { | ||||
| 	register char *store; | ||||
| 	register int value, c; | ||||
| 
 | ||||
| 	for (store = fmt; c = *fmt; ++fmt, ++store) { | ||||
| 		if (c != '\\') { | ||||
| 			*store = c; | ||||
| 			continue; | ||||
| 		} | ||||
| 		switch (*++fmt) { | ||||
| 		case '\0':		/* EOS, user error */ | ||||
| 			*store = '\\'; | ||||
| 			*++store = '\0'; | ||||
| 			return; | ||||
| 		case '\\':		/* backslash */ | ||||
| 		case '\'':		/* single quote */ | ||||
| 			*store = *fmt; | ||||
| 			break; | ||||
| 		case 'a':		/* bell/alert */ | ||||
| 			*store = '\7'; | ||||
| 			break; | ||||
| 		case 'b':		/* backspace */ | ||||
| 			*store = '\b'; | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 			return; | ||||
| 		case 'e': | ||||
| 		case 'E': | ||||
| 			*store = '\033'; | ||||
| 			break; | ||||
| 		case 'f':		/* form-feed */ | ||||
| 			*store = '\f'; | ||||
| 			break; | ||||
| 		case 'n':		/* newline */ | ||||
| 			*store = '\n'; | ||||
| 			break; | ||||
| 		case 'r':		/* carriage-return */ | ||||
| 			*store = '\r'; | ||||
| 			break; | ||||
| 		case 't':		/* horizontal tab */ | ||||
| 			*store = '\t'; | ||||
| 			break; | ||||
| 		case 'v':		/* vertical tab */ | ||||
| 			*store = '\13'; | ||||
| 			break; | ||||
| 					/* octal constant */ | ||||
| 		case '0': case '1': case '2': case '3': | ||||
| 		case '4': case '5': case '6': case '7': | ||||
| 			for (c = 3, value = 0; | ||||
| 			    c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) { | ||||
| 				value <<= 3; | ||||
| 				value += *fmt - '0'; | ||||
| 			} | ||||
| 			--fmt; | ||||
| 			*store = value; | ||||
| 			break; | ||||
| 		default: | ||||
| 			*store = *fmt; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	*store = '\0'; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| getchr() | ||||
| { | ||||
| 	if (!*gargv) | ||||
| 		return ('\0'); | ||||
| 	return ((int)**gargv++); | ||||
| } | ||||
| 
 | ||||
| static char * | ||||
| getstr() | ||||
| { | ||||
| 	if (!*gargv) | ||||
| 		return (""); | ||||
| 	return (*gargv++); | ||||
| } | ||||
| 
 | ||||
| static char *Number = "+-.0123456789"; | ||||
| static int | ||||
| getint(ip) | ||||
| 	int *ip; | ||||
| { | ||||
| 	long val; | ||||
| 
 | ||||
| 	if (getlong(&val)) | ||||
| 		return (1); | ||||
| 	if (val > INT_MAX) { | ||||
| 		warnx("%s: %s", *gargv, strerror(ERANGE)); | ||||
| 		return (1); | ||||
| 	} | ||||
| 	*ip = val; | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| getlong(lp) | ||||
| 	long *lp; | ||||
| { | ||||
| 	long val; | ||||
| 	char *ep; | ||||
| 
 | ||||
| 	if (!*gargv) { | ||||
| 		*lp = 0; | ||||
| 		return (0); | ||||
| 	} | ||||
| 	if (strchr(Number, **gargv)) { | ||||
| 		errno = 0; | ||||
| 		val = strtol(*gargv, &ep, 0); | ||||
| 		if (*ep != '\0') { | ||||
| 			warnx("%s: illegal number", *gargv, NULL); | ||||
| 			return (1); | ||||
| 		} | ||||
| 		if (errno == ERANGE) | ||||
| 			if (val == LONG_MAX) { | ||||
| 				warnx("%s: %s", *gargv, strerror(ERANGE)); | ||||
| 				return (1); | ||||
| 			} | ||||
| 			if (val == LONG_MIN) { | ||||
| 				warnx("%s: %s", *gargv, strerror(ERANGE)); | ||||
| 				return (1); | ||||
| 			} | ||||
| 			 | ||||
| 		*lp = val; | ||||
| 		++gargv; | ||||
| 		return (0); | ||||
| 	} | ||||
| 	*lp =  (long)asciicode(); | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| static double | ||||
| getdouble() | ||||
| { | ||||
| 	if (!*gargv) | ||||
| 		return ((double)0); | ||||
| 	if (strchr(Number, **gargv)) | ||||
| 		return (atof(*gargv++)); | ||||
| 	return ((double)asciicode()); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| asciicode() | ||||
| { | ||||
| 	register int ch; | ||||
| 
 | ||||
| 	ch = **gargv; | ||||
| 	if (ch == '\'' || ch == '"') | ||||
| 		ch = (*gargv)[1]; | ||||
| 	++gargv; | ||||
| 	return (ch); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| usage() | ||||
| { | ||||
| 	(void)fprintf(stderr, "usage: printf format [arg ...]\n"); | ||||
| } | ||||
							
								
								
									
										157
									
								
								examples/loadables/tee.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								examples/loadables/tee.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,157 @@ | |||
| /* tee - duplicate standard input */ | ||||
| 
 | ||||
| /* See Makefile for compilation details. */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include "bashtypes.h" | ||||
| #include "posixstat.h" | ||||
| #include "filecntl.h" | ||||
| 
 | ||||
| #include <signal.h> | ||||
| 
 | ||||
| #if defined (HAVE_UNISTD_H) | ||||
| #  include <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "bashansi.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| #include "bashgetopt.h" | ||||
| 
 | ||||
| #if !defined (errno) | ||||
| extern int errno; | ||||
| #endif | ||||
| 
 | ||||
| typedef struct flist { | ||||
|   struct flist *next; | ||||
|   int fd; | ||||
|   char *fname; | ||||
| } FLIST; | ||||
| 
 | ||||
| static FLIST *tee_flist; | ||||
| 
 | ||||
| #define TEE_BUFSIZE	8192 | ||||
| 
 | ||||
| extern int interrupt_immediately; | ||||
| 
 | ||||
| extern char *strerror (); | ||||
| 
 | ||||
| tee_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int opt, append, nointr, rval, fd, fflags; | ||||
|   int n, nr, nw; | ||||
|   FLIST *fl; | ||||
|   char *buf, *bp; | ||||
| 
 | ||||
|   char *t; | ||||
| 
 | ||||
|   reset_internal_getopt (); | ||||
|   append = nointr = 0; | ||||
|   tee_flist = (FLIST *)NULL; | ||||
|   while ((opt = internal_getopt (list, "ai")) != -1) | ||||
|     { | ||||
|       switch (opt) | ||||
| 	{ | ||||
| 	case 'a': | ||||
| 	  append = 1; | ||||
| 	  break; | ||||
| 	case 'i': | ||||
| 	  nointr = 1; | ||||
| 	  break; | ||||
| 	default: | ||||
| 	  builtin_usage (); | ||||
| 	  return (EX_USAGE); | ||||
| 	} | ||||
|     } | ||||
|   list = loptend; | ||||
| 
 | ||||
|   if (nointr == 0) | ||||
|     interrupt_immediately++; | ||||
| 
 | ||||
|   buf = xmalloc (TEE_BUFSIZE); | ||||
| 
 | ||||
|   /* Initialize output file list. */ | ||||
|   fl = tee_flist = (FLIST *)xmalloc (sizeof(FLIST)); | ||||
|   tee_flist->fd = 1; | ||||
|   tee_flist->fname = "stdout"; | ||||
|   tee_flist->next = (FLIST *)NULL; | ||||
| 
 | ||||
|   /* Add file arguments to list of output files. */ | ||||
|   fflags = append ? O_WRONLY|O_CREAT|O_APPEND : O_WRONLY|O_CREAT|O_TRUNC; | ||||
|   for (rval = EXECUTION_SUCCESS; list; list = list->next) | ||||
|     { | ||||
|       fd = open (list->word->word, fflags, 0666); | ||||
|       if (fd < 0) | ||||
|         { | ||||
|           builtin_error ("%s: cannot open: %s", list->word->word, strerror (errno)); | ||||
|           rval = EXECUTION_FAILURE; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           fl->next = (FLIST *)xmalloc (sizeof(FLIST)); | ||||
|           fl->next->fd = fd; | ||||
|           fl->next->fname = list->word->word; | ||||
|           fl = fl->next; | ||||
|           fl->next = (FLIST *)NULL; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|   while ((nr = read(0, buf, TEE_BUFSIZE)) > 0) | ||||
|     for (fl = tee_flist; fl; fl = fl->next) | ||||
|       { | ||||
| 	n = nr; | ||||
| 	bp = buf; | ||||
| 	do | ||||
| 	  { | ||||
| 	    if ((nw = write (fl->fd, bp, n)) == -1) | ||||
| 	      { | ||||
| 		builtin_error ("%s: write error: %s", fl->fname, strerror (errno)); | ||||
| 		rval = EXECUTION_FAILURE; | ||||
| 		break; | ||||
| 	      } | ||||
|             bp += nw; | ||||
| 	  } | ||||
| 	while (n -= nw); | ||||
|       } | ||||
|   if (nr < 0) | ||||
|     builtin_error ("read error: %s", strerror (errno)); | ||||
| 
 | ||||
|   /* Deallocate resources -- this is a builtin command. */ | ||||
|   tee_flist = tee_flist->next;		/* skip bogus close of stdout */ | ||||
|   while (tee_flist) | ||||
|     { | ||||
|       fl = tee_flist; | ||||
|       if (close (fl->fd) < 0) | ||||
| 	{ | ||||
| 	  builtin_error ("%s: close_error: %s", fl->fname, strerror (errno)); | ||||
| 	  rval = EXECUTION_FAILURE; | ||||
| 	} | ||||
|       tee_flist = tee_flist->next; | ||||
|       free (fl); | ||||
|     } | ||||
|    | ||||
|   return (rval); | ||||
| } | ||||
| 
 | ||||
| char *tee_doc[] = { | ||||
| 	"Copy standard input to standard output, making a copy in each", | ||||
| 	"filename argument.  If the `-a' option is gived, the specified", | ||||
| 	"files are appended to, otherwise they are overwritten.  If the", | ||||
| 	"`-i' option is supplied, tee ignores interrupts.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| struct builtin tee_struct = { | ||||
| 	"tee",			/* builtin name */ | ||||
| 	tee_builtin,		/* function implementing the builtin */ | ||||
| 	BUILTIN_ENABLED,	/* initial flags for builtin */ | ||||
| 	tee_doc,		/* array of long documentation strings. */ | ||||
| 	"tee [-ai] [file ...]",	/* usage synopsis; becomes short_doc */ | ||||
| 	0			/* reserved for internal use */ | ||||
| }; | ||||
							
								
								
									
										45
									
								
								examples/loadables/truefalse.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								examples/loadables/truefalse.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| /* true and false builtins */ | ||||
| 
 | ||||
| #include "bashtypes.h" | ||||
| #include "shell.h" | ||||
| #include "builtins.h" | ||||
| 
 | ||||
| true_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   return EXECUTION_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| false_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   return EXECUTION_FAILURE; | ||||
| } | ||||
| 
 | ||||
| static char *true_doc[] = { | ||||
| 	"Return a successful result.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| static char *false_doc[] = { | ||||
| 	"Return an unsuccessful result.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| struct builtin true_struct = { | ||||
| 	"true", | ||||
| 	true_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	true_doc, | ||||
| 	"true", | ||||
| 	0 | ||||
| }; | ||||
| 
 | ||||
| struct builtin false_struct = { | ||||
| 	"false", | ||||
| 	false_builtin, | ||||
| 	BUILTIN_ENABLED, | ||||
| 	false_doc, | ||||
| 	"false", | ||||
| 	0 | ||||
| }; | ||||
							
								
								
									
										59
									
								
								examples/loadables/tty.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								examples/loadables/tty.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| /* tty - return terminal name */ | ||||
| 
 | ||||
| /* See Makefile for compilation details. */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include "builtins.h" | ||||
| #include "shell.h" | ||||
| #include "bashgetopt.h" | ||||
| 
 | ||||
| extern char *ttyname (); | ||||
| 
 | ||||
| tty_builtin (list) | ||||
|      WORD_LIST *list; | ||||
| { | ||||
|   int opt, sflag; | ||||
|   char *t; | ||||
| 
 | ||||
|   reset_internal_getopt (); | ||||
|   sflag = 0; | ||||
|   while ((opt = internal_getopt (list, "s")) != -1) | ||||
|     { | ||||
|       switch (opt) | ||||
| 	{ | ||||
| 	case 's': | ||||
| 	  sflag = 1; | ||||
| 	  break; | ||||
| 	default: | ||||
| 	  builtin_usage (); | ||||
| 	  return (EX_USAGE); | ||||
| 	} | ||||
|     } | ||||
|   list = loptend; | ||||
| 
 | ||||
|   t = ttyname (0); | ||||
|   if (sflag == 0) | ||||
|     puts (t ? t : "not a tty"); | ||||
|   return (t ? EXECUTION_SUCCESS : EXECUTION_FAILURE); | ||||
| } | ||||
| 
 | ||||
| char *tty_doc[] = { | ||||
| 	"tty writes the name of the terminal that is opened for standard", | ||||
| 	"input to standard output.  If the `-s' option is supplied, nothing", | ||||
| 	"is written; the exit status determines whether or not the standard", | ||||
| 	"input is connected to a tty.", | ||||
| 	(char *)NULL | ||||
| }; | ||||
| 
 | ||||
| /* The standard structure describing a builtin command.  bash keeps an array
 | ||||
|    of these structures. */ | ||||
| struct builtin tty_struct = { | ||||
| 	"tty",			/* builtin name */ | ||||
| 	tty_builtin,		/* function implementing the builtin */ | ||||
| 	BUILTIN_ENABLED,	/* initial flags for builtin */ | ||||
| 	tty_doc,		/* array of long documentation strings. */ | ||||
| 	"tty [-s]",		/* usage synopsis; becomes short_doc */ | ||||
| 	0			/* reserved for internal use */ | ||||
| }; | ||||
							
								
								
									
										38
									
								
								examples/misc/alias-conv.bash
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										38
									
								
								examples/misc/alias-conv.bash
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # alias-conv.sh - convert csh aliases to bash aliases and functions | ||||
| # | ||||
| # usage: alias-conv.sh | ||||
| # | ||||
| # Chet Ramey | ||||
| # chet@po.cwru.edu | ||||
| # | ||||
| trap 'rm -f /tmp/cb$$.?' 0 1 2 3 6 15 | ||||
| 
 | ||||
| T=$'\t' | ||||
| 
 | ||||
| cat << \EOF >/tmp/cb$$.1 | ||||
| mkalias () | ||||
| { | ||||
| 	if [ "x$2" = "x" ]; then | ||||
| 		echo alias ${1}="''" | ||||
| 	elif echo "$2" | egrep -s '(\!|#)' >/dev/null 2>&1; then | ||||
| 		comm=$(echo $2 | sed  's/\!\*/"$\@"/g | ||||
| 				      s/\!:\([1-9]\)/"$\1"/g | ||||
| 			              s/#/\#/g') | ||||
| 		echo $1 \(\) "{" command "$comm"  "; }" | ||||
| 	else | ||||
| 		echo alias ${1}=\'$(echo "${2}" | sed "s:':'\\\\'':")\' | ||||
| 	fi | ||||
| } | ||||
| EOF | ||||
| 
 | ||||
| sed "s/^\([a-zA-Z0-9_-]*\)$T\(.*\)$/mkalias \1 '\2'/" >>/tmp/cb$$.1 | ||||
| 
 | ||||
| $BASH /tmp/cb$$.1 | sed -e 's/\$cwd/\$PWD/g' \ | ||||
| 		     -e 's/\$term/\$TERM/g' \ | ||||
| 		     -e 's/\$home/\$HOME/g' \ | ||||
| 		     -e 's/\$user/\$USER/g' \ | ||||
| 		     -e 's/\$prompt/\$PS1/g' | ||||
| 
 | ||||
| exit 0 | ||||
							
								
								
									
										38
									
								
								examples/misc/alias-conv.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										38
									
								
								examples/misc/alias-conv.sh
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # alias-conv.sh - convert csh aliases to bash aliases and functions | ||||
| # | ||||
| # usage: alias-conv.sh | ||||
| # | ||||
| # Chet Ramey | ||||
| # chet@po.cwru.edu | ||||
| # | ||||
| trap 'rm -f /tmp/cb$$.?' 0 1 2 3 6 15 | ||||
| 
 | ||||
| T='	' | ||||
| 
 | ||||
| cat << \EOF >/tmp/cb$$.1 | ||||
| mkalias () | ||||
| { | ||||
| 	if [ "x$2" = "x" ]; then | ||||
| 		echo alias ${1}="''" | ||||
| 	elif echo "$2" | egrep -s '(\!|#)' >/dev/null 2>&1; then | ||||
| 		comm=`echo $2 | sed  's/\\!\*/"$\@"/g | ||||
| 				      s/\\!:\([1-9]\)/"$\1"/g | ||||
| 			              s/#/\#/g'` | ||||
| 		echo $1 \(\) "{" command "$comm"  "; }" | ||||
| 	else | ||||
| 		echo alias ${1}=\'`echo "${2}" | sed "s:':'\\\\\\\\'':"`\' | ||||
| 	fi | ||||
| } | ||||
| EOF | ||||
| 
 | ||||
| sed "s/^\([a-zA-Z0-9_-]*\)$T\(.*\)$/mkalias \1 '\2'/" >>/tmp/cb$$.1 | ||||
| 
 | ||||
| sh /tmp/cb$$.1 | sed -e 's/\$cwd/\$PWD/g' \ | ||||
| 		     -e 's/\$term/\$TERM/g' \ | ||||
| 		     -e 's/\$home/\$HOME/g' \ | ||||
| 		     -e 's/\$user/\$USER/g' \ | ||||
| 		     -e 's/\$prompt/\$PS1/g' | ||||
| 
 | ||||
| exit 0 | ||||
							
								
								
									
										130
									
								
								examples/misc/cshtobash
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										130
									
								
								examples/misc/cshtobash
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,130 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # cshtobash - convert csh aliases, environment variables, and variables to | ||||
| #	      bash equivalents | ||||
| # | ||||
| # usage: cshtobash [filename] | ||||
| # | ||||
| # If filename is given, that file is sourced.  Note that csh always | ||||
| # sources .cshrc.  To recreate your csh login environment, run | ||||
| # `cshtobash ~/.login'. | ||||
| # | ||||
| # Inspired by (and some borrowed from) a similar program distributed with | ||||
| # zsh-3.0. | ||||
| # | ||||
| # Chet Ramey | ||||
| # chet@po.cwru.edu | ||||
| # | ||||
| trap 'rm -f /tmp/cb$$.? cshout cshin' 0 1 2 3 6 15 | ||||
| 
 | ||||
| T=$'\t' | ||||
| 
 | ||||
| SOURCE="${1:+source $1}" | ||||
| 
 | ||||
| cat << EOF >cshin | ||||
| $SOURCE | ||||
| alias >! /tmp/cb$$.a | ||||
| setenv >! /tmp/cb$$.e | ||||
| set >! /tmp/cb$$.v | ||||
| EOF | ||||
| 
 | ||||
| # give csh a minimal environment, similar to what login would provide | ||||
| /usr/bin/env - USER=$USER HOME=$HOME PATH=/usr/bin:/bin:/usr/ucb:. TERM=$TERM SHELL=$SHELL /bin/csh -i < ./cshin > cshout 2>&1 | ||||
| 
 | ||||
| # First convert aliases | ||||
| 
 | ||||
| cat << \EOF >/tmp/cb$$.1 | ||||
| mkalias () | ||||
| { | ||||
| 	if [ -z "$2" ]; then | ||||
| 		echo alias ${1}="''" | ||||
| 	elif echo "$2" | egrep -s '(\!|#)' >/dev/null 2>&1; then | ||||
| 		comm=$(echo $2 | sed  's/\!\*/"$\@"/g | ||||
| 				       s/\!:\([1-9]\)/"$\1"/g | ||||
| 			               s/#/\#/g') | ||||
| 		echo $1 \(\) "{" command "$comm"  "; }" | ||||
| 	else | ||||
| 		echo alias ${1}=\'$(echo "${2}" | sed "s:':'\\\\'':")\' | ||||
| 	fi | ||||
| } | ||||
| EOF | ||||
| 
 | ||||
| sed "s/^\([a-zA-Z0-9_]*\)$T\(.*\)$/mkalias \1 '\2'/" < /tmp/cb$$.a >>/tmp/cb$$.1 | ||||
| 
 | ||||
| echo '# csh aliases' | ||||
| echo | ||||
| 
 | ||||
| $BASH /tmp/cb$$.1 | sed -e 's/\$cwd/\$PWD/g' \ | ||||
| 		   -e 's/\$term/\$TERM/g' \ | ||||
| 		   -e 's/\$home/\$HOME/g' \ | ||||
| 		   -e 's/\$user/\$USER/g' \ | ||||
| 		   -e 's/\$prompt/\$PS1/g' | ||||
| 
 | ||||
| # Next, convert environment variables | ||||
| echo | ||||
| echo '# csh environment variables' | ||||
| echo | ||||
| 
 | ||||
| # Would be nice to deal with embedded newlines, e.g. in TERMCAP, but ... | ||||
| sed -e '/^SHLVL/d' \ | ||||
|     -e '/^PWD/d' \ | ||||
|     -e "s/'/'"\\\\"''"/g \ | ||||
|     -e "s/^\([A-Za-z0-9_]*=\)/export \1'/" \ | ||||
|     -e "s/$/'/" < /tmp/cb$$.e | ||||
| 
 | ||||
| # Finally, convert local variables | ||||
| echo | ||||
| echo '# csh variables' | ||||
| echo | ||||
| 
 | ||||
| sed -e 's/'"$T"'/=/' \ | ||||
|     -e "s/'/'"\\\\"''"/g \ | ||||
|     -e '/^[A-Za-z0-9_]*=[^(]/{ | ||||
| 	s/=/='"'/"' | ||||
| 	s/$/'"'/"' | ||||
| 	}' < /tmp/cb$$.v | | ||||
| sed -e '/^argv=/d' -e '/^cwd=/d' -e '/^filec=/d' -e '/^status=/d' \ | ||||
| 	 -e '/^verbose=/d' \ | ||||
| 	 -e '/^term=/d' \ | ||||
| 	 -e '/^home=/d' \ | ||||
| 	 -e '/^path=/d' \ | ||||
| 	 -e '/^user=/d' \ | ||||
| 	 -e '/^shell=/d' \ | ||||
| 	 -e '/^cdpath=/d' \ | ||||
| 	 -e '/^mail=/d' \ | ||||
| 	 -e '/^home=/s//HOME=/' \ | ||||
| 	 -e '/^prompt=/s//PS1=/' \ | ||||
| 	 -e '/^histfile=/s//HISTFILE=/' \ | ||||
| 	 -e '/^history=/s//HISTSIZE=/' \ | ||||
| 	 -e '/^savehist=$/s//HISTFILESIZE=${HISTSIZE-500}/' \ | ||||
| 	 -e '/^savehist=/s//HISTFILESIZE=/' \ | ||||
| 	 -e '/^ignoreeof=$/s/^.*$/set -o ignoreeof # ignoreeof/' \ | ||||
| 	 -e '/^ignoreeof=/s//IGNOREEOF=/' \ | ||||
| 	 -e '/^noclobber=/s/^.*$/set -C # noclobber/' \ | ||||
| 	 -e '/^notify=/s/^.*$/set -b # notify/' \ | ||||
| 	 -e '/^noglob=/s/^.*$/set -f # noglob/' \ | ||||
| 
 | ||||
| 
 | ||||
| # now some special csh variables converted to bash equivalents | ||||
| echo | ||||
| echo '# special csh variables converted to bash equivalents' | ||||
| echo | ||||
| 
 | ||||
| sed -e 's/'"$T"'/=/' < /tmp/cb$$.v | | ||||
| grep "^cdpath=" | | ||||
| sed 's/(// | ||||
|      s/ /:/g | ||||
|      s/)// | ||||
|      s/cdpath=/CDPATH=/' | ||||
| 
 | ||||
| 
 | ||||
| sed -e 's/'"$T"'/=/' < /tmp/cb$$.v | | ||||
| grep "^mail=" | | ||||
| sed 's/(// | ||||
|      s/ /:/g | ||||
|      s/)// | ||||
|      s/mail=/MAILPATH=/' | | ||||
| sed -e 's/MAILPATH=\([0-9][0-9][^:]*\)$/MAILCHECK=\1/' \ | ||||
|     -e 's/MAILPATH=\([0-9][0-9][^:]*\):\(.*\)/MAILCHECK=\1 MAILPATH=\2/' | ||||
| 
 | ||||
| exit 0 | ||||
							
								
								
									
										29
									
								
								examples/scripts.noah/PERMISSION
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								examples/scripts.noah/PERMISSION
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | |||
| From friedman@cli.com Thu May 25 12:19:06 1995 | ||||
| Flags: 10 | ||||
| Return-Path: friedman@cli.com | ||||
| Received: from po.cwru.edu (root@po.CWRU.Edu [129.22.4.2]) by odin.INS.CWRU.Edu with ESMTP (8.6.10+cwru/CWRU-2.1-ins) | ||||
| 	id MAA08685; Thu, 25 May 1995 12:19:05 -0400 (from friedman@cli.com for <chet@odin.INS.CWRU.Edu>) | ||||
| Received: from cli.com (cli.com [192.31.85.1]) by po.cwru.edu with SMTP (8.6.10+cwru/CWRU-2.3) | ||||
| 	id MAA11299; Thu, 25 May 1995 12:19:00 -0400 (from friedman@cli.com for <chet@po.cwru.edu>) | ||||
| Received: from tepui.cli.com by cli.com (4.1/SMI-4.1) | ||||
| 	id AA27213; Thu, 25 May 95 11:18:25 CDT | ||||
| Received: by tepui.cli.com (4.1) id AA16031; Thu, 25 May 95 11:18:23 CDT | ||||
| Message-Id: <9505251618.AA16031@tepui.cli.com> | ||||
| From: friedman@gnu.ai.mit.edu (Noah Friedman) | ||||
| To: chet@po.cwru.edu | ||||
| Subject: Bash scripts | ||||
| Reply-To: friedman@gnu.ai.mit.edu | ||||
| In-Reply-To: <chet@odin.ins.cwru.edu> Thu, 25 May 1995 11:19:59 -0400 | ||||
| References: <9505251519.AA06424.SM@odin.INS.CWRU.Edu> | ||||
| Date: Thu, 25 May 95 11:18:21 CST | ||||
| 
 | ||||
| >Hi.  I snagged some of your bash functions from your home directory on | ||||
| >the FSF machines (naughty, I know), and I was wondering if you'd let | ||||
| >me distribute them with bash-2.0.  Thanks. | ||||
| 
 | ||||
| Sure.  I think there's a later copy in | ||||
| ~ftp/friedman/shell-inits/init-4.89.tar.gz.  There are also some elisp and | ||||
| es frobs in that file. | ||||
| 
 | ||||
| It should serve as a pretty good example of how to get carried away.  :-) | ||||
| 
 | ||||
							
								
								
									
										24
									
								
								examples/scripts.noah/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								examples/scripts.noah/README
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| This collection of scripts was originally written for older versions | ||||
| of bash by Noah Friedman (friedman@gnu.ai.mit.edu).  The conversion | ||||
| to bash v2 syntax was done by Chet Ramey. | ||||
| 
 | ||||
| These scripts are as-is; there is no copyright associated with | ||||
| any of them.  They exist simply as examples of bash scripting. | ||||
| 
 | ||||
| Here's a description of what's in this directory: | ||||
| 
 | ||||
| aref.bash		pseudo-arrays and substring indexing examples | ||||
| bash.sub.bash		library functions used by require.bash | ||||
| bash_version.bash	a function to slice up $BASH_VERSION | ||||
| meta.bash		enable and disable eight-bit readline input | ||||
| mktmp.bash		make a temporary file with a unique name | ||||
| number.bash		a fun hack to translate numerals into english | ||||
| prompt.bash		a way to set PS1 to some predefined strings | ||||
| remap_keys.bash		a front end to `bind' to redo readline bindings | ||||
| require.bash		lisp-like require/provide library functions for bash | ||||
| send_mail.bash		replacement smtp client written in bash | ||||
| shcat.bash		bash replacement for `cat' | ||||
| source.bash		replacement for source that uses current directory | ||||
| string.bash		the string(3) functions at the shell level | ||||
| stty.bash		front-end to stty that changes readline bindings too | ||||
| y_or_n_p.bash		prompt for a yes/no/quit answer	 | ||||
							
								
								
									
										44
									
								
								examples/scripts.noah/aref.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								examples/scripts.noah/aref.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| # aref.bash --- pseudo-array manipulating routines | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created 1992-07-01 | ||||
| # Last modified: 1993-02-03 | ||||
| # Public domain | ||||
| 
 | ||||
| # Conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring aref: | ||||
| # Usage: aref NAME INDEX | ||||
| # | ||||
| # In array NAME, access element INDEX (0-origin) | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function aref () | ||||
| { | ||||
|     local name="$1" | ||||
|     local index="$2" | ||||
| 
 | ||||
|     set -- ${!name} | ||||
|     [ $index -ge 1 ] && shift $index | ||||
|     echo $1 | ||||
| } | ||||
| 
 | ||||
| #:docstring string_aref: | ||||
| # Usage: aref STRING INDEX | ||||
| # | ||||
| # Echo the INDEXth character in STRING (0-origin) on stdout.  | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function string_aref () | ||||
| { | ||||
|   local stuff=${1:$2} | ||||
|   echo ${stuff:0:1} | ||||
| } | ||||
| 
 | ||||
| provide aref | ||||
| 
 | ||||
| # aref.bash ends here | ||||
							
								
								
									
										28
									
								
								examples/scripts.noah/bash.sub.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								examples/scripts.noah/bash.sub.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| # bash.sub.bash --- stub for standalone shell scripts using bash library | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-07-13 | ||||
| # Last modified: 1993-09-29 | ||||
| # Public domain | ||||
| 
 | ||||
| #:docstring bash.sub: | ||||
| # Standard subroutines for bash scripts wishing to use "require" to load | ||||
| # libraries. | ||||
| # | ||||
| # Usage: In each directory where a bash script that uses this script | ||||
| # exists, place a copy of this script.  Then, at the top of such scripts, | ||||
| # put the command | ||||
| # | ||||
| #    source ${0%/*}/bash.sub || exit 1 | ||||
| # | ||||
| # Then you can use `require' to load packages.  | ||||
| # | ||||
| #:end docstring: | ||||
| 
 | ||||
| default_FPATH="~friedman/etc/init/bash/functions/lib" | ||||
| 
 | ||||
| source "${default_FPATH}/feature" | ||||
| REQUIRE_FAILURE_FATAL=t | ||||
| 
 | ||||
| FPATH="${FPATH-${default_FPATH}}" | ||||
| 
 | ||||
| # bash.sub.bash ends here | ||||
							
								
								
									
										42
									
								
								examples/scripts.noah/bash_version.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								examples/scripts.noah/bash_version.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| # bash_version.bash --- get major and minor components of bash version number | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1993-01-26 | ||||
| # Last modified: 1993-01-26 | ||||
| # Public domain | ||||
| 
 | ||||
| # Converted to bash v2 syntax by Chet Ramey | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring bash_version: | ||||
| # Usage: bash_version {major|minor} | ||||
| # | ||||
| # Echo the major or minor number of this version of bash on stdout, or | ||||
| # just echo $BASH_VERSION if no argument is given.  | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function bash_version () | ||||
| { | ||||
|     local major minor | ||||
| 
 | ||||
|     case "$1" in  | ||||
|     major) echo "${BASH_VERSION/.*/}" ;; | ||||
|     minor) major="${BASH_VERSION/.*/}" | ||||
| 	   minor="${BASH_VERSION#${major}.}" | ||||
|            echo "${minor%%.*}" ;; | ||||
|     patchlevel) minor="${BASH_VERSION#*.*.}" | ||||
| 		echo "${minor%(*}" ;; | ||||
|     version) minor=${BASH_VERSION/#*.*./} | ||||
| 	     echo ${BASH_VERSION/%.$minor/} ;; | ||||
|     release) echo ${BASH_VERSION%(*} ;; | ||||
|     build) minor="${BASH_VERSION#*.*.*(}" | ||||
| 	   echo ${minor%)} ;; | ||||
|     *) echo "${BASH_VERSION}" ;; | ||||
|     esac | ||||
| } | ||||
| 
 | ||||
| provide bash_version | ||||
| 
 | ||||
| # bash_version.bash ends here | ||||
							
								
								
									
										37
									
								
								examples/scripts.noah/meta.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								examples/scripts.noah/meta.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| # meta.bash --- meta key frobnications | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-06-28 | ||||
| # Last modified: 1993-01-26 | ||||
| # Public domain | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring meta: | ||||
| # Usage: meta [on|off] | ||||
| #  | ||||
| # An argument of "on" will make bash use the 8th bit of any input from | ||||
| # a terminal as a "meta" bit, i.e bash will be able to use a real meta | ||||
| # key. | ||||
| # | ||||
| # An argument of "off" causes bash to disregard the 8th bit, which is | ||||
| # assumed to be used for parity instead. | ||||
| #:end docstring: | ||||
| 
 | ||||
| function meta () | ||||
| { | ||||
|       case "$1" in | ||||
|          on) bind 'set input-meta On' | ||||
| 	     bind 'set output-meta on' | ||||
| 	     bind 'set convert-meta off' ;; | ||||
|          off) bind 'set input-meta Off' | ||||
| 	      bind 'set output-meta off' | ||||
| 	      bind 'set convert-meta on' ;; | ||||
|          *) echo "Usage: meta [on|off]" 1>&2 ; return 1 ;; | ||||
|       esac | ||||
|       return 0 | ||||
| } | ||||
| 
 | ||||
| provide meta | ||||
| 
 | ||||
| # meta.bash ends here | ||||
							
								
								
									
										66
									
								
								examples/scripts.noah/mktmp.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								examples/scripts.noah/mktmp.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| # mktmp.bash | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1993-02-03 | ||||
| # Last modified: 1993-02-03 | ||||
| # Public domain | ||||
| 
 | ||||
| # Conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring mktmp: | ||||
| # Usage: mktmp [template] {createp} | ||||
| # | ||||
| # Generate a unique filename from TEMPLATE by appending a random number to | ||||
| # the end.  | ||||
| # | ||||
| # If optional 2nd arg CREATEP is non-null, file will be created atomically | ||||
| # before returning.  This is to avoid the race condition that in between | ||||
| # the time that the temporary name is returned and the caller uses it, | ||||
| # someone else creates the file.  | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function mktmp () | ||||
| { | ||||
|     local template="$1" | ||||
|     local tmpfile="${template}${RANDOM}" | ||||
|     local createp="$2" | ||||
|     local noclobber_status | ||||
| 
 | ||||
|     case "$-" in | ||||
|     *C*)	noclobber_status=set;; | ||||
|     esac | ||||
| 
 | ||||
|     if [ "${createp:+set}" = "set" ]; then | ||||
|        # Version which creates file atomically through noclobber test.    | ||||
|        set -o noclobber | ||||
|        (> "${tmpfile}") 2> /dev/null | ||||
|        while [ $? -ne 0 ] ; do | ||||
|           # Detect whether file really exists or creation lost because of | ||||
|           # some other permissions problem.  If the latter, we don't want | ||||
|           # to loop forever. | ||||
|           if [ ! -e "${tmpfile}" ]; then | ||||
|              # Trying to create file again creates stderr message. | ||||
|              echo -n "mktmp: " 1>&2 | ||||
|              > "${tmpfile}" | ||||
|              return 1 | ||||
|           fi | ||||
|           tmpfile="${template}${RANDOM}" | ||||
|           (> "${tmpfile}") 2> /dev/null | ||||
|        done | ||||
|        test "${noclobber_status}" != "set" && set +o noclobber | ||||
|     else | ||||
|        # Doesn't create file, so it introduces race condition for caller.  | ||||
|        while [ -e "${tmpfile}" ]; do | ||||
|           tmpfile="${template}${RANDOM}" | ||||
|        done | ||||
|     fi | ||||
| 
 | ||||
|     echo "${tmpfile}" | ||||
| } | ||||
| 
 | ||||
| provide mktmp | ||||
| 
 | ||||
| # mktmp.bash ends here | ||||
							
								
								
									
										185
									
								
								examples/scripts.noah/number.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								examples/scripts.noah/number.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,185 @@ | |||
| # number.bash | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1993-02-22 | ||||
| # Last modified: 1993-04-01 | ||||
| # Public domain | ||||
| 
 | ||||
| # Conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring number: | ||||
| # Usage: number [number] | ||||
| # | ||||
| # Converts decimal integers to english notation.  Spaces and commas are | ||||
| # optional.  Numbers 67 digits and larger will overflow this script. | ||||
| # | ||||
| # E.g: number 99,000,000,000,000,454 | ||||
| #      => ninety-nine quadrillion four hundred fifty-four | ||||
| # | ||||
| #:end docstring: | ||||
| 
 | ||||
| function number () | ||||
| { | ||||
|  local result | ||||
|  local val1 | ||||
|  local val2 | ||||
|  local val3 | ||||
|  local d1 | ||||
|  local d2 | ||||
|  local d3 | ||||
| 
 | ||||
|    case "$*" in | ||||
|       *[!0-9,.]* )  | ||||
|          echo "number: invalid character in argument." 1>&2 | ||||
|          return 1  | ||||
|         ;; | ||||
|       *.* )  | ||||
|          echo "number: fractions not supported (yet)." 1>&2 | ||||
|          return 1  | ||||
|         ;; | ||||
|    esac | ||||
| 
 | ||||
|    result='' | ||||
| 
 | ||||
|    eval set - "`echo ${1+\"$@\"} | sed -n -e ' | ||||
|       s/[, ]//g;s/^00*/0/g;s/\(.\)\(.\)\(.\)$/\"\1 \2 \3\"/; | ||||
|       :l | ||||
|       /[0-9][0-9][0-9]/{ | ||||
|          s/\([^\" ][^\" ]*\)\([^\" ]\)\([^\" ]\)\([^\" ]\)/\1\"\2 \3 \4\"/g; | ||||
|          t l | ||||
|       } | ||||
|       /^[0-9][0-9][0-9]/s/\([^\" ]\)\([^\" ]\)\([^\" ]\)/\"\1 \2 \3\"/; | ||||
|       /^[0-9][0-9]/s/\([^\" ]\)\([^\" ]\)/\"\1 \2\"/; | ||||
|       /^[0-9]/s/^\([^\" ][^\" ]*\)/\"\1\"/g;s/\"\"/\" \"/g;p;'`" | ||||
| 
 | ||||
|    while test $# -ne 0 ; do | ||||
|       eval `set - $1;  | ||||
|             d3='' d2='' d1='' | ||||
|             case $# in | ||||
|                1 ) d1=$1 ;; | ||||
|                2 ) d2=$1 d1=$2 ;; | ||||
|                3 ) d3=$1 d2=$2 d1=$3 ;; | ||||
|             esac | ||||
|             echo "d3=\"${d3}\" d2=\"${d2}\" d1=\"${d1}\""` | ||||
| 
 | ||||
|       val1='' val2='' val3='' | ||||
| 
 | ||||
|       case "${d3}" in | ||||
|          '1' ) val3='one'   ;; | ||||
|          '2' ) val3='two'   ;; | ||||
|          '3' ) val3='three' ;; | ||||
|          '4' ) val3='four'  ;; | ||||
|          '5' ) val3='five'  ;; | ||||
|          '6' ) val3='six'   ;; | ||||
|          '7' ) val3='seven' ;; | ||||
|          '8' ) val3='eight' ;; | ||||
|          '9' ) val3='nine'  ;; | ||||
|       esac | ||||
| 
 | ||||
|       case "${d2}" in | ||||
|          '1' ) val2='teen'    ;; | ||||
|          '2' ) val2='twenty'  ;; | ||||
|          '3' ) val2='thirty'  ;; | ||||
|          '4' ) val2='forty'   ;; | ||||
|          '5' ) val2='fifty'   ;; | ||||
|          '6' ) val2='sixty'   ;; | ||||
|          '7' ) val2='seventy' ;; | ||||
|          '8' ) val2='eighty'  ;; | ||||
|          '9' ) val2='ninety'  ;; | ||||
|       esac | ||||
| 
 | ||||
|       case "${val2}" in | ||||
|          'teen') | ||||
|             val2='' | ||||
|             case "${d1}" in | ||||
|                '0') val1='ten'       ;; | ||||
|                '1') val1='eleven'    ;; | ||||
|                '2') val1='twelve'    ;; | ||||
|                '3') val1='thirteen'  ;; | ||||
|                '4') val1='fourteen'  ;; | ||||
|                '5') val1='fifteen'   ;; | ||||
|                '6') val1='sixteen'   ;; | ||||
|                '7') val1='seventeen' ;; | ||||
|                '8') val1='eighteen'  ;; | ||||
|                '9') val1='nineteen'  ;; | ||||
|             esac | ||||
|            ;; | ||||
|          0 ) : ;; | ||||
|          * ) | ||||
|             if test ".${val2}" != '.' -a ".${d1}" != '.0' ; then | ||||
|                val2="${val2}-" | ||||
|             fi | ||||
|             case "${d1}" in | ||||
|                '0') val2="${val2} " ;; | ||||
|                '1') val1='one'    ;; | ||||
|                '2') val1='two'    ;; | ||||
|                '3') val1='three'  ;; | ||||
|                '4') val1='four'   ;; | ||||
|                '5') val1='five'   ;; | ||||
|                '6') val1='six'    ;; | ||||
|                '7') val1='seven'  ;; | ||||
|                '8') val1='eight'  ;; | ||||
|                '9') val1='nine'   ;; | ||||
|             esac | ||||
|            ;; | ||||
|       esac | ||||
| 
 | ||||
|       if test ".${val3}" != '.' ; then | ||||
|          result="${result}${val3} hundred " | ||||
|       fi | ||||
| 
 | ||||
|       if test ".${val2}" != '.' ; then | ||||
|          result="${result}${val2}" | ||||
|       fi | ||||
| 
 | ||||
|       if test ".${val1}" != '.' ; then | ||||
|          result="${result}${val1} " | ||||
|       fi | ||||
| 
 | ||||
|       if test ".${d1}${d2}${d3}" != '.000' ; then | ||||
|          case $# in | ||||
|              0 | 1 ) ;; | ||||
|              2 ) result="${result}thousand " ;; | ||||
|              3 ) result="${result}million " ;; | ||||
|              4 ) result="${result}billion " ;; | ||||
|              5 ) result="${result}trillion " ;; | ||||
|              6 ) result="${result}quadrillion " ;; | ||||
|              7 ) result="${result}quintillion " ;; | ||||
|              8 ) result="${result}sextillion " ;; | ||||
|              9 ) result="${result}septillion " ;; | ||||
|             10 ) result="${result}octillion " ;; | ||||
|             11 ) result="${result}nonillion " ;; | ||||
|             12 ) result="${result}decillion " ;; | ||||
|             13 ) result="${result}undecillion " ;; | ||||
|             14 ) result="${result}duodecillion " ;; | ||||
|             15 ) result="${result}tredecillion " ;; | ||||
|             16 ) result="${result}quattuordecillion " ;; | ||||
|             17 ) result="${result}quindecillion " ;; | ||||
|             18 ) result="${result}sexdecillion " ;; | ||||
|             19 ) result="${result}septendecillion " ;; | ||||
|             20 ) result="${result}octodecillion " ;; | ||||
|             21 ) result="${result}novemdecillion " ;; | ||||
|             22 ) result="${result}vigintillion " ;; | ||||
|             * ) | ||||
|                echo "Error: number too large (66 digits max)." 1>&2 | ||||
|                return 1 | ||||
|               ;; | ||||
|          esac | ||||
|       fi | ||||
| 
 | ||||
|       shift | ||||
|    done | ||||
| 
 | ||||
|    set - ${result} | ||||
|    case "$*" in | ||||
|       '') set - 'zero' ;; | ||||
|    esac | ||||
| 
 | ||||
|    echo ${1+"$@"} | ||||
| } | ||||
| 
 | ||||
| provide number | ||||
| 
 | ||||
| # number.bash ends here | ||||
							
								
								
									
										40
									
								
								examples/scripts.noah/prompt.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								examples/scripts.noah/prompt.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | |||
| # prompt.bash | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-01-15 | ||||
| # Public domain | ||||
| 
 | ||||
| # $Id: prompt.bash,v 1.2 1994/10/18 16:34:35 friedman Exp $ | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring prompt: | ||||
| # Usage: prompt [chars] | ||||
| # | ||||
| # Various preformatted prompt strings selected by argument.  For a | ||||
| # list of available arguments and corresponding formats, do  | ||||
| # `type prompt'.  | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function prompt () | ||||
| { | ||||
|     case "$1" in | ||||
|     d)     PS1='$(dirs) \$ '               ;; | ||||
|     n)     PS1='\$ '                       ;; | ||||
|     hsw)   PS1='\h[$SHLVL]: \w \$ '        ;; | ||||
|     hw)    PS1='\h: \w \$ '                ;; | ||||
|     sh)    PS1='[$SHLVL] \h\$ '            ;; | ||||
|     sw)    PS1='[$SHLVL] \w \$ '           ;; | ||||
|     uh)    PS1='\u@\h\$ '                  ;; | ||||
|     uhsHw) PS1='\u@\h[$SHLVL]:\#: \w \$ '  ;; | ||||
|     uhsw)  PS1='\u@\h[$SHLVL]: \w \$ '     ;; | ||||
|     uhw)   PS1='\u@\h: \w \$ '             ;; | ||||
|     uw)    PS1='(\u) \w \$ '               ;; | ||||
|     w)     PS1='\w \$ '                    ;; | ||||
|     esac | ||||
| } | ||||
| 
 | ||||
| provide prompt | ||||
| 
 | ||||
| # prompt.bash ends here | ||||
							
								
								
									
										71
									
								
								examples/scripts.noah/remap_keys.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								examples/scripts.noah/remap_keys.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,71 @@ | |||
| # remap_keybindings.bash | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-01-11 | ||||
| # Last modified: 1993-02-03 | ||||
| # Public domain | ||||
| 
 | ||||
| # Conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring remap_keybindings: | ||||
| # Usage: remap_keybindings old_function new_function | ||||
| # | ||||
| # Clear all readline keybindings associated with OLD_FUNCTION (a Readline | ||||
| # function) rebinding them to NEW_FUNCTION (`self-insert' by default) | ||||
| # | ||||
| # This requires bash version 1.10 or newer, since previous versions did not | ||||
| # implement the `bind' builtin. | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function remap_keybindings () | ||||
| { | ||||
|     local unbind_function="$1" | ||||
|     local bind_function="${2:-'self-insert'}" | ||||
|     local bind_output | ||||
|     local arg | ||||
| 
 | ||||
|     # If they're the same thing, the work has already been done.  :-) | ||||
|     if [ "${unbind_function}" = "${bind_function}" ]; then | ||||
|        return 0 | ||||
|     fi | ||||
| 
 | ||||
|     while : ; do | ||||
|        bind_output="$(bind -q ${unbind_function} 2> /dev/null)" | ||||
| 
 | ||||
|        case "${bind_output}" in | ||||
|           "${unbind_function} can be invoked via"* ) ;; | ||||
|           "" ) return 1 ;;         # probably bad argument to bind | ||||
|           *) return 0 ;;           # unbound | ||||
|        esac | ||||
| 
 | ||||
|        # Format of bind_output is like: | ||||
|        # 'quoted-insert can be invoked via "\C-q", "\C-v".' | ||||
|        # 'self-insert can be invoked via " ", "!", """, "$", "%", ...' | ||||
|        set -- ${bind_output} | ||||
|        shift 5 | ||||
|         | ||||
|        for arg in "$@" ; do | ||||
|           # strip off trailing `.' or `,' | ||||
|           arg=${arg%.}; | ||||
|           arg=${arg%,}; | ||||
|         | ||||
|           case ${arg} in | ||||
|              ..) | ||||
|                 # bind -q didn't provide whole list of key bindings; jump | ||||
|                 # to top loop to get more | ||||
|                 continue 2 ;  | ||||
|                ;; | ||||
|              *) | ||||
|                 bind "${arg}: ${bind_function}" | ||||
|                ;; | ||||
|           esac | ||||
|        done | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| provide remap_keybindings | ||||
| 
 | ||||
| # remap_keybindings.bash ends here | ||||
							
								
								
									
										182
									
								
								examples/scripts.noah/require.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								examples/scripts.noah/require.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,182 @@ | |||
| # require.bash | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-07-08 | ||||
| # Last modified: 1993-09-29 | ||||
| # Public domain | ||||
| 
 | ||||
| # Commentary: | ||||
| 
 | ||||
| # These functions provide an interface based on the lisp implementation for | ||||
| # loading libraries when they are needed and eliminating redundant loading. | ||||
| # The basic idea is that each "package" (or set of routines, even if it is | ||||
| # only one function) registers itself with a symbol that marks a "feature" | ||||
| # as being "provided".  If later you "require" a given feature, you save | ||||
| # yourself the trouble of explicitly loading it again. | ||||
| #  | ||||
| # At the bottom of each package, put a "provide foobar", so when another | ||||
| # package has a "require foobar", it gets loaded and registered as a | ||||
| # "feature" that won't need to get loaded again.  (See warning below for | ||||
| # reasons why provide should be put at the end.) | ||||
| # | ||||
| # The list of provided features are kept in the `FEATURES' variable, which | ||||
| # is not exported.  Care should be taken not to munge this in the shell. | ||||
| # The search path comes from a colon-separated `FPATH' variable.  It has no | ||||
| # default value and must be set by the user. | ||||
| # | ||||
| # Require uses `fpath_search', which works by scanning all of FPATH for a | ||||
| # file named the same as the required symbol but with a `.bash' appended to | ||||
| # the name.  If that is found, it is loaded.  If it is not, FPATH is | ||||
| # searched again for a file name the same as the feature (i.e. without any | ||||
| # extension).  Fpath_search may be useful for doing library filename | ||||
| # lookups in other functions (such as a `load' or `autoload' function). | ||||
| # | ||||
| # Warning: Because require ultimately uses the builtin `source' command to | ||||
| # read in files, it has no way of undoing the commands contained in the | ||||
| # file if there is an error or if no provide statement appeared (this | ||||
| # differs from the lisp implementation of require, which normally undoes | ||||
| # most of the forms that were loaded if the require fails).  Therefore, to | ||||
| # minize the number of problems caused by requiring a faulty package (such | ||||
| # as syntax errors in the source file) it is better to put the provide at | ||||
| # the end of the file, rather than at the beginning. | ||||
| 
 | ||||
| # Code: | ||||
| 
 | ||||
| # Exporting this variable would cause considerable lossage, since none of | ||||
| # the functions are exported (or at least, they're not guaranteed to be) | ||||
| export -n FEATURES | ||||
| 
 | ||||
| #:docstring : | ||||
| # Null function.  Provided only so that one can put page breaks in source | ||||
| # files without any ill effects. | ||||
| #:end docstring: | ||||
| # | ||||
| # (\\014 == C-l) | ||||
| eval "function $(echo -e \\014) () { : }" | ||||
| 
 | ||||
| 
 | ||||
| #:docstring featurep: | ||||
| # Usage: featurep argument | ||||
| # | ||||
| # Returns 0 (true) if argument is a provided feature.  Returns 1 (false) | ||||
| # otherwise.  | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function featurep () | ||||
| { | ||||
|     local feature="$1" | ||||
| 
 | ||||
|     case " ${FEATURES} " in | ||||
|        *" ${feature} "* ) return 0 ;; | ||||
|     esac | ||||
| 
 | ||||
|     return 1 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #:docstring provide: | ||||
| # Usage: provide symbol ... | ||||
| # | ||||
| # Register a list of symbols as provided features | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function provide () | ||||
| { | ||||
|     local feature | ||||
| 
 | ||||
|     for feature in "$@" ; do | ||||
|        if ! featurep "${feature}" ; then | ||||
|           FEATURES="${FEATURES} ${feature}" | ||||
|        fi | ||||
|     done | ||||
| 
 | ||||
|     return 0 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #:docstring require: | ||||
| # Usage: require feature {file} | ||||
| # | ||||
| # Load FEATURE if it is not already provided.  Note that require does not | ||||
| # call `provide' to register features.  The loaded file must do that | ||||
| # itself.  If the package does not explicitly do a `provide' after being | ||||
| # loaded, require will complain about the feature not being provided on | ||||
| # stderr. | ||||
| # | ||||
| # Optional argument FILE means to try to load FEATURE from FILE.  If no | ||||
| # file argument is given, require searches through FPATH (see fpath_search) | ||||
| # for the appropriate file. | ||||
| # | ||||
| # If the variable REQUIRE_FAILURE_FATAL is set, require will cause the | ||||
| # current shell invocation to exit, rather than merely return.  This may be | ||||
| # useful for a shell script that vitally depends on a package.  | ||||
| # | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function require () | ||||
| { | ||||
|  local feature="$1" | ||||
|  local path="$2" | ||||
|  local file | ||||
|   | ||||
|    if ! featurep "${feature}" ; then | ||||
|       file=$(fpath_search "${feature}" "${path}") && source "${file}" | ||||
| 
 | ||||
|       if ! featurep "${feature}" ; then | ||||
|          echo "require: ${feature}: feature was not provided." 1>&2 | ||||
|          if [ "${REQUIRE_FAILURE_FATAL+set}" = "set" ]; then | ||||
|             exit 1 | ||||
|          fi | ||||
|          return 1 | ||||
|       fi | ||||
|    fi | ||||
| 
 | ||||
|    return 0 | ||||
| } | ||||
| 
 | ||||
| #:docstring fpath_search: | ||||
| # Usage: fpath_search filename {path ...} | ||||
| # | ||||
| # Search $FPATH for `filename' or, if `path' (a list) is specified, search | ||||
| # those directories instead of $FPATH.  First the path is searched for an | ||||
| # occurrence of `filename.bash, then a second search is made for just | ||||
| # `filename'. | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function fpath_search () | ||||
| { | ||||
|  local name="$1" | ||||
|  local path="$2" | ||||
|  local suffix=".bash" | ||||
|  local file | ||||
| 
 | ||||
|     if [ -z "${path}" ]; then path="${FPATH}"; fi | ||||
| 
 | ||||
|     for file in "${name}${suffix}" "${name}" ; do | ||||
|        set -- $(IFS=':' | ||||
|                  set -- ${path} | ||||
|                  for p in "$@" ; do | ||||
|                     echo -n "${p:-.} " | ||||
|                  done) | ||||
| 
 | ||||
|        while [ $# -ne 0 ]; do | ||||
|           test -f "${1}/${file}" && { file="${1}/${file}"; break 2 } | ||||
|           shift | ||||
|        done | ||||
|     done | ||||
| 
 | ||||
|     if [ $# -eq 0 ]; then | ||||
|        echo "fpath_search: ${name}: file not found in fpath" 1>&2 | ||||
|        return 1 | ||||
|     fi | ||||
| 
 | ||||
|     echo "${file}" | ||||
|     return 0 | ||||
| } | ||||
| 
 | ||||
| provide require | ||||
| 
 | ||||
| # require.bash ends here | ||||
							
								
								
									
										140
									
								
								examples/scripts.noah/send_mail.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								examples/scripts.noah/send_mail.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,140 @@ | |||
| # send_mail.bash | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-07-02 | ||||
| # Public domain | ||||
| 
 | ||||
| # Commentary: | ||||
| 
 | ||||
| # TODO: implement Fcc headers (see emacs manual) | ||||
| 
 | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring send_mail: | ||||
| # Usage: send_mail | ||||
| # | ||||
| # This function serves as a simple replacement for sendmail as a client | ||||
| # interface on those systems where it is not available.  It does assume | ||||
| # that one can talk to an SMTP mailer on port 25 either on the local host | ||||
| # or on the host specified by the MAILHOST environment variable.  If you | ||||
| # have access to sendmail, it's better to use 'sendmail -t' instead of this | ||||
| # script (which probably isn't as robust). | ||||
| # | ||||
| # Message is read from stdin, and headers are parsed to determine | ||||
| # recipients.   | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function send_mail () | ||||
| { | ||||
|     # Need gawk, since several extensions are taken advantage of (like | ||||
|     # IGNORECASE for regexps). | ||||
|     local awk="${GAWK_LOCATION:-gawk}" | ||||
|     local DefaultFrom="${USER:-${LOGNAME}}" | ||||
|     local From | ||||
|     local To | ||||
|     local Cc | ||||
|     local Bcc | ||||
|     local tmpfile="/tmp/send_mail$$" | ||||
| 
 | ||||
|     while [ -e "${tmpfile}" ]; do | ||||
|        tmpfile="/tmp/send_mail${RANDOM}" | ||||
|     done | ||||
| 
 | ||||
|     # Lines consisting only of dots need one more dot appended.  SMTP | ||||
|     # servers eat one of the dots (and if only 1 dot appears, it signifies | ||||
|     # the end of the message). | ||||
|     sed '/^\.\.*/s/^\(\.\.*\)$/\1./' > "${tmpfile}" | ||||
| 
 | ||||
|     # Parse mail headers in message to extract recipients list.  | ||||
|     # This doesn't affect what the user sees---it's only used to generate | ||||
|     # the rcpt-to lines for SMTP.  | ||||
|     eval $(${awk} -f - "${tmpfile}" <<- '__EOF__' | ||||
|        # Try to extract email address from amidst random data | ||||
|        function parse_address (data) | ||||
|        { | ||||
|            # From: "real name" <foobar@host> | ||||
|            # From: "" <foobar@host> | ||||
|            if (match(data, /^\"[^\"]*\"[ \t]*<.*>/)) { | ||||
|               data_idx = match(data, /^\"[^\"]*\"[ \t]*</) | ||||
|               data = substr(data, RSTART + RLENGTH); | ||||
|               if (data_idx = match(data, ">.*")) | ||||
|                  data = substr(data, 1, RSTART - 1); | ||||
|               return data | ||||
|            } | ||||
|            # From: real name <foobar@host> | ||||
|            if (match(data, /<.*>/)) { | ||||
|               data_idx = match(data, /</) | ||||
|               data = substr(data, RSTART + RLENGTH); | ||||
|               if (data_idx = match(data, ">")) | ||||
|                  data = substr(data, 1, RSTART - 1); | ||||
|               return data | ||||
|            } | ||||
|            # From: foobar@host (real name) | ||||
|            if (match(data, /\(.*\)/)) { | ||||
|               data_idx = match(data, /\(/); | ||||
|               data = substr(data, 1, RSTART - 1); | ||||
|               return data | ||||
|            } | ||||
|            # (hopefully) From: foobar@host | ||||
|            return data | ||||
|        } | ||||
| 
 | ||||
|        BEGIN { IGNORECASE = 1; } | ||||
| 
 | ||||
|        # Blank line signifies end of headers, so we can stop looking. | ||||
|        /^$/ { exit(0) } | ||||
| 
 | ||||
|        /^from:|^to:|^cc:|^bcc:/ { | ||||
|           header_idx = match($0, /^[^:]*:/) | ||||
|           if (header_idx) { | ||||
|              # Capitalize header name | ||||
|              header_firstchar = toupper(substr($0, RSTART, 1)); | ||||
|              header_rest = tolower(substr($0, RSTART + 1, RLENGTH - 2)); | ||||
|              header = header_firstchar header_rest | ||||
| 
 | ||||
|              $0 = substr($0, RSTART + RLENGTH + 1); | ||||
|              addresses = "" | ||||
|              # parse addresses | ||||
|              while ($0) { | ||||
|                 # Strip leading whitespace | ||||
|                 if (idx = match($0, /[ \t]*/)) | ||||
|                    $0 = substr($0, RSTART + RLENGTH); | ||||
| 
 | ||||
|                 # Find everything up to a nonquoted comma | ||||
|                 # FIXME: doesnt handle quoting yet | ||||
|                 if (idx = match($0, /,/)) { | ||||
|                    data = substr($0, 1, RSTART); | ||||
|                    $0 = substr($0, RSTART + 1); | ||||
|                 } else { | ||||
|                    data = $0 | ||||
|                    $0 = "" | ||||
|                 } | ||||
|                 addresses = addresses " " parse_address(data) | ||||
|              } | ||||
| 
 | ||||
|              printf("%s='%s'\n", header, addresses); | ||||
|           } | ||||
|        } | ||||
| 	__EOF__) | ||||
| 
 | ||||
|     # Not sure if an address is *required* after the HELO.. every sendmail | ||||
|     # I tried talking to didn't seem to care.  Some sendmails don't care | ||||
|     # if there's a HELO at all.  | ||||
|     cat <<- __EOF__ | telnet ${MAILHOST:-localhost} 25 > /dev/null 2>&1 | ||||
| 	HELO | ||||
| 	mail from: ${From:-${DefaultFrom}} | ||||
| 	$(for name in ${To} ${Cc} ${Bcc} ; do | ||||
| 	     echo "rcpt to: ${name}" | ||||
| 	  done) | ||||
| 	data | ||||
| 	$(cat "${tmpfile}") | ||||
| 	. | ||||
| 	quit | ||||
| 	__EOF__ | ||||
| 
 | ||||
|     rm -f "${tmpfile}" | ||||
| } | ||||
| 
 | ||||
| provide send_mail | ||||
| 
 | ||||
| # send_mail.bash ends here | ||||
							
								
								
									
										49
									
								
								examples/scripts.noah/shcat.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								examples/scripts.noah/shcat.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | |||
| # shcat.bash | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-07-17 | ||||
| # Last modified: 1993-09-29 | ||||
| # Public domain | ||||
| 
 | ||||
| # Conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring shcat: | ||||
| # Usage: shcat {file1} {file2} {...} | ||||
| # | ||||
| # Like `cat', only this is all inline bash.  | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function shcat () | ||||
| { | ||||
|  local IFS="" | ||||
|  local line | ||||
|  local file | ||||
|  local exitstat=0 | ||||
|   | ||||
|     if [ $# -eq 0 ]; then | ||||
|        while read -r line; do | ||||
|           echo "${line}" | ||||
|        done | ||||
|        return 0 | ||||
|     else | ||||
|        for file in "$@" ; do | ||||
|           if [ -r "${file}" ]; then | ||||
|                while read -r line; do | ||||
|                   echo "${line}" | ||||
|                done < "${file}" | ||||
|           else | ||||
|              # This will cause the error to be printed on stderr | ||||
|              < "${file}" | ||||
|              exitstat=1 | ||||
|           fi | ||||
|        done | ||||
|        return ${exitstat} | ||||
|     fi | ||||
| } | ||||
| 
 | ||||
| provide shcat | ||||
| 
 | ||||
| # shcat.bash ends here | ||||
							
								
								
									
										63
									
								
								examples/scripts.noah/source.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								examples/scripts.noah/source.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| # source.bash | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-05-17 | ||||
| # Last modified: 1993-09-29 | ||||
| # Public domain | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring source: | ||||
| # Usage: source file ... | ||||
| # | ||||
| # Source forces file arguments to be considered in the current directory | ||||
| # only, unless there is an absolute path starting with `/'.  I think it's | ||||
| # bad that the builtin "source" searches PATH, because PATH normally | ||||
| # contains directories with binary files that aren't useful for bash to | ||||
| # read and most people don't put "." first in their path. | ||||
| # | ||||
| # This "source" is capable of reading more than one file at a time.  Return | ||||
| # value is number of failed source attempts. | ||||
| #:end docstring: | ||||
| 
 | ||||
| # This function is not hygienic, but there's not much we can do about | ||||
| # variable name conflicts here. | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function source () | ||||
| { | ||||
|     local -i _source_failure_count=0 | ||||
|     local _source_file | ||||
|   | ||||
|     for _source_file ; do | ||||
|        # Check first part of each filename.  If it's not `/', `./', or | ||||
|        # `../' then prepend "./" to the path to force the builtin `source' | ||||
|        # not to go searching through PATH to find the file. | ||||
|        case "${_source_file}" in | ||||
|           /*|./*|../* ) ;; | ||||
|           * ) _source_file="./${_source_file}" ;; | ||||
|        esac   | ||||
| 
 | ||||
|        builtin source "${_source_file}" ||  | ||||
|          _source_failure_count="_source_failure_count + 1" | ||||
| 
 | ||||
|     done | ||||
| 
 | ||||
|     return ${_source_failure_count} | ||||
| } | ||||
| 
 | ||||
| #:docstring .: | ||||
| # See "source" | ||||
| #:end docstring: | ||||
| 
 | ||||
| # So that `.' will call function definition of `source' instead of builtin | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function . () | ||||
| { | ||||
|     source "$@" | ||||
| } | ||||
| 
 | ||||
| provide source | ||||
| 
 | ||||
| # source.bash ends here | ||||
							
								
								
									
										226
									
								
								examples/scripts.noah/string.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								examples/scripts.noah/string.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,226 @@ | |||
| # string.bash --- bash emulation of string(3) library routines | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-07-01 | ||||
| # Last modified: 1993-09-29 | ||||
| # Public domain | ||||
| 
 | ||||
| # Conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring strcat: | ||||
| # Usage: strcat s1 s2 | ||||
| # | ||||
| # Strcat appends the value of variable s2 to variable s1.  | ||||
| # | ||||
| # Example: | ||||
| #    a="foo" | ||||
| #    b="bar" | ||||
| #    strcat a b | ||||
| #    echo $a | ||||
| #    => foobar | ||||
| # | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function strcat () | ||||
| { | ||||
|     local s1_val s2_val | ||||
| 
 | ||||
|     s1_val=${!1}			# indirect variable expansion | ||||
|     s2_val=${!2} | ||||
|     eval "$1"=\'"${s1_val}${s2_val}"\' | ||||
| } | ||||
| 
 | ||||
| #:docstring strncat: | ||||
| # Usage: strncat s1 s2 $n | ||||
| #  | ||||
| # Line strcat, but strncat appends a maximum of n characters from the value | ||||
| # of variable s2.  It copies fewer if the value of variabl s2 is shorter | ||||
| # than n characters.  Echoes result on stdout. | ||||
| # | ||||
| # Example: | ||||
| #    a=foo | ||||
| #    b=barbaz | ||||
| #    strncat a b 3 | ||||
| #    echo $a | ||||
| #    => foobar | ||||
| # | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function strncat () | ||||
| { | ||||
|     local s1="$1" | ||||
|     local s2="$2" | ||||
|     local -i n="$3" | ||||
|     local s1_val s2_val | ||||
| 
 | ||||
|     s1_val=${!s1}			# indirect variable expansion | ||||
|     s2_val=${!s2} | ||||
| 
 | ||||
|     if [ ${#s2_val} -gt ${n} ]; then | ||||
|        s2_val=${s2_val:0:$n}		# substring extraction | ||||
|     fi | ||||
| 
 | ||||
|     eval "$s1"=\'"${s1_val}${s2_val}"\' | ||||
| } | ||||
| 
 | ||||
| #:docstring strcmp: | ||||
| # Usage: strcmp $s1 $s2 | ||||
| # | ||||
| # Strcmp compares its arguments and returns an integer less than, equal to, | ||||
| # or greater than zero, depending on whether string s1 is lexicographically | ||||
| # less than, equal to, or greater than string s2. | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function strcmp () | ||||
| { | ||||
|     [ "$1" = "$2" ] && return 0 | ||||
| 
 | ||||
|     [ "${1}" '<' "${2}" ] > /dev/null && return -1 | ||||
| 
 | ||||
|     return 1 | ||||
| } | ||||
| 
 | ||||
| #:docstring strncmp: | ||||
| # Usage: strncmp $s1 $s2 $n | ||||
| #  | ||||
| # Like strcmp, but makes the comparison by examining a maximum of n | ||||
| # characters (n less than or equal to zero yields equality). | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function strncmp () | ||||
| { | ||||
|     if [ -z "${3}" -o "${3}" -le "0" ]; then | ||||
|        return 0 | ||||
|     fi | ||||
|     | ||||
|     if [ ${3} -ge ${#1} -a ${3} -ge ${#2} ]; then | ||||
|        strcmp "$1" "$2" | ||||
|        return $? | ||||
|     else | ||||
|        s1=${1:0:$3} | ||||
|        s2=${2:0:$3} | ||||
|        strcmp $s1 $s2 | ||||
|        return $? | ||||
|     fi | ||||
| } | ||||
| 
 | ||||
| #:docstring strlen: | ||||
| # Usage: strlen s | ||||
| # | ||||
| # Strlen returns the number of characters in string literal s. | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function strlen () | ||||
| { | ||||
|     eval echo "\${#${1}}" | ||||
| } | ||||
| 
 | ||||
| #:docstring strspn: | ||||
| # Usage: strspn $s1 $s2 | ||||
| #  | ||||
| # Strspn returns the length of the maximum initial segment of string s1, | ||||
| # which consists entirely of characters from string s2. | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function strspn () | ||||
| { | ||||
|     # Unsetting IFS allows whitespace to be handled as normal chars.  | ||||
|     local IFS= | ||||
|     local result="${1%%[!${2}]*}" | ||||
|   | ||||
|     echo ${#result} | ||||
| } | ||||
| 
 | ||||
| #:docstring strcspn: | ||||
| # Usage: strcspn $s1 $s2 | ||||
| # | ||||
| # Strcspn returns the length of the maximum initial segment of string s1, | ||||
| # which consists entirely of characters not from string s2. | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function strcspn () | ||||
| { | ||||
|     # Unsetting IFS allows whitspace to be handled as normal chars.  | ||||
|     local IFS= | ||||
|     local result="${1%%[${2}]*}" | ||||
|   | ||||
|     echo ${#result} | ||||
| } | ||||
| 
 | ||||
| #:docstring strstr: | ||||
| # Usage: strstr s1 s2 | ||||
| #  | ||||
| # Strstr echoes a substring starting at the first occurrence of string s2 in | ||||
| # string s1, or nothing if s2 does not occur in the string.  If s2 points to | ||||
| # a string of zero length, strstr echoes s1. | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function strstr () | ||||
| { | ||||
|     # if s2 points to a string of zero length, strstr echoes s1 | ||||
|     [ ${#2} -eq 0 ] && { echo "$1" ; return 0; } | ||||
| 
 | ||||
|     # strstr echoes nothing if s2 does not occur in s1 | ||||
|     case "$1" in | ||||
|     *$2*) ;; | ||||
|     *) return 1;; | ||||
|     esac | ||||
| 
 | ||||
|     # use the pattern matching code to strip off the match and everything | ||||
|     # following it | ||||
|     first=${1/$2*/} | ||||
| 
 | ||||
|     # then strip off the first unmatched portion of the string | ||||
|     echo "${1##$first}" | ||||
| } | ||||
| 
 | ||||
| #:docstring strtok: | ||||
| # Usage: strtok s1 s2 | ||||
| # | ||||
| # Strtok considers the string s1 to consist of a sequence of zero or more | ||||
| # text tokens separated by spans of one or more characters from the | ||||
| # separator string s2.  The first call (with a non-empty string s1 | ||||
| # specified) echoes a string consisting of the first token on stdout. The | ||||
| # function keeps track of its position in the string s1 between separate | ||||
| # calls, so that subsequent calls made with the first argument an empty | ||||
| # string will work through the string immediately following that token.  In | ||||
| # this way subsequent calls will work through the string s1 until no tokens | ||||
| # remain.  The separator string s2 may be different from call to call. | ||||
| # When no token remains in s1, an empty value is echoed on stdout. | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function strtok () | ||||
| { | ||||
|  : | ||||
| } | ||||
| 
 | ||||
| #:docstring strtrunc: | ||||
| # Usage: strtrunc $n $s1 {$s2} {$...} | ||||
| # | ||||
| # Used by many functions like strncmp to truncate arguments for comparison. | ||||
| # Echoes the first n characters of each string s1 s2 ... on stdout.  | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function strtrunc () | ||||
| { | ||||
|     n=$1 ; shift | ||||
|     for z; do | ||||
| 	echo "${z:0:$n}" | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| provide string | ||||
| 
 | ||||
| # string.bash ends here | ||||
							
								
								
									
										64
									
								
								examples/scripts.noah/stty.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								examples/scripts.noah/stty.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | |||
| # stty.bash | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-01-11 | ||||
| # Last modified: 1993-09-29 | ||||
| # Public domain | ||||
| 
 | ||||
| # Conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| require remap_keybindings | ||||
| 
 | ||||
| #:docstring stty: | ||||
| # Track changes to certain keybindings with stty, and make those changes | ||||
| # reflect in bash's readline bindings as well.  | ||||
| # | ||||
| # This requires bash version 1.10 or newer, since previous versions did not | ||||
| # implement the `bind' builtin. | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function stty () | ||||
| { | ||||
|     local erase="backward-delete-char" | ||||
|     local kill="unix-line-discard" | ||||
|     local werase="backward-kill-word" | ||||
|     local lnext="quoted-insert" | ||||
|     local readline_function="" | ||||
|     local key="" | ||||
|     local stty_command="" | ||||
| 
 | ||||
|     while [ $# -gt 0 ]; do | ||||
|        case "$1" in | ||||
|           erase | kill | werase | lnext ) | ||||
|              key=$(echo "${2}" | cat -v | sed 's/\^/\\C-/') | ||||
|              readline_function=$(eval echo \$${1}) | ||||
| 
 | ||||
|              # Get rid of any current bindings; the whole point of this | ||||
|              # function is to make the distinction between readline | ||||
|              # bindings and particular cbreak characters transparent; old | ||||
|              # readline keybindings shouldn't hang around. | ||||
| 	     # could use bind -r here instead of binding to self-insert | ||||
|              remap_keybindings "${readline_function}" "self-insert" | ||||
|               | ||||
|              # Bind new key to appropriate readline function | ||||
|              bind "\"${key}\": ${readline_function}" | ||||
| 
 | ||||
|              stty_command="${stty_command} ${1} ${2}" | ||||
|              shift 2 | ||||
|             ;; | ||||
|           *) | ||||
|              stty_command="${stty_command} ${1}" | ||||
|              shift | ||||
|             ;; | ||||
|        esac | ||||
|     done | ||||
| 
 | ||||
|     command stty ${stty_command} | ||||
| } | ||||
| 
 | ||||
| provide stty | ||||
| 
 | ||||
| # stty.bash ends here | ||||
							
								
								
									
										78
									
								
								examples/scripts.noah/y_or_n_p.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								examples/scripts.noah/y_or_n_p.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,78 @@ | |||
| # y_or_n_p.bash | ||||
| # Author: Noah Friedman <friedman@prep.ai.mit.edu> | ||||
| # Created: 1992-06-18 | ||||
| # Last modified: 1993-03-01 | ||||
| # Public domain | ||||
| 
 | ||||
| # Conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| # Commentary: | ||||
| # Code: | ||||
| 
 | ||||
| #:docstring y_or_n_p: | ||||
| # Usage: y_or_n_p QUERY | ||||
| # | ||||
| # Print QUERY on stderr, then read stdin for a y-or-n response.  Actually, | ||||
| # user may type anything they like, but first character must be a `y', `n', | ||||
| # `q', or `!', otherwise the question is repeated until such an answer is | ||||
| # obtained.   | ||||
| # | ||||
| # If user typed `y', y_or_n_p returns 0. | ||||
| # | ||||
| # If user typed `n', y_or_n_p returns 1. | ||||
| # | ||||
| # If user typed `!', y_or_n_p returns 2.  This is an indication to the | ||||
| #  caller that no more queries should be made.  Assume `y' for all the rest.  | ||||
| # | ||||
| # If user typed `q', y_or_n_p returns 3.  This is an indication to the | ||||
| #  caller that no more queries should be made.  Assume `n' for all the rest. | ||||
| # | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function y_or_n_p () | ||||
| { | ||||
|  local ans | ||||
| 
 | ||||
|     [ ! -t 0 ] && return 1 | ||||
| 
 | ||||
|     while read -p "$*" -e ans ; do | ||||
| 	case "${ans}" in | ||||
|         y* | Y* ) return 0 ;; | ||||
|         n* | N* ) return 1 ;; | ||||
|         \! )      return 2 ;; | ||||
|         q* | Q* ) return 3 ;; | ||||
|         *) echo "Please answer one of \`y', \`n', \`q', or \`"\!"'" 1>&2 ;; | ||||
| 	esac | ||||
|    done | ||||
| } | ||||
| 
 | ||||
| #:docstring yes_or_no_p: | ||||
| # Usage: yes_or_no_p QUERY | ||||
| # | ||||
| # Like y_or_n_p, but require a full `yes', `no', `yes!', or `quit' response.  | ||||
| #:end docstring: | ||||
| 
 | ||||
| ###;;;autoload | ||||
| function yes_or_no_p () | ||||
| { | ||||
|     local ans | ||||
| 
 | ||||
|     [ ! -t 0 ] && return 3 | ||||
| 
 | ||||
|     while read -p "$*" -e ans; do | ||||
|         ans="$(echo ${ans} | tr '[A-Z]' '[a-z]')" | ||||
| 
 | ||||
|         case "${ans}" in | ||||
|         yes )   return 0 ;; | ||||
|         no )    return 1 ;; | ||||
|         yes\! ) return 2 ;; | ||||
|         quit )  return 3 ;; | ||||
|         *) echo "Please answer \`yes', \`no', \`yes"\!"', or \`quit'" 1>&2 ;; | ||||
|        esac | ||||
|    done | ||||
| } | ||||
| 
 | ||||
| provide y_or_n_p | ||||
| 
 | ||||
| # y_or_n_p.bash ends here | ||||
							
								
								
									
										59
									
								
								examples/scripts.v2/PERMISSION
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								examples/scripts.v2/PERMISSION
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| From spcecdt@armory.com Wed May 10 10:21:11 1995 | ||||
| Flags: 10 | ||||
| Return-Path: spcecdt@armory.com | ||||
| Received: from po.cwru.edu (root@po.CWRU.Edu [129.22.4.2]) by odin.INS.CWRU.Edu with ESMTP (8.6.10+cwru/CWRU-2.1-ins) | ||||
| 	id KAA22876; Wed, 10 May 1995 10:21:10 -0400 (from spcecdt@armory.com for <chet@odin.INS.CWRU.Edu>) | ||||
| Received: from deepthought.armory.com (mmdf@deepthought.armory.com [192.122.209.42]) by po.cwru.edu with SMTP (8.6.10+cwru/CWRU-2.3) | ||||
| 	id BAA16354; Wed, 10 May 1995 01:33:22 -0400 (from spcecdt@armory.com for <chet@po.cwru.edu>) | ||||
| From: John DuBois <spcecdt@armory.com> | ||||
| Date: Tue, 9 May 1995 22:33:12 -0700 | ||||
| In-Reply-To: Chet Ramey <chet@odin.ins.cwru.edu> | ||||
|        "ksh scripts" (May  9,  1:36pm) | ||||
| X-Www: http://www.armory.com/~spcecdt/ | ||||
| X-Mailer: Mail User's Shell (7.2.5 10/14/92) | ||||
| To: chet@po.cwru.edu | ||||
| Subject: Re: ksh scripts | ||||
| Message-ID:  <9505092233.aa13001@deepthought.armory.com> | ||||
| 
 | ||||
|      Sure.  The canonical versions are available on ftp.armory.com; you might | ||||
| want to pick up the latest versions before modifying them. | ||||
| 
 | ||||
|         John | ||||
| 
 | ||||
| On May 9,  1:36pm, Chet Ramey wrote: | ||||
| } Subject: ksh scripts | ||||
| } From odin.ins.cwru.edu!chet Tue May  9 10:39:51 1995 | ||||
| } Received: from odin.INS.CWRU.Edu by deepthought.armory.com id aa22336; | ||||
| }           9 May 95 10:39 PDT | ||||
| } Received: (chet@localhost) by odin.INS.CWRU.Edu (8.6.10+cwru/CWRU-2.1-ins) | ||||
| } 	id NAA20487; Tue, 9 May 1995 13:39:24 -0400 (from chet) | ||||
| } Date: Tue, 9 May 1995 13:36:54 -0400 | ||||
| } From: Chet Ramey <chet@odin.ins.cwru.edu> | ||||
| } To: john@armory.com | ||||
| } Subject: ksh scripts | ||||
| } Cc: chet@odin.ins.cwru.edu | ||||
| } Reply-To: chet@po.cwru.edu | ||||
| } Message-ID: <9505091736.AA20411.SM@odin.INS.CWRU.Edu> | ||||
| } Read-Receipt-To: chet@po.CWRU.Edu | ||||
| } MIME-Version: 1.0 | ||||
| } Content-Type: text/plain; charset=us-ascii | ||||
| } Status: OR | ||||
| }  | ||||
| } Hi.  I'm the maintainer of bash (the GNU `Bourne Again shell') for | ||||
| } the FSF. | ||||
| }  | ||||
| } I picked up a tar file of ksh scripts you wrote from an anon FTP site | ||||
| } a while back.  I'd like your permission to include modified versions | ||||
| } of some of them in the next major bash distribution (with proper credit | ||||
| } given, of course).  Is it OK if I do that? | ||||
| }  | ||||
| } Chet Ramey | ||||
| }  | ||||
| } --  | ||||
| } ``The lyf so short, the craft so long to lerne.'' - Chaucer | ||||
| }  | ||||
| } Chet Ramey, Case Western Reserve University	Internet: chet@po.CWRU.Edu | ||||
| }-- End of excerpt from Chet Ramey | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										33
									
								
								examples/scripts.v2/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								examples/scripts.v2/README
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| This collection of scripts was originally written for ksh-88 by | ||||
| John DuBois <spcecdt@armory.com>.  The conversion to bash v2 | ||||
| syntax was done by Chet Ramey. | ||||
| 
 | ||||
| These scripts are as-is; there is no copyright associated with | ||||
| any of them.  They exist simply as examples of bash scripting. | ||||
| 
 | ||||
| Here's a description of what's in this directory: | ||||
| 
 | ||||
| arc2tarz   Convert an "arc" archive to a compressed tar archive. | ||||
| corename   Tell what produced a core file. | ||||
| fman       Fast man replacement. | ||||
| frcp       Copy files using ftp but with rcp-type command line syntax. | ||||
| lowercase  Change filenames to lower case. | ||||
| ncp        A nicer front end for cp (has -i, etc.). | ||||
| newext     Change the extension of a group of files. | ||||
| nmv        A nicer front end for mv (has -i, etc.). | ||||
| pages      Print specified pages from files. | ||||
| pf         A pager front end that handles compressed files. | ||||
| rename     Change the names of files that match a pattern. | ||||
| repeat     Execute a command multiple times. | ||||
| untar      Unarchive a (possibly compressed) tarfile into a directory. | ||||
| uudec      Carefully uudecode multiple files. | ||||
| uuenc      uuencode multiple files. | ||||
| vtree      Print a visual display of a directory tree. | ||||
| where      Show where commands that match a pattern are. | ||||
| 
 | ||||
| The following scripts were written or converted by Chet Ramey: | ||||
| 
 | ||||
| bashrand   Random number generator with upper and lower bounds and optional seed | ||||
| cdhist     cd replacement with a directory stack added | ||||
| pmtop	   Poor man's `top' for SunOS 4.x and BSD/OS | ||||
| shprof     Line profiler for bash scripts | ||||
							
								
								
									
										85
									
								
								examples/scripts.v2/arc2tarz
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								examples/scripts.v2/arc2tarz
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,85 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # arc2tarz: convert arced file to tarred, compressed form. | ||||
| # @(#) arc2tarz.ksh 1.0 92/02/16 | ||||
| # 91/03/28 john h. dubois iii (john@armory.com) | ||||
| # 92/02/16 added -h option for help | ||||
| # | ||||
| # conversion to bash v2 syntax by Chet Ramey | ||||
| 
 | ||||
| unset ENV | ||||
| Usage="Usage: $0 arcfile [-hcg] [ tarzfile ]" | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo "$Usage | ||||
| arcfile is the name of an arc file to convert to tarred, compressed form.  | ||||
| The file must have a .arc extension, but only the base name needs to be | ||||
| given.  If no output file name is given, it will be created in the current | ||||
| directory with the name being the arcfile basename followed by .tar.EXT. | ||||
| If the -c option is given, compress will be used, and EXT will be Z. | ||||
| The default (also available with -g) is to use gzip, in which case EXT | ||||
| is gz.  If the basename is too long the extension may be truncated.  All | ||||
| uppercase letters in the names of files in the archive are moved to lowercase." | ||||
| } | ||||
| 
 | ||||
| compress=gzip | ||||
| ext=gz | ||||
| 
 | ||||
| while getopts "hcg" opt; do | ||||
| 	case "$opt" in | ||||
| 	h)	phelp; exit 0;; | ||||
| 	c)	compress=compress; ext=Z;; | ||||
| 	g)	compress=gzip ; ext=gz ;; | ||||
| 	*)	echo "$Usage" 1>&2 ; exit 2;; | ||||
| 	esac | ||||
| done | ||||
| 
 | ||||
| shift $((OPTIND - 1)) | ||||
| 
 | ||||
| if [ $# = 0 ]; then | ||||
| 	phelp | ||||
| 	exit 0 | ||||
| fi | ||||
| 
 | ||||
| [ -z "$TMP" ] && tmpdir=/tmp/arc2tarz.$$ || tmpdir=$TMP/arc2tarz.$$ | ||||
| 
 | ||||
| case "$1" in | ||||
| *.arc)	arcfile=$1 ;; | ||||
| *)	arcfile=$1.arc ;; | ||||
| esac | ||||
| 
 | ||||
| if [ ! -f $arcfile ] || [ ! -r $arcfile ]; then | ||||
| 	echo "Could not open arc file \"$arcfile\"." | ||||
| 	exit 1 | ||||
| fi | ||||
| 
 | ||||
| case "$arcfile" in | ||||
| /*)	;; | ||||
| *)	arcfile=$PWD/$arcfile ;; | ||||
| esac | ||||
| 
 | ||||
| basename=${arcfile%.arc} | ||||
| basename=${basename##*/} | ||||
| [ $# -lt 2 ] && tarzname=$PWD/$basename.tar.$ext || tarzname=$2 | ||||
| 
 | ||||
| trap 'rm -rf $tmpdir $tarzname' 1 2 3 6 15 | ||||
| 
 | ||||
| mkdir $tmpdir | ||||
| cd $tmpdir | ||||
| echo "unarcing files..." | ||||
| arc -ie $arcfile | ||||
| 
 | ||||
| # lowercase | ||||
| for f in *; do | ||||
| 	new=$(echo $f | tr A-Z a-z) | ||||
| 	if [ "$f" != "$new" ]; then | ||||
| 		mv $f $new | ||||
| 	fi | ||||
| done | ||||
| 
 | ||||
| echo "tarring/compressing files..." | ||||
| tar cf - * | $compress > $tarzname | ||||
| cd - | ||||
| rm -rf $tmpdir | ||||
							
								
								
									
										76
									
								
								examples/scripts.v2/bashrand
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								examples/scripts.v2/bashrand
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,76 @@ | |||
| #! /bin/bash | ||||
| # bashrand - generate a random number in a specified range with an | ||||
| #	     optionally specified ``seed'' value. | ||||
| # | ||||
| # Original Author: Peter Turnbull, May 1993 | ||||
| 
 | ||||
| usage() | ||||
| { | ||||
| 	echo "$PROG: usage: $PROG [-s seed] lower-limit upper-limit" >&2 | ||||
| } | ||||
| 
 | ||||
| PROG=${0##*/} | ||||
| 
 | ||||
| SEED=$$         # Initialize random-number seed value with PID | ||||
| 
 | ||||
| while getopts s: opt | ||||
| do | ||||
| 	case "$opt" in | ||||
| 	s)	SEED=$OPTARG ;; | ||||
| 	*)	usage ; exit 2 ;; | ||||
| 	esac | ||||
| done | ||||
| 
 | ||||
| shift $((OPTIND - 1)) | ||||
| 
 | ||||
| # Process command-line arguments: | ||||
| case $# in | ||||
|     2)  Lower=$1; Upper=$2 ;; | ||||
|     *)  usage ; exit 2 ;; | ||||
| esac | ||||
| 
 | ||||
| # Check that specified values are integers: | ||||
| expr "$Lower" + 0 >/dev/null 2>&1 || { | ||||
| 	echo "$PROG: lower ($Lower) not an integer" >&2 | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| expr "$Upper" + 0 >/dev/null 2>&1 || { | ||||
| 	echo "$PROG: upper ($Upper) not an integer" >&2 | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| expr "$SEED" + 0 >/dev/null 2>&1 || { | ||||
| 	echo "$PROG: seed ($SEED) not an integer" >&2 | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| # Check that values are in the correct range: | ||||
| (( $Lower < 0 )) || [ `expr "$Lower" : '.*'` -gt 5 ] && { | ||||
| 	echo "$PROG: Lower limit ($Lower) out of range" >&2 | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| (( $Upper > 32767 )) || [ `expr "$Upper" : '.*'` -gt 5 ] && { | ||||
| 	echo "$PROG: Upper limit ($Upper) out of range" >&2; | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| (( $SEED < 0 )) || (( $SEED > 32767 )) || [ `expr "$SEED" : '.*'` -gt 5 ] && { | ||||
| 	echo "$PROG: Seed value ($SEED) out of range (0 to 32767)" >&2 | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| (( $Upper <= $Lower )) && { | ||||
| 	echo "$PROG: upper ($Upper) <= lower value ($Lower)" >&2 | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| # Seed the random-number generator: | ||||
| RANDOM=$SEED | ||||
| 
 | ||||
| # Compute value, scaled within range: | ||||
| let rand="$RANDOM % ($Upper - $Lower + 1) + $Lower" | ||||
| 
 | ||||
| # Report result: | ||||
| echo $rand | ||||
							
								
								
									
										176
									
								
								examples/scripts.v2/cdhist.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								examples/scripts.v2/cdhist.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,176 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # cdhist - cd replacement with a directory stack like pushd/popd | ||||
| # | ||||
| # usage: cd [-l] [-n] [-] [dir] | ||||
| # | ||||
| # options: | ||||
| #	-l	print the cd directory stack, one entry per line | ||||
| #	-	equivalent to $OLDPWD | ||||
| #	-n	cd to nth directory in cd directory stack | ||||
| #	-s	cd to first directory in stack matching (substring) `s' | ||||
| # | ||||
| # arguments: | ||||
| #	dir	cd to dir and push dir onto the cd directory stack | ||||
| # | ||||
| # If the new directory is a directory in the stack and the options selected | ||||
| # it (-n, -s), the new working directory is printed | ||||
| # | ||||
| # If the variable CDHISTFILE is set, the cd directory stack is loaded from | ||||
| # and written to $CDHISTFILE every time `cd' is executed. | ||||
| # | ||||
| # Note: I got this off the net somewhere; I don't know the original author | ||||
| # | ||||
| # Chet Ramey | ||||
| # chet@po.cwru.edu	 | ||||
| 
 | ||||
| _cd_print() | ||||
| { | ||||
| 	echo -e "$@" | ||||
| } | ||||
| 
 | ||||
| cd() | ||||
| { | ||||
| 	typeset -i cdlen i | ||||
| 	typeset t | ||||
| 	 | ||||
| 	if [ $# -eq 0 ] | ||||
| 	then | ||||
| 		set -- $HOME | ||||
| 	fi | ||||
| 	 | ||||
| 	if [ "$CDHISTFILE" -a -r "$CDHISTFILE" ] # if directory history exists | ||||
| 	then | ||||
| 		typeset CDHIST | ||||
| 		i=-1 | ||||
| 		while read -r t			# read directory history file | ||||
| 		do | ||||
| 			CDHIST[i=i+1]=$t | ||||
| 		done <$CDHISTFILE | ||||
| 	fi | ||||
| 	 | ||||
| 	if [ "${CDHIST[0]}" != "$PWD" -a "$PWD" != "" ] | ||||
| 	then | ||||
| 		_cdins				# insert $PWD into cd history | ||||
| 	fi | ||||
| 	 | ||||
| 	cdlen=${#CDHIST[*]}			# number of elements in history | ||||
| 	 | ||||
| 	case "$@" in | ||||
| 	-)					# cd to new dir | ||||
| 		if [ "$OLDPWD" = "" ] && ((cdlen>1)) | ||||
| 		then | ||||
| 			'_cdprint' ${CDHIST[1]} | ||||
| 			builtin cd ${CDHIST[1]} | ||||
| 			pwd | ||||
| 		else | ||||
| 			builtin cd "$@" | ||||
| 			# pwd | ||||
| 		fi | ||||
| 		;; | ||||
| 	-l)					# _cdprint directory list | ||||
| 		((i=cdlen)) | ||||
| 		while (((i=i-1)>=0)) | ||||
| 		do | ||||
| 			num=$i | ||||
| 			'_cdprint' "$num ${CDHIST[i]}" | ||||
| 		done | ||||
| 		return | ||||
| 		;; | ||||
| 	-[0-9]|-[0-9][0-9])			# cd to dir in list | ||||
| 		if (((i=${1#-})<cdlen)) | ||||
| 		then | ||||
| 			'_cdprint' ${CDHIST[i]} | ||||
| 			builtin cd ${CDHIST[i]} | ||||
| 			pwd | ||||
| 		else | ||||
| 			builtin cd $@ | ||||
| 			# pwd | ||||
| 		fi | ||||
| 		;; | ||||
| 	-*)					# cd to matched dir in list | ||||
| 		t=${1#-} | ||||
| 		i=1 | ||||
| 		while ((i<cdlen)) | ||||
| 		do | ||||
| 			case ${CDHIST[i]} in | ||||
| 			*$t*) | ||||
| 				'_cdprint' ${CDHIST[i]} | ||||
| 				builtin cd ${CDHIST[i]} | ||||
| 				pwd | ||||
| 				break | ||||
| 				;; | ||||
| 			esac | ||||
| 			((i=i+1)) | ||||
| 		done | ||||
| 		if ((i>=cdlen)) | ||||
| 		then | ||||
| 			builtin cd $@ | ||||
| 			# pwd | ||||
| 		fi | ||||
| 		;; | ||||
| 	*)					# cd to new dir | ||||
| 		builtin cd $@ | ||||
| 		# pwd | ||||
| 		;; | ||||
| 	esac | ||||
| 
 | ||||
| 	_cdins					# insert $PWD into cd history | ||||
| 	 | ||||
| 	if [ "$CDHISTFILE" ] | ||||
| 	then | ||||
| 		cdlen=${#CDHIST[*]}		# number of elements in history | ||||
| 
 | ||||
| 		i=0 | ||||
| 		while ((i<cdlen)) | ||||
| 		do | ||||
| 			echo ${CDHIST[i]}	# update directory history | ||||
| 			((i=i+1)) | ||||
| 		done >$CDHISTFILE | ||||
| 	fi | ||||
| } | ||||
| 	 | ||||
| _cdins()					# insert $PWD into cd history | ||||
| {						# meant to be called only by cd | ||||
| 	typeset -i i | ||||
| 
 | ||||
| 	i=0 | ||||
| 
 | ||||
| 	while (( i < ${#CDHIST[*]} ))		# see if dir is already in list | ||||
| 	do | ||||
| 		if [ "${CDHIST[$i]}" = "$PWD" ] | ||||
| 		then | ||||
| 			break | ||||
| 		fi | ||||
| 		((i=i+1)) | ||||
| 	done | ||||
| 
 | ||||
| 	if (( i>22 ))				# limit max size of list | ||||
| 	then | ||||
| 		i=22 | ||||
| 	fi | ||||
| 
 | ||||
| 	while (((i=i-1)>=0))			# bump old dirs in list | ||||
| 	do | ||||
| 		CDHIST[i+1]=${CDHIST[i]} | ||||
| 	done | ||||
| 
 | ||||
| 	CDHIST[0]=$PWD				# insert new directory in list | ||||
| } | ||||
| 	 | ||||
| # examples | ||||
| shopt -s expand_aliases | ||||
| 
 | ||||
| # go to known place before doing anything | ||||
| cd / | ||||
| 
 | ||||
| echo CDHIST: "${CDHIST[@]}" | ||||
| for dir in /tmp /bin - -2 -l | ||||
| do | ||||
| 	cd $dir | ||||
| 	echo CDHIST: "${CDHIST[@]}" | ||||
| 	echo PWD: $PWD | ||||
| 
 | ||||
| done | ||||
| 
 | ||||
| exit 0 | ||||
							
								
								
									
										43
									
								
								examples/scripts.v2/corename
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								examples/scripts.v2/corename
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # @(#) corename.ksh 1.0 93/04/01 | ||||
| # 92/11/11 john h. dubois iii (john@armory.com) | ||||
| # 92/02/16 Added help option. | ||||
| # 92/02/22 Added cd to origdir to fix prob w/multiple relative paths. | ||||
| # 93/04/01 Added check for whether file exists. | ||||
| # | ||||
| # conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| # inspired by belal's equivalent utility | ||||
| 
 | ||||
| if [ "$1" = -h ]; then | ||||
|     echo \ | ||||
| "$0: print the names of executables that dumped core. | ||||
| Usage: $0 [corename ...] | ||||
| If no corename is given, \"core\" is assumed." | ||||
|     exit 0 | ||||
| fi | ||||
| 
 | ||||
| [ $# = 0 ] && set core | ||||
| origdir=$PWD | ||||
| for i; do | ||||
|     cd $origdir | ||||
|     file=${i##*/} | ||||
|     dir=${i%$file} | ||||
|     [ -z "$dir" ] && dir=$origdir/ | ||||
|     if [ ! -f $dir$file ]; then | ||||
| 	echo "$dir$file: No such file." | ||||
| 	continue | ||||
|     fi | ||||
|     if [ ! -r $dir$file ]; then | ||||
| 	echo "$dir$file: Cannot open." | ||||
| 	continue | ||||
|     fi | ||||
|     cd $dir | ||||
| 
 | ||||
|     # the adb output syntax is highly variable.  this works on SunOS 4.x | ||||
|     set -- $(adb $file < /dev/null 2>&1 | sed 1q) | ||||
|     name=${7#??} | ||||
|     echo "$i: ${name%??}" | ||||
| done | ||||
							
								
								
									
										281
									
								
								examples/scripts.v2/fman
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								examples/scripts.v2/fman
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,281 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # fman: new man program | ||||
| # @(#) fman.ksh 1.5 94/04/16 | ||||
| # 91/07/03 john h. dubois iii (john@armory.com) | ||||
| # 91/07/11 made it unpack man pages if neccessary | ||||
| # 91/07/16 fixed test for whether man file pattern was expanded | ||||
| # 92/01/21 made it read /etc/default/man to get section order, | ||||
| #          and only display the first section found. | ||||
| # 92/02/06 changed name to fman | ||||
| # 92/02/07 fixed bug in notfound | ||||
| # 92/02/13 incorporated changes from DOS version | ||||
| # 92/03/11 changed to use MANPATH from environment if set, | ||||
| #          and search all directories given in MANPATH | ||||
| # 92/03/15 exec pager or man w/o forking | ||||
| # 92/05/31 try using index if one exists | ||||
| # 92/10/01 Added "See also <other sections>" | ||||
| # 92/10/18 If PAGER is less, search for name of man page to make it easier | ||||
| #          to find information in man pages for multiple items | ||||
| # 92/11/11 Make it work for compressed files not listed in index; | ||||
| #          deal with man pages listed in index that don't exist. | ||||
| # 93/03/30 Fixed bug in MANPATH processing | ||||
| # 93/06/17 Include paths in "See also:" message if they would be needed | ||||
| #          to get to a man page.  Allow MANPATH spec on command line. | ||||
| # 93/07/09 Added -h and -e options. | ||||
| # 94/04/16 Added x option. | ||||
| # | ||||
| # conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| istrue() | ||||
| { | ||||
| 	test 0 -ne "$1" | ||||
| } | ||||
| 
 | ||||
| isfalse() | ||||
| { | ||||
| 	test 0 -eq "$1" | ||||
| } | ||||
| 
 | ||||
| # Finds all sections that man page $1 is in and puts them in the the | ||||
| # global array Sections[].   | ||||
| # The filename of each page is put in FileNames[] with the same index. | ||||
| # Global vars used: | ||||
| # patharr[] MANPATH directories. | ||||
| 
 | ||||
| FindSectionsInIndex () | ||||
| { | ||||
|     typeset index indexes section mpath page=$1 | ||||
|     typeset -i i=0 NIndex=0 | ||||
| 
 | ||||
|     for mpath in "${patharr[@]}"; do | ||||
| 	if [ -r $mpath/index ]; then | ||||
| 	    indexes="$indexes $mpath/index" | ||||
| 	    let NIndex+=1 | ||||
| 	fi | ||||
|     done | ||||
|     [ -z "$indexes" ] && return | ||||
|     # Make egrep give filename | ||||
|     [ NIndex -lt 2 ] && indexes="$indexes /dev/null" | ||||
|     # set positional parameters to | ||||
|     # indexfile:searchname pagename section ... | ||||
|     # e.g. | ||||
|     # /usr/man/index:FP_OFF Routines DOS | ||||
|     set -- `egrep "^$page[ 	]" $indexes` | ||||
|     while [ $# -gt 2 ]; do | ||||
| 	FileNames[i]=${1%%index*}cat$3/$2.$3 | ||||
| 	Sections[i]=$3 | ||||
| 	shift 3 | ||||
| 	let i+=1 | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| # Finds all sections that man page $1 is in by searching each man directory | ||||
| # in the order given in patharr[], | ||||
| # and puts them in the the global array Sections[].   | ||||
| # The filename of each page is put in FileNames[] with the same index. | ||||
| # Global vars used: | ||||
| # patharr[] MANPATH directories. | ||||
| FindSectionsInDirs () | ||||
| { | ||||
|     local page=$1 mpath AllPaths Path | ||||
|     typeset -i i | ||||
| 
 | ||||
|     for mpath in "${patharr[@]}"; do | ||||
| 	AllPaths="$AllPaths $mpath/cat[0-9]*/$page.* $mpath/man[0-9]*/$page.*" | ||||
|     done | ||||
| 
 | ||||
|     i=0 | ||||
|     for Path in $AllPaths; do | ||||
| 	istrue $debug && echo Path = $Path | ||||
| 	case "$Path" in | ||||
| 	*\*)	;; | ||||
| 	*) | ||||
| 	    # Remove compressed-file suffix to make FileNames be the same | ||||
| 	    # as it is when built by FindSectionsInIndex() | ||||
| 	    FileNames[i]=${Path%.[zZ]} | ||||
| 	    Path=${Path%/*} | ||||
| 	    Sections[i]=${Path##*/*.} | ||||
| 	    let i+=1 ;; | ||||
| 	esac | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| # FindSection: display man page. | ||||
| # Uses ordarr[] (built from $ORDER) to display the version of the man | ||||
| # page that occurs first in $ORDER. | ||||
| # Sections[] gives the sections that a man page was found in. | ||||
| # If the global variable "exist" is set to 1, nothing is displayed; | ||||
| # the function instead returns zero if a page is found, nonzero if not. | ||||
| # The filename of each page is in FileNames[] with the same index. | ||||
| # Global vars used: | ||||
| # Sections[], FileNames[], ordarr[] | ||||
| FindSection () | ||||
| { | ||||
|     typeset -i NumPages i foundsec | ||||
|     local section OtherSec filename NPAGER=$PAGER POpt page=$1 Pat | ||||
|     local PageFile | ||||
| 
 | ||||
|     NumPages=${#Sections[*]}	# Number of versions of man page found. | ||||
|     isfalse $NumPages && return 1  | ||||
|     case "$PAGER" in | ||||
|     *less)	Popt="-p$page" ;; | ||||
|     esac | ||||
| 
 | ||||
|     # For each section in ORDER, determine if any man page was found in | ||||
|     # that section | ||||
|     for section in "${ordarr[@]}"; do | ||||
| 	i=0 | ||||
| 	foundsec=0 | ||||
| 	while [ $i -lt $NumPages ]; do | ||||
| 	    if [ "${Sections[i]}" = $section ]; then | ||||
| 		# Found a man page from this section of ORDER | ||||
| 		filename=${FileNames[i]} | ||||
| 		if [ -z "$PageFile" ]; then | ||||
| 		    PageFile=$filename | ||||
| 		else | ||||
| 		    if istrue $foundsec; then | ||||
| 			OtherSec="$OtherSec$page(${filename%/*/*} $section) " | ||||
| 		    else | ||||
| 			OtherSec="$OtherSec$page($section) " | ||||
| 		    fi | ||||
| 		fi | ||||
| 		foundsec=1 | ||||
| 		istrue $exist && return | ||||
| 	    fi | ||||
| 	    let i+=1 | ||||
| 	done | ||||
|     done | ||||
|     # No pages with the specified section found. | ||||
|     [ -z "$PageFile" ] && return 1 | ||||
|     # Return if all we want to know is whether the man page exists. | ||||
|     [ "$exist" = 1 ] && return 0 | ||||
|     if [ -z "$OtherSec" ]; then | ||||
| 	NPAGER="exec $PAGER" | ||||
|     fi | ||||
|     if [ -r $PageFile ]; then | ||||
| 	$NPAGER $POpt $PageFile | ||||
|     elif [ -r $PageFile.z ]; then | ||||
| 	pcat $PageFile.z | $NPAGER $POpt | ||||
|     elif [ -r $PageFile.Z ]; then | ||||
| 	zcat $PageFile.Z | $NPAGER $POpt | ||||
|     elif [ -f $PageFile.gz ]; then | ||||
| 	gzip -dc $PageFile.gz | $NPAGER $POpt | ||||
|     else | ||||
| 	echo "$PageFile: cannot open." 1>&2 | ||||
| 	OtherSec= | ||||
| 	unset Sections[i] | ||||
| 	let i+=1 | ||||
| 	continue | ||||
|     fi | ||||
|     echo "See also $OtherSec" | ||||
|     exit 0 | ||||
| } | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo "$name: print man pages. | ||||
| $name locates and prints the specified manual pages from the online UNIX | ||||
| documentation. | ||||
| $Usage | ||||
| Options: | ||||
| -e: Determine whether the specified man page exists.  Nothing is printed; | ||||
|     $0 exits with a zero status if the page exists and a nonzero status if | ||||
|     it does not. | ||||
| -h: Print this help." | ||||
| } | ||||
| 
 | ||||
| # main program | ||||
| 
 | ||||
| typeset -i exist=0 debug=0 | ||||
| 
 | ||||
| name=${0##*/} | ||||
| Usage="Usage: $name [-eh] [[manpath] section] command-name" | ||||
| 
 | ||||
| while getopts :hex opt; do | ||||
|     case $opt in | ||||
|     h) phelp; exit 0;; | ||||
|     e) exist=1 ;; | ||||
|     x) debug=1 ;; | ||||
|     +?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;; | ||||
|     ?)  | ||||
| 	echo "$name: $OPTARG: bad option.  Use -h for help." 1>&2 ; exit 2 ;; | ||||
|     esac | ||||
| done | ||||
|   | ||||
| # remove args that were options | ||||
| shift $((OPTIND-1)) | ||||
| 
 | ||||
| if [ $# -lt 1 ]; then | ||||
|     echo -e "$Usage\nUse -h for help." 1>&2 | ||||
|     exit | ||||
| fi | ||||
| 
 | ||||
| P=$PAGER | ||||
| O=1:n:l:6:8:2:3:4:5:7:p:o | ||||
| T=$TERM | ||||
| M=${MANPATH:-/usr/local/man:/usr/man} | ||||
| [ -f /etc/default/man ] && . /etc/default/man | ||||
| [ -n "$P" ] && PAGER=$P | ||||
| [ -n "$O" ] && ORDER=$O | ||||
| [ -n "$T" ] && TERM=$T | ||||
| [ -n "$M" ] && MANPATH=$M | ||||
| 
 | ||||
| case $# in | ||||
| 0)  echo "No man page specified." ; exit 1;; | ||||
| 1)  page=$1;; | ||||
| 2)  ORDER=$(echo $1 | tr a-z A-Z) ; page=$2;; | ||||
| 3)  MANPATH=$1  | ||||
|     [ -n "$2" ] && ORDER=$(echo $2 | tr a-z A-Z) | ||||
|     page=$3;; | ||||
| *)  echo "Too many arguments."; exit 1;; | ||||
| esac | ||||
| 
 | ||||
| aargs=("$@") | ||||
| [ ! -t 0 ] && PAGER=cat | ||||
| 
 | ||||
| OIFS=$IFS | ||||
| IFS=: | ||||
| patharr=($MANPATH) | ||||
| i=0 | ||||
| for d in $MANPATH; do | ||||
|     for sec in $ORDER; do | ||||
| 	ordarr[i]=$d/cat${sec} | ||||
| 	let i+=1 | ||||
| 	ordarr[i]=$d/man${sec} | ||||
| 	let i+=1 | ||||
|     done | ||||
| done | ||||
| IFS=$OIFS | ||||
| 
 | ||||
| istrue $debug && echo patharr = "${patharr[@]}" | ||||
| 
 | ||||
| # if less or more is being used, remove multiple blank lines | ||||
| export LESS="-s $LESS" | ||||
| export MORE="-s $MORE" | ||||
| 
 | ||||
| # Try using index | ||||
| FindSectionsInIndex "$page" | ||||
| # Exit 0 if a page was found and we're just testing for existence. | ||||
| FindSection "$page" && exit 0 | ||||
| 
 | ||||
| # Try searching directories | ||||
| unset Sections[*] | ||||
| FindSectionsInDirs "$page" | ||||
| FindSection "$page" && exit 0 | ||||
| 
 | ||||
| istrue $exist && exit 1 | ||||
| 
 | ||||
| # Try using man | ||||
| # If using more or less, make man run faster by letting more or less compress | ||||
| # multiple blank lines instead of rmb | ||||
| #case "$PAGER" in | ||||
| #*more|*less)	manopt=-b;; | ||||
| #esac | ||||
| 
 | ||||
| #cmd=(man $manopt -p$PAGER "${aargs[@]}") | ||||
| export PAGER | ||||
| cmd=(man $manopt "${aargs[@]}") | ||||
| istrue $debug && echo "$name: running ${cmd[*]}" 1>&2 | ||||
| exec "${cmd[@]}" | ||||
							
								
								
									
										288
									
								
								examples/scripts.v2/frcp
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										288
									
								
								examples/scripts.v2/frcp
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,288 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # | ||||
| # @(#) frcp.ksh 2.2 93/11/14 | ||||
| # 92/06/29 john h. dubois iii (john@armory.com) | ||||
| # 92/10/14 Cleaned up, improved, added -d and -r options | ||||
| # 92/11/11 Made work with a dest of '.' | ||||
| # 93/07/09 Added -l and -n options, & login as anonymous if no .netrc entry | ||||
| # 93/11/14 Use either passwd or password in .netrc, since ftp does. | ||||
| # | ||||
| # conversion to bash v2 syntax by Chet Ramey | ||||
| # | ||||
| # frcp: ftp front end with rcp-like syntax. | ||||
| # Note: requires any machine names given to be listed with | ||||
| #       user and password in .netrc.  If not, anonymous FTP is | ||||
| #	done. | ||||
| # | ||||
| # full path to ftp binary | ||||
| if [ -x /usr/bin/ftp ]; then | ||||
| 	FTP=/usr/bin/ftp; | ||||
| elif [ -x /usr/ucb/ftp ]; then | ||||
| 	FTP=/usr/ucb/ftp | ||||
| else | ||||
| 	FTP=ftp | ||||
| fi | ||||
| 
 | ||||
| istrue() | ||||
| { | ||||
| 	test 0 -ne "$1" | ||||
| } | ||||
| isfalse() | ||||
| { | ||||
| 	test 0 -eq "$1" | ||||
| } | ||||
| 
 | ||||
| # For each filename given, put the filename in filename[n] | ||||
| # and the machine it is on in machine[n]. | ||||
| function SplitNames { | ||||
|     typeset file | ||||
|     typeset -i i=1 | ||||
| 
 | ||||
|     unset filename[*] machine[*] | ||||
|     for file; do | ||||
| 	case "$file" in | ||||
| 	*:*) machine[i]=${file%%:*} ;; | ||||
| 	*)   machine[i]=$LocalMach ;; | ||||
| 	esac | ||||
| 	filename[i]=${file#*:} | ||||
| 	let i+=1 | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| function verboseprint { | ||||
|     echo "$@" | ||||
|     echo "$@" 1>&2 | ||||
| } | ||||
| 
 | ||||
| function MakeDir { | ||||
|     OFS=$IFS | ||||
|     local IFS=/ dir component | ||||
| 
 | ||||
|     case "$1" in | ||||
|     /*)	;; | ||||
|      *) dir=. | ||||
|     esac | ||||
|     set -- $1 | ||||
|     IFS=$OFS | ||||
|     for component; do | ||||
| 	dir=$dir/$component | ||||
| 	if [ ! -d "$dir" ]; then | ||||
| 	    if mkdir "$dir"; then :; else | ||||
| 		echo "Could not make directory $dir." >&2 | ||||
| 		return 1 | ||||
| 	    fi | ||||
| 	fi | ||||
|     done | ||||
|     return 0 | ||||
| } | ||||
| 
 | ||||
| lastisdot () | ||||
| { | ||||
| 	case "$1" in | ||||
| 	*/.|*/..)	return 0;; | ||||
| 	*)	return 1;; | ||||
| 	esac | ||||
| } | ||||
| 
 | ||||
| # CopyFiles: issue ftp(TC) commands to copy files. | ||||
| # Usage: CopyFiles [sourcemachine:]sourcepath ... [destmachine:]destpath | ||||
| # Global vars: | ||||
| # Uses LocalMach (should be name of local machine) | ||||
| # Sets global arrs machine[]/filename[] | ||||
| function CopyFiles { | ||||
|     unset machine[*] filename[*] | ||||
| 
 | ||||
|     SplitNames "$@"	# split names into filename[1..n] and machine[1..n] | ||||
| 
 | ||||
|     local DestMach=${machine[$#]}	# Machine to copy files to | ||||
|     local DestPath=${filename[$#]} 	# Destination file/dir | ||||
| 
 | ||||
|     unset machine[$#] filename[$#] | ||||
| 
 | ||||
|     [ -z "$DestPath" ] && DestPath=.	# dest was given as machine: | ||||
| 
 | ||||
|     # Try to determine if destination should be a directory | ||||
|     # so that it can be forced to be a directory. | ||||
| 
 | ||||
|     case "$DestPath" in | ||||
|     */)	;;	# don't add / if trailing / already present | ||||
|     *)  if [ $# -gt 2 ] || # if more than two args given, last must be a dir | ||||
| 	    # If dest in on local machine, check whether it is a directory | ||||
|     	   [ $DestMach = $LocalMach -a -d $DestPath ] ||  | ||||
| 	    # If dest ends with . or .., it is a directory | ||||
| 	   lastisdot "$DestPath" | ||||
| 	then | ||||
| 		DestPath=$DestPath/ | ||||
| 	fi ;; | ||||
|     esac | ||||
| 
 | ||||
|     # If one of the above tests made us think dest is a directory, | ||||
|     # but it isn't, complain | ||||
|     case "$DestPath" in | ||||
|     */)	if [ "$DestMach" = "$LocalMach" ] && [ ! -d "$DestPath" ]; then | ||||
| 		echo "Destination is not a directory." 1>&2 | ||||
| 		exit 1 | ||||
|         fi ;; | ||||
|     esac | ||||
| 
 | ||||
|     DoCopy "$DestMach" "$DestPath" | ||||
| } | ||||
| 
 | ||||
| # Usage: OpenMachine machine-name | ||||
| # Emits login sequence or doesn't, depending on .netrc file and global | ||||
| # variables anon and noanon | ||||
| OpenMachine () | ||||
| { | ||||
|     local machine=$1 netrc=$HOME/.netrc user= password= | ||||
| 
 | ||||
|     if isfalse $anon && [ -r $netrc ]; then | ||||
| 	set -- $(gawk ' | ||||
| 	/machine (.* )?'"$machine"'($| )/,/^ *$/ { | ||||
| 	    Fields[$1] = $2 | ||||
| 	    if ("passwd" in Fields) | ||||
| 		Fields["password"] = Fields["passwd"] | ||||
| 	    if ("login" in Fields && "password" in Fields) { | ||||
| 		print Fields["login"] " " Fields["password"] | ||||
| 		exit | ||||
| 	    } | ||||
| 	} | ||||
| 	' $netrc ) | ||||
| 	user=$1 | ||||
| 	password=$2 | ||||
|     fi | ||||
|     if [ -z "$password" ]; then | ||||
| 	if istrue $noanon; then | ||||
| 	    echo "No .netrc entry for machine $machine" 1>&2 | ||||
| 	    exit 1 | ||||
| 	fi | ||||
| 	user=anonymous | ||||
| 	password=$USER@$LocalMach | ||||
|     fi | ||||
|     verboseprint open $machine | ||||
|     echo user $user "*******" 1>&2 | ||||
|     echo user $user $password | ||||
| } | ||||
| 
 | ||||
| # Usage: DoCopy destination-machine destination-path | ||||
| # Copies the files in global arrs machine[]/filename[] to the given dest | ||||
| # Global vars: | ||||
| # Uses machine[], filename[], LocalMach, check | ||||
| DoCopy () | ||||
| { | ||||
|     local DestMach=$1 | ||||
|     local DestPath=$2 | ||||
|     local OpenMach	# Machine that connection is currently open to | ||||
|     local OWD=$PWD SourceMach SourceFile | ||||
|     local FileName | ||||
|     typeset -i i=1 | ||||
| 
 | ||||
|     while [ $i -le ${#machine[*]} ]; do | ||||
| 	istrue $check && verboseprint "runique" | ||||
| 
 | ||||
| 	SourceMach=${machine[i]} | ||||
| 	SourceFile=${filename[i]} | ||||
| 
 | ||||
| 	DestFile=$DestPath | ||||
| 	# if DestPath is a dir, | ||||
| 	# add source filename to it without source path | ||||
| 	case "$DestFile" in | ||||
| 	*/)	DestFile=$DestFile${SourceFile##*/} ;; | ||||
| 	esac | ||||
| 
 | ||||
| 	if [ $SourceMach = $LocalMach ]; then | ||||
| 	    if [ $DestMach != "$OpenMach" ]; then | ||||
| 		OpenMachine $DestMach | ||||
| 		OpenMach=$DestMach | ||||
| 	    fi | ||||
| 	    verboseprint put $SourceFile $DestFile | ||||
| 	elif [ $DestMach = $LocalMach ]; then | ||||
| 	    if istrue $check && [ -f "$DestFile" ]; then | ||||
| 		echo "$DestFile already exists." 1>&2 | ||||
| 		continue | ||||
| 	    fi | ||||
| 	    # If destination is on local machine, | ||||
| 	    # the dest will be a full dir/filename | ||||
| 	    if istrue $createdirs; then | ||||
| 		MakeDir "${DestFile%/*}" || continue | ||||
| 	    fi | ||||
| 	    if [ $SourceMach != "$OpenMach" ]; then | ||||
| 		OpenMachine $SourceMach | ||||
| 		OpenMach=$SourceMach | ||||
| 	    fi | ||||
| 	    # If source filename has wildcards ([, ], *, ?) do an mget | ||||
| 	    case "$SourceFile" in | ||||
| 	    \[*\]|*\**|*\?*) | ||||
| 		verboseprint lcd "$DestFile" | ||||
| 		verboseprint mget "$SourceFile" | ||||
| 		verboseprint lcd $OWD ;; | ||||
| 	    *)  verboseprint get "$SourceFile" "$DestFile" ;; | ||||
| 	    esac | ||||
| 	else | ||||
| 	    echo "Neither source machine \"$SourceMach\" "\ | ||||
| "nor destination machine \"$DestMach\" is local." 1>&2 | ||||
| 	fi | ||||
| 	let i+=1 | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| # Start of main program | ||||
| name=${0##*/} | ||||
| 
 | ||||
| if [ "$1" = -h ]; then | ||||
|     echo \ | ||||
| "$name: do ftp transfers using rcp-style parameters. | ||||
| Usage: $name <source> <destpath>   or   $name <source> [<source> ...] <destdir> | ||||
| At least one of <source> and <destpath> must be the local system. | ||||
| A remote filename is given as machinename:filename | ||||
| If remote filenames contain wildcards, they will be globbed on the remote | ||||
| machine.  Make sure they are quoted when $name is invoked. | ||||
| If the invoking user's .netrc file (see ftp(TC)) contains an entry for the | ||||
| remote system with a login and password supplied, $name will log in using | ||||
| the given login and password.  If not, $name will login in as user | ||||
| anonymous and with the user@localsystem as the password. | ||||
| Options: | ||||
| -c: check: do not overwrite files. | ||||
| -d: create directories as needed. | ||||
| -f: force: overwrite files (default). | ||||
| -h: print this help. | ||||
| -l: fail if there is no entry with login and password for the remote system, | ||||
|     instead of logging in as anonymous. | ||||
| -n: log in as anonymous even if there is an entry for the remote system in | ||||
|     the user's .netrc file. | ||||
| -r: read source/dest filename pairs from the standard input, | ||||
|     one pair per line, and copy files accordingly." | ||||
|     exit 0 | ||||
| fi | ||||
| 
 | ||||
| typeset -i check=0 createdirs=0 readinput=0 anon=0 noanon=0 | ||||
| 
 | ||||
| while getopts :cdflnr Option | ||||
| do | ||||
|     case "$Option" in | ||||
|     c) check=1;; | ||||
|     d) createdirs=1;; | ||||
|     f) check=0;; | ||||
|     l) noanon=1;; | ||||
|     n) anon=1;; | ||||
|     r) readinput=1;; | ||||
|     \?) echo "$OPTARG: invalid option."; exit 1;; | ||||
|     esac | ||||
| done | ||||
| 
 | ||||
| shift $((OPTIND-1)) | ||||
| 
 | ||||
| LocalMach=`hostname`  | ||||
| 
 | ||||
| if istrue $readinput; then | ||||
|     while read line; do | ||||
| 	CopyFiles $line | ||||
|     done | $FTP -nv | ||||
| else | ||||
|     if [ $# -lt 2 ]; then | ||||
| 	echo "$name: Not enough arguments.  Use -h for help." 1>&2 | ||||
| 	exit | ||||
|     fi | ||||
|     CopyFiles "$@" | $FTP -nv | ||||
| fi | ||||
							
								
								
									
										44
									
								
								examples/scripts.v2/lowercase
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								examples/scripts.v2/lowercase
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from | ||||
| # @(#) lowercase.ksh 1.0 92/10/08 | ||||
| # 92/10/08 john h. dubois iii (john@armory.com) | ||||
| # | ||||
| # conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| Usage="Usage: $name file ..." | ||||
| phelp() | ||||
| { | ||||
| echo "$name: change filenames to lower case. | ||||
| $Usage | ||||
| Each file is moved to a name with the same directory component, if any, | ||||
| and with a filename component that is the same as the original but with | ||||
| any upper case letters changed to lower case." | ||||
| } | ||||
| 
 | ||||
| name=${0##*/} | ||||
| 
 | ||||
| while getopts "h" opt; do | ||||
| 	case "$opt" in | ||||
| 	h)	phelp; exit 0;; | ||||
| 	*)	echo "$Usage" 1>&2; exit 2;; | ||||
| 	esac | ||||
| done | ||||
| 
 | ||||
| shift $((OPTIND - 1)) | ||||
| 
 | ||||
| for file; do | ||||
|     filename=${file##*/} | ||||
|     case "$file" in | ||||
|     */*)    dirname=${file%/*} ;; | ||||
|     *)    dirname=. ;; | ||||
|     esac | ||||
|     nf=$(echo $filename | tr A-Z a-z) | ||||
|     newname="${dirname}/${nf}" | ||||
|     if [ "$nf" != "$filename" ]; then | ||||
| 	mv "$file" "$newname" | ||||
| 	echo "$0: $file -> $newname" | ||||
|     else | ||||
| 	echo "$0: $file not changed." | ||||
|     fi | ||||
| done | ||||
							
								
								
									
										187
									
								
								examples/scripts.v2/ncp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								examples/scripts.v2/ncp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,187 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # @(#) ncp.ksh,nmv.ksh 1.1 94/07/23 | ||||
| # 92/01/18 john h. dubois iii (john@armory.com) | ||||
| # 92/01/31 added check for no args left after shifts | ||||
| # 92/02/17 added help | ||||
| # 92/02/25 remove path component from filename before tacking it onto dest. | ||||
| # 92/03/15 exec mv or cp | ||||
| # 93/07/13 Added -i | ||||
| # 93/09/29 Made abort if file exists optional. | ||||
| # 93/11/19 Exit before invoking mv if no files to move | ||||
| # 94/01/03 Added o option | ||||
| # 94/04/13 Added x option. | ||||
| #          Fixed appending of source filename, broken by earlier change. | ||||
| # 94/07/23 Append only the filename part of the source path. | ||||
| # | ||||
| # conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| false() | ||||
| { | ||||
| 	return 1 | ||||
| } | ||||
| 
 | ||||
| true() | ||||
| { | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo "$name: do a $cmd with extra checking and options. | ||||
| $Usage | ||||
| $name is used as a front end for $cmd to get the [icfo] options, and so | ||||
| that a trailing / will force the last component of the path to be | ||||
| interpreted as a directory, so that   $name foo bar/   will fail if bar is | ||||
| not an existing directory, instead of changing the name of foo to bar.  | ||||
| Effectively,  $name foo bar/   is short for  $name foo bar/foo | ||||
| Options:  | ||||
| -h prints this help. | ||||
| -c checks first for the existence of each file, and fails if it exists. | ||||
| -i is like -c except that if the file exists and stdin and stdout are a | ||||
|    tty, a query is printed and a reply is read; a file is overwritten only | ||||
|    if the reply begins with 'y'. | ||||
| -f unsets -c and -i (in case $cmd is aliased to $name). | ||||
| -o (overwrite only) checks that the named file(s) exist and fails for any | ||||
|    that do not.  It is the complement of the -c option. | ||||
| Whichever of [cifo] comes later on the command line determines the behaviour. | ||||
| Any of these options must come before any standard $cmd options." | ||||
| } | ||||
| 
 | ||||
| # interactive: Attempt to overwrite file should result in interactive | ||||
| # query rather than automatic failure. | ||||
| # noover: Do not overwrite files (if interactive is true, query, else fail) | ||||
| # overwrite: Only overwriting is allowed, not creation of new files. | ||||
| # debug: Print debugging info. | ||||
| typeset interactive=false noover=false overwrite=false debug=false | ||||
| name=${0##*/} | ||||
| 
 | ||||
| case "$name" in | ||||
| ncp|nmv) cmd=/bin/${name#?} ;; | ||||
| *) echo "$name: Must be invoked as ncp or nmv." 1>&2 ; exit 2;; | ||||
| esac | ||||
| 
 | ||||
| Usage="Usage: $name [-cfhio] $cmd-cmd-line" | ||||
| 
 | ||||
| while getopts :cfhiox opt; do | ||||
|     case $opt in | ||||
|     h) phelp; exit 0;; | ||||
|     x) debug=true ;; | ||||
|     c) noover=true ;; | ||||
|     i) noover=true ; interactive=true ;; | ||||
|     f) noover=false ; interactive=false ;; | ||||
|     o) overwrite=true ; noover=false ; interactive=false;; | ||||
|     +?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;; | ||||
|     ?)  echo "$name: $OPTARG: bad option.  Use -h for help." 1>&2 ; exit 2;; | ||||
|     esac | ||||
| done | ||||
|   | ||||
| # remove args that were options | ||||
| shift $((OPTIND - 1)) | ||||
| 
 | ||||
| if [ $# -lt 2 ]; then | ||||
|     echo -e "$Usage\nUse -h for help." | ||||
|     exit | ||||
| fi | ||||
| 
 | ||||
| Check() | ||||
| { | ||||
|     if [ ! -f "$1" ] && $overwrite; then | ||||
| 	echo "$name: $1: File does not exist." 1>&2 | ||||
| 	return 1 | ||||
|     elif [ -f "$1" ] && $noover; then | ||||
| 	if [ $interactive = false ] || [ ! -t 0 ] || [ ! -t 1 ]; then | ||||
| 	    echo "$name: $1: File exists." 1>&2 | ||||
| 	    return 1 | ||||
| 	else | ||||
| 	    while :; do | ||||
| 		echo -n \ | ||||
| "$name: $1: File exists.  Overwrite? (y)es/(n)o/(a)bort/(Y)es for all: " 1>&2 | ||||
| 		read reply | ||||
| 		case "$reply" in | ||||
| 		y*) | ||||
| 		    echo "$name: Overwriting $1." | ||||
| 		    return 0 | ||||
| 		    ;; | ||||
| 		Y*) | ||||
| 		    echo "$name: Overwriting $1." | ||||
| 		    interactive=false | ||||
| 		    noover=false | ||||
| 		    return 0 | ||||
| 		    ;; | ||||
| 		[nN]*) | ||||
| 		    echo "$name: Skipping $2." | ||||
| 		    return 1 | ||||
| 		    ;; | ||||
| 		[aA]*) | ||||
| 		    echo "$name: Aborting." | ||||
| 		    exit 1 | ||||
| 		    ;; | ||||
| 		*) | ||||
| 		    echo "$name: Invalid response." 1>&2 | ||||
| 		    ;; | ||||
| 		esac | ||||
| 	    done | ||||
| 	fi | ||||
|     else | ||||
| 	return 0 | ||||
|     fi | ||||
| } | ||||
| 
 | ||||
| # i is the index of the filename being examined | ||||
| # lastarg is the index of the last filename before the dest directory name | ||||
| typeset -i i=0 lastarg=$(($#-1)) | ||||
| 
 | ||||
| # Sets argv[0..$#-1] | ||||
| argv=("$@") | ||||
| $debug && echo argv = "${argv[@]}" 1>&2 | ||||
| dest=${argv[lastarg]} | ||||
| 
 | ||||
| if $debug; then | ||||
|     echo \ | ||||
| "interactive=$interactive noover=$noover overwrite=$overwrite debug=$debug | ||||
| lastarg=$lastarg dest=$dest name=$name cmd=$cmd | ||||
| files=$*" 1>&2 | ||||
| fi | ||||
| 
 | ||||
| if $noover || $overwrite; then | ||||
|     $debug && echo "checking for existance of directories..." 1>&2 | ||||
|     # If the destination is not intended to be a directory... | ||||
|     if [ $# -eq 2 ] && [ ! -d "$dest" ]; then | ||||
| 	Check "$dest" "$1" || exit 0		# No files to copy | ||||
|     else | ||||
| 	while [ $i -lt $lastarg ]; do | ||||
| 	    Check "$dest/${argv[i]##*/}" "${argv[i]}" || unset argv[i] | ||||
| 	    let i+=1 | ||||
| 	done | ||||
|     fi | ||||
| fi | ||||
| 
 | ||||
| [ ${#argv[@]} -lt 2 ] && exit 0 | ||||
| 
 | ||||
| # If only 2 args are given, mv/cp will not insist that the destination | ||||
| # be a directory, which we want if the destination ends in "/" or if | ||||
| # the original number of args was >2. | ||||
| # $# is still the original number of args. | ||||
| # Tack the file name onto the destination to force this behaviour. | ||||
| 
 | ||||
| lastisslash() | ||||
| { | ||||
| 	case "$1" in | ||||
| 	*/)	return 0;; | ||||
| 	*)	return 1;; | ||||
| 	esac | ||||
| } | ||||
| 
 | ||||
| if [ ${#argv[@]} = 2 ] && { lastisslash "$2" || [ $# -gt 2 ]; }; then | ||||
|     $debug && echo "Appending filename." 1>&2 | ||||
|     # Don't know which element of argv[] holds the source filename,  | ||||
|     # since may have started with more than 1 source file & had some unset. | ||||
|     # So, compact args to make it easy to find the set one. | ||||
|     argv=("${argv[@]}") | ||||
|     argv[1]="${argv[1]}/${argv[0]##*/}" | ||||
| fi | ||||
| 
 | ||||
| $debug && echo "Executing command: $cmd ${argv[@]}" 1>&2 | ||||
| exec $cmd "${argv[@]}" | ||||
							
								
								
									
										64
									
								
								examples/scripts.v2/newext
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								examples/scripts.v2/newext
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # newext: change filename extension | ||||
| # @(#) newext.sh 1.1 93/04/13 | ||||
| # 90/06/06 john h. dubois iii (john@armory.com) | ||||
| # 90/11/14 changed ksh-specific code to hybrid: if running under Bourne, | ||||
| #          uses expr instead of ksh builtin ops.  Removed SYSV specific code. | ||||
| # 91/08/06 added -t option | ||||
| # 92/11/06 made earlier code actually work! | ||||
| # 93/04/13 If no filenames given, act on files in current dir | ||||
| # | ||||
| # conversion to bash v2 syntax by Chet Ramey | ||||
| 
 | ||||
| usage="Usage: newext [-th] <oldext> <newext> [filename ...]" | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo "$usage | ||||
| Rename all given files that end in oldext with newext replacing oldext. | ||||
| If no filenames are given, all files in the current directory that end | ||||
| in oldext are acted on (no filename is equivalent to '*'). | ||||
| Options: | ||||
| -h: Print this help. | ||||
| -t: Test: No action is taken except to print the mv commands that would | ||||
| be executed if -t was not given." | ||||
| } | ||||
| 
 | ||||
| while getopts "th" opt; do | ||||
|     case "$opt" in | ||||
|     t) echo=echo;; | ||||
|     h) phelp; exit 0;; | ||||
|     *) echo "$usage" 1>&2; exit 2;; | ||||
|    esac | ||||
| done | ||||
| 
 | ||||
| shift $((OPTIND - 1)) | ||||
| 
 | ||||
| oldext=$1 | ||||
| newext=$2 | ||||
| 
 | ||||
| case $# in  | ||||
| [01])	echo -e "$usage\nUse -h for help." 1>&2; exit 2;; | ||||
| 2)	shift ; shift; set -- *;; | ||||
| *)	shift ; shift;; | ||||
| esac | ||||
| 
 | ||||
| found= | ||||
| 
 | ||||
| for file | ||||
| do | ||||
|     case "$file" in | ||||
|     *$oldext)  | ||||
| 	newname="${file%$oldext}$newext" | ||||
| 	$echo mv "$file" "$newname" | ||||
| 	found=true;; | ||||
|     esac | ||||
| done | ||||
| 
 | ||||
| if [ -z "$found" ]; then | ||||
|     echo "No files ending in \"$oldext\"." | ||||
|     exit 1 | ||||
| fi | ||||
| exit 0 | ||||
							
								
								
									
										187
									
								
								examples/scripts.v2/nmv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								examples/scripts.v2/nmv
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,187 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # @(#) ncp.ksh,nmv.ksh 1.1 94/07/23 | ||||
| # 92/01/18 john h. dubois iii (john@armory.com) | ||||
| # 92/01/31 added check for no args left after shifts | ||||
| # 92/02/17 added help | ||||
| # 92/02/25 remove path component from filename before tacking it onto dest. | ||||
| # 92/03/15 exec mv or cp | ||||
| # 93/07/13 Added -i | ||||
| # 93/09/29 Made abort if file exists optional. | ||||
| # 93/11/19 Exit before invoking mv if no files to move | ||||
| # 94/01/03 Added o option | ||||
| # 94/04/13 Added x option. | ||||
| #          Fixed appending of source filename, broken by earlier change. | ||||
| # 94/07/23 Append only the filename part of the source path. | ||||
| # | ||||
| # conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| false() | ||||
| { | ||||
| 	return 1 | ||||
| } | ||||
| 
 | ||||
| true() | ||||
| { | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo "$name: do a $cmd with extra checking and options. | ||||
| $Usage | ||||
| $name is used as a front end for $cmd to get the [icfo] options, and so | ||||
| that a trailing / will force the last component of the path to be | ||||
| interpreted as a directory, so that   $name foo bar/   will fail if bar is | ||||
| not an existing directory, instead of changing the name of foo to bar.  | ||||
| Effectively,  $name foo bar/   is short for  $name foo bar/foo | ||||
| Options:  | ||||
| -h prints this help. | ||||
| -c checks first for the existence of each file, and fails if it exists. | ||||
| -i is like -c except that if the file exists and stdin and stdout are a | ||||
|    tty, a query is printed and a reply is read; a file is overwritten only | ||||
|    if the reply begins with 'y'. | ||||
| -f unsets -c and -i (in case $cmd is aliased to $name). | ||||
| -o (overwrite only) checks that the named file(s) exist and fails for any | ||||
|    that do not.  It is the complement of the -c option. | ||||
| Whichever of [cifo] comes later on the command line determines the behaviour. | ||||
| Any of these options must come before any standard $cmd options." | ||||
| } | ||||
| 
 | ||||
| # interactive: Attempt to overwrite file should result in interactive | ||||
| # query rather than automatic failure. | ||||
| # noover: Do not overwrite files (if interactive is true, query, else fail) | ||||
| # overwrite: Only overwriting is allowed, not creation of new files. | ||||
| # debug: Print debugging info. | ||||
| typeset interactive=false noover=false overwrite=false debug=false | ||||
| name=${0##*/} | ||||
| 
 | ||||
| case "$name" in | ||||
| ncp|nmv) cmd=/bin/${name#?} ;; | ||||
| *) echo "$name: Must be invoked as ncp or nmv." 1>&2 ; exit 2;; | ||||
| esac | ||||
| 
 | ||||
| Usage="Usage: $name [-cfhio] $cmd-cmd-line" | ||||
| 
 | ||||
| while getopts :cfhiox opt; do | ||||
|     case $opt in | ||||
|     h) phelp; exit 0;; | ||||
|     x) debug=true ;; | ||||
|     c) noover=true ;; | ||||
|     i) noover=true ; interactive=true ;; | ||||
|     f) noover=false ; interactive=false ;; | ||||
|     o) overwrite=true ; noover=false ; interactive=false;; | ||||
|     +?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;; | ||||
|     ?)  echo "$name: $OPTARG: bad option.  Use -h for help." 1>&2 ; exit 2;; | ||||
|     esac | ||||
| done | ||||
|   | ||||
| # remove args that were options | ||||
| shift $((OPTIND - 1)) | ||||
| 
 | ||||
| if [ $# -lt 2 ]; then | ||||
|     echo -e "$Usage\nUse -h for help." | ||||
|     exit | ||||
| fi | ||||
| 
 | ||||
| Check() | ||||
| { | ||||
|     if [ ! -f "$1" ] && $overwrite; then | ||||
| 	echo "$name: $1: File does not exist." 1>&2 | ||||
| 	return 1 | ||||
|     elif [ -f "$1" ] && $noover; then | ||||
| 	if [ $interactive = false ] || [ ! -t 0 ] || [ ! -t 1 ]; then | ||||
| 	    echo "$name: $1: File exists." 1>&2 | ||||
| 	    return 1 | ||||
| 	else | ||||
| 	    while :; do | ||||
| 		echo -n \ | ||||
| "$name: $1: File exists.  Overwrite? (y)es/(n)o/(a)bort/(Y)es for all: " 1>&2 | ||||
| 		read reply | ||||
| 		case "$reply" in | ||||
| 		y*) | ||||
| 		    echo "$name: Overwriting $1." | ||||
| 		    return 0 | ||||
| 		    ;; | ||||
| 		Y*) | ||||
| 		    echo "$name: Overwriting $1." | ||||
| 		    interactive=false | ||||
| 		    noover=false | ||||
| 		    return 0 | ||||
| 		    ;; | ||||
| 		[nN]*) | ||||
| 		    echo "$name: Skipping $2." | ||||
| 		    return 1 | ||||
| 		    ;; | ||||
| 		[aA]*) | ||||
| 		    echo "$name: Aborting." | ||||
| 		    exit 1 | ||||
| 		    ;; | ||||
| 		*) | ||||
| 		    echo "$name: Invalid response." 1>&2 | ||||
| 		    ;; | ||||
| 		esac | ||||
| 	    done | ||||
| 	fi | ||||
|     else | ||||
| 	return 0 | ||||
|     fi | ||||
| } | ||||
| 
 | ||||
| # i is the index of the filename being examined | ||||
| # lastarg is the index of the last filename before the dest directory name | ||||
| typeset -i i=0 lastarg=$(($#-1)) | ||||
| 
 | ||||
| # Sets argv[0..$#-1] | ||||
| argv=("$@") | ||||
| $debug && echo argv = "${argv[@]}" 1>&2 | ||||
| dest=${argv[lastarg]} | ||||
| 
 | ||||
| if $debug; then | ||||
|     echo \ | ||||
| "interactive=$interactive noover=$noover overwrite=$overwrite debug=$debug | ||||
| lastarg=$lastarg dest=$dest name=$name cmd=$cmd | ||||
| files=$*" 1>&2 | ||||
| fi | ||||
| 
 | ||||
| if $noover || $overwrite; then | ||||
|     $debug && echo "checking for existance of directories..." 1>&2 | ||||
|     # If the destination is not intended to be a directory... | ||||
|     if [ $# -eq 2 ] && [ ! -d "$dest" ]; then | ||||
| 	Check "$dest" "$1" || exit 0		# No files to copy | ||||
|     else | ||||
| 	while [ $i -lt $lastarg ]; do | ||||
| 	    Check "$dest/${argv[i]##*/}" "${argv[i]}" || unset argv[i] | ||||
| 	    let i+=1 | ||||
| 	done | ||||
|     fi | ||||
| fi | ||||
| 
 | ||||
| [ ${#argv[@]} -lt 2 ] && exit 0 | ||||
| 
 | ||||
| # If only 2 args are given, mv/cp will not insist that the destination | ||||
| # be a directory, which we want if the destination ends in "/" or if | ||||
| # the original number of args was >2. | ||||
| # $# is still the original number of args. | ||||
| # Tack the file name onto the destination to force this behaviour. | ||||
| 
 | ||||
| lastisslash() | ||||
| { | ||||
| 	case "$1" in | ||||
| 	*/)	return 0;; | ||||
| 	*)	return 1;; | ||||
| 	esac | ||||
| } | ||||
| 
 | ||||
| if [ ${#argv[@]} = 2 ] && { lastisslash "$2" || [ $# -gt 2 ]; }; then | ||||
|     $debug && echo "Appending filename." 1>&2 | ||||
|     # Don't know which element of argv[] holds the source filename,  | ||||
|     # since may have started with more than 1 source file & had some unset. | ||||
|     # So, compact args to make it easy to find the set one. | ||||
|     argv=("${argv[@]}") | ||||
|     argv[1]="${argv[1]}/${argv[0]##*/}" | ||||
| fi | ||||
| 
 | ||||
| $debug && echo "Executing command: $cmd ${argv[@]}" 1>&2 | ||||
| exec $cmd "${argv[@]}" | ||||
							
								
								
									
										187
									
								
								examples/scripts.v2/pages
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								examples/scripts.v2/pages
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,187 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # @(#) pages.sh 1.0 92/09/26 | ||||
| # 92/09/05 John H. DuBois III (jhdiii@armory.com) | ||||
| # 92/09/26 Added help | ||||
| # | ||||
| # conversion to bash v2 syntax by Chet Ramey | ||||
| 
 | ||||
| Usage="$0 [-h] [-n lines/page] page-ranges [file ...]" | ||||
| 
 | ||||
| usage() | ||||
| { | ||||
| 	echo "$Usage" 1>&2 | ||||
| } | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo "$0: print selected pages. | ||||
| Usage: $Usage | ||||
| 
 | ||||
| If no file names are given, the standard input is read. | ||||
| 
 | ||||
| The input is grouped into pages and a selected subset of them is printed. | ||||
| Formfeeds are acted on correctly. | ||||
| 
 | ||||
| If the output device does automatic line wrap, lines that longer than | ||||
| the width of the output device will result in incorrect output. | ||||
| The first non-option argument is a list of pages to print. | ||||
| 
 | ||||
| Pages are given as a list of ranges separated by commas. | ||||
| A range is either one number, two numbers separted by a dash, | ||||
| or one number followed by a dash.  A range consisting of one | ||||
| number followed by a dash extends to the end of the document. | ||||
| 
 | ||||
| Options:  | ||||
| -n sets the number of lines per page to n.  The default is 66." | ||||
| } | ||||
| 
 | ||||
| while getopts "n:h" opt; do | ||||
| 	case "$opt" in | ||||
| 	n)	LinesPerPage=$OPTARG;; | ||||
| 	h)	phelp; exit 0;; | ||||
| 	*)	usage; exit 2;; | ||||
| 	esac | ||||
| done | ||||
| 
 | ||||
| shift $(($OPTIND - 1)) | ||||
| 
 | ||||
| if [ $# -eq 0 ]; then | ||||
|     echo $0: no page ranges given. 1>&2 | ||||
|     usage | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| PageList=$1 | ||||
| shift | ||||
| 
 | ||||
| gawk " | ||||
| BEGIN { | ||||
|     PageList = \"$PageList\"; LinesPerPage = \"$LinesPerPage\""' | ||||
|     if (LinesPerPage == "") | ||||
| 	LinesPerPage = 66 | ||||
|     else | ||||
| 	if (LinesPerPage !~ "[1-9][0-9]*") | ||||
| 	    ErrExit("Bad value for lines per page: " LinesPerPage) | ||||
|     LinesPerPage += 0 | ||||
|     NumRanges = split(PageList,Ranges,",") | ||||
|     for (i = 1; i <= NumRanges; i++) { | ||||
| 	if ((StartRange = EndRange = Ranges[i]) !~ "^[0-9]+(-([0-9]+)?)?$") | ||||
| 	    ErrExit("Bad range \"" StartRange "\"") | ||||
| 	sub("-.*","",StartRange) | ||||
| 	sub(".*-","",EndRange) | ||||
| 	if (EndRange == "") | ||||
| 	    EndRange = 2 ^ 30 | ||||
| 	# Force StartRange and EndRange to be numeric values | ||||
| 	if ((StartRange += 0) == 0 || (EndRange += 0) == 0) | ||||
| 	    ErrExit("Invalid page number \"0\" in range " Ranges[i]) | ||||
| 	if (StartRange > EndRange) | ||||
| 	    ErrExit("Start page comes after end page in range " Ranges[i]) | ||||
| 	TmpRangeStarts[i] = StartRange | ||||
| 	TmpRangeEnds[i] = EndRange | ||||
|     } | ||||
| 
 | ||||
|     # Sort ranges | ||||
|     qsort(TmpRangeStarts,k) | ||||
|     RangeEnds[0] = 0 | ||||
|     for (i = 1; i <= NumRanges; i++) { | ||||
| 	RangeEnds[i] = TmpRangeEnds[k[i]] | ||||
| 	if ((RangeStarts[i] = TmpRangeStarts[k[i]]) <= RangeEnds[i - 1]) | ||||
| 	    ErrExit("Overlapping ranges: " Ranges[k[i]] "," Ranges[k[i - 1]]) | ||||
|     } | ||||
| 
 | ||||
|     RangeNum = LineNum = PageNum = 1 | ||||
|     InRange = In(PageNum,RangeStarts[RangeNum],RangeEnds[RangeNum]) | ||||
|     FS = "\014" | ||||
| } | ||||
| 
 | ||||
| { | ||||
|     if (LineNum > LinesPerPage) | ||||
| 	NewPage() | ||||
|     if (InRange) | ||||
| 	printf "%s",$1 | ||||
|     # Deal with formfeeds | ||||
|     for (i = 2; i <= NF; i++) { | ||||
| 	if (InRange) | ||||
| 	    printf "\014" | ||||
| 	NewPage() | ||||
| 	if (InRange) | ||||
| 	    printf "%s",$i | ||||
|     } | ||||
|     if (InRange) | ||||
| 	print "" | ||||
|     LineNum++ | ||||
| } | ||||
| 
 | ||||
| function NewPage() { | ||||
|     PageNum++ | ||||
|     LineNum = 1 | ||||
|     # At the start of each page, check whether we are in a print range | ||||
|     WereInRange = InRange | ||||
|     InRange = In(PageNum,RangeStarts[RangeNum],RangeEnds[RangeNum]) | ||||
|     # If last page was in range and we no longer are, move to next range | ||||
|     if (WereInRange && !InRange && ++RangeNum > NumRanges) | ||||
| 	exit | ||||
| } | ||||
| 
 | ||||
| function In(a,Min,Max) { | ||||
|     return (Min <= a && a <= Max) | ||||
| } | ||||
| 
 | ||||
| function ErrExit(S) { | ||||
|     print S > "/dev/stderr" | ||||
|     Err = 1 | ||||
|     exit 1 | ||||
| } | ||||
| 
 | ||||
| # Arr is an array of values with arbitrary indices. | ||||
| # Array k is returned with numeric indices 1..n. | ||||
| # The values in k are the indices of array arr,  | ||||
| # ordered so that if array arr is stepped through | ||||
| # in the order arr[k[1]] .. arr[k[n]], it will be stepped | ||||
| # through in order of the values of its elements. | ||||
| # The return value is the number of elements in the array (n). | ||||
| function qsort(arr,k,  ArrInd,end) { | ||||
|     end = 0 | ||||
|     for (ArrInd in arr) | ||||
| 	k[++end] = ArrInd; | ||||
|     qsortseg(arr,k,1,end); | ||||
|     return end | ||||
| } | ||||
| 
 | ||||
| function qsortseg(arr,k,start,end,  left,right,sepval,tmp,tmpe,tmps) { | ||||
|     # handle two-element case explicitely for a tiny speedup | ||||
|     if ((end - start) == 1) { | ||||
| 	if (arr[tmps = k[start]] > arr[tmpe = k[end]]) { | ||||
| 	    k[start] = tmpe | ||||
| 	    k[end] = tmps | ||||
| 	} | ||||
| 	return | ||||
|     } | ||||
|     left = start; | ||||
|     right = end; | ||||
|     sepval = arr[k[int((left + right) / 2)]] | ||||
|     # Make every element <= sepval be to the left of every element > sepval | ||||
|     while (left < right) { | ||||
| 	while (arr[k[left]] < sepval) | ||||
| 	    left++ | ||||
| 	while (arr[k[right]] > sepval) | ||||
| 	    right-- | ||||
| 	if (left < right) { | ||||
| 	    tmp = k[left] | ||||
| 	    k[left++] = k[right] | ||||
| 	    k[right--] = tmp  | ||||
| 	} | ||||
|     } | ||||
|     if (left == right) | ||||
| 	if (arr[k[left]] < sepval) | ||||
| 	    left++ | ||||
| 	else | ||||
| 	    right-- | ||||
|     if (start < right) | ||||
| 	qsortseg(arr,k,start,right) | ||||
|     if (left < end) | ||||
| 	qsortseg(arr,k,left,end) | ||||
| } | ||||
| ' "$@" | ||||
							
								
								
									
										127
									
								
								examples/scripts.v2/pf
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								examples/scripts.v2/pf
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,127 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # | ||||
| # @(#) p.ksh 1.1 93/11/09 | ||||
| # p: page compressed & plain files in the order given  | ||||
| # 92/01/23 john h. dubois iii (john@armory.com) | ||||
| # 92/02/14 changed incorrect zpack to pcat | ||||
| # 92/02/16 added help | ||||
| # 92/10/11 search for file.Z and file.z if file not found | ||||
| # 92/10/18 pass options to pager | ||||
| # 93/11/09 Understand gzipped files too | ||||
| #          Wait after printing message about unreadable files | ||||
| #          Make less prompt include name of file being uncompressed | ||||
| # | ||||
| # conversion to bash v2 by Chet Ramey; renamed to pf | ||||
| # | ||||
| DefPager=/local/bin/less | ||||
| 
 | ||||
| istrue() | ||||
| { | ||||
| 	test 0 -ne "$1" | ||||
| } | ||||
| 
 | ||||
| warn() | ||||
| { | ||||
| 	echo "$@" 1>&2 | ||||
| } | ||||
| 
 | ||||
| if [ "$1" = -h ]; then | ||||
|     echo \ | ||||
| "$0: page a file. | ||||
| Usage: $0 [pager-option ...] [filename ...] | ||||
| Files are paged by the program specified in the user's PAGER | ||||
| environment variable, or by $DefPager if PAGER is not set. | ||||
| If no filename is given, text to page is read from the standard input. | ||||
| If filenames are given, they are either paged directly, or unpacked/ | ||||
| uncompressed and then paged.  Files are assumed to be in packed, compressed, | ||||
| or gzipped format if the filename ends in .Z, .z, or .gz respectively. | ||||
| If a filename that does not end in .Z, .z, or .gz is not found, it is | ||||
| searched for with one of those extensions attached. | ||||
| Each group of plain files is paged by a single instance of the pager. | ||||
| Each packed or compressed file is paged by a separate instance of the | ||||
| pager.  | ||||
| Initial arguments beginning with + or - are taken to be pager options and | ||||
| are passed to each instance of the pager.   | ||||
| If a pager option takes a value it should be given with the option as a | ||||
| single argument (with no space between the option and the value)." | ||||
|     exit 0 | ||||
| fi | ||||
| 
 | ||||
| # Get pager options | ||||
| while [ $# -gt 0 ]; do | ||||
|     case "$1" in | ||||
|     -*|+*)	Opts="$Opts $1" ; shift;; | ||||
|     *)	break;; | ||||
|     esac | ||||
| done | ||||
| 
 | ||||
| [ -z "$PAGER" ] && PAGER=$DefPager | ||||
| 
 | ||||
| # Read from stdin | ||||
| [ $# = 0 ] && exec $PAGER $Opts | ||||
| 
 | ||||
| typeset -i filenum=0 badfile=0 | ||||
| 
 | ||||
| for file; do | ||||
|     if [ ! -r "$file" ]; then | ||||
| 	case "$file" in | ||||
| 	*.[Zz]|*.gz) | ||||
| 		# Check if user specified a compressed file without giving its extension | ||||
| 		for ext in Z z gz; do | ||||
| 		    if [ -r "$file.$ext" ]; then | ||||
| 			file="$file.$ext" | ||||
| 			break | ||||
| 		    fi | ||||
| 		done;; | ||||
| 	esac | ||||
|     fi | ||||
|     if [ ! -r "$file" ]; then | ||||
| 	warn "$file: cannot read." | ||||
| 	badfile=1 | ||||
|     else | ||||
| 	files[filenum]=$file | ||||
| 	let filenum+=1 | ||||
|     fi | ||||
| done | ||||
| 
 | ||||
| if istrue $badfile && [ $filenum -gt 0 ]; then | ||||
|     echo -n "Press return to continue..." 1>&2 | ||||
|     read | ||||
| fi | ||||
| 
 | ||||
| unset plain | ||||
| 
 | ||||
| for file in "${files[@]}"; do | ||||
|     case "$file" in | ||||
|     *.[zZ]|*.gz) | ||||
| 	set -- Z zcat z pcat gz gzcat | ||||
| 	# Find correct uncompression program | ||||
| 	while [ $# -gt 0 ]; do | ||||
| 	    case "$file" in | ||||
| 	    *.$1) | ||||
| 		# Page any uncompressed files so that they will be read | ||||
| 		# in the correct order | ||||
| 		[ ${#plain[@]} -gt 0 ] && $PAGER $Opts "${plain[@]}" | ||||
| 		unset plain[*] | ||||
| 		# If page is less, set the prompt to include the name of | ||||
| 		# the file being uncompressed.  Escape the . in the extension | ||||
| 		# because less treats is specially in prompts (other dots | ||||
| 		# in filenames will still be mucked with). | ||||
| 		case "$PAGER" in | ||||
| 		*less)  Prompt="-P[${file%.$1}\\.$1] (%pb\\%)" ;; | ||||
| 		*)	unset Prompt ;; | ||||
| 		esac | ||||
| 		$2 "$file" | $PAGER "$Prompt" $Opts | ||||
| 		break | ||||
| 	    esac | ||||
| 	    shift 2 | ||||
| 	done | ||||
| 	;; | ||||
|     *)	plain[${#plain[@]}]=$file;; | ||||
|     esac | ||||
| done | ||||
| 
 | ||||
| # Page any uncompressed files that haven't been paged yet | ||||
| [ ${#plain[@]} -gt 0 ] && exec $PAGER $Opts "${plain[@]}" | ||||
							
								
								
									
										25
									
								
								examples/scripts.v2/pmtop
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								examples/scripts.v2/pmtop
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # pmtop - poor man's `top' for SunOS 4.x | ||||
| # | ||||
| 
 | ||||
| CLEAR=clear	# could also be 'tput clear' | ||||
| HEADER="USER       PID %CPU %MEM   SZ  RSS TT STAT START  TIME COMMAND" | ||||
| 
 | ||||
| if [ -n "$LINES" ]; then | ||||
| 	SS=$(( $LINES - 2 )) | ||||
| else | ||||
| 	SS=20 | ||||
| fi | ||||
| 
 | ||||
| while : | ||||
| do | ||||
| 	$CLEAR | ||||
| 	echo "$HEADER" | ||||
| 	ps -aux | sort -nr +2 | sed ${SS}q | ||||
| 	sleep 5 | ||||
| done | ||||
| 
 | ||||
| exit 0 | ||||
| 
 | ||||
| 	 | ||||
							
								
								
									
										122
									
								
								examples/scripts.v2/rename
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								examples/scripts.v2/rename
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,122 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # @(#) rename.ksh 1.1 94/05/10 | ||||
| # 90/06/01 John DuBois (spcecdt@armory.com) | ||||
| # 91/02/25 Improved help info | ||||
| # 92/06/07 remove quotes from around shell pattern as required by new ksh | ||||
| # 94/05/10 Exit if no globbing chars given. | ||||
| # | ||||
| # conversion to bash v2 syntax by Chet Ramey | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo "$usage | ||||
| All files that match oldpattern will be renamed with the | ||||
| filename components that match the constant parts of oldpattern | ||||
| changed to the corresponding constant parts of newpattern. | ||||
| The components of the filename that match variable parts of | ||||
| oldpattern will be preserved.  Variable parts in oldpattern | ||||
| must occur in the same order in newpattern.  Variables parts | ||||
| can be '?' and '*'. | ||||
| Example:  | ||||
| rename \"/tmp/foo*.ba.?\" \"/tmp/new*x?\" | ||||
| All files in /tmp that match foo*.ba.? will have the \"foo\" part | ||||
| replaced by \"new\" and the \".ba.\" part replaced by \"x\"." | ||||
| } | ||||
| 
 | ||||
| usage="usage: $name [-htv] oldpattern newpattern" | ||||
| name=${0##/} | ||||
| 
 | ||||
| while getopts "htv" opt; do | ||||
|     case "$opt" in | ||||
|     t) tell=true;; | ||||
|     v) verbose=true;; | ||||
|     h) phelp; exit 0;; | ||||
|     *) echo "$name: $usage" 1>&2; exit 2;; | ||||
|     esac | ||||
| done | ||||
| shift $((OPTIND - 1)) | ||||
| 
 | ||||
| if [ $# -lt 2 ]; then | ||||
|     phelp | ||||
|     exit 2 | ||||
| fi | ||||
| 
 | ||||
| oldpat=$1 | ||||
| newpat=$2 | ||||
| 
 | ||||
| set $1 | ||||
| if [ ! -a "$1" ]; then | ||||
|     echo "$name: no files match $oldpat." | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| typeset -i i=1 j | ||||
| 
 | ||||
| # Example oldpat: foo*.a | ||||
| # Example newpat: bar*.b | ||||
| 
 | ||||
| # Examples given for first iteration (in the example, the only interation) | ||||
| while :; do | ||||
|     case "$oldpat" in | ||||
|     *[\*\?]*)	;; | ||||
|     *)		break;; | ||||
|     esac | ||||
| 
 | ||||
|     # Get leftmost globbing pattern in oldpat | ||||
|     pat=${oldpat#*[\*\?]}	# pat=.a | ||||
|     pat=${oldpat%%"$pat"}	# pat=foo* | ||||
|     pat=${pat##*[!\?\*]}	# pat=* | ||||
|     # Find parts before & after pattern | ||||
|     oldpre[i]=${oldpat%%"$pat"*}	# oldpre[1]=foo | ||||
|     oldsuf[i]=${oldpat#*"$pat"}		# oldsuf[1]=.a | ||||
|     newpre[i]=${newpat%%"$pat"*}	# newpre[1]=bar | ||||
|     # Get rid of processed part of patterns | ||||
|     oldpat=${oldpat#${oldpre[i]}"$pat"}	# oldpat=.a | ||||
|     newpat=${newpat#${newpre[i]}"$pat"}	# newpat=.b | ||||
|     let i=i+1 | ||||
| done | ||||
| 
 | ||||
| if [ $i -eq 1 ]; then | ||||
|     print -u2 "No globbing chars in pattern." | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| oldpre[i]=${oldpat%%"$pat"*}	# oldpre[2]=.a | ||||
| oldsuf[i]=${oldpat#*"$pat"}	# oldsuf[2]=.a | ||||
| newpre[i]=${newpat%%"$pat"*}	# newpre[2]=.b | ||||
| 
 | ||||
| if [ -n "$verbose" ]; then | ||||
|     j=1 | ||||
|     while let "j < i"; do | ||||
| 	echo \ | ||||
| "Old prefix: ${oldpre[j]}   Old suffix: ${oldsuf[j]}   New prefix: ${newpre[j]}" | ||||
| 	let j=j+1 | ||||
|     done | ||||
| fi | ||||
| 
 | ||||
| # Example file: foox.a | ||||
| 
 | ||||
| for file; do | ||||
|     j=1 | ||||
|     origname=$file	# origname=foox.a | ||||
|     newfile= | ||||
|     while let "j <= i"; do | ||||
| 	# Peel off a prefix	interation	1		2 | ||||
| 	file=${file#${oldpre[j]}}		# file=x.a	file= | ||||
| 	# Save the part of this prefix that is to be retained | ||||
| 	const=${file%${oldsuf[j]}}		# const=x	const= | ||||
| 	newfile=$newfile${newpre[j]}$const	# newfile=barx	newfile=barx.b | ||||
| 	file=${file#$const}			# file=.a	file=.a | ||||
| 	let j=j+1 | ||||
|     done | ||||
|     if [ -n "$tell" ]; then | ||||
| 	echo "Would move \"$origname\" to \"$newfile\"." | ||||
|     else | ||||
| 	if [ -n "$verbose" ]; then | ||||
| 	    echo "Moving \"$origname\" to \"$newfile\"." | ||||
| 	fi | ||||
| 	mv $origname $newfile | ||||
|     fi | ||||
| done | ||||
							
								
								
									
										119
									
								
								examples/scripts.v2/repeat
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								examples/scripts.v2/repeat
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,119 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # repeat: repeat a command. | ||||
| # @(#) repeat.ksh 1.1 93/06/03 | ||||
| # 90/05 john h. dubois iii (john@armory.com) | ||||
| # 90/11 added help | ||||
| # 93/06/03 Added s, h, p, and v options | ||||
| # | ||||
| # conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| istrue() | ||||
| { | ||||
| 	test 0 -ne "$1" | ||||
| } | ||||
| 
 | ||||
| isfalse() | ||||
| { | ||||
| 	test 0 -eq "$1" | ||||
| } | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo "$name: repeatedly execute a command line. | ||||
| $Usage | ||||
| commandline is executed once for each integer from startcount through endcount | ||||
| inclusive.  The default for startcount is 1 if a positive endcount or no | ||||
| endcount is given, and -1 if a negative endcount is given.  A count | ||||
| parameter consisting of a single number is taken to be an endcount.  If | ||||
| only an endcount is given and it is positive, commandline is executed | ||||
| endcount times.  endcount may be less than startcount.  If no endcount is | ||||
| given (e.g. a count parameter of \"10-\"), commandline execution repeats | ||||
| indefinitely with the iteration variable incrementing in a positive | ||||
| direction.  A count parameter of consisting of \"-\" will repeat | ||||
| indefinitely starting with 1. | ||||
| 
 | ||||
| Note that quoting and variables in commandline are interpreted twice, once | ||||
| when it is passed to the repeat command, and once when it is actually executed. | ||||
| 
 | ||||
| The iteration variable is \"count\".  If \$count is used in commandline, make | ||||
| sure it is quoted with ' or \. | ||||
| 
 | ||||
| Options: | ||||
| -h: Print this help. | ||||
| -p: Print value of iteration variable on stderr before each iteration. | ||||
| -s <sec>: sleep for <sec> seconds after each iteration except the last. | ||||
| -v: Print start and end values before beginning." | ||||
| } | ||||
| 
 | ||||
| name=${0##*/} | ||||
| Usage="Usage: repeat [-hpv] [-s <sec>] [[startcount]-][endcount] command [arg ...]" | ||||
| 
 | ||||
| typeset -i count=1 forever=0 sleep=0 print=0 verbose=0 | ||||
| 
 | ||||
| while getopts :0123456789hpvs: opt; do | ||||
|     case $opt in | ||||
|     h) phelp; exit 0;; | ||||
|     s) sleep=$OPTARG || exit 1;; | ||||
|     p) print=1;; | ||||
|     v)verbose=1;; | ||||
|     [0-9]) break;; | ||||
|     +?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;; | ||||
|     ?)  echo "$name: $OPTARG: bad option.  Use -h for help." 1>&2; exit 2;; | ||||
|     esac | ||||
| done | ||||
|   | ||||
| # remove args that were options | ||||
| shift $((OPTIND-1)) | ||||
| 
 | ||||
| if [ $# -lt 2 ]; then | ||||
|     echo -e "$Usage\nUse -h for help." 1>&2 | ||||
|     exit 2 | ||||
| fi | ||||
| 
 | ||||
| case "$1" in | ||||
| -[0-9]*-|[0-9]*-) | ||||
|     # Start value only | ||||
|     count=${1%-} | ||||
|     forever=1 | ||||
|     ;; | ||||
| -[0-9]*-[0-9]*|[0-9]*-[0-9]*) | ||||
|     # Start and end value | ||||
|     s=${1%-} | ||||
|     end=${s##[0-9]*-} | ||||
|     count=${s%-$end} | ||||
|     ;; | ||||
| -[0-9]*|[0-9]*) | ||||
|     end=$1 | ||||
|     case "$end" in | ||||
|     -\*)	count=-1;; | ||||
|     esac | ||||
|     ;; | ||||
| -) | ||||
|     forever=1 | ||||
|     ;; | ||||
| *)  | ||||
|     echo "$name: bad count parameter: $1" 1>&2 | ||||
|     exit 1 | ||||
|     ;; | ||||
| esac | ||||
| 
 | ||||
| shift | ||||
| 
 | ||||
| [ -z "$end" -o $count -le "$end" ] && increment=1 || increment=-1 | ||||
| 
 | ||||
| istrue $verbose && echo "start=$count end=$end" 1>&2 | ||||
| 
 | ||||
| # Need to do this here so that up to this point, -0 will keep the leading - | ||||
| # and end will not be 0 if no value assigned | ||||
| typeset -i end | ||||
| 
 | ||||
| let end+=increment	# make loop inclusive of original endcount | ||||
| 
 | ||||
| while istrue $forever || [ $count -ne $end ]; do | ||||
|     istrue $print && echo $count 1>&2 | ||||
|     eval "$@" | ||||
|     istrue $sleep && sleep $sleep | ||||
|     let count+=increment | ||||
| done | ||||
							
								
								
									
										66
									
								
								examples/scripts.v2/shprof
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								examples/scripts.v2/shprof
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # shprof - a line profiler for shell scripts | ||||
| # | ||||
| # adapted from a similar program included in `The New KornShell' by | ||||
| # Bolsky and Korn and posted to usenet by bsh20858@challenger.fhda.edu | ||||
| # | ||||
| # converted to bash v2 syntax by Chet Ramey | ||||
| # | ||||
| TMPFILE=${TMP:-/tmp}/shprof$$ | ||||
| 
 | ||||
| trap 'rm -f $TMPFILE' EXIT | ||||
| 
 | ||||
| errexit() | ||||
| { | ||||
| 	echo $0: "$@" >&2 | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| # create script with profiling enabled | ||||
| cat > $TMPFILE <<- \_EOF_ | ||||
| 	declare -a _line | ||||
| 	_profend() | ||||
| 	{ | ||||
| 		case "$1" in | ||||
| 		/*|./*)	file="$1" ;; | ||||
| 		*) file=$(type -path "$1") ;; | ||||
| 		esac | ||||
| 
 | ||||
| 		echo "*** line profile for $file ***" | ||||
| 		i=1; | ||||
| 		while read -r && [ $i -le $NLINE ]; do | ||||
| 			count=${_line[$i]} | ||||
| 			if [ "$count" -gt 0 ]; then | ||||
| 				echo "[$count] $i: $REPLY" | ||||
| 			fi | ||||
| 			i=$((i + 1)) | ||||
| 		done <$file | ||||
| _EOF_ | ||||
| # make the profiling script remove itself after printing line stats | ||||
| echo "rm -f $TMPFILE" >> $TMPFILE | ||||
| cat >> $TMPFILE <<- \_EOF_ | ||||
| 	} | ||||
| 	_command=$1 | ||||
| 	shift | ||||
| 	i=1 | ||||
| 	NLINE=$(wc -l < "$_command") | ||||
| 	while [ $i -le $NLINE ]; do | ||||
| 		_line[$i]=0 | ||||
| 		i=$((i + 1)) | ||||
| 	done | ||||
| 	unset i | ||||
| 	trap "_profend ${_command}" EXIT | ||||
| 	trap '_line[$LINENO]=$((${_line[$LINENO]} + 1))' DEBUG | ||||
| 	LINENO=0 | ||||
| _EOF_ | ||||
| 
 | ||||
| case "$1" in | ||||
| /*|./*)	file=$1 ;; | ||||
| *)	file=$((type -path "$1")) ;; | ||||
| esac | ||||
| 
 | ||||
| cat "${file-$1}" >> $TMPFILE || errexit "${1}: cannot open" | ||||
| chmod +x $TMPFILE | ||||
| 
 | ||||
| exec -a "$file" $TMPFILE "$@" | ||||
							
								
								
									
										80
									
								
								examples/scripts.v2/untar
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								examples/scripts.v2/untar
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,80 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # @(#) untar.ksh 1.0 93/11/10 | ||||
| # 92/10/08 john h. dubois iii (john@armory.com) | ||||
| # 92/10/31 make it actually work if archive isn't in current dir! | ||||
| # 93/11/10 Added pack and gzip archive support | ||||
| # | ||||
| # conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo \ | ||||
| "$name: extract tar archives into directories, uncompressing if neccessary. | ||||
| Usage: $name archive[.tar[.[Z|gz]]] .. | ||||
| If an archive name given does not end in .tar, .tar.Z, or .tar.gz, it is | ||||
| searched for first with .tar added, then .tar.Z, and then .tar.gz added.  | ||||
| The real filename must end in either .tar, .tar.Z, or .tar.gz.  A | ||||
| directory with the name of the archive is created in the current directory | ||||
| (not necessarily the directory that the archive is in) if it does not | ||||
| exist, and the the contents of the archive are extracted into it.  | ||||
| Absolute pathnames in tarfiles are suppressed." | ||||
| } | ||||
| 
 | ||||
| if [ $# -eq 0 ]; then | ||||
|     phelp | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| name=${0##/} | ||||
| OWD=$PWD | ||||
| 
 | ||||
| for file; do | ||||
|     cd $OWD | ||||
|     case "$file" in | ||||
|     *.tar.Z)	ArchiveName=${file%%.tar.Z} zcat=zcat;; | ||||
|     *.tar.z)	ArchiveName=${file%%.tar.z} zcat=pcat;; | ||||
|     *.tar.gz)	ArchiveName=${file%%.tar.gz} zcat=gzcat;; | ||||
|     *)	ArchiveName=$file | ||||
| 	for ext in "" .Z .z .gz; do | ||||
| 	    if [ -f "$file.tar$ext" ]; then | ||||
| 		file="$file.tar$ext" | ||||
| 		break | ||||
| 	    fi | ||||
| 	done | ||||
| 	if [ ! -f "$file" ]; then | ||||
| 	    echo "$file: cannot find archive." 1>&2 | ||||
| 	    continue | ||||
| 	fi | ||||
| 	;; | ||||
|     esac | ||||
|     if [ ! -r "$file" ]; then | ||||
| 	echo "$file: cannot read." >&2 | ||||
| 	continue | ||||
|     fi | ||||
|     DirName=${ArchiveName##*/} | ||||
|     [ -d "$DirName" ] || { | ||||
| 	mkdir "$DirName" || { | ||||
| 		echo "$DirName: could not make archive directory." 1>&2 | ||||
| 		continue | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|     cd $DirName || { | ||||
| 	echo "$name: cannot cd to $DirName" 1>&2 | ||||
| 	continue | ||||
|     } | ||||
| 
 | ||||
|     case "$file" in | ||||
|     /*)	;; | ||||
|     *) file=$OWD/$file ;; | ||||
|     esac | ||||
| 
 | ||||
|     echo "Extracting archive $file into directory $DirName..." | ||||
|     case "$file" in | ||||
|     *.tar.Z|*.tar.z|*.tar.gz) $zcat $file | tar xvf -;; | ||||
|     *.tar) tar xvf $file;; | ||||
|     esac | ||||
|     echo "Done extracting archive $file into directory $DirName." | ||||
| done | ||||
							
								
								
									
										45
									
								
								examples/scripts.v2/uudec
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								examples/scripts.v2/uudec
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| : | ||||
| # @(#) uudec.sh 1.0 93/11/22 | ||||
| # 92/08/04 john@armory.com (John H. DuBois III) | ||||
| # 93/11/22 Added help. | ||||
| 
 | ||||
| isfalse() | ||||
| { | ||||
| 	test 0 -eq "$1" | ||||
| } | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| "$name: process uuencoded files. | ||||
| Usage: uudec [-h] filename ... | ||||
| Options: | ||||
| -h: Print this help." | ||||
| } | ||||
| 
 | ||||
| name=${0##*/} | ||||
| 
 | ||||
| typeset -i force=0 | ||||
| 
 | ||||
| while getopts "hf" opt; do | ||||
| 	case "$opt" in | ||||
| 	h)	phelp; exit 0;; | ||||
| 	f)	force=1;; | ||||
| 	*)	echo "$Usage" 1>&2; exit 2;; | ||||
| 	esac | ||||
| done | ||||
| 
 | ||||
| shift $((OPTIND - 1)) | ||||
| 
 | ||||
| for file; do | ||||
|     echo "$file" | ||||
|     while read b mode filename && [ "$b" != begin ]; do :; done < "$file" | ||||
|     if [ "$b" = begin ]; then | ||||
| 	if [ -f "$filename" ] && isfalse $force; then | ||||
| 	    echo "Output file \"$filename\" exists.  Not written." | ||||
| 	else | ||||
| 	    uudecode "$file" | ||||
| 	fi | ||||
|     else | ||||
| 	echo "No begin line." | ||||
|     fi | ||||
| done | ||||
							
								
								
									
										69
									
								
								examples/scripts.v2/uuenc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								examples/scripts.v2/uuenc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,69 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # @(#) uuenc.ksh 1.0 93/09/18 | ||||
| # 93/09/18 john h. dubois iii (john@armory.com) | ||||
| # | ||||
| # conversion to bash v2 syntax by Chet Ramey | ||||
| 
 | ||||
| istrue() | ||||
| { | ||||
| 	test 0 -ne "$1" | ||||
| } | ||||
| 
 | ||||
| isfalse() | ||||
| { | ||||
| 	test 0 -eq "$1" | ||||
| } | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo "$name: uuencode files. | ||||
| $Usage | ||||
| For each filename given, $name uuencodes the file, using the final | ||||
| component of the file's path as the stored filename in the uuencoded | ||||
| archive and, with a .${SUF} appended, as the name to store the archive in. | ||||
| Example:  | ||||
| $name /tmp/foo | ||||
| The file /tmp/foo is uuencoded, with \"foo\" stored as the name to uudecode | ||||
| the file into, and the output is stored in a file in the current directory | ||||
| with the name \"foo.${SUF}\". | ||||
| Options: | ||||
| -f: Normally, if the file the output would be stored in already exists, | ||||
|     it is not overwritten and an error message is printed.  If -f (force) | ||||
|     is given, it is silently overwritten. | ||||
| -h: Print this help." | ||||
| } | ||||
| 
 | ||||
| name=${0##*/} | ||||
| Usage="Usage: $name [-hf] <filename> ..." | ||||
| typeset -i force=0 | ||||
| 
 | ||||
| SUF=uu | ||||
| 
 | ||||
| while getopts :hf opt; do | ||||
|     case $opt in | ||||
|     h)	phelp; exit 0;; | ||||
|     f)	force=1;; | ||||
|     +?)	echo "$name: options should not be preceded by a '+'." 1>&2 ; exit 2;; | ||||
|     ?)	echo "$name: $OPTARG: bad option.  Use -h for help." 1>&2 ; exit 2;; | ||||
|     esac | ||||
| done | ||||
|   | ||||
| # remove args that were options | ||||
| shift $((OPTIND - 1)) | ||||
| 
 | ||||
| if [ $# -lt 1 ]; then | ||||
|     echo "$Usage\nUse -h for help." 1>&2 | ||||
|     exit | ||||
| fi | ||||
| 
 | ||||
| for file; do | ||||
|     tail=${file##*/} | ||||
|     out="$tail.${SUF}" | ||||
|     if isfalse $force && [ -a "$out" ]; then | ||||
| 	echo "$name: $out: file exists.  Use -f to overwrite." 1>&2 | ||||
|     else | ||||
| 	uuencode $file $tail > $out | ||||
|     fi | ||||
| done | ||||
							
								
								
									
										137
									
								
								examples/scripts.v2/vtree
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								examples/scripts.v2/vtree
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,137 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # vtree: visual directory tree | ||||
| # @(#) vtree.sh 1.1 91/07/01 | ||||
| # 90/04 john h. dubois iii (john@armory.com) | ||||
| # 91/07/01 fixed bug that caused problems when dir given on command line, | ||||
| #          added some info to help, changed to 4-space indenting | ||||
| # | ||||
| # conversion to bash v2 syntax done by Chet Ramey | ||||
| # | ||||
| help=\ | ||||
| "Syntax: vtree [startdir] [namelen=#] [linelen=#] | ||||
| If startdir is not specified, tree will start at current dir. | ||||
| 
 | ||||
| namelen specifies the minimum number of characters of a directory name that | ||||
| are guaranteed to be printed. | ||||
| This is a tradeoff between the number of tree levels that can fit on a | ||||
| screen line and the number of chars of each dir name that can be printed. | ||||
| In most cases it will be possible to print more than namelen characters of | ||||
| the name (a name up to namelen+1 chars will always be printed in full), | ||||
| but in some cases truncation down to namelen chars will occur. | ||||
| If truncation occurs, a '>' is printed at the end of the name. | ||||
| namelen=8 (the default) typically causes about 5 dirs/1000 to be truncated. | ||||
| namelen=7 typically causes about 10 dirs/1000 to be truncated. | ||||
| namelen=8 will allow 6 full length dirs to be printed in 79 columns. | ||||
| namelen=7 will allow 7 full length dirs to be printed in 79 columns; | ||||
| 
 | ||||
| linelen specifies the maximum number of characters to print on one screen | ||||
| line.  All characters beyond this are truncated.  The default is 1024. | ||||
| To avoid line wrap on an 80 column terminal with autowrap, use linelen=79. | ||||
| " | ||||
| 
 | ||||
| for i in "$@"; do | ||||
|     case $i in | ||||
|     -h) echo "$help"; exit;; | ||||
|     *=*) | ||||
|         vars="$vars $i" | ||||
|         ;; | ||||
|     *) | ||||
|         if [ ! -x $i -o ! -d $i ]; then     # arg must be a dir and executable | ||||
|             echo "$i: directory not accessible." | ||||
|             exit | ||||
|         fi | ||||
|         cd $i | ||||
|         ;; | ||||
|     esac | ||||
|     shift | ||||
| done | ||||
| 
 | ||||
| pwd     # print path of root of tree | ||||
| 
 | ||||
| # find all directories depth first; ignore permission errors | ||||
| find . -type d -print 2> /dev/null | \ | ||||
| gawk -F/ ' | ||||
| 
 | ||||
| # Do this block for NR == 1 instead of BEGIN because command line var | ||||
| # assignments are not done until after BEGIN block is executed. | ||||
| NR == 1 { | ||||
|     if (namelen) | ||||
|         MaxLen = namelen; | ||||
|     else | ||||
|         MaxLen = 8; | ||||
|     if (!linelen) | ||||
|         linelen = 1024 | ||||
|     HSpace = substr("              ",1,MaxLen);     # used to indent tree | ||||
|     n = 0;          # number of dirs found on one major branch | ||||
| } | ||||
| 
 | ||||
| $0 != "." {     # do for every line produced by find except tree root dir | ||||
|     if (NF == 2 && n > 0)   # print major branch whenever a new one starts | ||||
|         list(); | ||||
|     Depth[n] = NF - 1;      # record depth and name of dir | ||||
|      Name[n++] = $NF; | ||||
| } | ||||
| 
 | ||||
| END { | ||||
|     list()  # print last major branch | ||||
| } | ||||
| 
 | ||||
| function list() { | ||||
|     Line = Name[0];     # initialize first line of branch to be branch base | ||||
|     for (i = 1; i < n; i++) {   # for each name in major branch | ||||
|         if (Depth[i] == Depth[i-1] + 1) | ||||
|             AddHLink(); # if moving deeper into branch, use same line | ||||
|         else { | ||||
|             print substr(Line,1,linelen);   # last line is done; print it | ||||
|             Line = "";  # start new line | ||||
|             # print indentation, vert links, and vert/horiz links | ||||
|             for (d = 1; d < Depth[i] - 1; d++)  # for each level of indentation | ||||
|                 # if a vert. link has been established for this level | ||||
|                 if (VLink[d]) | ||||
|                     Line = Line HSpace " |  "; | ||||
|                 else        # print empty indentation | ||||
|                     Line = Line HSpace "    "; | ||||
|             # Print last part of vert. link | ||||
|             if (VLink[d] == i) { | ||||
|                 VLink[d] = 0;   # mark level for no vert link | ||||
|                 Line = Line HSpace " \\--"; | ||||
|             } | ||||
|             else | ||||
|                 Line = Line HSpace " |--"; | ||||
|         } | ||||
|         Line = Line Name[i];    # Add dir name to line | ||||
|     } | ||||
|     print substr(Line,1,linelen);   # print last line of major branch | ||||
|     n = 0;      # reset name counter | ||||
| } | ||||
| 
 | ||||
| function AddHLink() { | ||||
|     NDepth = Depth[i];  # Depth of this name | ||||
|     VLink[NDepth - 1] = 0; | ||||
|     # search until a name found at a level less than this one | ||||
|     for (j = i + 1; j < n && Depth[j] >= NDepth; j++) | ||||
|         # keep track of last name that VLink should connect to | ||||
|         if (Depth[j] == NDepth) | ||||
|             VLink[NDepth - 1] = j; | ||||
|     if (VLink[NDepth - 1]) { | ||||
|         NLine = substr(Line,1,(NDepth - 2) * (MaxLen + 4) + MaxLen + 1); | ||||
|         if (length(NLine) < length(Line)) | ||||
|             Line = substr(NLine,1,length(NLine) - 1) ">" | ||||
|         else | ||||
|             Line = NLine; | ||||
|         Line = Line substr("--------------+--", | ||||
|             18 - ((NDepth - 1) * (MaxLen + 4) - length(Line))); | ||||
|     } | ||||
|     else { | ||||
|         NLine = substr(Line,1,(NDepth - 2) * (MaxLen + 4) + MaxLen + 3); | ||||
|         if (length(NLine) < length(Line)) | ||||
|             Line = substr(NLine,1,length(NLine) - 1) ">" | ||||
|         else | ||||
|             Line = NLine; | ||||
|         Line = Line substr("-----------------", | ||||
|             1,(NDepth - 1) * (MaxLen + 4) - length(Line)); | ||||
|     } | ||||
| } | ||||
| ' $vars | ||||
							
								
								
									
										111
									
								
								examples/scripts.v2/where
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								examples/scripts.v2/where
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,111 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # original from: | ||||
| # @(#) where.ksh 1.1 94/07/11 | ||||
| # 91/01/12 john h. dubois iii (john@armory.com) | ||||
| # 92/08/10 Only print executable *files*. | ||||
| # 92/10/06 Print err msg if no match found. | ||||
| # 92/11/27 Added implicit * | ||||
| # 93/07/23 Print help only if -h is given. | ||||
| # 94/01/01 Added -x option | ||||
| # 94/07/11 Don't bother with eval | ||||
| # | ||||
| # conversion to bash v2 syntax done by Chet Ramey | ||||
| 
 | ||||
| name=${0##*/} | ||||
| Usage="Usage: $name [-hx] 'pattern' ..." | ||||
| typeset -i exact=0 | ||||
| 
 | ||||
| phelp() | ||||
| { | ||||
| echo "$name: find executable files in PATH that match patterns. | ||||
| $Usage | ||||
| $name searches each directory specified in the PATH environment variable | ||||
| for executable files that match the specified patterns.  Patterns are | ||||
| given as Korn shell filename patterns.  They are surrounded by implicit | ||||
| '*' characters, so that \"foo\" will match any executble file whose name | ||||
| contains contains \"foo\".  This can be overridden by using '^' and '$' to | ||||
| force a match to start at the beginning and end at the end of a filename | ||||
| respectively.  Characters that are special to the shell must generally | ||||
| be protected from the shell by surrounding them with quotes. | ||||
| Examples: | ||||
| $name foo | ||||
| lists all executable files in PATH that contain foo. | ||||
| $name '^b*sh$' | ||||
| lists all executable files in PATH that start with b and end with sh. | ||||
| An error message is printed if a no matching file is found for a pattern. | ||||
| Options: | ||||
| -h: Print this help. | ||||
| -x: Find exact matches only; equivalent to putting ^ and $ at the start | ||||
|     and end of each pattern." | ||||
| } | ||||
| 
 | ||||
| istrue() | ||||
| { | ||||
| 	test 0 -ne "$1" | ||||
| } | ||||
| 
 | ||||
| isfalse() | ||||
| { | ||||
| 	test 0 -eq "$1" | ||||
| } | ||||
| 
 | ||||
| while getopts "xh" opt; do | ||||
| 	case "$opt" in | ||||
| 	x)	exact=1;; | ||||
| 	h)	phelp ; exit 0;; | ||||
| 	*)	echo -e "$Usage\nUse -h for help." 1>&2; exit 2;; | ||||
| 	esac | ||||
| done | ||||
| 
 | ||||
| shift $((OPTIND-1)) | ||||
| 
 | ||||
| set +f			# make sure filename globbing is on | ||||
| Args=("$@")		# save args | ||||
| 
 | ||||
| OIFS=$IFS | ||||
| IFS=:		# Make PATH be split on : | ||||
| Paths=($PATH) | ||||
| IFS=$OIFS | ||||
| 
 | ||||
| for arg in "${Args[@]}"; do | ||||
| 
 | ||||
|     # get rid of leading ^ | ||||
|     if istrue $exact; then | ||||
| 	arg=${arg} | ||||
|     else | ||||
| 	    case "$arg" in | ||||
| 	    ^*)	arg=${arg#?};; | ||||
| 	    *) arg="*$arg" ;;	# Pattern is not anchored at start | ||||
| 	    esac | ||||
|     fi | ||||
| 
 | ||||
|     # get rid of trailing $ | ||||
|     if istrue $exact; then | ||||
| 	arg="$arg" | ||||
|     else | ||||
| 	case "$arg" in | ||||
| 	*\$)	arg=${arg%?} ;; | ||||
| 	*)	arg="$arg*" ;; | ||||
| 	esac | ||||
|     fi | ||||
| 
 | ||||
|     found=0	# Pattern not found yet | ||||
|     Patterns= | ||||
|     # Make a pattern for each element of PATH | ||||
|     for PathElem in "${Paths[@]}"; do | ||||
| 	[ -z "$PathElem" ] && PathElem=. | ||||
| 	Patterns="$Patterns $PathElem/$arg" | ||||
|     done | ||||
| 
 | ||||
|     # Find all pattern matches that are executable regular files. | ||||
|     for file in $Patterns; do | ||||
| 	if [ -x "$file" ] && [ -f "$file" ]; then | ||||
| 	    echo "$file" | ||||
| 	    found=1 | ||||
| 	fi | ||||
|     done | ||||
|     if [ $found = 0 ]; then | ||||
| 	echo "$arg: not found." 1>&2 | ||||
|     fi | ||||
| done | ||||
							
								
								
									
										0
									
								
								examples/scripts/bcsh.sh
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								examples/scripts/bcsh.sh
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										19
									
								
								examples/scripts/inpath
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										19
									
								
								examples/scripts/inpath
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| #! /bin/sh | ||||
| # | ||||
| # Search $PATH for a file the same name as $1; return TRUE if found. | ||||
| # | ||||
| 
 | ||||
| command=$1 | ||||
| [ -n "$command" ] || exit 1 | ||||
| 
 | ||||
| set `echo $PATH | sed 's/^:/.:/ | ||||
| 			s/::/:.:/g | ||||
| 			s/:$/:./ | ||||
| 			s/:/ /g'` | ||||
| 	 | ||||
| while [ $# -ne 0 ] ; do | ||||
| 	[ -f $1/$command ] && exit 0	# test -x not universal | ||||
| 	shift | ||||
| done | ||||
| 
 | ||||
| exit 1 | ||||
							
								
								
									
										51
									
								
								examples/scripts/nohup.bash
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								examples/scripts/nohup.bash
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | |||
| # | ||||
| # BASH VERSION OF nohup COMMAND | ||||
| # | ||||
| ctype() | ||||
| { | ||||
| 	path=$(builtin type -p $cmd | sed 1q) | ||||
| 	if [ -n "$path" ]; then | ||||
| 		echo "$path" | ||||
| 		return 0 | ||||
| 	else | ||||
| 		case "$cmd" in | ||||
| 		*/*)	[ -x "$cmd ] && { echo "$cmd" ; return 0; } ;; | ||||
| 		  *)	case "$(builtin type -t $cmd)" in | ||||
| 			"")	return 1;; | ||||
| 			*)	echo "$cmd" ; return 0;; | ||||
| 			esac ;; | ||||
| 		esac | ||||
| 	fi | ||||
| 	return 1 | ||||
| } | ||||
| 
 | ||||
| trap '' HUP		# ignore hangup | ||||
| command=$(ctype "$1") | ||||
| oldmask=$(umask) | ||||
| umask u=rw,og=		# default mode for nohup.out | ||||
| exec 0< /dev/null	# disconnect input | ||||
| if [ -t 1 ]; then	# redirect output if necessary | ||||
| 	if [ -w . ]; then | ||||
| 		echo 'Sending output to nohup.out' | ||||
| 		exec >> nohup.out | ||||
| 	else	echo "Sending output to $HOME/nohup.out" | ||||
| 		exec >> $HOME/nohup.out | ||||
| 	fi | ||||
| fi | ||||
| 
 | ||||
| umask "$oldmask" | ||||
| 
 | ||||
| # direct unit 2 to a file | ||||
| if [ -t 2 ]; then | ||||
| 	exec 2>&1 | ||||
| fi | ||||
| 
 | ||||
| # run the command | ||||
| case $command in | ||||
| */*)	exec "$@" | ||||
| 	;; | ||||
| time)	eval "$@" | ||||
| 	;; | ||||
| *)	"$@" | ||||
| 	;; | ||||
| esac | ||||
							
								
								
									
										0
									
								
								examples/scripts/precedence
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								examples/scripts/precedence
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										25
									
								
								examples/scripts/scrollbar
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										25
									
								
								examples/scripts/scrollbar
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| #!/bin/bash | ||||
| # | ||||
| # scrollbar - display scrolling text | ||||
| # | ||||
| # usage: scrollbar args | ||||
| # | ||||
| # A cute hack originally from Heiner Steven <hs@bintec.de> | ||||
| # | ||||
| # converted from ksh syntax to bash v2 syntax by Chet Ramey | ||||
| 
 | ||||
| WIDTH=${COLUMNS:-80} | ||||
| 
 | ||||
| [ $# -lt 1 ] && set -- TESTING | ||||
| 
 | ||||
| # Posix.2 compatible printf command or bash loadable builtin | ||||
| # in examples/loadables/printf | ||||
| Text=$(printf "%-${WIDTH}s" "$*") | ||||
| Text=$(echo "$Text" | tr ' ' '_') | ||||
| 
 | ||||
| while : | ||||
| do | ||||
| 	printf "%-.${WIDTH}s\r" "$Text" | ||||
| 	LastC=$(expr "$Text" : '.*\(.\)$') | ||||
| 	Text=$(printf "%-.${WIDTH}s" "$LastC$Text") | ||||
| done | ||||
							
								
								
									
										42
									
								
								examples/scripts/vtree2
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										42
									
								
								examples/scripts/vtree2
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| #!/bin/bash | ||||
| # | ||||
| # vtree - make a tree printout of the specified directory, with disk usage | ||||
| #	  in 1k blocks | ||||
| # | ||||
| # usage: vtree [-a] [dir] | ||||
| # | ||||
| # Original posted to Usenet sometime in February, 1996 | ||||
| # | ||||
| usage() | ||||
| { | ||||
| 	echo "vtree: usage: vtree [-a] [dir]" >&2 | ||||
| } | ||||
| 
 | ||||
| while getopts a opt | ||||
| do | ||||
| 	case "$opt" in | ||||
| 	a)	andfiles=-a ;; | ||||
| 	*)	usage ; exit 2 ;; | ||||
| 	esac | ||||
| done | ||||
| 
 | ||||
| shift $((OPTIND - 1)) | ||||
| 
 | ||||
| export BLOCKSIZE=1k	# 4.4 BSD systems need this | ||||
| 
 | ||||
| [ $# -eq 0 ] && set . | ||||
| 
 | ||||
| while [ $# -gt 0 ] | ||||
| do | ||||
| 	cd "$1" || { shift; [ $# -ge 1 ] && echo >&2; continue; } | ||||
| 	echo -n "$PWD" | ||||
| 
 | ||||
| 	du $andfiles | sort +1f | sed \ | ||||
| 		's/\([^	]*\)	\(.*\)/\2  (\1)/ | ||||
| 		'"s#^$1##"' | ||||
| 		s#[^/]*/\([^/]*\)$#|____\1# | ||||
| 		s#[^/]*/#|    #g' | ||||
| 	 | ||||
| 	[ $# -gt 1 ] && echo  | ||||
| 	shift | ||||
| done | ||||
							
								
								
									
										26
									
								
								examples/scripts/zprintf
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										26
									
								
								examples/scripts/zprintf
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| #! /bin/bash | ||||
| # | ||||
| # zprintf - function that calls gawk to do printf for those systems that | ||||
| #	    don't have a printf executable | ||||
| # | ||||
| # The format and arguments can have trailing commas, just like gawk | ||||
| # | ||||
| # example: | ||||
| #	zprintf 'Eat %x %x and suck %x!\n' 57005 48879 64206 | ||||
| # | ||||
| # Chet Ramey | ||||
| # chet@po.cwru.edu | ||||
| 
 | ||||
| [ $# -lt 1 ] && { | ||||
| 	echo "zprintf: usage: zprintf format [args ...]" >&2 | ||||
| 	exit 2 | ||||
| } | ||||
| 
 | ||||
| fmt="${1%,}" | ||||
| shift | ||||
| 
 | ||||
| for a in "$@"; do | ||||
| 	args="$args,\"${a%,}\"" | ||||
| done | ||||
| 
 | ||||
| gawk "BEGIN { printf \"$fmt\" $args }" | ||||
|  | @ -13,7 +13,6 @@ alias j="jobs -l" | |||
| alias l="ls -l " | ||||
| alias ll="ls -l" | ||||
| alias ls="ls -F" | ||||
| alias term='set noglob; eval `tset -Q -s `' | ||||
| alias pu="pushd" | ||||
| alias po="popd" | ||||
| 
 | ||||
|  | @ -53,11 +52,12 @@ seq () | |||
| {  | ||||
|     local lower upper output; | ||||
|     lower=$1 upper=$2; | ||||
| 
 | ||||
|     if [ $lower -ge $upper ]; then return; fi | ||||
|     while [ $lower -le $upper ]; | ||||
|     do | ||||
|         output="$output $lower"; | ||||
|         lower=$[ $lower + 1 ]; | ||||
|     done; | ||||
|     echo $output | ||||
| 	echo -n "$lower " | ||||
|         lower=$(($lower + 1)) | ||||
|     done | ||||
|     echo "$lower" | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,9 +2,9 @@ | |||
| # | ||||
| default_dir=/usr/local/lib/ | ||||
| 
 | ||||
| if [ "$PS1" ]; then | ||||
|   PS1='\u@\h(\#)$ ' | ||||
|   ignoreeof=3 | ||||
| if [ -n "$PS1" ]; then | ||||
| 	PS1='\u@\h(\#)\$ ' | ||||
| 	IGNOREEOF=3 | ||||
| fi | ||||
| 
 | ||||
| LOGIN_SHELL=true | ||||
|  | @ -12,9 +12,7 @@ LOGIN_SHELL=true | |||
| # If the user has her own init file, then use that one, else use the | ||||
| # canonical one. | ||||
| if [ -f ~/.bashrc ]; then | ||||
|   source ~/.bashrc | ||||
| else if [ -f ${default_dir}Bashrc ]; then | ||||
|   source ${default_dir}Bashrc; | ||||
|   fi | ||||
| 	. ~/.bashrc | ||||
| elif [ -f ${default_dir}Bashrc ]; then | ||||
| 	. ${default_dir}Bashrc; | ||||
| fi | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,57 +16,55 @@ X11=/usr/bin/X11 | |||
| 
 | ||||
| UTIL_PATH=$GNU:$X11 | ||||
| STANDARD_PATH=/usr/local/bin:/usr/ucb:/bin:/usr/bin:/usr/etc:/etc:/usr/games | ||||
| if [ "$HOSTTYPE" = "sony" ]; then STANDARD_PATH=STANDARD_PATH:/usr/sony/bin; fi | ||||
| 
 | ||||
| if [ -d $HOME/bin/$HOSTTYPE ]; then | ||||
|   MY_PATH=$HOME/bin/$HOSTTYPE | ||||
| 	MY_PATH=$HOME/bin/$HOSTTYPE | ||||
| fi | ||||
| 
 | ||||
| if [ -d $HOME/bin ]; then | ||||
|   MY_PATH=$MY_PATH:$HOME/bin | ||||
| 	MY_PATH=$MY_PATH:$HOME/bin | ||||
| fi | ||||
| 
 | ||||
| if [ -d /usr/hosts ]; then | ||||
|   STANDARD_PATH=$STANDARD_PATH:/usr/hosts | ||||
| 	STANDARD_PATH=$STANDARD_PATH:/usr/hosts | ||||
| fi | ||||
| 
 | ||||
| PATH=.:$MY_PATH:$UTIL_PATH:$STANDARD_PATH | ||||
| 
 | ||||
| # If running interactively, then: | ||||
| if [ "$PS1" ]; then | ||||
| 
 | ||||
|   # Set ignoreeof if you don't want EOF as the sole input to the shell to | ||||
|   # immediately signal a quit condition.  This only happens at the start | ||||
|   # of a line if the line is empty, and you haven't just deleted a character | ||||
|   # with C-d.  I turn this on in ~/.bash_profile so that only login shells | ||||
|   # have the right to be obnoxious. | ||||
|   # ignoreeof= | ||||
| 
 | ||||
|   # Set auto_resume if you want to resume on "emacs", as well as on | ||||
|   # "%emacs". | ||||
|   auto_resume= | ||||
| 
 | ||||
|   # Set notify if you want to be asynchronously notified about background | ||||
|   # job completion. | ||||
|   notify= | ||||
| 
 | ||||
|   # Make it so that failed `exec' commands don't flush this shell. | ||||
|   no_exit_on_failed_exec= | ||||
| 
 | ||||
|   if [ ! "$LOGIN_SHELL" ]; then | ||||
|     PS1="\u@\h\$ " | ||||
|   fi | ||||
| 
 | ||||
|   HISTSIZE=256 | ||||
|   MAILCHECK=60 | ||||
| 
 | ||||
|   # A couple of default aliases. | ||||
|   alias j='jobs -l' | ||||
|   alias po=popd | ||||
|   alias pu=pushd | ||||
|   alias ls='ls -F' | ||||
| 
 | ||||
|   if [ -f ~/.bash_aliases ]; then | ||||
|     source ~/.bash_aliases | ||||
|   fi | ||||
| # If not running interactively, then return | ||||
| if [ -z "$PS1" ]; then | ||||
| 	return | ||||
| fi | ||||
| 
 | ||||
| # Set ignoreeof if you don't want EOF as the sole input to the shell to | ||||
| # immediately signal a quit condition.  This only happens at the start | ||||
| # of a line if the line is empty, and you haven't just deleted a character | ||||
| # with C-d.  I turn this on in ~/.bash_profile so that only login shells | ||||
| # have the right to be obnoxious. | ||||
| # set -o ignoreeof | ||||
| 
 | ||||
| # Set auto_resume if you want to resume on "emacs", as well as on | ||||
| # "%emacs". | ||||
| auto_resume=exact | ||||
| 
 | ||||
| # Set notify if you want to be asynchronously notified about background | ||||
| # job completion. | ||||
| set -o notify | ||||
| 
 | ||||
| # Make it so that failed `exec' commands don't flush this shell. | ||||
| shopt -s execfail | ||||
| 
 | ||||
| if [ -z "$LOGIN_SHELL" ]; then | ||||
| 	PS1="\u@\h\$ " | ||||
| fi | ||||
| 
 | ||||
| HISTSIZE=256 | ||||
| MAILCHECK=60 | ||||
| 
 | ||||
| # A couple of default aliases. | ||||
| alias j='jobs -l' | ||||
| alias po=popd | ||||
| alias pu=pushd | ||||
| alias ls='ls -F' | ||||
| 
 | ||||
| [ -f ~/.bash_aliases ] && . ~/.bash_aliases | ||||
|  |  | |||
							
								
								
									
										5
									
								
								examples/startup-files/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								examples/startup-files/README
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| Some sample startup files.  The ones starting with capital letters | ||||
| are originally from Brian Fox.  The ones starting with lowercase | ||||
| letters are from Chet Ramey. | ||||
| 
 | ||||
| They will require changes for your environment. | ||||
|  | @ -1,52 +1,37 @@ | |||
| HOME=/usr/homes/chet | ||||
| MAIL=/usr/homes/chet/mbox | ||||
| # This is the filename where your incoming mail arrives. | ||||
| MAIL=~/mbox | ||||
| MAILCHECK=30 | ||||
| HISTFILE=/usr/homes/chet/.history | ||||
| 
 | ||||
| MACHINE=$(/usr/local/bin/machine) | ||||
| HOST=$(hostname) | ||||
| HISTFILE=~/.history/history.$HOSTNAME | ||||
| 
 | ||||
| PATH1=/usr/homes/chet/bin.$MACHINE:/usr/local/bin/gnu: | ||||
| PATH1=/usr/homes/chet/bin.$HOSTTYPE:/usr/local/bin/gnu: | ||||
| PATH2=/usr/local/bin:/usr/ucb:/bin:/usr/bin/X11:. | ||||
| PATH3=/usr/andrew/bin:/usr/bin:/usr/ibm:/usr/local/bin/mh:/usr/new/bin: | ||||
| PATH3=/usr/bin:/usr/new/bin:/usr/contrib/bin | ||||
| PATH=$PATH1:$PATH2:$PATH3 | ||||
| 
 | ||||
| EDITOR=/usr/homes/chet/bin.$MACHINE/ce | ||||
| VISUAL=/usr/homes/chet/bin.$MACHINE/ce | ||||
| FCEDIT=/usr/homes/chet/bin.$MACHINE/ce | ||||
| EDITOR=/usr/local/bin/ce VISUAL=/usr/local/bin/ce FCEDIT=/usr/local/bin/ce | ||||
| 
 | ||||
| if [ "$BASH" ] ; then | ||||
| 	SHELL=$BASH | ||||
| else | ||||
| 	SHELL=/bin/bash | ||||
| fi | ||||
| 
 | ||||
| if [ "$MACHINE" = "ibm032" ] ; then | ||||
| 	stty erase ^H | ||||
| fi | ||||
| 
 | ||||
| PAGER=/usr/ucb/more | ||||
| NNTPSERVER=kiwi | ||||
| NS=/nfs/cwjcc/fs1/ns-engr/proj/netsrv/cwpub/proto/src | ||||
| SHELL=${SHELL:-${BASH:-/bin/bash}} | ||||
| 
 | ||||
| PAGER=/usr/local/bin/less | ||||
| LESS='-i -e -M -P%t?f%f :stdin .?pb%pb\%:?lbLine %lb:?bbByte %bb:-...' | ||||
| # | ||||
| # Bogus 1003.2 variables.  This should really be in /etc/profile | ||||
| # | ||||
| LOGNAME=${USER-$(whoami)} | ||||
| TZ=EST5EDT | ||||
| TZ=US/Eastern | ||||
| 
 | ||||
| export HOME ENV VISUAL EDITOR MAIL SHELL PATH TERM  | ||||
| export PAGER LESS TERMCAP HISTSZIE HISTFILE | ||||
| export MAIL MAILCHECK HOST HOSTNAME NNTPSERVER NS LOGNAME TZ | ||||
| export HOME VISUAL EDITOR MAIL SHELL PATH TERM  | ||||
| export PAGER LESS TERMCAP HISTSIZE HISTFILE MAIL MAILCHECK LOGNAME TZ | ||||
| 
 | ||||
| PS1="${HOST}$ " | ||||
| PS1="${HOSTNAME}\$ " | ||||
| PS2='> ' | ||||
| export PS1 PS2 | ||||
| 
 | ||||
| umask 022 | ||||
| 
 | ||||
| if [ -f /unix ] ; then | ||||
| 	stty intr ^c | ||||
| 	stty intr ^c	# bogus | ||||
| fi | ||||
| 
 | ||||
| if [ -f ~/.bashrc ] ; then | ||||
|  |  | |||
|  | @ -1,35 +1,35 @@ | |||
| if [ "$PS1" != "" ] ; then | ||||
| 
 | ||||
| if [ -f /unix ] ; then | ||||
| 	alias ls='/bin/ls -CF' | ||||
| 	alias ll='/bin/ls -lCF' | ||||
| 	alias dir='/bin/ls -bCalF' | ||||
| else | ||||
| 	alias ls='/bin/ls -F' | ||||
| 	alias ll='/bin/ls -lF' | ||||
| 	alias dir='/bin/ls -balF' | ||||
| if [ -z "$PS1" ]; then | ||||
| 	return | ||||
| fi | ||||
| 
 | ||||
| # bogus | ||||
| if [ -f /unix ] ; then	 | ||||
| 	alias ls='/bin/ls -CF' | ||||
| else | ||||
| 	alias ls='/bin/ls -F' | ||||
| fi | ||||
| alias ll='ls -l' | ||||
| alias dir='ls -ba' | ||||
| 
 | ||||
| alias ss="ps -aux" | ||||
| alias mail=/usr/ucb/mail | ||||
| alias dot='ls .[a-zA-Z0-9]*' | ||||
| alias mroe=more | ||||
| alias pwd='echo $PWD' | ||||
| alias pdw='echo $PWD' | ||||
| alias news="xterm -g 80x45 -e rn -e &" | ||||
| alias back='cd $OLDPWD' | ||||
| alias manroff="nroff /usr/lib/tmac/tmac.an.4.3" | ||||
| alias laser="lpr -Palw2" | ||||
| alias lw="lpr -Palw2" | ||||
| alias dot='ls .[a-zA-Z0-9_]*' | ||||
| alias news="xterm -g 80x45 -e trn -e -S1 -N &" | ||||
| 
 | ||||
| alias c="clear" | ||||
| alias m="more" | ||||
| alias j="jobs" | ||||
| 
 | ||||
| # common misspellings | ||||
| alias mroe=more | ||||
| alias pdw=pwd | ||||
| 
 | ||||
| hash -p /usr/bin/mail mail | ||||
| 
 | ||||
| if [ -z "$HOST" ] ; then | ||||
| 	export HOST=`hostname` | ||||
| 	export HOST=${HOSTNAME} | ||||
| fi | ||||
| 
 | ||||
| history_control=ignoredups | ||||
| HISTIGNORE="[   ]*:&:bg:fg" | ||||
| 
 | ||||
| psgrep() | ||||
| { | ||||
|  | @ -57,10 +57,14 @@ term() | |||
| 	tset | ||||
| } | ||||
| 
 | ||||
| xtitle ()  | ||||
| {  | ||||
| 	echo -n -e "\033]0;$*\007" | ||||
| } | ||||
| 
 | ||||
| cd() | ||||
| { | ||||
| 	builtin cd $* | ||||
| 	xtitle $HOST: $PWD | ||||
| 	builtin cd "$@" && xtitle $HOST: $PWD | ||||
| } | ||||
| 
 | ||||
| bold() | ||||
|  | @ -126,14 +130,3 @@ function chmog() | |||
| 		chgrp $3 $4 | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| # | ||||
| # Source kshenv for ksh-compatibility definitions | ||||
| # | ||||
| 
 | ||||
| if [ -f ~/.kshenv ] ; then | ||||
| 	. ~/.kshenv | ||||
| fi | ||||
| 
 | ||||
| fi | ||||
| #end of .bashrc | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jari Aalto
				Jari Aalto