aboutsummaryrefslogtreecommitdiffstats
path: root/examples/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'examples/scripts')
-rwxr-xr-xexamples/scripts/adventure.sh553
-rwxr-xr-xexamples/scripts/bcsh.sh1254
-rw-r--r--examples/scripts/cat.sh12
-rw-r--r--examples/scripts/center24
-rw-r--r--examples/scripts/dd-ex.sh476
-rw-r--r--examples/scripts/fixfiles.bash92
-rw-r--r--examples/scripts/hanoi.bash21
-rwxr-xr-xexamples/scripts/inpath19
-rwxr-xr-xexamples/scripts/krand.bash74
-rw-r--r--examples/scripts/line-input.bash184
-rw-r--r--examples/scripts/nohup.bash51
-rwxr-xr-xexamples/scripts/precedence75
-rw-r--r--examples/scripts/randomcard.bash18
-rwxr-xr-xexamples/scripts/scrollbar25
-rwxr-xr-xexamples/scripts/scrollbar224
-rw-r--r--examples/scripts/self-repro9
-rw-r--r--examples/scripts/showperm.bash53
-rwxr-xr-xexamples/scripts/shprompt137
-rw-r--r--examples/scripts/spin.bash21
-rw-r--r--examples/scripts/timeout53
-rwxr-xr-xexamples/scripts/timeout229
-rw-r--r--examples/scripts/timeout391
-rwxr-xr-xexamples/scripts/vtree243
-rw-r--r--examples/scripts/vtree399
-rw-r--r--examples/scripts/vtree3a100
-rw-r--r--examples/scripts/websrv.sh230
-rwxr-xr-xexamples/scripts/xterm_title27
-rwxr-xr-xexamples/scripts/zprintf26
28 files changed, 3820 insertions, 0 deletions
diff --git a/examples/scripts/adventure.sh b/examples/scripts/adventure.sh
new file mode 100755
index 0000000..1694450
--- /dev/null
+++ b/examples/scripts/adventure.sh
@@ -0,0 +1,553 @@
+#!/bin/bash
+# ash -- "Adventure shell"
+# last edit: 86/04/21 D A Gwyn
+# SCCS ID: @(#)ash.sh 1.4
+
+OPATH=$PATH
+
+ask()
+{
+ echo -n "$@" '[y/n] '
+ read ans
+
+ case "$ans" in
+ y*|Y*)
+ return 0
+ ;;
+ *)
+ return 1
+ ;;
+ esac
+}
+
+CAT=${PAGER:-more}
+
+ash_inst()
+{
+ cat <<- EOF
+
+ Instructions for the Adventure shell
+
+ Welcome to the Adventure shell! In this exploration of the UNIX file
+ system, I will act as your eyes and hands. As you move around, I will
+ describe whatever is visible and will carry out your commands. The
+ general form of a command is
+ Verb Object Extra_stuff.
+ Most commands pay no attention to the "Extra_stuff", and many do not
+ need an "Object". A typical command is
+ get all
+ which picks up all files in the current "room" (directory). You can
+ find out what you are carrying by typing the command
+ inventory
+ The command "help" results in a full description of all commands that I
+ understand. To quit the Adventure shell, type
+ quit
+
+ There are UNIX monsters lurking in the background. These are also
+ known as "commands with arguments".
+
+ Good luck!
+ EOF
+}
+
+ash_help()
+{
+echo "I understand the following commands (synonyms in parentheses):"
+echo ""
+
+echo "change OBJECT to NEW_NAME changes the name of the object"
+echo "clone OBJECT as NEW_NAME duplicates the object"
+echo "drop OBJECTS leaves the objects in the room"
+echo "enter (go) PASSAGE takes the labeled passage"
+echo "examine OBJECTS describes the objects in detail"
+echo "feed OBJECT to MONSTER stuffs the object into a UNIX monster"
+echo "get (take) OBJECTS picks up the specified objects"
+echo "gripe (bug) report a problem with the Adventure shell"
+echo "help prints this summary"
+echo "inventory (i) tells what you are carrying"
+echo "kill (destroy) OBJECTS destroys the objects"
+echo "look (l) describes the room, including hidden objects"
+echo "open (read) OBJECT shows the contents of an object"
+echo "quit (exit) leaves the Adventure shell"
+echo "resurrect OBJECTS attempts to restore dead objects"
+echo "steal OBJECT from MONSTER obtains the object from a UNIX monster"
+echo "throw OBJECT at daemon feeds the object to the printer daemon"
+echo "up takes the overhead passage"
+echo "wake MONSTER awakens a UNIX monster"
+echo "where (w) tells you where you are"
+echo "xyzzy moves you to your home"
+}
+
+MAINT=chet@ins.cwru.edu
+
+PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin:.
+export PATH
+
+trap 'echo Ouch!' 2 3
+#trap '' 18 # disable Berkeley job control
+
+#ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; }
+ash_lk(){ echo " $1 " | fgrep -q " $2 " >/dev/null 2>&1 ; }
+ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; }
+ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; }
+
+# enable history, bang history expansion, and emacs editing
+set -o history
+set -o histexpand
+set -o emacs
+
+cd
+LIM=.limbo # $HOME/$LIM contains "destroyed" objects
+mkdir $LIM || {
+ echo "ash: cannot mkdir $LIM: exiting"
+ exit 1
+}
+KNAP=.knapsack # $HOME/$KNAP contains objects being "carried"
+if [ ! -d $KNAP ]
+then mkdir $KNAP >/dev/null 2>&1
+ if [ $? = 0 ]
+ then echo 'You found a discarded empty knapsack.'
+ else echo 'You have no knapsack to carry things in.'
+ exit 1
+ fi
+else echo 'One moment while I peek in your old knapsack...'
+fi
+
+kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\``
+
+if ask 'Welcome to the Adventure shell! Do you need instructions?'
+then
+ ash_inst
+ echo -n 'Type a newline to continue: '
+ read
+fi
+
+wiz=false
+cha=false
+prev=$LIM
+while :
+do room=`pwd`
+ if [ $room != $prev ]
+ then if [ $room = $HOME ]
+ then echo 'You are in your own home.'
+ else echo "You have entered $room."
+ fi
+ exs=
+ obs=
+ hexs=
+ hobs=
+ f=false
+ for i in `ls -a`
+ do case $i in
+ .|..) ;;
+ .*) if [ -f $i ]
+ then hobs="$hobs $i"
+ elif [ -d $i ]
+ then hexs="$hexs $i"
+ else f=true
+ fi
+ ;;
+ *) if [ -f $i ]
+ then obs="$obs $i"
+ elif [ -d $i ]
+ then exs="$exs $i"
+ else f=true
+ fi
+ ;;
+ esac
+ done
+ if [ "$obs" ]
+ then echo 'This room contains:'
+ ash_pr $obs
+ else echo 'The room looks empty.'
+ fi
+ if [ "$exs" ]
+ then echo 'There are exits labeled:'
+ ash_pr $exs
+ echo 'as well as a passage overhead.'
+ else echo 'There is a passage overhead.'
+ fi
+ if sh -c $f
+ then echo 'There are shadowy figures in the corner.'
+ fi
+ prev=$room
+ fi
+
+ read -e -p '-advsh> ' verb obj x # prompt is '-advsh> '
+ if [ $? != 0 ]
+ then verb=quit # EOF
+ fi
+
+ case $verb in
+ change) if [ "$obj" ]
+ then if ash_lk "$obs $hobs" "$obj"
+ then set -- $x
+ case "$1" in
+ to) if [ "$2" ]
+ then if [ -f $2 ]
+ then echo "You must destroy $2 first."
+ set --
+ fi
+ if [ "$2" ]
+ then if mv $obj $2 # >&- 2>&-
+ then echo "The $obj shimmers and turns into $2."
+ obs=`ash_rm "$2 $obs" "$obj"`
+ else echo "There is a cloud of smoke but the $obj is unchanged."
+ fi
+ fi
+ else echo 'To what?'
+ fi
+ ;;
+ *) echo "Change $obj to what?"
+ ;;
+ esac
+ else if ash_lk "$kn" "$obj"
+ then echo 'You must drop it first.'
+ else echo "I see no $obj here."
+ fi
+ fi
+ else echo 'Change what?'
+ fi
+ ;;
+ clone) if [ "$obj" ]
+ then if ash_lk "$obs $hobs" "$obj"
+ then if [ ! -r $obj ]
+ then echo "The $obj does not wish to be cloned."
+ else set -- $x
+ case "$1" in
+ as) if [ "$2" ]
+ then if [ -f $2 ]
+ then echo "You must destroy $2 first."
+ else if cp $obj $2 # >&- 2>&-
+ then echo "Poof! When the smoke clears, you see the new $2."
+ obs="$obs $2"
+ else echo 'You hear a dull thud but no clone appears.'
+ fi
+ fi
+ else echo 'As what?'
+ fi
+ ;;
+ *) echo "Clone $obj as what?"
+ ;;
+ esac
+ fi
+ else if ash_lk "$kn" "$obj"
+ then echo 'You must drop it first.'
+ else echo "I see no $obj here."
+ fi
+ fi
+ else echo 'Clone what?'
+ fi
+ ;;
+ drop) if [ "$obj" ]
+ then for it in $obj $x
+ do if ash_lk "$kn" "$it"
+ then if [ -w $it ]
+ then echo "You must destroy $it first."
+ else if mv $HOME/$KNAP/$it $it # >&- 2>&-
+ then echo "$it: dropped."
+ kn=`ash_rm "$kn" "$it"`
+ obs=`echo $it $obs`
+ else echo "The $it is caught in your knapsack."
+ fi
+ fi
+ else echo "You're not carrying the $it!"
+ fi
+ done
+ else echo 'Drop what?'
+ fi
+ ;;
+ enter|go) if [ "$obj" ]
+ then if [ $obj != up ]
+ then if ash_lk "$exs $hexs" "$obj"
+ then if [ -x $obj ]
+ then if cd $obj
+ then echo 'You squeeze through the passage.'
+ else echo "You can't go that direction."
+ fi
+ else echo 'An invisible force blocks your way.'
+ fi
+ else echo 'I see no such passage.'
+ fi
+ else if cd ..
+ then echo 'You struggle upwards.'
+ else echo "You can't reach that high."
+ fi
+ fi
+ else echo 'Which passage?'
+ fi
+ ;;
+ examine) if [ "$obj" ]
+ then if [ $obj = all ]
+ then $obj=`echo $obs $exs`
+ x=
+ fi
+ for it in $obj $x
+ do if ash_lk "$obs $hobs $exs $hexs" "$it"
+ then echo "Upon close inspection of the $it, you see:"
+ ls -ld $it 2>/dev/null
+ if [ $? != 0 ]
+ then echo "-- when you look directly at the $it, it vanishes."
+ fi
+ else if ash_lk "$kn" "$it"
+ then echo 'You must drop it first.'
+ else echo "I see no $it here."
+ fi
+ fi
+ done
+ else echo 'Examine what?'
+ fi
+ ;;
+ feed) if [ "$obj" ]
+ then if ash_lk "$obs $hobs" "$obj"
+ then set -- $x
+ case "$1" in
+ to) if [ "$2" ]
+ then shift
+ if PATH=$OPATH $* <$obj 2>/dev/null
+ then echo "The $1 monster devours your $obj."
+ if rm -f $obj # >&- 2>&-
+ then obs=`ash_rm "$obs" "$obj"`
+ else echo 'But he spits it back up.'
+ fi
+ else echo "The $1 monster holds his nose in disdain."
+ fi
+ else echo 'To what?'
+ fi
+ ;;
+ *) echo "Feed $obj to what?"
+ ;;
+ esac
+ else if ash_lk "$kn" "$obj"
+ then echo 'You must drop it first.'
+ else echo "I see no $obj here."
+ fi
+ fi
+ else echo 'Feed what?'
+ fi
+ ;;
+ get|take) if [ "$obj" ]
+ then if [ $obj = all ]
+ then obj="$obs"
+ x=
+ fi
+ for it in $obj $x
+ do if ash_lk "$obs $hobs" "$it"
+ then if ash_lk "$kn" "$it"
+ then echo 'You already have one.'
+ else if mv $it $HOME/$KNAP/$it # >&- 2>&-
+ then echo "$it: taken."
+ kn="$it $kn"
+ obs=`ash_rm "$obs" "$it"`
+ else echo "The $it is too heavy."
+ fi
+ fi
+ else echo "I see no $it here."
+ fi
+ done
+ else echo 'Get what?'
+ fi
+ ;;
+ gripe|bug) echo 'Please describe the problem and your situation at the time it failed.\nEnd the bug report with a line containing just a Ctrl-D.'
+ cat | mail $MAINT -s 'ash bug'
+ echo 'Thank you!'
+ ;;
+ help) ash_help
+ ;;
+ inventory|i) if [ "$kn" ]
+ then echo 'Your knapsack contains:'
+ ash_pr $kn
+ else echo 'You are poverty-stricken.'
+ fi
+ ;;
+ kill|destroy) if [ "$obj" ]
+ then if [ $obj = all ]
+ then x=
+ if ask "Do you really want to attempt to $verb them all?"
+ then obj=`echo $obs`
+ else echo 'Chicken!'
+ obj=
+ fi
+ fi
+ for it in $obj $x
+ do if ash_lk "$obs $hobs" "$it"
+ then if mv $it $HOME/$LIM # <&- >&- 2>&-
+ then if [ $verb = kill ]
+ then echo "The $it cannot defend himself; he dies."
+ else echo "You have destroyed the $it; it vanishes."
+ fi
+ obs=`ash_rm "$obs" "$it"`
+ else if [ $verb = kill ]
+ then echo "Your feeble blows are no match for the $it."
+ else echo "The $it is indestructible."
+ fi
+ fi
+ else if ash_lk "$kn" "$it"
+ then echo "You must drop the $it first."
+ found=false
+ else echo "I see no $it here."
+ fi
+ fi
+ done
+ else echo 'Kill what?'
+ fi
+ ;;
+ look|l) obs=`echo $obs $hobs`
+ hobs=
+ if [ "$obs" ]
+ then echo 'The room contains:'
+ ash_pr $obs
+ else echo 'The room is empty.'
+ fi
+ exs=`echo $exs $hexs`
+ hexs=
+ if [ "$exs" ]
+ then echo 'There are exits plainly labeled:'
+ ash_pr $exs
+ echo 'and a passage directly overhead.'
+ else echo 'The only exit is directly overhead.'
+ fi
+ ;;
+ magic) if [ "$obj" = mode ]
+ then if sh -c $cha
+ then echo 'You had your chance and you blew it.'
+ else if ask 'Are you a wizard?'
+ then echo -n 'Prove it! Say the magic word: '
+ read obj
+ if [ "$obj" = armadillo ]
+ then echo 'Yes, master!!'
+ wiz=true
+ else echo "Homie says: I don't think so"
+ cha=true
+ fi
+ else echo "I didn't think so."
+ fi
+ fi
+ else echo 'Nice try.'
+ fi
+ ;;
+ open|read) if [ "$obj" ]
+ then if ash_lk "$obs $hobs" "$obj"
+ then if [ -r $obj ]
+ then if [ -s $obj ]
+ then echo "Opening the $obj reveals:"
+ $CAT < $obj
+ if [ $? != 0 ]
+ then echo '-- oops, you lost the contents!'
+ fi
+ else echo "There is nothing inside the $obj."
+ fi
+ else echo "You do not have the proper tools to open the $obj."
+ fi
+ else if ash_lk "$kn" "$obj"
+ then echo 'You must drop it first.'
+ found=false
+ else echo "I see no $obj here."
+ fi
+ fi
+ else echo 'Open what?'
+ fi
+ ;;
+ quit|exit) if ask 'Do you really want to quit now?'
+ then if [ "$kn" ]
+ then echo 'The contents of your knapsack will still be there next time.'
+ fi
+ rm -rf $HOME/$LIM
+ echo 'See you later!'
+ exit 0
+ fi
+ ;;
+ resurrect) if [ "$obj" ]
+ then for it in $obj $x
+ do if ash_lk "$obs $hobs" "$it"
+ then echo "The $it is already alive and well."
+ else if mv $HOME/$LIM/$it $it # <&- >&- 2>&-
+ then echo "The $it staggers to his feet."
+ obs=`echo $it $obs`
+ else echo "There are sparks but no $it appears."
+ fi
+ fi
+ done
+ else echo 'Resurrect what?'
+ fi
+ ;;
+ steal) if [ "$obj" ]
+ then if ash_lk "$obs $hobs" "$obj"
+ then echo 'There is already one here.'
+ else set -- $x
+ case "$1" in
+ from) if [ "$2" ]
+ then shift
+ if PATH=$OPATH $* >$obj 2>/dev/null
+ then echo "The $1 monster drops the $obj."
+ obs=`echo $obj $obs`
+ else echo "The $1 monster runs away as you approach."
+ rm -f $obj # >&- 2>&-
+ fi
+ else echo 'From what?'
+ fi
+ ;;
+ *) echo "Steal $obj from what?"
+ ;;
+ esac
+ fi
+ else echo 'Steal what?'
+ fi
+ ;;
+ throw) if [ "$obj" ]
+ then if ash_lk "$obs $hobs" "$obj"
+ then set -- $x
+ case "$1" in
+ at) case "$2" in
+ daemon) if sh -c "lpr -r $obj"
+ then echo "The daemon catches the $obj, turns it into paper,\nand leaves it in the basket."
+ obs=`ash_rm "$obs" "$obj"`
+ else echo "The daemon is nowhere to be found."
+ fi
+ ;;
+ *) echo 'At what?'
+ ;;
+ esac
+ ;;
+ *) echo "Throw $obj at what?"
+ ;;
+ esac
+ else if ash_lk "$kn" "$obj"
+ then echo 'It is in your knapsack.'
+ found=false
+ else echo "I see no $obj here."
+ fi
+ fi
+ else echo 'Throw what?'
+ fi
+ ;;
+ u|up) if cd ..
+ then echo 'You pull yourself up a level.'
+ else echo "You can't reach that high."
+ fi
+ ;;
+ wake) if [ "$obj" ]
+ then echo "You awaken the $obj monster:"
+ PATH=$OPATH $obj $x
+ echo 'The monster slithers back into the darkness.'
+ else echo 'Wake what?'
+ fi
+ ;;
+ w|where) echo "You are in $room."
+ ;;
+ xyzzy) if cd
+ then echo 'A strange feeling comes over you.'
+ else echo 'Your spell fizzles out.'
+ fi
+ ;;
+ *) if [ "$verb" ]
+ then if sh -c $wiz
+ then PATH=$OPATH $verb $obj $x
+ else echo "I don't know how to \"$verb\"."
+ echo 'Type "help" for assistance.'
+ fi
+ else echo 'Say something!'
+ fi
+ ;;
+ esac
+done
diff --git a/examples/scripts/bcsh.sh b/examples/scripts/bcsh.sh
new file mode 100755
index 0000000..b810cab
--- /dev/null
+++ b/examples/scripts/bcsh.sh
@@ -0,0 +1,1254 @@
+# 1-Feb-86 09:37:35-MST,30567;000000000001
+# Return-Path: <unix-sources-request@BRL.ARPA>
+# Received: from BRL-TGR.ARPA by SIMTEL20.ARPA with TCP; Sat 1 Feb 86 09:36:16-MST
+# Received: from usenet by TGR.BRL.ARPA id a002623; 1 Feb 86 9:33 EST
+# From: chris <chris@globetek.uucp>
+# Newsgroups: net.sources
+# Subject: Improved Bcsh (Bourne Shell Cshell-Emulator)
+# Message-ID: <219@globetek.UUCP>
+# Date: 30 Jan 86 17:34:26 GMT
+# To: unix-sources@BRL-TGR.ARPA
+#
+# This is a new, improved version of my Bourne shell cshell-emulator.
+# The code has been cleaned up quite a bit, and a couple of new features
+# added (now supports 'noclobber' and 'iclobber' variables). A bug with
+# 'eval' that caused "illegal I/O" error messages on vanilla V7 shells has
+# also been fixed.
+
+# I have posted the program in its entirety because a context diff of the
+# old and new versions was longer than the new version...
+
+# --Chris
+# Bcsh -- A Simple Cshell-Like Command Pre-Processor For The Bourne Shell
+#
+# "Copyright (c) Chris Robertson, December 1985"
+#
+# This software may be used for any purpose provided the original
+# copyright notice and this notice are affixed thereto. No warranties of
+# any kind whatsoever are provided with this software, and it is hereby
+# understood that the author is not liable for any damagages arising
+# from the use of this software.
+#
+# Features Which the Cshell Does Not Have:
+# ----------------------------------------
+#
+# + command history persists across bcsh sessions
+# + global last-command editing via 'g^string1^string2^' syntax
+# + edit any command via $EDITOR or $VISUAL editors
+# + history file name, .bcshrc file name, alias file name, and number
+# of commands saved on termination can be set by environment variables
+# + prompt may evaluate commands, such as `pwd`, `date`, etc.
+# + the whole text of interactive 'for' and 'while' loops and 'if'
+# statements goes into the history list and may be re-run or edited
+# + multiple copies of commands and requests to see command history
+# are not added to the history list
+# + the history mechanism actually stores all commands entered in a
+# current session, not just $history of them. This means that you
+# can increase $history on the fly and at once have a larger history.
+#
+#
+# Synonyms:
+# ---------
+#
+# logout, exit, bye write out history file and exit
+# h, history show current history list
+#
+#
+# Aliases:
+# --------
+#
+# alias NAME CMND create an alias called NAME to run CMND
+# unalias NAME remove the alias NAME
+#
+# There are no 'current-session only' aliases -- all alias and unalias
+# commands are permanent, and stored in the $aliasfile.
+#
+# If an alias contains positional variables -- $1, $2, $*, etc. -- any
+# arguments following the alias name are considered to be values for
+# those variables, and the alias is turned into a command of the form
+# 'set - arguments;alias'. Otherwise, a simple substitution is performed
+# for the alias and the rest of the command preserved. The cshell
+# convention of using '\!:n' in an alias to get bits of the current
+# command is mercifully abandoned.
+#
+# Quotes are not necessary around the commands comprising an alias;
+# in fact, any enclosing quotes are stripped when the alias is added
+# to the file.
+#
+# A couple of typical aliases might be:
+#
+# goto cd $1;pwd
+# l ls -F
+#
+# Note that aliasing something to "commands;logout" will not work -- if
+# you want something to happen routinely on logout put it in the file
+# specified by $logoutfile, default = $HOME/.blogout.
+#
+#
+# Command Substitutions:
+# ----------------------
+#
+# !! substitute last command from history list
+# !!:N substitute Nth element of last command from
+# history list -- 0 = command name, 1 = 1st arg
+# !!:$ substitute last element of last command from
+# history list
+# !!:* substitute all arguments to last command
+# from history list
+# !NUMBER substitute command NUMBER from the history list
+# !NUMBER:N as above, but substitute Nth element, where
+# 0 = command name, 1 = 1st arg, etc.
+# !NUMBER:$ as above, but substitute last element
+# !NUMBER:* as above, but substitute all arguments
+# !-NUMBER substitute the command NUMBER lines from the
+# end of the history list; 1 = last command
+# !-NUMBER:N as above, but substitute Nth element, where
+# 0 = command name, 1 = 1st arg, etc.
+# !-NUMBER:$ as above, but substitute last element
+# !-NUMBER:* as above, but substitute all arguments
+# !?STRING substitute most-recent command from history list
+# containing STRING -- STRING must be enclosed in
+# braces if followed by any other characters
+# !?STRING:N as above, but substitute Nth element, where
+# 0 = command name, 1 = 1st arg, etc.
+# !?STRING:$ as above, but substitute last element
+# !?STRING:* as above, but substitute all arguments
+#
+#
+# Command Editing:
+# ----------------
+#
+# CMND~e edit CMND using $EDITOR, where CMND may be found
+# using a history substitution
+# CMND~v edit CMND using $VISUAL, where CMND may be found
+# using a history substitution
+# " ^string1^string2^ substitute string2 for string1 in last command"
+# command and run it
+# " g^string1^string2^ globally substitute string2 for string1 in "
+# last command and run it
+# !NUMBER:s/string1/string2/
+# substitute string2 for string1 in
+# command NUMBER and run it
+# !NUMBER:gs/string1/string2/
+# globally substitute string2 for string1 in
+# command NUMBER and run it
+# !?STRING:s/string1/string2/
+# substitute string2 for string1 in last command
+# containing STRING and run it
+# !?STRING:gs/string1/string2/
+# globally substitute string2 for string1 in last
+# command containing STRING and run it
+#
+# Any command which ends in the string ":p" is treated as a normal
+# command until all substitutions have been completed. The trailing
+# ":p" is then stripped, and the command is simply echoed and added to
+# the history list instead of being executed.
+#
+# None of the other colon extensions of the cshell are supported.
+#
+#
+# Shell Environment Variables:
+# ----------------------------
+#
+# EDITOR editor used by ~e command, default = "ed"
+# VISUAL editor used by ~v command, default = "vi"
+# MAIL your system mailbox
+# PAGER paging program used by history command, default = "more"
+# PS1 primary prompt
+# PS2 secondary prompt
+# history number of commands in history list, default = 22
+# histfile file history list is saved in, default = $HOME/.bhistory
+# savehist number of commands remembered from last bcsh session
+# aliasfile file of aliased commands, default = $HOME/.baliases
+# logoutfile file of commands to be executed before termination
+# inc_cmdno yes/no -- keep track of command numbers or not
+# noclobber if set, existing files are not overwritten by '>'
+# iclobber if both noclobber and iclobber are set, the user is
+# prompted for confirmation before existing files are
+# overwritten by '>'
+#
+# Note: if you are setting either noclobber or iclobber mid-session,
+# set them to 'yes'
+#
+#
+# Regular Shell Variables:
+# ------------------------
+#
+# Shell variables may be set via Bourne or cshell syntax, e.g., both
+# "set foo=bar" and "foo=bar" set a variable called "foo" with the value
+# "bar". However, all variables are automatically set as environment
+# variables, so there is no need to export them. Conversely, there
+# are NO local variables. Sorry, folks.
+#
+# A cshell-style "setenv" command is turned into a regular "set" command.
+#
+#
+# The Prompt:
+# ----------
+#
+# You may, if you wish, have a command executed in your prompt. If
+# the variable PS1 contains a dollar sign or a backquote, it is
+# evaluated and the result used as the prompt, provided the evaluation
+# did not produce a "not found" error message. The two special cases
+# of PS1 consisting solely of "$" or "$ " are handled correctly. For
+# example, to have the prompt contain the current directory followed
+# by a space, enter:
+#
+# PS1=\'echo "`pwd` "\'
+#
+# You need the backslashed single quotes to prevent the command being
+# evaluated by the variable-setting mechanism and the shell before it
+# is assigned to PS1.
+#
+# To include the command number in your prompt, enter the command:
+#
+# PS1=\'echo "$cmdno "\'
+#
+#
+# Shell Control-Flow Syntax:
+# --------------------------
+#
+# 'While', 'for', 'case', and 'if' commands entered in Bourne shell
+# syntax are executed as normal.
+#
+# A valiant attempt is made to convert 'foreach' loops into 'for' loops,
+# cshell-syntax 'while' loops into Bourne shell syntax, and 'switch'
+# statements into 'case' statements. I cannot guarantee to always get it
+# right. If you forget the 'do' in a 'while' or 'for' loop, or finish
+# them with 'end' instead of 'done', this will be corrected.
+#
+# Note that cshell-to-Bourne control flow conversions do not take place
+# if control is nested -- e.g., a 'foreach' inside a 'while' will fail.
+#
+# The simple-case cshell "if (condition) command" is turned into Bourne
+# syntax. Other 'if' statements are left alone apart from making the
+# 'then' a separate statement, because constructing a valid interactive
+# cshell 'if' statement is essentially an exercise in frustration anyway.
+# The cshell and Bourne shell have sufficiently different ideas about
+# conditions that if is probably best to resign yourself to learning
+# the Bourne shell conventions.
+#
+# Note that since most of the testing built-ins of the cshell are
+# not available in the Bourne shell, a complex condition in a 'while'
+# loop or an 'if' statement will probably fail.
+#
+#
+# Bugs, Caveats, etc.:
+# --------------------
+#
+# This is not a super-speedy program. Be patient, especially on startup.
+#
+# To the best of my knowledge this program should work on ANY Bourne
+# shell -- note that if your shell does not understand 'echo -n' you
+# will have to re-set the values of '$n' and '$c'.
+#
+# This program may run out of stack space on a 16-bit machine where
+# /bin/sh is not split-space.
+#
+# Mail checking is done every 10 commands if $MAIL is set in your
+# environment. For anything fancier, you will have to hack the code.
+#
+# Because commands are stuffed in a file before sh is invoked on them,
+# error messages from failed commands are ugly.
+#
+# Failed history substitutions either give nothing at all, or a
+# "not found" style of error message.
+#
+# A command history is kept whether you want it or not. This may be
+# perceived as a bug or a feature, depending on which side of bed you
+# got out on.
+#
+# If you want a real backslash in a command, you will have to type two
+# of them because the shell swallows the first backslash in the initial
+# command pickup. This means that to include a non-history '!' in a
+# command you need '\\!' -- a real wart, especially for net mail,
+# but unavoidable.
+#
+# Commands containing an '@' will break all sorts of things.
+#
+# Very complex history substitutions may fail.
+#
+# File names containing numbers may break numeric history sustitutions.
+#
+# Commands containing bizzare sequences of characters may conflict
+# with internal kludges.
+#
+# Aliasing something to "commands;logout" will not work -- if you
+# want something to happen routinely on logout, put it in the file
+# specified by $logoutfile, default = $HOME/.blogout.
+#
+# Please send all bug reports to ihnp4!utzoo!globetek!chris.
+# Flames will be posted to net.general with 'Reply-to' set to your
+# ' path... :-) '
+#
+#
+#
+# ************* VERY IMPORTANT NOTICE *************
+#
+# If your shell supports # comments, then REPLACE all the colon 'comments'
+# with # comments. If it does not, then REMOVE all the 'comment' lines from the
+# working copy of the file, as it will run MUCH faster -- the shell evaluates
+# lines starting with a colon but does not actually execute them, so you will
+# save the read-and-evaluate time by removing them.
+
+case "`echo -n foo`" in
+ -n*)
+ n=
+ c="\c"
+ ;;
+ foo)
+ n=-n
+ c=
+ ;;
+ *)
+ echo "Your 'echo' command is broken."
+ exit 1
+ ;;
+esac
+history=${history-22}
+savehist=${savehist-22}
+histfile=${histfile-$HOME/.bhistory}
+logoutfile=${logoutfile-$HOME/.blogout}
+EDITOR=${EDITOR-ed}
+VISUAL=${VISUAL-vi}
+PAGER=${PAGER-more}
+
+aliasfile=${aliasfile-$HOME/.baliases}
+
+# the alias file may contain 1 blank line, so a test -s will not work
+
+case "`cat $aliasfile 2> /dev/null`" in
+ "")
+ doalias=no
+ ;;
+ *)
+ doalias=yes
+ ;;
+esac
+
+if test -s "${sourcefile-$HOME/.bcshrc}"
+ then
+ . ${sourcefile-$HOME/.bcshrc}
+fi
+
+if test -s "$histfile"
+ then
+ cmdno="`set - \`wc -l $histfile\`;echo $1`"
+ cmdno="`expr \"$cmdno\" + 1`"
+ lastcmd="`sed -n '$p' $histfile`"
+ copy=false
+ ohist=$histfile
+ while test ! -w "$histfile"
+ do
+ echo "Cannot write to history file '$histfile'."
+ echo $n "Please enter a new history filename: $c"
+ read histfile
+ copy=true
+ done
+ if $copy
+ then
+ cp $ohist $histfile
+ fi
+else
+ cat /dev/null > $histfile
+ cmdno=1
+ lastcmd=
+fi
+
+# keep track of command number as the default
+
+inc_cmdno=${inc_cmdo-yes}
+
+# default prompts -- PS1 and PS2 may be SET but EMPTY, so '${PS1-% }' syntax
+# is not used here
+
+case "$PS1" in
+ "")
+ PS1="% "
+ ;;
+esac
+case "$PS2" in
+ "")
+ PS2="> "
+ ;;
+esac
+
+export histfile savehist history aliasfile EDITOR VISUAL PAGER cmdno PS1 PS2
+
+case "$MAIL" in
+ "")
+ ;;
+ *)
+ if [ -f $MAIL ]; then
+ mailsize=`set - \`wc -c $MAIL\`;echo $1`
+ else
+ mailsize=0
+ fi
+ ;;
+esac
+
+trap ':' 2
+trap exit 3
+trap "tail -n $savehist $histfile>/tmp/hist$$;uniq /tmp/hist$$ > $histfile;\
+rm -f /tmp/*$$;exit 0" 15
+
+getcmd=yes
+mailcheck=
+exclaim=
+echoit=
+mailprompt=
+
+while :
+do
+
+ run=yes
+ case "$mailprompt" in
+ "")
+ ;;
+ *)
+ echo "$mailprompt"
+ ;;
+ esac
+ case "$getcmd" in
+ yes)
+ : guess if the prompt should be evaluated or not
+ case "$PS1" in
+ \$|\$\ )
+ echo $n "$PS1$c"
+ ;;
+ *\`*|*\$*)
+ tmp="`(eval $PS1) 2>&1`"
+ case "$tmp" in
+ *not\ found)
+ echo $n "$PS1$c"
+ ;;
+ *)
+ echo $n "$tmp$c"
+ ;;
+ esac
+ ;;
+ *)
+ echo $n "$PS1$c"
+ ;;
+ esac
+
+ read cmd || cmd="exit"
+ ;;
+ *) ;;
+ esac
+
+ case "$MAIL" in
+ "")
+ ;;
+ *)
+ : check for mail every 10 commands
+ case "$mailcheck" in
+ 1111111111)
+ mailcheck=
+ if [ -f $MAIL ]; then
+ newsize="`set - \`wc -c $MAIL\`;echo $1`"
+ else
+ newsize=0
+ fi
+ if test "$newsize" -gt "$mailsize"; then
+ mailprompt="You have new mail"
+ else
+ mailprompt=
+ fi
+ mailsize=$newsize
+ ;;
+ *)
+ mailcheck=1$mailcheck
+ ;;
+ esac
+ ;;
+ esac
+ hist=no
+
+ case "$cmd" in
+ "")
+ continue
+ ;;
+ sh)
+ sh
+ run=no
+ ;;
+ !!)
+ cmd=$lastcmd
+ echoit=yes
+ getcmd=no
+ continue
+ ;;
+ *:p)
+ cmd="`expr \"$cmd\" : '\(.*\):p'` +~+p"
+ getcmd=no
+ continue
+ ;;
+ foreach[\ \ ]*)
+ while test "$line" != "end"; do
+ echo $n "$PS2$c"
+ read line
+ cmd="${cmd};$line"
+ done
+ echo "$cmd" > /tmp/bcsh$$
+ ed - /tmp/bcsh$$ << ++++
+ s/end/done/
+ s/foreach[ ]\(.*\)(/for \1 in /
+ s/)//
+ s/;/;do /
+ w
+++++
+ ;;
+ for[\ \ ]*|while[\ \ ]*)
+ # try to catch the most common cshell-to-Bourne-shell
+ # mistakes
+
+ echo $n "$PS2$c"
+ read line
+ case "$line" in
+ *do)
+ line="do :"
+ ;;
+ *do*)
+ ;;
+ *)
+ line="do $line"
+ ;;
+ esac
+
+ cmd="${cmd};$line"
+ while test "$line" != "done" && test "$line" != "end"
+ do
+ echo $n "$PS2$c"
+ read line
+ case "$line" in
+ end)
+ line=done
+ ;;
+ esac
+ cmd="${cmd};$line"
+ done
+ echo "$cmd" > /tmp/bcsh$$
+ ;;
+ if[\ \ ]*)
+ while test "$line" != "fi" && test "$line" != "endif"
+ do
+ echo $n "$PS2$c"
+ read line
+ case "$line" in
+ *[a-z]*then)
+ line="`expr \"$line\" : '\(.*\)then'`;then"
+ ;;
+ endif)
+ line=fi
+ ;;
+ esac
+ cmd="${cmd};$line"
+ done
+ echo "$cmd" > /tmp/bcsh$$
+ case "`grep then /tmp/bcsh$$`" in
+ "")
+ # fix 'if foo bar' cases
+
+ ed - /tmp/bcsh$$ << ++++
+ s/)/);then/
+ s/.*/;fi/
+ w
+++++
+ ;;
+ esac
+ ;;
+ case[\ \ ]*)
+ while test "$line" != "esac"
+ do
+ echo $n "$PS2$c"
+ read line
+ cmd="${cmd}@$line"
+ done
+ cmd="`echo \"$cmd\" | tr '@' ' '`"
+ echo "$cmd" > /tmp/bcsh$$
+ ;;
+ switch[\ \ ]*)
+ while test "$line" != "endsw"
+ do
+ echo $n "$PS2$c"
+ read line
+ cmd="${cmd}@$line"
+ done
+ echo "$cmd" > /tmp/bcsh$$
+ ed - /tmp/bcsh$$ << '++++'
+ 1,$s/@/\
+/g
+ g/switch.*(/s//case "/
+ s/)/" in/
+ 1,$s/case[ ]\(.*\):$/;;\
+ \1)/
+ 2d
+ 1,$s/endsw/;;\
+esac/
+ g/breaksw/s///
+ 1,$s/default.*/;;\
+ *)/
+ w
+++++
+ cmd="`cat /tmp/bcsh$$`"
+ ;;
+ *!*)
+ hist=yes
+ ;;
+ esac
+
+ case "$hist" in
+ yes)
+ # deal with genuine exclamation marks, go back and parse again
+
+ case "$cmd" in
+ *\>![\ \ ]*|*\\!*)
+ cmd="`echo \"$cmd\" | sed -e 's@\\!@REALEXCLAMATIONMARK@g'`"
+ exclaim=yes
+ getcmd=no
+ continue
+ ;;
+ esac
+
+ # break command into elements, parse each one
+
+ tmp=
+ for i in $cmd
+ do
+ # find element with !, peel off stuff up to !
+
+ case "$i" in
+ !)
+ # most likely a typo for !!, so fix it
+ front=
+ $i=!!
+ ;;
+ !!*)
+ front=
+ i="`expr \"$i\" : '.*\(!!.*\)'`"
+ ;;
+ *!!*)
+ front="`expr \"$i\" : '\(.*\)!!.*'`"
+ i="`expr \"$i\" : '.*\(!!.*\)'`"
+ ;;
+ !*)
+ front=
+ i="`expr \"$i\" : '.*!\(.*\)'`"
+ ;;
+ *)
+ tmp="$tmp$i "
+ continue
+ ;;
+ esac
+ case "$i" in
+ !!*)
+ # want last command
+
+ rest="`expr \"$i\" : '!!\(.*\)'`"
+ i=$lastcmd
+ ;;
+ -*)
+ # we want to search back through the history list
+
+ case "$i" in
+ -)
+ rest="`expr \"$i\" : '-\(.*\)'`"
+ i=$lastcmd
+ ;;
+ -[0-9]*)
+ wanted="`expr \"$i\" : '-\([0-9][0-9]*\).*'`"
+ rest="`expr \"$i\" : '-[0-9][0-9]*\(.*\)'`"
+ i="`tail -n $wanted $histfile | sed -e "1q"`"
+ ;;
+ esac
+ ;;
+ [0-9]*)
+ # find which number command is wanted
+
+ wanted="`expr \"$i\" : '\([0-9][0-9]*\).*'`"
+ rest="`expr \"$i\" : '[0-9][0-9]*\(.*\)'`"
+ i="`grep -n . $histfile | grep \"^$wanted\"`"
+ i="`expr \"$i\" : \"${wanted}.\(.*\)\"`"
+ ;;
+ \?*)
+
+ # find which 'command-contains' match is wanted
+
+ case "$i" in
+ \?{*}*)
+ wanted="`expr \"$i\" : '?{\(.*\)}.*'`"
+ rest="`expr \"$i\" : '?.*}\(.*\)'`"
+ ;;
+ \?*:*)
+ wanted="`expr \"$i\" : '?\(.*\):.*'`"
+ rest="`expr \"$i\" : '?.*\(:.*\)'`"
+ ;;
+ \?*)
+ wanted="`expr \"$i\" : '?\(.*\)'`"
+ rest=
+ ;;
+ esac
+ i="`grep \"$wanted\" $histfile | sed -n '$p'`"
+ ;;
+ *)
+ # find which 'start-of-command' match is wanted
+
+ case "$i" in
+ {*}*)
+ wanted="`expr \"$i\" : '{\(.*\)}.*'`"
+ rest="`expr \"$i\" : '.*}\(.*\)'`"
+ ;;
+ *:*)
+ wanted="`expr \"$i\" : '\(.*\):.*'`"
+ rest="`expr \"$i\" : '.*\(:.*\)'`"
+ ;;
+ *)
+ wanted="$i"
+ rest=
+ ;;
+ esac
+ i="`grep \"^$wanted\" $histfile | sed -n '$p'`"
+ ;;
+ esac
+
+ # see if we actually found anything to substitute
+
+ case "$i" in
+ "")
+ badsub="Event not found"
+ break
+ ;;
+ *)
+ badsub=no
+ ;;
+ esac
+
+ case "$rest" in
+ "")
+ tmp="$front$tmp$i "
+ continue
+ ;;
+ :[0-9]*)
+ # find which element of $i is wanted
+
+ number="`expr \"$rest\" : ':\([0-9][0-9]*\).*'`"
+ rest="`expr \"$rest\" : ':[0-9][0-9]*\(.*\)'`"
+
+ # count through $i till we get to the
+ # right element
+
+ counter=0
+ for element in $i
+ do
+ case "$counter" in
+ $number)
+ break
+ ;;
+ *)
+ counter="`expr \"$counter\" + 1`"
+ # counter=$[ $counter + 1 ]
+ ;;
+ esac
+ done
+ case "$counter" in
+ $number)
+ badsub=no
+ ;;
+ *)
+ badsub="Bad command element"
+ break
+ ;;
+ esac
+ tmp="$tmp$front$element$rest "
+ continue
+ ;;
+ :\$*)
+ # spin through $i till we hit the last element
+
+ rest="`expr \"$rest\" : ':\$\(.*\)'`"
+ for element in $i
+ do
+ :
+ done
+ tmp="$tmp$front$element$rest "
+ continue
+ ;;
+ :\**)
+ # we want all elements except the command itself
+
+ rest="`expr \"$rest\" : ':\*\(.*\)'`"
+ save=$i
+ set - $i
+ shift
+ case "$*" in
+ "")
+ badsub="No arguments to command '$save'"
+ break
+ ;;
+ *)
+ badsub=no
+ ;;
+ esac
+ tmp="$tmp$front$*$rest "
+ continue
+ ;;
+ :s*|:gs*)
+ # we are doing a substitution
+ # put / on end if needed
+
+ case "$rest" in
+ :s/*/*/*|:gs/*/*/*)
+ ;;
+ :s/*/*|:gs/*/*)
+ rest="${rest}/"
+ ;;
+ esac
+
+ # find what substitution is wanted
+
+ first="`expr \"$rest\" : ':*s\/\(.*\)\/.*\/.*'`"
+ second="`expr \"$i\" : ':*s/.*/\(.*\)/.*'`"
+
+ # see if it is a global substitution
+
+ case "$rest" in
+ :gs*)
+ global=g
+ ;;
+ :s*)
+ global=
+ ;;
+ esac
+ rest="`expr \"$rest\" : '.*/.*/.*/\(.*\)'`"
+ i="`echo \"$i\" | sed -e \"s@$first@$second@$global\"`"
+
+ # see if subsitution worked
+
+ case "$i" in
+ "")
+ badsub="Substiution failed"
+ break
+ ;;
+ *)
+ badsub=no
+ ;;
+ esac
+ tmp="$tmp$front$i$rest "
+ continue
+ ;;
+ *)
+ tmp="$tmp$front$i$rest "
+ ;;
+ esac
+ done
+ case "$badsub" in
+ no)
+ ;;
+ *)
+ echo "$badsub"
+ badsub=no
+ continue
+ ;;
+ esac
+ cmd="$tmp"
+ echoit=yes
+ getcmd=no
+ continue
+ ;;
+ *)
+ run=yes
+ ;;
+ esac
+
+ case "$cmd" in
+ *\^*\^*\^*)
+ # see if the substitution is global
+ case "$cmd" in
+ g*)
+ global=g
+ ;;
+ *)
+ global=
+ ;;
+ esac
+
+ # put a '^' on the end if necessary
+ case "$cmd" in
+ *\^)
+ ;;
+ *)
+ cmd="${cmd}^"
+ ;;
+ esac
+
+ # find what substitution is wanted
+
+ first="`expr \"$cmd\" : '*\^\(.*\)\^.*\^.*'`"
+ second="`expr \"$cmd\" : '*\^.*\^\(.*\)\^.*'`"
+ rest="`expr \"$cmd\" : '*\^.*\^.*\^\(.*\)'`"
+ cmd="`echo \"$lastcmd\" | sed -e \"s@$first@$second@$global\"`$rest"
+
+ # see if the substitution worked
+
+ case "$cmd" in
+ "")
+ echo "Substitution failed"
+ continue
+ ;;
+ esac
+ echoit=yes
+ getcmd=no
+ continue
+ ;;
+ *~e)
+ echo "$cmd" | sed -e "s@~e@@" > /tmp/bcsh$$
+ $EDITOR /tmp/bcsh$$
+ cmd="`cat /tmp/bcsh$$`"
+ getcmd=no
+ continue
+ ;;
+ *~v)
+ echo "$cmd" | sed -e "s@~v@@" > /tmp/bcsh$$
+ echo "$lastcmd" > /tmp/bcsh$$
+ $VISUAL /tmp/bcsh$$
+ cmd="`cat /tmp/bcsh$$`"
+ getcmd=no
+ continue
+ ;;
+ exec[\ \ ]*)
+ tail -n $savehist $histfile>/tmp/hist$$
+ uniq /tmp/hist$$ > $histfile
+ rm -f /tmp/*$$
+ echo $cmd > /tmp/cmd$$
+ . /tmp/cmd$$
+ ;;
+ login[\ \ ]*|newgrp[\ \ ]*)
+ tail -n $savehist $histfile>/tmp/hist$$
+ uniq /tmp/hist$$ > $histfile
+ rm -f /tmp/*$$
+ echo $cmd > /tmp/cmd$$
+ . /tmp/cmd$$
+ ;;
+ logout|exit|bye)
+ if test -s "$logoutfile"
+ then
+ # sh $logoutfile
+ $SHELL $logoutfile
+ fi
+ tail -n $savehist $histfile > /tmp/hist$$
+ uniq /tmp/hist$$ > $histfile
+ rm -f /tmp/*$$
+ exit 0
+ ;;
+ h|history)
+ grep -n . $histfile | tail -n $history | sed -e 's@:@ @' | $PAGER
+ continue
+ ;;
+ h[\ \ ]\|*|h[\ \ ]\>*|h\|*|h\>*)
+ cmd="`echo \"$cmd\" | sed -e \"s@h@grep -n . $histfile | tail -n $history | sed -e 's@:@ @'@\"`"
+ getcmd=no
+ continue
+ ;;
+ history[\ \ ]*\|*|history[\ \ ]*\>*)
+ cmd="`echo \"$cmd\" | sed -e \"s@history@grep -n . $histfile | tail -n $history | sed -e 's@:@ @'@\"`"
+ getcmd=no
+ continue
+ ;;
+ source[\ \ ]*)
+ set - $cmd
+ shift
+ echo . $* > /tmp/cmd$$
+ . /tmp/cmd$$
+ run=no
+ ;;
+ wait)
+ wait
+ run=no
+ ;;
+ .[\ \ ]*)
+ echo $cmd > /tmp/cmd$$
+ . /tmp/cmd$$
+ run=no
+ ;;
+ cd|cd[\ \ ]*)
+ # check if it will work first, or else this shell will terminate
+ # if the cd dies. If you have a built-in test, you might want
+ # to replace the try-it-and-see below with a couple of tests,
+ # but it is probably just as fast like this.
+
+ echo $cmd > /tmp/cmd$$
+ if ($SHELL /tmp/cmd$$) ; then
+ . /tmp/cmd$$
+ fi
+ run=no
+ ;;
+ awk[\ \ ]*|dd[\ \ ]*|cc[\ \ ]*|make[\ \ ]*)
+ # these are the only commands I can think of whose syntax
+ # includes an equals sign. Add others as you find them.
+
+ echo "$cmd" > /tmp/bcsh$$
+ ;;
+ setenv*|*=*)
+ # handle setting shell variables, turning cshell syntax to Bourne
+ # syntax -- note all variables must be exported or they will not
+ # be usable in other commands
+
+ echo "$cmd" > /tmp/cmd$$
+ ed - /tmp/cmd$$ << ++++
+ g/^setenv[ ]/s/[ ]/@/
+ g/^setenv@/s/[ ]/=/
+ g/^setenv@/s///
+ g/^set/s///
+ .t.
+ \$s/=.*//
+ s/^/export /
+ w
+++++
+ . /tmp/cmd$$
+ rm -f /tmp/cmd$$
+ run=no
+ ;;
+ unset[\ \ ]*|umask[\ \ ]*|export[\ \ ]*|set[\ \ ]*)
+ # handle commands which twiddle current environment
+
+ $cmd
+ run=no
+ ;;
+ alias|alias[\ \ ])
+ if [ -f $aliasfile ]; then
+ $PAGER $aliasfile
+ fi
+ lastcmd=$cmd
+ run=no
+ continue
+ ;;
+ alias[\ \ ]*)
+ case "$cmd" in
+ alias[\ \ ]\|*|alias[\ \ ]\>*)
+ cmd="`echo \"$cmd\" | sed -e \"s@alias@cat $aliasfile@\"`"
+ getcmd=no
+ continue
+ ;;
+ alias[\ \ ]*[\ \ ]*)
+ ;;
+ *)
+ echo "Syntax: alias name command"
+ cmd=
+ continue
+ ;;
+ esac
+ set - $cmd
+ shift
+ cmd="$*"
+
+ # make sure there is always 1 blank line in file so
+ # unaliasing will always work -- ed normally refuses
+ # to write an empty file
+ echo "" >> $aliasfile
+ cat << ++++ >> $aliasfile
+$cmd
+++++
+
+# ed - $aliasfile << '++++'
+# g/alias[ ]/s///
+# g/^['"]\(.*\)['"]$/s//\1/
+# g/^/s//alias /
+# w
+#++++
+
+ sort -u -o $aliasfile $aliasfile
+ doalias=yes
+ cmd="alias $cmd"
+ run=no
+ ;;
+ unalias[\ \ ]*)
+ set - $cmd
+ case "$#" in
+ 2)
+ cmd=$2
+ ;;
+ *)
+ echo "Syntax: unalias alias_name"
+ continue
+ ;;
+ esac
+ ed - $aliasfile << ++++
+ /^$cmd[ ]/d
+ w
+++++
+ case "`set - \`wc -l $aliasfile\`;echo $1`" in
+ 1)
+ # just removed last alias
+ doalias=no
+ ;;
+ esac
+ run=no
+ ;;
+ *)
+ case "$doalias" in
+ yes)
+ set - $cmd
+ tmp="`grep \"^$1 \" $aliasfile`"
+ case "$tmp" in
+ $1[\ \ ]*)
+ shift
+ cmd=$*
+ set - $tmp
+ shift
+ tmp=$*
+ case "$tmp" in
+ *\$*)
+ # uses positional variables
+
+ cmd="set - $cmd ; $tmp"
+ getcmd=no
+ continue
+ ;;
+ *)
+ cmd="$tmp $cmd"
+ getcmd=no
+ continue
+ ;;
+ esac
+ ;;
+ *)
+ echo "$cmd" > /tmp/bcsh$$
+ ;;
+ esac
+ ;;
+ no)
+ echo "$cmd" > /tmp/bcsh$$
+ ;;
+ esac
+ ;;
+ esac
+
+ case "$cmd" in
+ *+~+p)
+ cmd="`expr \"$cmd\" : '\(.*\)+~+p'`"
+ echoit=yes
+ run=no
+ ;;
+ esac
+
+ case "$cmd" in
+ "")
+ continue
+ ;;
+ *)
+ case "$exclaim" in
+ yes)
+ cmd="`echo \"$cmd\" | sed -e 's@REALEXCLAMATIONMARK@!@g'`"
+ echo "$cmd" > /tmp/bcsh$$
+ ;;
+ esac
+ case "$echoit" in
+ yes)
+ echo $cmd
+ ;;
+ esac
+ case "$run" in
+ yes)
+ case "${noclobber+yes}" in
+ yes)
+ case "$cmd" in
+ *\>![\ \ ]*)
+ ed - /tmp/bcsh$$ << ++++
+ g/>!/s//>/
+ w
+++++
+ ;;
+ *\>\>*)
+ ;;
+ *\>*)
+ outfile="`expr \"$cmd\" : '.*>\(.*\)'`"
+ case "$outfile" in
+ \&*)
+ ;;
+ *)
+ set - $outfile
+ outfile="$1"
+ if test -s "$outfile"
+ then
+ case "${iclobber+yes}" in
+ yes)
+ echo $n "Overwrite ${outfile}? $c"
+ read answer
+ case "$answer" in
+ y*)
+ ;;
+ *)
+ echo ':' > /tmp/bcsh$$
+ ;;
+ esac
+ ;;
+ *)
+ echo "${outfile}: file exists"
+ echo ':' > /tmp/bcsh$$
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *)
+ case "$cmd" in
+ *\>![\ \ ]*)
+ ed - /tmp/bcsh$$ << ++++
+ g/>!/s//>/g
+ w
+++++
+ ;;
+ esac
+ ;;
+ esac
+ (trap 'exit 1' 2 3; $BASH /tmp/bcsh$$)
+ ;;
+ esac
+ case "$cmd" in
+ $lastcmd)
+ ;;
+ *)
+ case "$exclaim" in
+ yes)
+ cmd="`echo \"$cmd\" | sed -e 's@!@\\\\!@g'`"
+ ;;
+ esac
+
+ cat << ++++ >> $histfile
+$cmd
+++++
+ lastcmd=$cmd
+
+ case "$inc_cmdno" in
+ yes)
+ cmdno="`expr \"$cmdno\" + 1`"
+ # cmdno=$[$cmdno + 1]
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+
+ # The next commented-out line sets the prompt to include the command
+ # number -- you should only un-comment this if it is the ONLY thing
+ # you ever want as your prompt, because it will override attempts
+ # to set PS1 from the command level. If you want the command number
+ # in your prompt without sacrificing the ability to change the prompt
+ # later, replace the default setting for PS1 before the beginning of
+ # the main loop with the following: PS1='echo -n "${cmdno}% "'
+ # Doing it this way is, however, slower than the simple version below.
+
+ PS1="${cmdno}% "
+
+ getcmd=yes
+ echoit=no
+ exclaim=no
+done
+exit 0
+
+# Christine Robertson {linus, ihnp4, decvax}!utzoo!globetek!chris
diff --git a/examples/scripts/cat.sh b/examples/scripts/cat.sh
new file mode 100644
index 0000000..3e65b3f
--- /dev/null
+++ b/examples/scripts/cat.sh
@@ -0,0 +1,12 @@
+shcat()
+{
+ while read -r ; do
+ printf "%s\n" "$REPLY"
+ done
+}
+
+if [ -n "$1" ]; then
+ shcat < "$1"
+else
+ shcat
+fi
diff --git a/examples/scripts/center b/examples/scripts/center
new file mode 100644
index 0000000..8d367d3
--- /dev/null
+++ b/examples/scripts/center
@@ -0,0 +1,24 @@
+#! /bin/bash
+#
+# center - center a group of lines
+#
+# tabs in the lines might cause this to look a little bit off
+#
+#
+
+width=${COLUMNS:-80}
+
+if [[ $# == 0 ]]
+then
+ set -- /dev/stdin
+fi
+
+for file
+do
+ while read -r
+ do
+ printf "%*s\n" $(( (width+${#REPLY})/2 )) "$REPLY"
+ done < $file
+done
+
+exit 0
diff --git a/examples/scripts/dd-ex.sh b/examples/scripts/dd-ex.sh
new file mode 100644
index 0000000..fafc83f
--- /dev/null
+++ b/examples/scripts/dd-ex.sh
@@ -0,0 +1,476 @@
+#!/bin/sh
+
+# this is a line editor using only /bin/sh, /bin/dd and /bin/rm
+
+# /bin/rm is not really required, but it is nice to clean up temporary files
+
+PATH=
+dd=/bin/dd
+rm=/bin/rm
+
+# temporary files we might need
+tmp=/tmp/silly.$$
+ed=/tmp/ed.$$
+trap "$rm -f $tmp $tmp.1 $tmp.2 $tmp.3 $tmp.4 $tmp.5 $tmp.6 $ed.a $ed.b $ed.c; exit" 0 1 2 3
+
+# from now on, no more rm - the above trap is enough
+unset rm
+
+# we do interesting things with IFS, but better save it...
+saveIFS="$IFS"
+
+# in case "echo" is not a shell builtin...
+
+Echo () {
+case "$1" in
+ -n) shift
+ $dd of=$tmp 2>/dev/null <<EOF
+$@
+EOF
+ IFS="+"
+ set `$dd if=$tmp bs=1 of=/dev/null skip=1 2>&1`
+ IFS="$saveIFS"
+ $dd if=$tmp bs=1 count=$1 2>/dev/null
+ ;;
+ *) $dd 2>/dev/null <<EOF
+$@
+EOF
+ ;;
+esac
+}
+
+# this is used to generate garbage files
+
+true () {
+ return 0
+}
+
+false () {
+ return 1
+}
+
+zero () {
+ ( trap 'go=false' 13
+ go=true
+ while $go
+ do
+ $dd "if=$0"
+ case "$?" in
+ 0) ;;
+ *) go=false ;;
+ esac
+ done
+ ) 2>/dev/null
+}
+
+# arithmetic using dd!
+
+# add variable n1 n2 n3...
+# assigns n1+n2+n3+... to variable
+
+add () {
+ result="$1"
+ shift
+ $dd if=/dev/null of=$tmp bs=1 2>/dev/null
+ for n in "$@"
+ do
+ case "$n" in
+ 0) ;;
+ *) zero | $dd of=$tmp.1 bs=1 "count=$n" 2>/dev/null
+ ( $dd if=$tmp; $dd if=$tmp.1 ) 2>/dev/null | $dd of=$tmp.2 2>/dev/null
+ $dd if=$tmp.2 of=$tmp 2>/dev/null
+ ;;
+ esac
+ done
+ IFS="+"
+ set `$dd if=$tmp bs=1 of=/dev/null 2>&1`
+ IFS="$saveIFS"
+ eval $result='$1'
+}
+
+# subtract variable n1 n2
+# subtracts n2 from n1, assigns result to variable
+
+subtract () {
+ result="$1"
+ zero | $dd of=$tmp bs=1 "count=$2" 2>/dev/null
+ IFS="+"
+ set `$dd if=$tmp bs=1 of=/dev/null "skip=$3" 2>&1`
+ IFS="$saveIFS"
+ case "$1" in
+ dd*) set 0 ;;
+ esac
+ eval $result='$1'
+}
+
+# multiply variable n1 n2
+# variable = n1 * n2
+
+multiply () {
+ result="$1"
+ zero | $dd "bs=$2" of=$tmp "count=$3" 2>/dev/null
+ IFS="+"
+ set `$dd if=$tmp bs=1 of=/dev/null 2>&1`
+ IFS="$saveIFS"
+ eval $result='$1'
+}
+
+# divide variable n1 n2
+# variable = int( n1 / n2 )
+
+divide () {
+ result="$1"
+ zero | $dd bs=1 of=$tmp "count=$2" 2>/dev/null
+ IFS="+"
+ set `$dd if=$tmp "bs=$3" of=/dev/null 2>&1`
+ IFS="$saveIFS"
+ eval $result='$1'
+}
+
+# compare variable n1 n2 sets variable to lt if n1<n2, gt if n1>n2, eq if n1==n2
+
+compare () {
+ res="$1"
+ n1="$2"
+ n2="$3"
+ subtract somename "$n1" "$n2"
+ case "$somename" in
+ 0) ;;
+ *) eval $res=gt; return;
+ esac
+ subtract somename "$n2" "$n1"
+ case "$somename" in
+ 0) ;;
+ *) eval $res=lt; return;
+ esac
+ eval $res=eq
+}
+
+# lt n1 n2 returns true if n1 < n2
+
+lt () {
+ n1="$1"
+ n2="$2"
+ subtract somename "$n2" "$n1"
+ case "$somename" in
+ 0) return 1 ;;
+ esac
+ return 0
+}
+
+# le n1 n2 returns true if n1 <= n2
+
+le () {
+ n1="$1"
+ n2="$2"
+ subtract somename "$n1" "$n2"
+ case "$somename" in
+ 0) return 0 ;;
+ esac
+ return 1
+}
+
+# gt n1 n2 returns true if n1 > n2
+
+gt () {
+ n1="$1"
+ n2="$2"
+ subtract somename "$n1" "$n2"
+ case "$somename" in
+ 0) return 1 ;;
+ esac
+ return 0
+}
+
+# ge n1 n2 returns true if n1 >= n2
+
+ge () {
+ n1="$1"
+ n2="$2"
+ subtract somename "$n2" "$n1"
+ case "$somename" in
+ 0) return 0 ;;
+ esac
+ return 1
+}
+
+# useful functions for the line editor
+
+# open a file - copy it to the buffers
+
+open () {
+ file="$1"
+ set `$dd "if=$file" of=/dev/null 2>&1`
+ case "$1" in
+ dd*) return 1
+ esac
+ # copy the first line to $ed.c
+ go=true
+ len=0
+ while $go
+ do
+ case "`$dd "if=$file" bs=1 skip=$len count=1 2>/dev/null`" in
+ ?*) go=true ;;
+ *) go=false ;;
+ esac
+ add len 1 $len
+ done
+ # now $len is the length of the first line (including newline)
+ $dd "if=$file" bs=1 count=$len of=$ed.c 2>/dev/null
+ $dd "if=$file" bs=1 skip=$len of=$ed.b 2>/dev/null
+ $dd if=/dev/null of=$ed.a 2>/dev/null
+ lineno=1
+}
+
+# save a file - copy the buffers to the file
+
+save () {
+ # make a backup copy of the original
+ $dd "if=$1" "of=$1.bak" 2>/dev/null
+ # and save
+ ( $dd if=$ed.a; $dd if=$ed.c; $dd if=$ed.b ) > "$1" 2>/dev/null
+}
+
+# replace n1 n2 bla replaces n2 chars of current line, starting n1-th
+
+replace () {
+ $dd if=$ed.c of=$tmp.1 bs=1 "count=$1" 2>/dev/null
+ ( $dd if=$ed.c "skip=$1" bs=1 | $dd of=$tmp.2 bs=1 "skip=$2" ) 2>/dev/null
+ shift
+ shift
+ ( $dd if=$tmp.1; Echo -n "$@"; $dd if=$tmp.2 ) > $tmp.3 2>/dev/null
+ $dd if=$tmp.3 of=$ed.c 2>/dev/null
+}
+
+# rstring n s bla
+# replace the n-th occurence of s with bla
+
+rstring () {
+ n="$1"
+ shift;
+ # first we have to find it - this is fun!
+ # we have $tmp.4 => text before string, $tmp.5 => text after
+ $dd if=/dev/null of=$tmp.4 2>/dev/null
+ $dd if=$ed.c of=$tmp.5 2>/dev/null
+ string="$1"
+ shift
+ $dd of=$tmp.6 2>/dev/null <<EOF
+$@
+EOF
+ while :
+ do
+ case "`$dd if=$tmp.5 2>/dev/null`" in
+ $string*)
+ if lt $n 2
+ then
+ # now we want to replace the string
+ Echo -n "$@" > $tmp.2
+ Echo -n "$string" > $tmp.1
+ IFS="+"
+ set `$dd bs=1 if=$tmp.1 of=/dev/null 2>&1`
+ IFS="$saveIFS"
+ slen=$1
+ IFS="+"
+ ( $dd if=$tmp.4; $dd if=$tmp.2; $dd if=$tmp.5 bs=1 skip=$slen ) \
+ 2>/dev/null > $tmp
+ $dd if=$tmp of=$ed.c 2>/dev/null
+ return 0
+ else
+ subtract n $n 1
+ ( $dd if=$tmp.4; $dd if=$tmp.5 bs=1 count=1 ) > $tmp 2>/dev/null
+ $dd if=$tmp of=$tmp.4 2>/dev/null
+ # and remove it from $tmp.5
+ $dd if=$tmp.5 of=$tmp bs=1 skip=1 2>/dev/null
+ $dd if=$tmp of=$tmp.5 2>/dev/null
+ fi
+ ;;
+ ?*) # add one more byte...
+ ( $dd if=$tmp.4; $dd if=$tmp.5 bs=1 count=1 ) > $tmp 2>/dev/null
+ $dd if=$tmp of=$tmp.4 2>/dev/null
+ # and remove it from $tmp.5
+ $dd if=$tmp.5 of=$tmp bs=1 skip=1 2>/dev/null
+ $dd if=$tmp of=$tmp.5 2>/dev/null
+ ;;
+ *) # not found
+ return 1
+ ;;
+ esac
+ done
+}
+
+# skip to next line
+next () {
+ add l $lineno 1
+ ( $dd if=$ed.a; $dd if=$ed.c ) 2>/dev/null > $tmp.3
+ $dd if=$ed.b of=$tmp.4 2>/dev/null
+ open $tmp.4
+ $dd if=$tmp.3 of=$ed.a 2>/dev/null
+ lineno=$l
+}
+
+# delete current line
+delete () {
+ l=$lineno
+ $dd if=$ed.a 2>/dev/null > $tmp.1
+ $dd if=$ed.b of=$tmp.2 2>/dev/null
+ open $tmp.2
+ $dd if=$tmp.1 of=$ed.a 2>/dev/null
+ lineno=$l
+}
+
+# insert before current line (without changing current)
+insert () {
+ ( $dd if=$ed.a; Echo "$@" ) 2>/dev/null > $tmp.1
+ $dd if=$tmp.1 of=$ed.a 2>/dev/null
+ add lineno $lineno 1
+}
+
+# previous line
+prev () {
+ case "$lineno" in
+ 1) ;;
+ *) subtract lineno $lineno 1
+ # read last line of $ed.a
+ IFS='+'
+ set `$dd if=$ed.a of=/dev/null bs=1 2>&1`
+ IFS="$saveIFS"
+ size=$1
+ # empty?
+ case "$size" in
+ 0) return ;;
+ esac
+ subtract size $size 1
+ # skip final newline
+ case "$size" in
+ 0) ;;
+ *) subtract size1 $size 1
+ case "`$dd if=$ed.a bs=1 skip=$size count=1 2>/dev/null`" in
+ ?*) ;;
+ *) size=$size1 ;;
+ esac
+ ;;
+ esac
+ go=true
+ while $go
+ do
+ case "$size" in
+ 0) go=false ;;
+ *) case "`$dd if=$ed.a bs=1 skip=$size count=1 2>/dev/null`" in
+ ?*) go=true; subtract size $size 1 ;;
+ *) go=false; add size $size 1 ;;
+ esac
+ ;;
+ esac
+ done
+ # now $size is the size of the first n-1 lines
+ # add $ed.c to $ed.b
+ ( $dd if=$ed.c; $dd if=$ed.b ) 2>/dev/null > $tmp.5
+ $dd if=$tmp.5 of=$ed.b 2>/dev/null
+ # move line to ed.c
+ case "$size" in
+ 0) $dd if=$ed.a of=$ed.c 2>/dev/null
+ $dd if=/dev/null of=$tmp.5 2>/dev/null
+ ;;
+ *) $dd if=$ed.a of=$ed.c bs=1 skip=$size 2>/dev/null
+ $dd if=$ed.a of=$tmp.5 bs=1 count=$size 2>/dev/null
+ ;;
+ esac
+ # move rest to ed.a
+ $dd if=$tmp.5 of=$ed.a 2>/dev/null
+ ;;
+ esac
+}
+
+# goes to a given line
+goto () {
+ rl="$1"
+ compare bla "$rl" $lineno
+ case "$bla" in
+ eq) return
+ ;;
+ gt) while gt "$rl" $lineno
+ do
+ next
+ done
+ ;;
+ lt) while lt "$rl" $lineno
+ do
+ prev
+ done
+ ;;
+ esac
+}
+
+lineout () {
+ Echo -n "$lineno: "
+ $dd if=$ed.c 2>/dev/null
+}
+
+state=closed
+name=
+autoprint=true
+
+while true
+do
+ Echo -n '> '
+ read cmd arg
+ case "$cmd:$state" in
+ open:open) Echo "There is a file open already" ;;
+ open:*) if open "$arg"
+ then state=open; name="$arg"; $autoprint
+ else Echo "Cannot open $arg"
+ fi
+ ;;
+ new:open) Echo "There is a file open already" ;;
+ new:*) open "$arg"
+ state=open
+ name="$arg"
+ $autoprint
+ ;;
+ close:changed) Echo "Use 'discard' or 'save'" ;;
+ close:closed) Echo "Closed already" ;;
+ close:*) state=closed ;;
+ save:closed) Echo "There isn't a file to save" ;;
+ save:*) case "$arg" in
+ ?*) save "$arg" ;;
+ *) save "$name" ;;
+ esac
+ state=open
+ ;;
+ discard:changed) Echo "Your problem!"; state=closed ;;
+ discard:*) state=closed ;;
+ print:closed) Echo "No current file" ;;
+ print:*) lineout ;;
+ goto:closed) Echo "No current file" ;;
+ goto:*) goto "$arg"; $autoprint ;;
+ next:closed) Echo "No current file" ;;
+ next:*) next; $autoprint ;;
+ prev:closed) Echo "No current file" ;;
+ prev:*) prev; $autoprint ;;
+ name:closed) Echo "No current file" ;;
+ name:*) name="$arg" ;;
+ replace:closed) Echo "No current file" ;;
+ replace:*) if rstring 1 $arg
+ then state=changed; $autoprint
+ else Echo "Not found"
+ fi
+ ;;
+ nreplace:closed) Echo "No current file" ;;
+ nreplace:*) if rstring $arg
+ then state=changed; $autoprint
+ else Echo "Not found"
+ fi
+ ;;
+ delete:closed) Echo "No current file" ;;
+ delete:*) delete; state=changed; $autoprint ;;
+ insert:closed) Echo "No current file" ;;
+ insert:*) insert "$arg"; prev; state=changed; $autoprint ;;
+ quit:changed) Echo "Use 'save' or 'discard'" ;;
+ quit:*) Echo "bye"; exit;;
+ autoprint:*) autoprint="lineout" ;;
+ noprint:*) autoprint="" ;;
+ :*) ;;
+ *) Echo "Command not understood" ;;
+ esac
+done
+
diff --git a/examples/scripts/fixfiles.bash b/examples/scripts/fixfiles.bash
new file mode 100644
index 0000000..15f3ba8
--- /dev/null
+++ b/examples/scripts/fixfiles.bash
@@ -0,0 +1,92 @@
+#! /bin/bash
+#
+# From: c2a192@ugrad.cs.ubc.ca (Kazimir Kylheku)
+# Newsgroups: comp.unix.shell,comp.os.linux.misc
+# Subject: GNU Bash Script to fix filenames
+# Date: 28 Mar 1996 14:54:43 -0800
+# Organization: Computer Science, University of B.C., Vancouver, B.C., Canada
+#
+#This is a script which takes a list of directories, descends through each one
+#and ``corrects'' filenames that:
+#
+# - contain filename globbing characters: * ? [ ]
+# - quote characters: ' "
+# - control characters: 0-31 (127 is not dealt with---oops)
+# - - or + as the first character
+#
+# The GNU version of 'tr' is required. Also requires 'sed'.
+#
+# Script to process a given list of directories recursively
+# and rename each file to something that is reasonable.
+#
+# The rules are:
+#
+# 1. replace each space, [, ], *, ", and ' character in the name with a
+# period.
+# 2. replace each control character 1..31 with a printable character obtained
+# by adding 64 to the ascii value. ^A becomes A, ^B becomes B and so on.
+# 3. replace a - or + occuring at the beginning of the name with a #
+#
+# 4. if the resulting name has been changed in any way, then
+# 5. if a file of the new name already exists, then
+# 6. add a . to the new name and goto step 5.
+# 7. rename the old name to the new name
+#
+# written by Kaz Kylheku <kaz@cafe.net>
+# March 1996
+# Vancouver, Canada
+#
+# requires GNU 'bash', GNU 'tr', and some sort of 'sed' program.
+#
+# minimal conversion to bash v2 syntax done by Chet Ramey
+
+processfile()
+{
+ new_name="`echo -n $1 | tr '\173\175\052\077\042\047 ' '.......' |
+ tr '[\000-\037]' '[\100-\137]' |
+ sed -e 's/^-/#/' -e 's/+/#/'`"
+ if [ "$new_name" != "$1" ] ; then
+ while [ -e "$new_name" ] ; do
+ new_name="${new_name}."
+ done
+ echo changing \"$1\" to \"$new_name\" in `pwd`
+ mv -- "$1" "$new_name"
+ fi
+}
+
+processdir()
+{
+ set -f
+ local savepwd="$PWD"
+ if cd "$1" ; then
+ set +f
+ for file in * ; do
+ set -f
+ if [ "$file" != "." ] && [ "$file" != ".." ] ; then
+ if [ -L "$file" ] ; then
+ echo "skipping symlink" $file in `pwd`
+ elif [ -d "$file" ] ; then
+ processdir "$file"
+ elif [ -f "$file" ] ; then
+ processfile "$file"
+ fi
+ fi
+ done
+ cd "$savepwd"
+ fi
+}
+
+shopt -s nullglob dotglob
+
+if [ $# = 0 ] ; then
+ echo "$0: must specify a list of directories" >&2
+ echo "$0: usage: $0 directory [directory ...]" >&2
+ exit 2
+fi
+
+while [ $# != 0 ] ; do
+ processdir "$1"
+ shift
+done
+
+exit 0
diff --git a/examples/scripts/hanoi.bash b/examples/scripts/hanoi.bash
new file mode 100644
index 0000000..c308125
--- /dev/null
+++ b/examples/scripts/hanoi.bash
@@ -0,0 +1,21 @@
+# Towers of Hanoi in bash
+#
+# cribbed from the ksh93 book, example from exercises on page 85
+#
+# Chet Ramey
+# chet@po.cwru.edu
+
+hanoi() # n from to spare
+{
+ typeset -i nm1=$1-1
+ ((nm1>0)) && hanoi $nm1 $2 $4 $3
+ echo "Move disc $2 to $3"
+ ((nm1>0)) && hanoi $nm1 $4 $3 $2
+}
+
+case $1 in
+[1-9])
+ hanoi $1 1 2 3;;
+*) echo "${0##*/}: Argument must be from 1 to 9"
+ exit 1;;
+esac
diff --git a/examples/scripts/inpath b/examples/scripts/inpath
new file mode 100755
index 0000000..95f28bc
--- /dev/null
+++ b/examples/scripts/inpath
@@ -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
diff --git a/examples/scripts/krand.bash b/examples/scripts/krand.bash
new file mode 100755
index 0000000..dfdfd32
--- /dev/null
+++ b/examples/scripts/krand.bash
@@ -0,0 +1,74 @@
+# Originally
+#
+# From: bsh20858@news.fhda.edu (Brian S Hiles)
+# Newsgroups: comp.unix.shell
+# Subject: Re: getting random numbers
+# Date: 23 Jan 1997 23:27:30 GMT
+# Message-ID: <5c8s52$eif@tiptoe.fhda.edu>
+
+# @(#) krand Produces a random number within integer limits
+# "krand" Korn shell script generates a random number in a
+# specified range with an optionally specified ``seed'' value.
+# Author: Peter Turnbull, May 1993
+# Modified by: Becca Thomas, January 1994
+
+# changed the optional third argument to a -s option, converted to
+# bash v2 syntax -- chet@po.cwru.edu
+
+PROGNAME=${0##*/}
+USAGE="usage: $PROGNAME [-s seed] lower-limit upper-limit"
+
+Seed=$$ # Initialize random-number seed value with PID
+
+usage()
+{
+ echo ${PROGNAME}: "$USAGE" >&2
+}
+
+errexit()
+{
+ echo ${PROGNAME}: "$@" >&2
+ exit 1
+}
+
+# Process command-line arguments:
+while getopts "s:" opt; do
+ case "$opt" in
+ s) Seed=$OPTARG ;;
+ *) usage ; exit 2;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+
+case $# in
+ 2) Lower=$1; Upper=$2 ;;
+ *) usage ; exit 2;;
+esac
+
+# Check that specified values are integers:
+expr "$Lower" + 0 >/dev/null 2>&1
+[ $? -eq 2 ] && { errexit "lower ($Lower) not an integer"; }
+expr "$Upper" + 0 >/dev/null 2>&1
+[ $? -eq 2 ] && { errexit "upper ($Upper) not an integer"; }
+expr "$Seed" + 0 >/dev/null 2>&1
+[ $? -eq 2 ] && { errexit "seed ($Seed) not an integer"; }
+
+# Check that values are in the correct range:
+if (( "$Lower" < 0 )) || [ ${#Lower} -gt 5 ]; then
+ errexit "lower limit ($Lower) less than zero"
+fi
+if (( "$Upper" > 32767 )) || [ ${#Upper} -gt 5 ]; then
+ errexit "upper limit ($Upper) greater than 32767"
+fi
+if (( "$Seed" < 0 )) || (( "$Seed" > 32767 )) || [ ${#Seed} -gt 5 ]; then
+ errexit "seed value ($Seed) out of range (0 to 32767)"
+fi
+(( "$Upper" <= "$Lower" )) && errexit "upper limit ($Upper) <= lower limit ($Lower)"
+
+# Seed the random-number generator:
+RANDOM=$Seed
+# Compute value, scaled within range:
+let rand="$RANDOM % ($Upper - $Lower + 1) + $Lower"
+# Report result:
+echo $rand
diff --git a/examples/scripts/line-input.bash b/examples/scripts/line-input.bash
new file mode 100644
index 0000000..3f2efae
--- /dev/null
+++ b/examples/scripts/line-input.bash
@@ -0,0 +1,184 @@
+#! /bin/bash
+#
+#From: kaz@cafe.net (Kaz Kylheku)
+#Newsgroups: comp.unix.shell
+#Subject: Funky little bash script
+#Message-ID: <6mspb9$ft2@espresso.cafe.net>
+#Date: Thu, 25 Jun 1998 06:11:39 GMT
+
+#Here is something I wrote a few years ago when I was bored one day.
+#Warning: this contains control characters.
+
+# Line input routine for GNU Bourne-Again Shell
+# plus terminal-control primitives.
+#
+# by Kaz Kylheku
+# June 1996, Vancouver, Canada
+
+
+#
+# Function to disable canonical input processing.
+# Terminal modes are saved into variable "savetty"
+#
+#
+
+function raw
+{
+ savetty=$(stty -g)
+ stty -icanon -isig -echo -echok -echonl inlcr
+}
+
+#
+# Function to restore terminal settings from savetty variable
+#
+
+function restore
+{
+ stty $savetty
+}
+
+#
+# Set terminal MIN and TIME values.
+# If the input argument is a zero, set up terminal to wait for
+# a keystroke indefinitely. If the argument is non-zero, set up
+# an absolute timeout of that many tenths of a second. The inter-keystroke
+# timer facility of the terminal driver is not exploited.
+#
+
+function settimeout
+# $1 = tenths of a second
+{
+ if [ "$1" = "0" ] ; then
+ min=1
+ timeout=0
+ else
+ min=0
+ timeout="$1"
+ fi
+
+ stty min $min time $timeout
+
+ unset min timeout
+}
+
+#
+# Input a single key using 'dd' and echo it to standard output.
+# Launching an external program to get a single keystroke is a bit
+# of a pig, but it's the best you can do! Maybe we could convince the
+# GNU guys to make 'dd' a bash builtin.
+#
+
+function getkey
+{
+ eval $1="\"\$(dd bs=1 count=1 2> /dev/null)\""
+}
+
+#
+# Input a line of text gracefully.
+# The first argument is the name of a variable where the input line is
+# to be stored. If this variable is not empty, its contents are printed
+# and treated as though the user had entered them.
+# The second argument gives the maximum length of the input line; if it
+# is zero, the input is unlimited (bad idea).
+# ^W is used to delete words
+# ^R redraws the line at any time by backspacing over it and reprinting it
+# ^U backspaces to the beginning
+# ^H or ^? (backspace or del) delete a single character
+# ^M (enter) terminates the input
+# all other control keys are ignored and cause a beep when pressed
+#
+#
+
+
+function getline
+{
+ settimeout 0 # No keystroke timeout.
+ save_IFS="$IFS" # Save word delimiter and set it to
+ IFS="" # to null so ${#line} works correctly.
+ eval line=\${$1} # Fetch line contents
+ echo -n "$line" # and print the existing line.
+ while [ 1 ] ; do
+ getkey key # fetch a single keystroke
+ case "$key" in
+  |  ) # BS or DEL
+ if [ ${#line} != 0 ] ; then # if line not empty
+ echo -n " " # print destructive BS
+ line="${line%%?}" # chop last character
+ else # else if line empty
+ echo -n  # beep the terminal
+ fi
+ ;;
+  ) # kill to line beg
+ while [ ${#line} != 0 ] ; do # while line not empty
+ echo -n " " # print BS, space, BS
+ line="${line%?}" # shorten line by 1
+ done
+ ;;
+  ) # redraw line
+ linesave="$line" # save the contents
+ while [ ${#line} != 0 ] ; do # kill to line beg
+ echo -n " "
+ line="${line%?}"
+ done
+ echo -n "$linesave" # reprint, restore
+ line="$linesave"
+ unset linesave # forget temp var
+ ;;
+  )
+ while [ "${line% }" != "$line" ] && [ ${#line} != 0 ] ; do
+ echo -n " "
+ line="${line%?}"
+ done
+ while [ "${line% }" = "$line" ] && [ ${#line} != 0 ] ; do
+ echo -n " "
+ line="${line%?}"
+ done
+ ;;
+  |  |  |  |  |  |  |  |  | | | )
+ echo -n  # ignore various control characters
+ ;; # with an annoying beep
+  |  |  |  |  |  |  |  |  |  |  |  |  )
+ echo -n 
+ ;;
+ ' ' |  |  |  |  |  )
+ echo -n 
+ ;;
+ '' ) # Break out of loop on carriage return.
+ echo # Send a newline to the terminal.
+ break # (Also triggered by NUL char!).
+ ;;
+ * ) # Append character to the end of the line.
+ # If length is restricted, and the line is too
+ # long, then beep...
+
+ if [ "$2" != 0 ] && [ $(( ${#line} >= $2 )) = 1 ] ; then
+ echo -n 
+ else # Otherwise add
+ line="$line$key" # the character.
+ echo -n "$key" # And echo it.
+ fi
+ ;;
+ esac
+ done
+ eval $1=\"\$line\"
+ IFS="$save_IFS"
+ unset line save_IFS
+}
+
+# uncomment the lines below to create a standalone test program
+#
+echo "Line input demo for the GNU Bourne-Again Shell."
+echo "Hacked by Kaz Kylheku"
+echo
+echo "Use ^H/Backspace/Del to erase, ^W to kill words, ^U to kill the"
+echo "whole line of input, ^R to redraw the line."
+echo "Pass an argument to this program to prime the buffer contents"
+raw
+echo -n "go: "
+if [ ${#1} != 0 ] ; then
+ LINE=$1
+fi
+getline LINE 50
+restore
+
+echo "<$LINE>"
diff --git a/examples/scripts/nohup.bash b/examples/scripts/nohup.bash
new file mode 100644
index 0000000..3781293
--- /dev/null
+++ b/examples/scripts/nohup.bash
@@ -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
diff --git a/examples/scripts/precedence b/examples/scripts/precedence
new file mode 100755
index 0000000..9bbdb97
--- /dev/null
+++ b/examples/scripts/precedence
@@ -0,0 +1,75 @@
+# @(#)precedence_test 1.0 91/07/24 Maarten Litmaath
+# test of relative precedences for `&&' and `||' operators
+
+echo "\`Say' echos its argument. Its return value is of no interest."
+case `echo -n` in
+ '') Say () { echo -n "$*" ; } ;;
+ *) Say () { echo "$*\c" ; } ;;
+esac
+
+echo "\`Truth' echos its argument and returns a TRUE result."
+Truth () {
+ Say $1;
+ return 0;
+}
+
+echo "\`False' echos its argument and returns a FALSE result."
+False () {
+ Say $1;
+ return 1;
+}
+
+echo ""
+
+cmd1='$open $test1 && $test2 $close || $test3'
+cmd2='$test1 || $open $test2 && $test3 $close'
+
+grouping_sh=
+grouping_C='( )'
+
+test3='Say 3'
+
+for i in 1 2
+do
+ eval proto=\$cmd$i
+
+ for test1 in 'Truth 1' 'False 1'
+ do
+ for test2 in 'Truth 2' 'False 2'
+ do
+ for precedence in sh C
+ do
+ eval set x \$grouping_$precedence
+ shift
+ open=${1-' '}
+ close=${2-' '}
+ eval cmd=\""$proto"\"
+ Say "$cmd output="
+ output=`eval "$cmd"`
+ Say "$output"
+ read correct || { echo 'Input fubar. Abort.' >&2; exit 1; }
+ test "X$output" = "X$correct" || echo " correct=$correct"
+ echo ''
+ done
+
+ echo ''
+ done
+ done
+done << EOF
+12
+12
+123
+123
+13
+13
+13
+13
+13
+1
+13
+1
+123
+123
+12
+12
+EOF
diff --git a/examples/scripts/randomcard.bash b/examples/scripts/randomcard.bash
new file mode 100644
index 0000000..9cb6b50
--- /dev/null
+++ b/examples/scripts/randomcard.bash
@@ -0,0 +1,18 @@
+# The following prints a random card from a card deck.
+#
+# cribbed from the ksh93 book, example from page 70
+#
+# chet@po.cwru.edu
+#
+declare -i i=0
+
+# load the deck
+for suit in clubs diamonds hearts spades; do
+ for n in ace 2 3 4 5 6 7 8 9 10 jack queen king; do
+ card[i]="$n of $suit"
+ i=i+1 # let is not required with integer variables
+ done
+done
+
+# and print a random card
+echo ${card[RANDOM%52]}
diff --git a/examples/scripts/scrollbar b/examples/scripts/scrollbar
new file mode 100755
index 0000000..388bea8
--- /dev/null
+++ b/examples/scripts/scrollbar
@@ -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}
+WMINUS=$(( $WIDTH - 1 ))
+
+[ $# -lt 1 ] && set -- TESTING
+
+# use the bash-2.02 printf builtin
+Text=$(printf "%-${WIDTH}s" "$*")
+Text=${Text// /_}
+
+while :
+do
+ printf "%-.${WIDTH}s\r" "$Text"
+ LastC=${Text:${WMINUS}:1}
+ Text="$LastC""${Text%?}"
+done
diff --git a/examples/scripts/scrollbar2 b/examples/scripts/scrollbar2
new file mode 100755
index 0000000..0e53634
--- /dev/null
+++ b/examples/scripts/scrollbar2
@@ -0,0 +1,24 @@
+#!/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}
+WMINUS=$(( $WIDTH - 1 ))
+
+[ $# -lt 1 ] && set -- TESTING
+
+# use the bash-2.02 printf builtin
+Text=$(printf "%-${WIDTH}s" "$*")
+
+while :
+do
+ printf "%-.${WIDTH}s\r" "$Text"
+ LastC=${Text:${WMINUS}:1}
+ Text="$LastC""${Text%?}"
+done
diff --git a/examples/scripts/self-repro b/examples/scripts/self-repro
new file mode 100644
index 0000000..951d4e4
--- /dev/null
+++ b/examples/scripts/self-repro
@@ -0,0 +1,9 @@
+# self-reproducing script (except for these comment lines -- remove them)
+# i got this from the ksh93 faq:
+# http://www.kornshell.com/doc/faq.html
+#
+n="
+" q="'" x="cat <<-!" y=! z='n="$n" q="$q" x="$x" y=$y z=$q$z$q$n$x$n$z$n$y'
+cat <<-!
+n="$n" q="$q" x="$x" y=$y z=$q$z$q$n$x$n$z$n$yb
+!
diff --git a/examples/scripts/showperm.bash b/examples/scripts/showperm.bash
new file mode 100644
index 0000000..2e06c0b
--- /dev/null
+++ b/examples/scripts/showperm.bash
@@ -0,0 +1,53 @@
+#Newsgroups: comp.unix.shell
+#From: gwc@root.co.uk (Geoff Clare)
+#Subject: Re: Determining permissions on a file
+#Message-ID: <Dr79nw.DtL@root.co.uk>
+#Date: Fri, 10 May 1996 17:23:56 GMT
+
+#Here's a bit of Korn shell that converts the symbolic permissions produced
+#by "ls -l" into octal, using only shell builtins. How to create a script
+#combining this with an "ls -l" is left as an exercise...
+#
+#
+# Converted to Bash v2 syntax by Chet Ramey <chet@po.cwru.edu>
+#
+# usage: showperm modestring
+#
+# example: showperm '-rwsr-x--x'
+#
+
+[ -z "$1" ] && {
+ echo "showperm: usage: showperm modestring" >&2
+ exit 2
+}
+
+tmode="$1"
+
+typeset -i omode sbits
+typeset pmode
+
+# check for set-uid, etc. bits
+sbits=0
+case $tmode in
+???[sS]*) (( sbits += 8#4000 )) ;; # set-uid
+??????[sSl]*) (( sbits += 8#2000 )) ;; # set-gid or mand. lock
+?????????[tT]*) (( sbits += 8#1000 )) ;; # sticky
+esac
+
+omode=0
+while :
+do
+ tmode=${tmode#?}
+ case $tmode in
+ "") break ;;
+ [-STl]*) (( omode *= 2 )) ;;
+ [rwxst]*) (( omode = omode*2 + 1 )) ;;
+ *) echo "$0: first letter of \"$tmode\" is unrecognized" >&2
+ (( omode *= 2 ))
+ ;;
+ esac
+done
+
+(( omode += sbits ))
+
+printf "0%o\n" $omode
diff --git a/examples/scripts/shprompt b/examples/scripts/shprompt
new file mode 100755
index 0000000..ec8b997
--- /dev/null
+++ b/examples/scripts/shprompt
@@ -0,0 +1,137 @@
+#
+# shprompt -- give a prompt and get an answer satisfying certain criteria
+#
+# shprompt [-dDfFsy] prompt
+# s = prompt for string
+# f = prompt for filename
+# F = prompt for full pathname to a file or directory
+# d = prompt for a directory name
+# D = prompt for a full pathname to a directory
+# y = prompt for y or n answer
+#
+# Chet Ramey
+# chet@ins.CWRU.Edu
+
+type=file
+
+OPTS=dDfFsy
+
+succeed()
+{
+ echo "$1"
+ exit 0
+}
+
+while getopts "$OPTS" c
+do
+ case "$c" in
+ s) type=string
+ ;;
+ f) type=file
+ ;;
+ F) type=path
+ ;;
+ d) type=dir
+ ;;
+ D) type=dirpath
+ ;;
+ y) type=yesno
+ ;;
+ ?) echo "usage: $0 [-$OPTS] prompt" 1>&2
+ exit 2
+ ;;
+ esac
+done
+
+if [ "$OPTIND" -gt 1 ] ; then
+ shift $[$OPTIND - 1]
+fi
+
+while :
+do
+ case "$type" in
+ string)
+ echo -n "$1" 1>&2
+ read ans || exit 1
+ if [ -n "$ans" ] ; then
+ succeed "$ans"
+ fi
+ ;;
+ file|path)
+ echo -n "$1" 1>&2
+ read ans || exit 1
+ #
+ # use `fn' and eval so that bash will do tilde expansion for
+ # me
+ #
+ eval fn="$ans"
+ case "$fn" in
+ /*) if test -e "$fn" ; then
+ succeed "$fn"
+ else
+ echo "$0: '$fn' does not exist" 1>&2
+ fi
+ ;;
+ *) if [ "$type" = "path" ] ; then
+ echo "$0: must give full pathname to file" 1>&2
+ else
+ if test -e "$fn" ; then
+ succeed "$fn"
+ else
+ echo "$0: '$fn' does not exist" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ ;;
+ dir|dirpath)
+ echo -n "$1" 1>&2
+ read ans || exit 1
+ #
+ # use `fn' and eval so that bash will do tilde expansion for
+ # me
+ #
+ eval fn="$ans"
+ case "$fn" in
+ /*) if test -d "$fn" ; then
+ succeed "$fn"
+ elif test -e "$fn" ; then
+ echo "$0 '$fn' is not a directory" 1>&2
+ else
+ echo "$0: '$fn' does not exist" 1>&2
+ fi
+ ;;
+ *) if [ "$type" = "dirpath" ] ; then
+ echo "$0: must give full pathname to directory" 1>&2
+ else
+ if test -d "$fn" ; then
+ succeed "$fn"
+ elif test -e "$fn" ; then
+ echo "$0 '$fn' is not a directory" 1>&2
+ else
+ echo "$0: '$fn' does not exist" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ ;;
+ yesno)
+ echo -n "$1" 1>&2
+ read ans || exit 1
+ case "$ans" in
+ y|Y|[yY][eE][sS])
+ succeed "yes"
+ ;;
+ n|N|[nN][oO])
+ succeed "no"
+ exit 0
+ ;;
+ *)
+ echo "$0: yes or no required" 1>&2
+ ;;
+ esac
+ ;;
+ esac
+done
+
+exit 1
diff --git a/examples/scripts/spin.bash b/examples/scripts/spin.bash
new file mode 100644
index 0000000..dc6a66a
--- /dev/null
+++ b/examples/scripts/spin.bash
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# spin.bash -- provide a `spinning wheel' to show progress
+#
+# Chet Ramey
+# chet@po.cwru.edu
+#
+bs=$'\b'
+
+chars="|${bs} \\${bs} -${bs} /${bs}"
+
+# Infinite loop for demo. purposes
+while :
+do
+ for letter in $chars
+ do
+ echo -n ${letter}
+ done
+done
+
+exit 0
diff --git a/examples/scripts/timeout b/examples/scripts/timeout
new file mode 100644
index 0000000..ac8d88f
--- /dev/null
+++ b/examples/scripts/timeout
@@ -0,0 +1,53 @@
+#Newsgroups: comp.unix.admin,comp.unix.solaris,comp.unix.shell
+#From: gwc@root.co.uk (Geoff Clare)
+#Subject: Re: timeout -t <sec> <unix command> (Re: How to give rsh a shorter timeout?)
+#Message-ID: <EoBxrs.223@root.co.uk>
+#Date: Fri, 13 Feb 1998 18:23:52 GMT
+
+#
+# Conversion to bash v2 syntax done by Chet Ramey <chet@po.cwru.edu
+# UNTESTED
+#
+
+prog=${0##*/}
+usage="usage: $prog [-signal] [timeout] [:interval] [+delay] [--] <command>"
+
+SIG=-TERM # default signal sent to the process when the timer expires
+timeout=60 # default timeout
+interval=15 # default interval between checks if the process is still alive
+delay=2 # default delay between posting the given signal and
+ # destroying the process (kill -KILL)
+
+while :
+do
+ case $1 in
+ --) shift; break ;;
+ -*) SIG=$1 ;;
+ [0-9]*) timeout=$1 ;;
+ :*) EXPR='..\(.*\)' ; interval=`expr x"$1" : "$EXPR"` ;;
+ +*) EXPR='..\(.*\)' ; delay=`expr x"$1" : "$EXPR"` ;;
+ *) break ;;
+ esac
+ shift
+done
+
+case $# in
+0) echo "$prog: $usage" >&2 ; exit 2 ;;
+esac
+
+(
+ for t in $timeout $delay
+ do
+ while (( $t > $interval ))
+ do
+ sleep $interval
+ kill -0 $$ || exit
+ t=$(( $t - $interval ))
+ done
+ sleep $t
+ kill $SIG $$ && kill -0 $$ || exit
+ SIG=-KILL
+ done
+) 2> /dev/null &
+
+exec "$@"
diff --git a/examples/scripts/timeout2 b/examples/scripts/timeout2
new file mode 100755
index 0000000..2c6fb77
--- /dev/null
+++ b/examples/scripts/timeout2
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Author: P@draigBrady.com
+# V1.0 : Nov 3 2006
+#
+# Execute a command with a timeout.
+# If the timeout occurs the exit status is 128
+#
+# Note there is an asynchronous equivalent of this
+# script packaged with bash (under /usr/share/doc/ in my distro),
+# which I only noticed after writing this.
+
+if [ "$#" -lt "2" ]; then
+ echo "Usage: `basename $0` timeout_in_seconds command" >&2
+ echo "Example: `basename $0` 2 sleep 3 || echo timeout" >&2
+ exit 1
+fi
+
+cleanup()
+{
+ kill %1 2>/dev/null #kill sleep $timeout if running
+ kill %2 2>/dev/null && exit 128 #kill monitored job if running
+}
+
+set -m #enable job control
+trap "cleanup" 17 #cleanup after timeout or command
+timeout=$1 && shift #first param is timeout in seconds
+sleep $timeout& #start the timeout
+"$@" #start the job
diff --git a/examples/scripts/timeout3 b/examples/scripts/timeout3
new file mode 100644
index 0000000..5c19d2e
--- /dev/null
+++ b/examples/scripts/timeout3
@@ -0,0 +1,91 @@
+#!/bin/bash
+#
+# The Bash shell script executes a command with a time-out.
+# Upon time-out expiration SIGTERM (15) is sent to the process. If the signal
+# is blocked, then the subsequent SIGKILL (9) terminates it.
+#
+# Based on the Bash documentation example.
+
+# Hello Chet,
+# please find attached a "little easier" :-) to comprehend
+# time-out example. If you find it suitable, feel free to include
+# anywhere: the very same logic as in the original examples/scripts, a
+# little more transparent implementation to my taste.
+#
+# Dmitry V Golovashkin <Dmitry.Golovashkin@sas.com>
+
+scriptName="${0##*/}"
+
+declare -i DEFAULT_TIMEOUT=9
+declare -i DEFAULT_INTERVAL=1
+declare -i DEFAULT_DELAY=1
+
+# Timeout.
+declare -i timeout=DEFAULT_TIMEOUT
+# Interval between checks if the process is still alive.
+declare -i interval=DEFAULT_INTERVAL
+# Delay between posting the SIGTERM signal and destroying the process by SIGKILL.
+declare -i delay=DEFAULT_DELAY
+
+function printUsage() {
+ cat <<EOF
+
+Synopsis
+ $scriptName [-t timeout] [-i interval] [-d delay] command
+ Execute a command with a time-out.
+ Upon time-out expiration SIGTERM (15) is sent to the process. If SIGTERM
+ signal is blocked, then the subsequent SIGKILL (9) terminates it.
+
+ -t timeout
+ Number of seconds to wait for command completion.
+ Default value: $DEFAULT_TIMEOUT seconds.
+
+ -i interval
+ Interval between checks if the process is still alive.
+ Positive integer, default value: $DEFAULT_INTERVAL seconds.
+
+ -d delay
+ Delay between posting the SIGTERM signal and destroying the
+ process by SIGKILL. Default value: $DEFAULT_DELAY seconds.
+
+As of today, Bash does not support floating point arithmetic (sleep does),
+therefore all delay/time values must be integers.
+EOF
+}
+
+# Options.
+while getopts ":t:i:d:" option; do
+ case "$option" in
+ t) timeout=$OPTARG ;;
+ i) interval=$OPTARG ;;
+ d) delay=$OPTARG ;;
+ *) printUsage; exit 1 ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+# $# should be at least 1 (the command to execute), however it may be strictly
+# greater than 1 if the command itself has options.
+if (($# == 0 || interval <= 0)); then
+ printUsage
+ exit 1
+fi
+
+# kill -0 pid Exit code indicates if a signal may be sent to $pid process.
+(
+ ((t = timeout))
+
+ while ((t > 0)); do
+ sleep $interval
+ kill -0 $$ || exit 0
+ ((t -= interval))
+ done
+
+ # Be nice, post SIGTERM first.
+ # The 'exit 0' below will be executed if any preceeding command fails.
+ kill -s SIGTERM $$ && kill -0 $$ || exit 0
+ sleep $delay
+ kill -s SIGKILL $$
+) 2> /dev/null &
+
+exec "$@"
diff --git a/examples/scripts/vtree2 b/examples/scripts/vtree2
new file mode 100755
index 0000000..878cbab
--- /dev/null
+++ b/examples/scripts/vtree2
@@ -0,0 +1,43 @@
+#!/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
+# I believe that the original author is Brian S. Hiles <bsh29256@atc.fhda.edu>
+#
+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 -k 2f | sed \
+ -e 's/\([^ ]*\) \(.*\)/\2 (\1)/' \
+ -e "s#^$1##" \
+ -e 's#[^/]*/\([^/]*\)$#|____\1#' \
+ -e 's#[^/]*/#| #g'
+
+ [ $# -gt 1 ] && echo
+ shift
+done
diff --git a/examples/scripts/vtree3 b/examples/scripts/vtree3
new file mode 100644
index 0000000..2059b9f
--- /dev/null
+++ b/examples/scripts/vtree3
@@ -0,0 +1,99 @@
+#!/bin/ksh
+#
+# Name: dirtree
+# Programmer:
+# Hemant T. Shah
+# Life Insurance Data Processing
+# July 12 1994
+#
+# Description:
+# Print directory tree structure as follows:
+# |___Mail
+# |___scheduler
+# |___cics_scripts
+# |___tar_msdos
+# |___awk
+# |___attributes
+# |___tmp
+# |___News
+# |___dosscsi
+# |___FAQ_xterminal
+# |___shell_history.Z
+# |___FAQ_AIX
+# |___aix_ftp_site
+# |___hp_software
+# |___dnload
+# |___telnet.h
+# |___msdos
+# |___tnetd.tar.Z
+# |___aix
+# |___hp
+# |___xkey.c
+#
+# Conversion to bash v2 syntax done by Chet Ramey
+# - removed command substitutions calling `basename'
+#
+
+ProgramName=${0##*/}
+Path="."
+ShowAll=1
+ShowDir=0
+
+
+ExpandDirectory()
+{
+local object # Local variable
+
+cd "$1"
+
+for object in $PWD/.??* $PWD/*
+do
+ if [ -d $object ]; # It is a directory
+ then
+ echo "${indent}|___${object##*/}/"
+ indent="${indent}! " # Add to indentation
+ if [ -x $object ];
+ then
+ ExpandDirectory $object
+ fi
+ indent=${indent%????} # Remove from indentation
+ elif [ -e $object ]; then
+ if (( ShowAll == 1 ));
+ then
+ echo "${indent}|___${object##*/}"
+ fi
+ fi
+done
+
+}
+
+usage()
+{
+ echo -e "Usage: $ProgramName [-h] [-f] [-d] [path] "
+ echo -e "\t-h ... display this help message."
+ echo -e "\t-f path ... shows all files and directories below path (default)."
+ echo -e "\t-d path ... shows all directories only below path."
+}
+
+while getopts "fd" opt
+do
+ case $opt in
+ f) ShowAll=1 ;;
+ d) ShowDir=1 ;;
+ *) usage ; exit 2;;
+ esac
+done
+
+shift $(( $OPTIND - 1 ))
+
+Path=${1:-.}
+
+if [ ! -d "$Path" ]; then
+ echo "$0: error: specified path is not a directory." >&2
+ exit 1
+fi
+
+
+
+echo "!$Path/"
+ExpandDirectory $Path
diff --git a/examples/scripts/vtree3a b/examples/scripts/vtree3a
new file mode 100644
index 0000000..0678764
--- /dev/null
+++ b/examples/scripts/vtree3a
@@ -0,0 +1,100 @@
+#!/bin/bash
+#
+# Name: dirtree
+# Programmer:
+# Hemant T. Shah
+# Life Insurance Data Processing
+# July 12 1994
+#
+# Description:
+# Print directory tree structure as follows:
+# |___Mail
+# |___scheduler
+# |___cics_scripts
+# |___tar_msdos
+# |___awk
+# |___attributes
+# |___tmp
+# |___News
+# |___dosscsi
+# |___FAQ_xterminal
+# |___shell_history.Z
+# |___FAQ_AIX
+# |___aix_ftp_site
+# |___hp_software
+# |___dnload
+# |___telnet.h
+# |___msdos
+# |___tnetd.tar.Z
+# |___aix
+# |___hp
+# |___xkey.c
+#
+# Conversion to bash v2 syntax done by Chet Ramey
+# - removed command substitutions calling `basename'
+#
+
+ProgramName=${0##*/}
+Path="."
+ShowAll=1
+ShowDir=0
+
+
+ExpandDirectory()
+{
+local object # Local variable
+
+cd "$1"
+
+for object in $PWD/.??* $PWD/*
+do
+ if [ -d $object ]; # It is a directory
+ then
+ echo "${indent}|___${object##*/}/"
+ indent="${indent}! " # Add to indentation
+ if [ -x $object ];
+ then
+ ExpandDirectory $object
+ fi
+ indent=${indent%????} # Remove from indentation
+ elif [ -e $object ]; then
+ if (( ShowAll == 1 ));
+ then
+ echo "${indent}|___${object##*/}"
+ fi
+ fi
+done
+
+}
+
+usage()
+{
+ echo -e "Usage: $ProgramName [-h] [-f] [-d] [path] "
+ echo -e "\t-h ... display this help message."
+ echo -e "\t-f path ... shows all files and directories below path (default)."
+ echo -e "\t-d path ... shows all directories only below path."
+}
+
+while getopts "fd" opt
+do
+ case $opt in
+ f) ShowAll=1 ;;
+ #d) ShowDir=1 ;;
+ d) ShowAll=0 ;;
+ *) usage ; exit 2;;
+ esac
+done
+
+shift $(( $OPTIND - 1 ))
+
+Path=${1:-.}
+
+if [ ! -d "$Path" ]; then
+ echo "$0: error: specified path is not a directory." >&2
+ exit 1
+fi
+
+
+
+echo "!$Path/"
+ExpandDirectory $Path
diff --git a/examples/scripts/websrv.sh b/examples/scripts/websrv.sh
new file mode 100644
index 0000000..e07746b
--- /dev/null
+++ b/examples/scripts/websrv.sh
@@ -0,0 +1,230 @@
+#!/bin/sh
+#for instructions or updates go to:
+#<A HREF="http://math.ucr.edu:8889/">This script's home page</A>
+#email me questions or comments at:
+#<A HREF="mailto:insom@math.ucr.edu">insom@math.ucr.edu</A>
+#copyright chris ulrich; This software may be used or modified
+#in any way so long as this notice remains intact.
+#
+# WWW server in sh
+# Author: Chris Ulrich <chris@tinker.ucr.edu>
+#
+
+INDEX=index.html
+date=`date`
+DOCHOME=/home/insom/web-docs
+BINHOME=/home/insom/web-bin
+LOGHOME=/home/insom/web-logs
+LOGFILE=$LOGHOME/access_log
+#verbose=:
+verbose=echo
+exec 2>> $LOGHOME/error_log
+
+hheader() {
+echo "HTTP/1.0 200 OK
+Server: WebSH/2.00
+Connection: close
+Date: $date"
+}
+
+header() {
+echo "Content-type: $1
+"
+}
+
+no_url() {
+ header "text/plain"
+ echo "No such url $1"
+}
+
+send() {
+ #case "$#" in 2) ;; *) echo eep! | mailx insom@math.ucr.edu ; exit 3 ;; esac
+ if test -f "$DOCHOME/$2"
+ then
+ header "$1"
+ cat "$DOCHOME/$2"
+ else
+ no_url "$2"
+ fi
+}
+
+LsToHTML() {
+ if test -f "$DOCHOME/$url/.title"
+ then
+ header "text/html; charset=US-ASCII"
+ echo "<pre>"
+ cat "$DOCHOME/$url/.title"
+ echo "</pre>"
+ elif test -f "$DOCHOME/$url/.title.html"
+ then
+ header "text/html; charset=US-ASCII"
+ cat "$DOCHOME/$url/.title.html"
+ else
+ header "text/html; charset=US-ASCII"
+ fi
+
+ case "$url" in
+ /) ;;
+ *) url="$url/"
+ esac
+
+ while read link
+ do
+ case $link in
+ *.cgi) ;;
+ *)
+ echo "<A HREF=\"$url$link\">$link</A> <BR>"
+ ;;
+ esac
+ done
+}
+
+read method data
+
+$verbose "
+$date access from ${TCPREMOTEINFO:=NO-IDENT}@${TCPREMOTEHOST:=$TCPREMOTEIP}
+ on local machine $TCPLOCALHOST
+ $method $data " >> $LOGFILE
+
+for hopeurl in $data
+do
+ url="${url}${url:+ }$second"
+ second="$hopeurl"
+done
+
+case "$second" in
+ *[1-9].*)
+ read inheader
+ while
+ case "$inheader" in
+ ?|'') false
+ ;;
+ *)
+ read inheader
+ ;;
+ esac
+ do
+ :
+ done
+ hheader
+ ;;
+esac
+
+case "$url" in
+ *..*)
+ no_url "$url"
+ exit 1
+ ;;
+ *.txt|*.[ch])
+ send "text/plain; charset=US-ASCII" "$url"
+ ;;
+ *.html)
+ send "text/html; charset=US-ASCII" "$url"
+ ;;
+ *.cgi)
+ if test -x "$DOCHOME/$url"
+ then
+ read message
+ echo "$message" | "$DOCHOME/$url"
+ else
+ no_url "$url"
+ fi
+ ;;
+ *".cgi?"*)
+ oIFS="$IFS"
+ echo "$url" | {
+ IFS='?' read url QUERY_STRING
+ if test -x "$DOCHOME/$url"
+ then
+ IFS="$oIFS"
+ export QUERY_STRING
+ "$DOCHOME/$url"
+ else
+ no_url "$url"
+ fi
+ }
+ ;;
+ *.[Gg][Ii][Ff])
+ send "image/gif" "$url"
+ ;;
+ *.[Jj][Pp][Gg]|*.[Jj][Pp][Ee][Gg])
+ send "image/jpeg" "$url"
+ ;;
+ *.tbl)
+ header "text/html; charset=US-ASCII"
+ echo "<pre>"
+ test -f "$DOCHOME/$url" &&
+ tbl < "$DOCHOME/$url" | nroff ||
+ no_url "$url"
+ echo "</pre>"
+ ;;
+ *.nroff)
+ header "text/html; charset=US-ASCII"
+ echo "<pre>"
+ test -f "$DOCHOME/$url" &&
+ nroff < "$DOCHOME/$url" ||
+ no_url "$url"
+ echo "</pre>"
+ ;;
+ *mp[23])
+ if test -f "$DOCHOME/$url"
+ then
+ header "application/mpstream"
+ echo "+$TCPLOCALIP:${MPSERVPORT:=9001}/$url"
+ else
+ no_url "$url"
+ fi
+ ;;
+ *.[0-9]|*.[0-9][a-z])
+ header "text/html; charset=US-ASCII"
+ echo "<pre>"
+ if test -f "$DOCHOME/$url"
+ then
+ #nroff -man "$DOCHOME/$url" | $BINHOME/man2html
+ echo "perl at the moment is broken, so man2html doesn't work. Sorry."
+ echo "</pre>"
+ else
+ no_url "$url"
+ fi
+ ;;
+ *.???|*.??)
+ send "unknown/data" "$url"
+ ;;
+ */)
+ if test -d "$DOCHOME/$url"
+ then
+ ls "$DOCHOME/$url" | LsToHTML
+ fi
+ ;;
+ *)
+ if test -f "$DOCHOME/$url"
+ then
+ read filetype < "$DOCHOME/$url"
+ case "$filetype" in
+ \#!/*/*|\#!?/*/*)
+ header "text/plain; charset=US-ASCII"
+ cat "$DOCHOME/$url"
+ ;;
+ '<!*>')
+ header "text/html; charset=US-ASCII"
+ cat "$DOCHOME/$url"
+ ;;
+ *)
+ header "text/html; charset=US-ASCII"
+ echo "<pre>"
+ cat "$DOCHOME/$url"
+ echo "</pre>"
+ ;;
+ esac
+ elif test -f "$DOCHOME/$url/$INDEX"
+ then
+ header "text/html; charset=US-ASCII"
+ cat "$DOCHOME/$url/$INDEX"
+ elif test -d "$DOCHOME/$url"
+ then
+ ls "$DOCHOME/$url" | LsToHTML
+ else
+ no_url "$url"
+ fi
+ ;;
+esac
diff --git a/examples/scripts/xterm_title b/examples/scripts/xterm_title
new file mode 100755
index 0000000..72ba099
--- /dev/null
+++ b/examples/scripts/xterm_title
@@ -0,0 +1,27 @@
+#! /bin/bash
+#
+# xterm_title - print the contents of the xterm title bar
+#
+# Derived from http://www.clark.net/pub/dickey/xterm/xterm.faq.html#how2_title
+#
+P=${0##*/}
+[ -z "$DISPLAY" ] && {
+ echo "${P}: not running X" >&2
+ exit 1
+}
+
+if [ -z "$TERM" ] || [ "$TERM" != "xterm" ]; then
+ echo "${P}: not running in an xterm" >&2
+ exit 1
+fi
+
+exec </dev/tty
+old=$(stty -g)
+stty raw -echo min 0 time ${1-10}
+echo -e "\033[21t\c" > /dev/tty
+IFS='' read -r a
+stty $old
+b=${a#???}
+echo "${b%??}"
+
+exit 0
diff --git a/examples/scripts/zprintf b/examples/scripts/zprintf
new file mode 100755
index 0000000..5e2e3ad
--- /dev/null
+++ b/examples/scripts/zprintf
@@ -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 }"