diff options
Diffstat (limited to 'examples/functions')
-rw-r--r-- | examples/functions/autoload | 103 | ||||
-rw-r--r-- | examples/functions/basename | 23 | ||||
-rw-r--r-- | examples/functions/csh-compat | 36 | ||||
-rw-r--r-- | examples/functions/dirfuncs | 142 | ||||
-rw-r--r-- | examples/functions/dirname | 21 | ||||
-rw-r--r-- | examples/functions/exitstat | 22 | ||||
-rw-r--r-- | examples/functions/external | 50 | ||||
-rw-r--r-- | examples/functions/fact | 13 | ||||
-rw-r--r-- | examples/functions/fstty | 59 | ||||
-rw-r--r-- | examples/functions/func | 27 | ||||
-rw-r--r-- | examples/functions/jj.bash | 12 | ||||
-rw-r--r-- | examples/functions/kshenv | 183 | ||||
-rw-r--r-- | examples/functions/manpage | 129 | ||||
-rw-r--r-- | examples/functions/notify.bash | 58 | ||||
-rw-r--r-- | examples/functions/shcat | 7 | ||||
-rw-r--r-- | examples/functions/substr | 79 | ||||
-rw-r--r-- | examples/functions/substr2 | 81 | ||||
-rw-r--r-- | examples/functions/term | 35 | ||||
-rw-r--r-- | examples/functions/whatis | 52 | ||||
-rw-r--r-- | examples/functions/whence | 59 |
20 files changed, 1191 insertions, 0 deletions
diff --git a/examples/functions/autoload b/examples/functions/autoload new file mode 100644 index 0000000..a6ae421 --- /dev/null +++ b/examples/functions/autoload @@ -0,0 +1,103 @@ +# +# 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 func [func...] +# +# The first cut of this was by Bill Trost, trost@reed.bitnet +# +# Chet Ramey +# chet@ins.CWRU.Edu + +# +# 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 $?; }' +} + +# +# 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() +{ + # + # Save the list of functions; we're going to blow away the arguments + # in a second. If any of the names contain white space, TFB. + # + + local args="$*" + + # + # This should, I think, list the functions marked as autoload and not + # yet defined, but we don't have enough information to do that here. + # + if [ $# -eq 0 ] ; then + echo "usage: autoload function [function...]" + return 1 + fi + + # + # If there is no $FPATH, there is no work to be done + # + + if [ -z "$FPATH" ] ; then + echo autoload: FPATH not set + return 1 + fi + + # + # This treats FPATH exactly like PATH: a null field anywhere in the + # FPATH is treated the same as the current directory. + # + # The path splitting command is taken from Kernighan and Pike + # + + fp=$(echo $FPATH | sed 's/^:/.:/ + s/::/:.:/g + s/:$/:./ + s/:/ /g') + + for FUNC in $args ; do + # + # We're blowing away the arguments to autoload here... + # We have to; there are no arrays. + # + set $fp + + while [ $# -ne 0 ] ; do + if [ -f $1/$FUNC ] ; then + break # found it! + fi + shift + done + + if [ $# -eq 0 ] ; then + echo "$FUNC: autoload function not found" + continue + fi + +# echo auto-loading $FUNC from $1/$FUNC + aload $FUNC $1/$FUNC + done + + return 0 +} diff --git a/examples/functions/basename b/examples/functions/basename new file mode 100644 index 0000000..a541349 --- /dev/null +++ b/examples/functions/basename @@ -0,0 +1,23 @@ +# Date: Fri, 11 Oct 91 11:22:36 edt +# From: friedman@gnu.ai.mit.edu +# To: bfox@gnu.ai.mit.edu + +# A replacement for basename(1). Not all the systems I use have this +# program. Usage: basename [path] {extension} +function basename () +{ + local path="$1" + local suffix="$2" + local tpath="${path%/}" + + # Strip trailing '/' characters from path (unusual that this should + # ever occur, but basename(1) seems to deal with it.) + while [ "${tpath}" != "${path}" ]; do + tpath="${path}" + path="${tpath%/}" + done + + path="${path##*/}" # Strip off pathname + echo ${path%${suffix}} # Also strip off extension, if any. +} + diff --git a/examples/functions/csh-compat b/examples/functions/csh-compat new file mode 100644 index 0000000..8eaf754 --- /dev/null +++ b/examples/functions/csh-compat @@ -0,0 +1,36 @@ +# C-shell compatabilty package. +# setenv VAR VALUE +function setenv () { + export $1="$2" +} + +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".' +} + +# Make this work like csh's. Special case "term" and "path". +#set () { +#} + +chdir () { + builtin cd $* + } diff --git a/examples/functions/dirfuncs b/examples/functions/dirfuncs new file mode 100644 index 0000000..3958bbe --- /dev/null +++ b/examples/functions/dirfuncs @@ -0,0 +1,142 @@ +# +# Directory manipulation functions from the book 'The Korn Shell' +# Modified for use with bash Mon Apr 18 08:37 1994 by +# Ken Konecki (kenk@wfg.com) +# +# Modified by Chet Ramey +# +# This could stand to have calls to `select' added back in +# + +alias integer="declare -i" + +integer _push_max=${CDSTACK-31} _push_top=${CDSTACK-31} + +unalias cd +# alias cd=_cd + +# Display directory stack -- $HOME display as ~ +dirs() +{ + dir="${PWD#$HOME/}" + case $dir in + $HOME) dir=\~ ;; + /*) ;; + *) dir=\~/$dir ;; + esac + + integer i=_push_top + integer n=1 + + echo "$n) $dir" + while let "i < $_push_max" + do + n=n+1 + eval "echo \$n\) \$_push_stack_$i" + i=i+1 + done +} + +# Change directory and put directory on front of stack +cd() +{ + typeset dir= + integer n=0 type=4 i + case $1 in + -|-1|2) # cd - + n=_push_top type=1 + ;; + -[1-9]|-[1-9][0-9]) # cd -n + n=_push_top+${1#-}-1 type=2 + ;; + + 1) # keep present directory + echo "$PWD" + return + ;; + + [2-9]|[1-9][0-9]) # cd n + n=_push_top+${1}-2 type=2 + ;; + + *) + if let "_push_top <= 0"; then + type=3 n=_push_max + fi + ;; + esac + + if let "type < 3"; then + if let "n >= _push_max"; then + echo cd: Directory stack not that deep + return 1 + else + eval dir=\${_push_stack_$n} + fi + fi + + case $dir in + ~*) dir=$HOME${dir#\~} ;; + esac + + cd2 ${dir:-$@} > /dev/null || return 1 + dir=${OLDPWD#$HOME/} + case $dir in + $HOME) dir=\~ ;; + /*) ;; + *) dir=\~/$dir ;; + esac + + case $type in + 1) # swap first two elements + eval _push_stack_$_push_top=\$dir ;; + + 2|3) # put $dir on top and shift down by one until top + i=_push_top + unset _dirlist + while let "i < $_push_max" ; do + eval _dirlist=\"\$_dirlist \$_push_stack_$i\" + i=i+1 + done + + i=_push_top + for dir in "$dir" ${_dirlist} ; do + let "i > n" && break + eval _push_stack_$i=\$dir + i=i+1 + done + ;; + 4) # push name + _push_top=_push_top-1; + eval _push_stack_$_push_top=\$dir + ;; + esac + + echo "$PWD" + +} + +# Menu-driven change directory command +function mcd +{ + dirs + echo -n "Select by number or enter a name: " + read + cd $REPLY +} + + +# Emulate ksh cd substitution +cd2() +{ + case "$#" in + 0) builtin cd "$HOME" ;; + 1) builtin cd "$1" ;; + 2) newDir=$(echo $PWD | sed -e "s:$1:$2:g") + case "$newDir" in + $PWD) echo "bash:: cd: bad substitution" >&2 ; return 1 ;; + *) builtin cd "$newDir" ;; + esac ;; + *) echo "bash: cd: wrong arg count" 1>&2 ; return 1 ;; + esac +} diff --git a/examples/functions/dirname b/examples/functions/dirname new file mode 100644 index 0000000..ccb8c84 --- /dev/null +++ b/examples/functions/dirname @@ -0,0 +1,21 @@ +# Date: Fri, 11 Oct 91 11:22:36 edt +# From: friedman@gnu.ai.mit.edu +# To: bfox@gnu.ai.mit.edu + +# A replacement for dirname(1). This one appears less often on some +# systems I use than basename(1), and I really depend on it for some +# things. Usage: dirname [path] +function dirname () +{ + local dir="$1" + local tdir="${dir%/}" + + # Strip trailing '/' characters from dir (unusual that this should + # ever occur, but dirname(1) seems to deal with it.) + while [ "${tdir}" != "${dir}" ]; do + tdir="${dir}" + dir="${tdir%/}" + done + + echo "${dir%/*}" +} diff --git a/examples/functions/exitstat b/examples/functions/exitstat new file mode 100644 index 0000000..bae3f27 --- /dev/null +++ b/examples/functions/exitstat @@ -0,0 +1,22 @@ +# Contributed by Noah Friedman and Roland McGrath. + +# To be run by the PROMPT_COMMAND variable, so that one can see what +# the exit status of processes are. + +function check_exit_status () +{ + local status="$?" + local signal="" + + 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)" + if [ "$signal" ]; then signal="($signal)"; fi + fi + echo "[Exit ${status} ${signal}]" 1>&2 + fi + return 0 +} + +PROMPT_COMMAND=check_exit_status diff --git a/examples/functions/external b/examples/functions/external new file mode 100644 index 0000000..c2e52cd --- /dev/null +++ b/examples/functions/external @@ -0,0 +1,50 @@ +# Contributed by Noah Friedman. + +# To avoid using a function in bash, you can use the `builtin' or +# `command' builtins, but neither guarantees that you use an external +# program instead of a bash builtin if there's a builtin by that name. So +# this function can be used like `command' except that it guarantees the +# program is external by first disabling any builtin by that name. After +# the command is done executing, the state of the builtin is restored. +function external () +{ + local state="" + local exit_status + + if builtin_p "$1"; then + state="builtin" + enable -n "$1" + fi + + command "$@" + exit_status=$? + + if [ "$state" = "builtin" ]; then + enable "$1" + fi + + return ${exit_status} +} + +# What is does is tell you if a particular keyword is currently enabled as +# a shell builtin. It does NOT tell you if invoking that keyword will +# necessarily run the builtin. For that, do something like +# +# test "$(builtin type -type [keyword])" = "builtin" +# +# Note also, that disabling a builtin with "enable -n" will make builtin_p +# return false, since the builtin is no longer available. +function builtin_p () +{ + local word + + set $(builtin type -all -type "$1") + + for word in "$@" ; do + if [ "${word}" = "builtin" ]; then + return 0 + fi + done + + return 1 +} diff --git a/examples/functions/fact b/examples/functions/fact new file mode 100644 index 0000000..cd7bf46 --- /dev/null +++ b/examples/functions/fact @@ -0,0 +1,13 @@ +# Who said shells can't use recursion? Here is a factorial function. +# You call it with a number as an argument, and it returns the factorial +# of that number. + +fact () +{ + local num=$1; + if [ "$num" = 1 ] ; then + echo 1 + return ; + fi; + echo $[ $num * $(fact $[ $num - 1 ])] +} diff --git a/examples/functions/fstty b/examples/functions/fstty new file mode 100644 index 0000000..a770d84 --- /dev/null +++ b/examples/functions/fstty @@ -0,0 +1,59 @@ +# +# A function that works as a front end for both stty and the `bind' +# builtin, so the tty driver and readline see the same changes +# + +# +# Convert between the stty ^H control character form and the readline \C-H +# form +# +cvt() +{ + echo "$@" | cat -v | sed 's/\^/\\C-/' +} + +# +# stty front-end. Parses the argument list and creates two command strings, +# one for stty, another for bind. +# +fstty() +{ + local cmd="" bargs="" + local e + + while [ $# -gt 0 ] + do + case "$1" in + -a) cmd="$cmd everything" + ;; + erase) shift; + e=$(cvt "$1") + cmd="$cmd erase $1" + bargs="$bargs '\"$e\": backward-delete-char'" + ;; + kill) shift + e=$(cvt "$1") + cmd="$cmd kill $1" + bargs="$bargs '\"$e\": unix-line-discard'" + ;; + werase) shift; + e=$(cvt "$1") + cmd="$cmd erase $1" + bargs="$bargs '\"$e\": backward-kill-word'" + ;; + lnext) shift; + e=$(cvt "$1") + cmd="$cmd erase $1" + bargs="$bargs '\"$e\": quoted-insert'" + ;; + *) cmd="$cmd $1" + ;; + esac + shift + done + + command stty $cmd + if [ -n "$bargs" ]; then + builtin bind $bargs + fi +} diff --git a/examples/functions/func b/examples/functions/func new file mode 100644 index 0000000..710f643 --- /dev/null +++ b/examples/functions/func @@ -0,0 +1,27 @@ +# +# func -- print out definitions for functions named by arguments +# +# usage: func name [name ...] +# +# Chet Ramey +# chet@ins.CWRU.Edu +func() +{ + local status=0 + + if [ $# -eq 0 ] ; then + echo "usage: func name [name...]" 1>&2 + return 1 + fi + + for f + do + if [ "$(builtin type -type $f)" != "function" ] ; then + echo "func: $f: not a function" 1>&2 + status=1 # one failed + continue + fi + builtin type $f | sed 1d + done + return $status +} diff --git a/examples/functions/jj.bash b/examples/functions/jj.bash new file mode 100644 index 0000000..212c9ce --- /dev/null +++ b/examples/functions/jj.bash @@ -0,0 +1,12 @@ +jj () +{ + p=$(jobs $1); + echo $p + + case "$p" in + [*) echo matches '[*' + ;; + *) echo not a match\? + ;; + esac +} diff --git a/examples/functions/kshenv b/examples/functions/kshenv new file mode 100644 index 0000000..fbec76f --- /dev/null +++ b/examples/functions/kshenv @@ -0,0 +1,183 @@ +# +# .kshenv -- functions and aliases to provide the beginnings of a ksh +# environment for bash. +# +# Chet Ramey +# chet@ins.CWRU.Edu +# +# +# These are definitions for the ksh compiled-in `exported aliases'. There +# are others, but we already have substitutes for them: "history", "type", +# and "hash". +# +alias r="fc -e -" +alias functions="typeset -f" +alias integer="typeset -i" +alias nohup="nohup " +alias true=":" +alias false="let 0" +alias hist="fc" + +# +# An almost-ksh compatible `whence' command. This is as hairy as it is +# because of the desire to exactly mimic ksh (whose behavior was determined +# empirically). +# +# This depends somewhat on knowing the format of the output of the bash +# `builtin type' command. +# + +whence() +{ + local vflag + local path + + vflag= + path= + if [ "$#" = "0" ] ; then + echo "whence: argument expected" + return 1 + fi + case "$1" in + -v) vflag=1 + shift 1 + ;; + -*) echo "whence: bad option: $1" + return 1 + ;; + *) ;; + esac + + if [ "$#" = "0" ] ; then + echo "whence: bad argument count" + return 1 + fi + + for cmd + do + if [ "$vflag" ] ; then + echo $(builtin type $cmd | sed 1q) + else + path=$(builtin type -path $cmd) + if [ "$path" ] ; then + echo $path + else + case "$cmd" in + /*) echo "" + ;; + *) case "$(builtin type -type $cmd)" in + "") echo "" + ;; + *) echo "$cmd" + ;; + esac + ;; + esac + fi + fi + done + return 0 +} + +# +# For real ksh homeboy fanatics, redefine the `type' builtin with a ksh +# version. +# +#type() +#{ +# whence -v "$*" +#} + +cd() +{ + case $# in + 0) builtin cd "$HOME" ;; + 1) builtin cd "$@" ;; + 2) old="$1" + new="$2" + dir=$(echo "$PWD" | sed "s:$old:$new:g") + case "$dir" in + "$PWD") echo "bash: cd: bad substitution" >&2 ; return 1 ;; + *) echo "$dir" + builtin cd "$dir" + ;; + esac + ;; + *) echo "cd: wrong arg count" >&2 ; return 1 ;; + esac +} + +# +# ksh print emulation +# +# print [-Rnprsu[n]] [arg ...] +# +# - end of options +# -R BSD-style -- only accept -n, no escapes +# -n do not add trailing newline +# -p no-op (no coprocesses) +# -r no escapes +# -s no-op (print to the history file) +# -u n redirect output to fd n +# + +print() +{ + local eflag=-e + local nflag= + local fd=1 + + OPTIND=1 + while getopts "Rnprsu:" c + do + case $c in + R) eflag= + ;; + r) eflag= + ;; + n) nflag=-n + ;; + u) fd=$OPTARG + ;; + p|s) ;; + esac + done + shift $[ $OPTIND - 1 ] + + builtin echo $eflag $nflag "$@" >&$fd +} + +# substring function +# this function should be equivalent to the substring built-in which was +# eliminated after the 06/29/84 version +substring () +{ + local lpat flag str #local variables + set -f + case $1 in + -l|-L) + flag=$1 + lpat=$2 + shift 2 + ;; + esac + # test for too few or too many arguments + if [ x"$1" = x -o $# -gt 2 ]; then + print -u2 'substring: bad argument count' + return 1 + fi + str=$1 + if [ x"$flag" = x-l ]; then #substring -l lpat + str=${str#$lpat} + elif [ x"$flag" = x-L ]; then + str=${str##$lpat} #substring -L lpat + fi + + if [ x"$2" != x ]; then + echo ${str%$2} + else + echo $str + fi + + return 0 +} diff --git a/examples/functions/manpage b/examples/functions/manpage new file mode 100644 index 0000000..3fdc7ac --- /dev/null +++ b/examples/functions/manpage @@ -0,0 +1,129 @@ +# Written from scratch by Tom Tromey (tromey@cns.caltech.edu) +# +# manpage -- find and print a manual page. +# usage: manpage section name [printing] +# +function manpage () +{ + local i h cmd zot sec + local num="$1" + local page="$2" + local printing="$3" + local mp + + mp="${MANPATH:-/usr/man}" + if [ "$#" -lt 2 ]; then return 1; fi # should print usage + if [ "$num" != "" ]; then + sec="${num%%[a-zA-Z]*}" + else + sec='[168234571lnpo]' + num="$sec" + fi + for i in $(echo "$mp" | tr : ' '); do + if [ ! -d "$i" ]; then continue; fi + file="$i"/man"$sec"/"$page"."$num"* + set $file + file="$1" + if [ -f "$file" ]; then + zot=$(head -1 "$file") + cmd=${MANROFF:-"nroff -man - | col | cat -s"} + h=${zot##"'"'\"'} + if [ "$h" != "$zot" ]; then + while [ "$h" != "" ]; do + case "$h" in + *e) cmd="${MANEQN:-neqn} | $cmd";; + *r) cmd="refer | $cmd";; + *t) cmd="tbl | $cmd";; + *v) cmd="vgrind | $cmd";; + *) ;; # should print error + esac + h=${h%?} + done + fi + if [ "$printing" != "" ]; then + (cd "$i"; eval "$cmd") < "$file" | ${PAGER:-more} + else + (cd "$i"; eval "$cmd") < "$file" > /tmp/manpage-$$ + ${PAGER:-more} /tmp/manpage-$$ + rm -f /tmp/manpage-$$ + fi + break + fi + done +} + +function whatis_internal () +{ + local j + for j in $(echo "$MANPATH" | tr : ' '); do + if [ -f "$j/whatis" ]; then + eval $2 -i -e "$1" $j/whatis + fi + done +} + +function whatis () +{ + local name=$(basename "$1") + whatis_internal "$name" "grep -w" +} + +function apropos () +{ + whatis_internal "$1" "fgrep" +} + +# Note: "-" and "-t" together not supported. This man could be +# made a lot better, but it does everything I want. +function man () +{ + local PAGER printing mpath MANROFF num + mpath="${MANPATH:-/usr/man}" + while true; do + case "$1" in + -) PAGER=cat + printing= ;; + -t) + MANROFF=${TROFF:-"ptroff -man -t"} + PAGER="${TCAT:-lpr}" + printing=yes ;; + -M) + mpath="$2" + shift;; + *) break;; + esac + shift + done + local MANPATH="$mpath" + case "$1" in + -f | -k) + local g a + if [ "$1" = "-f" ]; then + g="grep -w" + a=$(basename "$2") + else + g=fgrep + a="$2" + fi + whatis_internal "$a" "$g" + ;; + [0-9npol] | [0-9][a-z]* | new | public | old | local) + if [ "$1" = "new" ]; then + num=n + elif [ "$1" = "public" ]; then + num=p + elif [ "$1" = "old" ]; then + num=o + elif [ "$1" = "local" ]; then + num=l + else + num="$1" + fi + shift + manpage "$num" "$1" "$printing" + ;; + *) + manpage "$num" "$1" "$printing" + ;; + esac +} diff --git a/examples/functions/notify.bash b/examples/functions/notify.bash new file mode 100644 index 0000000..dafbac5 --- /dev/null +++ b/examples/functions/notify.bash @@ -0,0 +1,58 @@ +trap _notify CHLD +NOTIFY_ALL=false +unset NOTIFY_LIST +unalias false + +false() +{ + return 1 +} + +_notify () +{ + local i j + local newlist= + + if $NOTIFY_ALL + then + return # let bash take care of this itself + elif [ -z "$NOTIFY_LIST" ]; then + return + else + set -- $NOTIFY_LIST + for i in "$@" + do + j=$(jobs -n %$i) + if [ -n "$j" ]; then + echo "$j" + jobs -n %$i >/dev/null + else + newlist="newlist $i" + fi + done + NOTIFY_LIST="$newlist" + fi +} + +notify () +{ + local i j + + if [ $# -eq 0 ]; then + NOTIFY_ALL=: + set -b + return + else + for i in "$@" + do + # turn a valid job spec into a job number + j=$(jobs $i) + case "$j" in + [*) j=${j%%]*} + j=${j#[} + NOTIFY_LIST="$NOTIFY_LIST $j" + ;; + esac + done + fi +} diff --git a/examples/functions/shcat b/examples/functions/shcat new file mode 100644 index 0000000..55a3096 --- /dev/null +++ b/examples/functions/shcat @@ -0,0 +1,7 @@ +shcat() +{ + while read line + do + echo "$line" + done +} diff --git a/examples/functions/substr b/examples/functions/substr new file mode 100644 index 0000000..c557677 --- /dev/null +++ b/examples/functions/substr @@ -0,0 +1,79 @@ +# +# substr -- a function to emulate the ancient ksh builtin +# + +# +# -l == shortest from left +# -L == longest from left +# -r == shortest from right (the default) +# -R == longest from right + +substr() +{ + local flag pat str + local usage="usage: substr -lLrR pat string or substr string pat" + + case "$1" in + -l | -L | -r | -R) + flag="$1" + pat="$2" + shift 2 + ;; + -*) + echo "substr: unknown option: $1" + echo "$usage" + return 1 + ;; + *) + flag="-r" + pat="$2" + ;; + esac + + if [ "$#" -eq 0 -o "$#" -gt 2 ] ; then + echo "substr: bad argument count" + return 2 + fi + + str="$1" + + # + # We don't want -f, but we don't want to turn it back on if + # we didn't have it already + # + case "$-" in + "*f*") + ;; + *) + fng=1 + set -f + ;; + esac + + case "$flag" in + -l) + str="${str#$pat}" # substr -l pat string + ;; + -L) + str="${str##$pat}" # substr -L pat string + ;; + -r) + str="${str%$pat}" # substr -r pat string + ;; + -R) + str="${str%%$pat}" # substr -R pat string + ;; + *) + str="${str%$2}" # substr string pat + ;; + esac + + echo "$str" + + # + # If we had file name generation when we started, re-enable it + # + if [ "$fng" = "1" ] ; then + set +f + fi +} diff --git a/examples/functions/substr2 b/examples/functions/substr2 new file mode 100644 index 0000000..f5e7547 --- /dev/null +++ b/examples/functions/substr2 @@ -0,0 +1,81 @@ +# +# substr -- a function to emulate the ancient ksh builtin +# + +# -l == remove shortest from left +# -L == remove longest from left +# -r == remove shortest from right (the default) +# -R == remove longest from right + +substr() +{ + local flag pat str + local usage="usage: substr -lLrR pat string or substr string pat" + local options="l:L:r:R:" + + OPTIND=1 + while getopts "$options" c + do + case "$c" in + l | L | r | R) + flag="-$c" + pat="$OPTARG" + ;; + '?') + echo "$usage" + return 1 + ;; + esac + done + + if [ "$OPTIND" -gt 1 ] ; then + shift $[ $OPTIND -1 ] + fi + + if [ "$#" -eq 0 -o "$#" -gt 2 ] ; then + echo "substr: bad argument count" + return 2 + fi + + str="$1" + + # + # We don't want -f, but we don't want to turn it back on if + # we didn't have it already + # + case "$-" in + "*f*") + ;; + *) + fng=1 + set -f + ;; + esac + + case "$flag" in + -l) + str="${str#$pat}" # substr -l pat string + ;; + -L) + str="${str##$pat}" # substr -L pat string + ;; + -r) + str="${str%$pat}" # substr -r pat string + ;; + -R) + str="${str%%$pat}" # substr -R pat string + ;; + *) + str="${str%$2}" # substr string pat + ;; + esac + + echo "$str" + + # + # If we had file name generation when we started, re-enable it + # + if [ "$fng" = "1" ] ; then + set +f + fi +} diff --git a/examples/functions/term b/examples/functions/term new file mode 100644 index 0000000..fbe99f1 --- /dev/null +++ b/examples/functions/term @@ -0,0 +1,35 @@ +# +# term -- a shell function to set the terminal type interactively or not. +# + +term() +{ + local t + + if [ $# != 0 ] ; then + eval $(tset -sQ $1) + else # interactive + if [ -z "$TERM" ] ; then + TERM="unknown" + fi + + case "$TERM" in + network|dialup|unknown|lat) + TERM=unknown + ;; + *) + eval $(tset -sQ) + ;; + esac + + while [ "$TERM" = "unknown" ] ; do + echo -n "Terminal type: " + read t + if [ -n "$t" ] ; then + eval $(tset -sQ $t) + fi + done + fi +} + + diff --git a/examples/functions/whatis b/examples/functions/whatis new file mode 100644 index 0000000..56c5a58 --- /dev/null +++ b/examples/functions/whatis @@ -0,0 +1,52 @@ +# +# whatis -- and implementation of the 10th Edition Unix sh builtin `whatis' +# command. +# +# usage: whatis arg [...] +# +# For each argument, whatis prints the associated value as a parameter, +# builtin, function, alias, or executable file as appropriate. In each +# case, the value is printed in a form which would yield the same value +# if typed as input to the shell itself. +# + +whatis() +{ + local wusage='usage: whatis arg [arg...]' + local fail=0 + + if [ $# -eq 0 ] ; then + echo "$wusage" + return 1 + fi + + for arg + do + case $(builtin type -type $arg 2>/dev/null) in + "alias") + builtin alias "$arg" + ;; + "function") + builtin type "$arg" | sed 1d + ;; + "builtin") + echo builtin "$arg" + ;; + "file") + builtin type -path "$arg" + ;; + *) + # OK, we could have a variable, or we could have nada + if [ "$(eval echo \${$arg+set})" = "set" ] ; then + # It is a variable, and it is set + echo -n "$arg=" + eval echo '\"'\$$arg'\"' + else + echo whatis: $arg: not found + fail=1 + fi + ;; + esac + done + return $fail +} diff --git a/examples/functions/whence b/examples/functions/whence new file mode 100644 index 0000000..70b2322 --- /dev/null +++ b/examples/functions/whence @@ -0,0 +1,59 @@ +# +# An almost-ksh compatible `whence' command. This is as hairy as it is +# because of the desire to exactly mimic ksh. +# +# This depends somewhat on knowing the format of the output of the bash +# `builtin type' command. +# +# Chet Ramey +# chet@ins.CWRU.Edu +# +whence() +{ + local vflag= path= + + if [ "$#" = "0" ] ; then + echo "whence: argument expected" + return 1 + fi + case "$1" in + -v) vflag=1 + shift 1 + ;; + -*) echo "whence: bad option: $1" + return 1 + ;; + *) ;; + esac + + if [ "$#" = "0" ] ; then + echo "whence: bad argument count" + return 1 + fi + + for cmd + do + if [ "$vflag" ] ; then + echo $(builtin type $cmd | sed 1q) + else + path=$(builtin type -path $cmd) + if [ "$path" ] ; then + echo $path + else + case "$cmd" in + /*) if [ -x "$cmd" ]; then + echo "$cmd" + fi + ;; + *) case "$(builtin type -type $cmd)" in + "") ;; + *) echo "$cmd" + ;; + esac + ;; + esac + fi + fi + done + return 0 +} |