Adding upstream version 5.2.37.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
parent
cf91100bce
commit
fa1b3d3922
1435 changed files with 757174 additions and 0 deletions
122
examples/functions/array-stuff
Normal file
122
examples/functions/array-stuff
Normal file
|
@ -0,0 +1,122 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 1999 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
# usage: reverse arrayname
|
||||
reverse()
|
||||
{
|
||||
local -a R
|
||||
local -i i
|
||||
local rlen temp
|
||||
|
||||
# make r a copy of the array whose name is passed as an arg
|
||||
eval R=\( \"\$\{$1\[@\]\}\" \)
|
||||
|
||||
# reverse R
|
||||
rlen=${#R[@]}
|
||||
|
||||
for ((i=0; i < rlen/2; i++ ))
|
||||
do
|
||||
temp=${R[i]}
|
||||
R[i]=${R[rlen-i-1]}
|
||||
R[rlen-i-1]=$temp
|
||||
done
|
||||
|
||||
# and assign R back to array whose name is passed as an arg
|
||||
eval $1=\( \"\$\{R\[@\]\}\" \)
|
||||
}
|
||||
|
||||
A=(1 2 3 4 5 6 7)
|
||||
echo "${A[@]}"
|
||||
reverse A
|
||||
echo "${A[@]}"
|
||||
reverse A
|
||||
echo "${A[@]}"
|
||||
|
||||
# unset last element of A
|
||||
alen=${#A[@]}
|
||||
unset A[$alen-1]
|
||||
echo "${A[@]}"
|
||||
|
||||
# ashift -- like shift, but for arrays
|
||||
|
||||
ashift()
|
||||
{
|
||||
local -a R
|
||||
local n
|
||||
|
||||
case $# in
|
||||
1) n=1 ;;
|
||||
2) n=$2 ;;
|
||||
*) echo "$FUNCNAME: usage: $FUNCNAME array [count]" >&2
|
||||
exit 2;;
|
||||
esac
|
||||
|
||||
# make r a copy of the array whose name is passed as an arg
|
||||
eval R=\( \"\$\{$1\[@\]\}\" \)
|
||||
|
||||
# shift R
|
||||
R=( "${R[@]:$n}" )
|
||||
|
||||
# and assign R back to array whose name is passed as an arg
|
||||
eval $1=\( \"\$\{R\[@\]\}\" \)
|
||||
}
|
||||
|
||||
ashift A 2
|
||||
echo "${A[@]}"
|
||||
|
||||
ashift A
|
||||
echo "${A[@]}"
|
||||
|
||||
ashift A 7
|
||||
echo "${A[@]}"
|
||||
|
||||
# Sort the members of the array whose name is passed as the first non-option
|
||||
# arg. If -u is the first arg, remove duplicate array members.
|
||||
array_sort()
|
||||
{
|
||||
local -a R
|
||||
local u
|
||||
|
||||
case "$1" in
|
||||
-u) u=-u ; shift ;;
|
||||
esac
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "array_sort: argument expected" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# make r a copy of the array whose name is passed as an arg
|
||||
eval R=\( \"\$\{$1\[@\]\}\" \)
|
||||
|
||||
# sort R
|
||||
R=( $( printf "%s\n" "${A[@]}" | sort $u) )
|
||||
|
||||
# and assign R back to array whose name is passed as an arg
|
||||
eval $1=\( \"\$\{R\[@\]\}\" \)
|
||||
return 0
|
||||
}
|
||||
|
||||
A=(3 1 4 1 5 9 2 6 5 3 2)
|
||||
array_sort A
|
||||
echo "${A[@]}"
|
||||
|
||||
A=(3 1 4 1 5 9 2 6 5 3 2)
|
||||
array_sort -u A
|
||||
echo "${A[@]}"
|
15
examples/functions/array-to-string
Normal file
15
examples/functions/array-to-string
Normal file
|
@ -0,0 +1,15 @@
|
|||
#! /bin/bash
|
||||
|
||||
# Format: array_to_string vname_of_array vname_of_string separator
|
||||
array_to_string()
|
||||
{
|
||||
(( ($# < 2) || ($# > 3) )) && {
|
||||
"$FUNCNAME: usage: $FUNCNAME arrayname stringname [separator]"
|
||||
return 2
|
||||
}
|
||||
|
||||
local array=$1 string=$2
|
||||
((3==$#)) && [[ $3 = ? ]] && local IFS="${3}${IFS}"
|
||||
eval $string="\"\${$array[*]}\""
|
||||
return 0
|
||||
}
|
146
examples/functions/arrayops.bash
Normal file
146
examples/functions/arrayops.bash
Normal file
|
@ -0,0 +1,146 @@
|
|||
# arrayops.bash --- hide some of the nasty syntax for manipulating bash arrays
|
||||
# Author: Noah Friedman <friedman@splode.com>
|
||||
# Created: 2016-07-08
|
||||
# Public domain
|
||||
|
||||
# $Id: arrayops.bash,v 1.3 2016/07/28 15:38:55 friedman Exp $
|
||||
|
||||
# Commentary:
|
||||
|
||||
# These functions try to tame the syntactic nightmare that is bash array
|
||||
# syntax, which makes perl's almost look reasonable.
|
||||
#
|
||||
# For example the apush function below lets you write:
|
||||
#
|
||||
# apush arrayvar newval
|
||||
#
|
||||
# instead of
|
||||
#
|
||||
# ${arrayvar[${#arrayvar[@]}]}=newval
|
||||
#
|
||||
# Because seriously, you've got to be kidding me.
|
||||
|
||||
# These functions avoid the use of local variables as much as possible
|
||||
# (especially wherever modification occurs) because those variable names
|
||||
# might shadow the array name passed in. Dynamic scope!
|
||||
|
||||
# Code:
|
||||
|
||||
#:docstring apush:
|
||||
# Usage: apush arrayname val1 {val2 {...}}
|
||||
#
|
||||
# Appends VAL1 and any remaining arguments to the end of the array
|
||||
# ARRAYNAME as new elements.
|
||||
#:end docstring:
|
||||
apush()
|
||||
{
|
||||
eval "$1=(\"\${$1[@]}\" \"\${@:2}\")"
|
||||
}
|
||||
|
||||
#:docstring apop:
|
||||
# Usage: apop arrayname {n}
|
||||
#
|
||||
# Removes the last element from ARRAYNAME.
|
||||
# Optional argument N means remove the last N elements.
|
||||
#:end docstring:
|
||||
apop()
|
||||
{
|
||||
eval "$1=(\"\${$1[@]:0:\${#$1[@]}-${2-1}}\")"
|
||||
}
|
||||
|
||||
#:docstring aunshift:
|
||||
# Usage: aunshift arrayname val1 {val2 {...}}
|
||||
#
|
||||
# Prepends VAL1 and any remaining arguments to the beginning of the array
|
||||
# ARRAYNAME as new elements. The new elements will appear in the same order
|
||||
# as given to this function, rather than inserting them one at a time.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# foo=(a b c)
|
||||
# aunshift foo 1 2 3
|
||||
# => foo is now (1 2 3 a b c)
|
||||
# but
|
||||
#
|
||||
# foo=(a b c)
|
||||
# aunshift foo 1
|
||||
# aunshift foo 2
|
||||
# aunshift foo 3
|
||||
# => foo is now (3 2 1 a b c)
|
||||
#
|
||||
#:end docstring:
|
||||
aunshift()
|
||||
{
|
||||
eval "$1=(\"\${@:2}\" \"\${$1[@]}\")"
|
||||
}
|
||||
|
||||
#:docstring ashift:
|
||||
# Usage: ashift arrayname {n}
|
||||
#
|
||||
# Removes the first element from ARRAYNAME.
|
||||
# Optional argument N means remove the first N elements.
|
||||
#:end docstring:
|
||||
ashift()
|
||||
{
|
||||
eval "$1=(\"\${$1[@]: -\${#$1[@]}+${2-1}}\")"
|
||||
}
|
||||
|
||||
#:docstring aset:
|
||||
# Usage: aset arrayname idx newval
|
||||
#
|
||||
# Assigns ARRAYNAME[IDX]=NEWVAL
|
||||
#:end docstring:
|
||||
aset()
|
||||
{
|
||||
eval "$1[\$2]=${@:3}"
|
||||
}
|
||||
|
||||
#:docstring aref:
|
||||
# Usage: aref arrayname idx {idx2 {...}}
|
||||
#
|
||||
# Echoes the value of ARRAYNAME at index IDX to stdout.
|
||||
# If more than one IDX is specified, each one is echoed.
|
||||
#
|
||||
# Unfortunately bash functions cannot return arbitrary values in the usual way.
|
||||
#:end docstring:
|
||||
aref()
|
||||
{
|
||||
eval local "v=(\"\${$1[@]}\")"
|
||||
local x
|
||||
for x in ${@:2} ; do echo "${v[$x]}"; done
|
||||
}
|
||||
|
||||
#:docstring aref:
|
||||
# Usage: alen arrayname
|
||||
#
|
||||
# Echoes the length of the number of elements in ARRAYNAME.
|
||||
#
|
||||
# It also returns number as a numeric value, but return values are limited
|
||||
# by a maximum of 255 so don't rely on this unless you know your arrays are
|
||||
# relatively small.
|
||||
#:end docstring:
|
||||
alen()
|
||||
{
|
||||
eval echo "\${#$1[@]}"
|
||||
eval return "\${#$1[@]}"
|
||||
}
|
||||
|
||||
#:docstring anreverse:
|
||||
# Usage: anreverse arrayname
|
||||
#
|
||||
# Reverse the order of the elements in ARRAYNAME.
|
||||
# The array variable is altered by this operation.
|
||||
#:end docstring:
|
||||
anreverse()
|
||||
{
|
||||
eval set $1 "\"\${$1[@]}\""
|
||||
eval unset $1
|
||||
while [ $# -gt 1 ]; do
|
||||
eval "$1=(\"$2\" \"\${$1[@]}\")"
|
||||
set $1 "${@:3}"
|
||||
done
|
||||
}
|
||||
|
||||
#provide arrayops
|
||||
|
||||
# arrayops.bash ends here
|
111
examples/functions/autoload
Normal file
111
examples/functions/autoload
Normal file
|
@ -0,0 +1,111 @@
|
|||
#
|
||||
# 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
|
||||
# containing 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...]" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
#
|
||||
# If there is no $FPATH, there is no work to be done
|
||||
#
|
||||
|
||||
if [ -z "$FPATH" ] ; then
|
||||
echo autoload: FPATH not set or null >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
#
|
||||
# This treats FPATH exactly like PATH: a null field anywhere in the
|
||||
# FPATH is treated the same as the current directory.
|
||||
#
|
||||
# The path splitting command is taken from Kernighan and Pike
|
||||
#
|
||||
|
||||
# fp=$(echo $FPATH | sed 's/^:/.:/
|
||||
# s/::/:.:/g
|
||||
# s/:$/:./
|
||||
# s/:/ /g')
|
||||
|
||||
# replaced with builtin mechanisms 2001 Oct 10
|
||||
|
||||
fp=${FPATH/#:/.:}
|
||||
fp=${fp//::/:.:}
|
||||
fp=${fp/%:/:.}
|
||||
fp=${fp//:/ }
|
||||
|
||||
for FUNC in $args ; do
|
||||
#
|
||||
# We're blowing away the arguments to autoload here...
|
||||
# We have to; there are no arrays (well, there are, but
|
||||
# this doesn't use them yet).
|
||||
#
|
||||
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" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
# echo auto-loading $FUNC from $1/$FUNC
|
||||
aload $FUNC $1/$FUNC
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
192
examples/functions/autoload.v2
Normal file
192
examples/functions/autoload.v2
Normal file
|
@ -0,0 +1,192 @@
|
|||
#
|
||||
# An almost ksh-compatible `autoload'. A function declared as `autoload' will
|
||||
# be read in from a file the same name as the function found by searching the
|
||||
# $FPATH (which works the same as $PATH), then that definition will be run.
|
||||
#
|
||||
# To do this without source support, we define a dummy function that, when
|
||||
# executed, will load the file (thereby re-defining the function), then
|
||||
# execute that newly-redefined function with the original arguments.
|
||||
#
|
||||
# It's not identical to ksh because ksh apparently does lazy evaluation
|
||||
# and looks for the file to load from only when the function is referenced.
|
||||
# This one requires that the file exist when the function is declared as
|
||||
# `autoload'.
|
||||
#
|
||||
# usage: autoload [-pu] [func ...]
|
||||
#
|
||||
# options:
|
||||
# -p print in a format that can be reused as input
|
||||
# -u unset each function and remove it from the autoload list
|
||||
#
|
||||
# The first cut of this was by Bill Trost, trost@reed.edu
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@ins.CWRU.Edu
|
||||
|
||||
unset _AUTOLOADS
|
||||
_aindex=0
|
||||
|
||||
#
|
||||
# Declare a function ($1) to be autoloaded from a file ($2) when it is first
|
||||
# called. This defines a `temporary' function that will `.' the file
|
||||
# containing the real function definition, then execute that new definition with
|
||||
# the arguments given to this `fake' function. The autoload function defined
|
||||
# by the file and the file itself *must* be named identically.
|
||||
#
|
||||
|
||||
_aload()
|
||||
{
|
||||
eval $1 '() { . '$2' ; '$1' "$@" ; return $? ; }'
|
||||
_autoload_addlist "$1"
|
||||
}
|
||||
|
||||
_autoload_addlist()
|
||||
{
|
||||
local i=0
|
||||
|
||||
while (( i < $_aindex )); do
|
||||
case "${_AUTOLOADS[i]}" in
|
||||
"$1") return 1 ;;
|
||||
esac
|
||||
(( i += 1 ))
|
||||
done
|
||||
_AUTOLOADS[_aindex]="$1"
|
||||
(( _aindex += 1 ))
|
||||
return 0
|
||||
}
|
||||
|
||||
_autoload_dump()
|
||||
{
|
||||
local func
|
||||
|
||||
for func in ${_AUTOLOADS[@]}; do
|
||||
[ -n "$1" ] && echo -n "autoload "
|
||||
echo "$func"
|
||||
done
|
||||
}
|
||||
|
||||
# Remove $1 from the list of autoloaded functions
|
||||
_autoload_remove_one()
|
||||
{
|
||||
local i=0 nnl=0
|
||||
local -a nlist
|
||||
|
||||
while (( i < _aindex )); do
|
||||
case "${_AUTOLOADS[i]}" in
|
||||
"$1") ;;
|
||||
*) nlist[nnl]="${_AUTOLOADS[i]}" ; (( nnl += 1 ));;
|
||||
esac
|
||||
(( i += 1 ))
|
||||
done
|
||||
unset _AUTOLOADS _aindex
|
||||
eval _AUTOLOADS=( ${nlist[@]} )
|
||||
_aindex=$nnl
|
||||
}
|
||||
|
||||
# Remove all function arguments from the list of autoloaded functions
|
||||
_autoload_remove()
|
||||
{
|
||||
local func i es=0
|
||||
|
||||
# first unset the autoloaded functions
|
||||
for func; do
|
||||
i=0
|
||||
while (( i < _aindex )); do
|
||||
case "${_AUTOLOADS[i]}" in
|
||||
"$func") unset -f $func ; break ;;
|
||||
esac
|
||||
(( i += 1 ))
|
||||
done
|
||||
if (( i == _aindex )); then
|
||||
echo "autoload: $func: not an autoloaded function" >&2
|
||||
es=1
|
||||
fi
|
||||
done
|
||||
|
||||
# then rebuild the list of autoloaded functions
|
||||
for func ; do
|
||||
_autoload_remove_one "$func"
|
||||
done
|
||||
|
||||
return $es
|
||||
}
|
||||
|
||||
#
|
||||
# Search $FPATH for a file the same name as the function given as $1, and
|
||||
# autoload the function from that file. There is no default $FPATH.
|
||||
#
|
||||
|
||||
autoload()
|
||||
{
|
||||
local -a fp
|
||||
local _autoload_unset nfp i
|
||||
|
||||
if (( $# == 0 )) ; then
|
||||
_autoload_dump
|
||||
return 0
|
||||
fi
|
||||
|
||||
OPTIND=1
|
||||
while getopts pu opt
|
||||
do
|
||||
case "$opt" in
|
||||
p) _autoload_dump printable; return 0;;
|
||||
u) _autoload_unset=y ;;
|
||||
*) echo "autoload: usage: autoload [-pu] [function ...]" >&2
|
||||
return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
if [ -n "$_autoload_unset" ]; then
|
||||
_autoload_remove "$@"
|
||||
return $?
|
||||
fi
|
||||
|
||||
#
|
||||
# If there is no $FPATH, there is no work to be done
|
||||
#
|
||||
|
||||
if [ -z "$FPATH" ] ; then
|
||||
echo "autoload: FPATH not set or null" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
#
|
||||
# This treats FPATH exactly like PATH: a null field anywhere in the
|
||||
# FPATH is treated the same as the current directory.
|
||||
#
|
||||
# This turns $FPATH into an array, substituting `.' for `'
|
||||
#
|
||||
eval fp=( $(
|
||||
IFS=':'
|
||||
set -- ${FPATH}
|
||||
for p in "$@" ; do echo -n "${p:-.} "; done
|
||||
)
|
||||
)
|
||||
|
||||
nfp=${#fp[@]}
|
||||
|
||||
for FUNC ; do
|
||||
i=0;
|
||||
while (( i < nfp )) ; do
|
||||
if [ -f ${fp[i]}/$FUNC ] ; then
|
||||
break # found it!
|
||||
fi
|
||||
(( i += 1 ))
|
||||
done
|
||||
|
||||
if (( i == nfp )) ; then
|
||||
echo "autoload: $FUNC: autoload function not found" >&2
|
||||
es=1
|
||||
continue
|
||||
fi
|
||||
|
||||
# echo auto-loading $FUNC from ${fp[i]}/$FUNC
|
||||
_aload $FUNC ${fp[i]}/$FUNC
|
||||
es=0
|
||||
done
|
||||
|
||||
return $es
|
||||
}
|
125
examples/functions/autoload.v3
Normal file
125
examples/functions/autoload.v3
Normal file
|
@ -0,0 +1,125 @@
|
|||
#From: Mark Kennedy <mark.t.kennedy@gmail.com> (<mtk@ny.ubs.com>)
|
||||
#Message-ID: <35E2B899.63A02DF5@ny.ubs.com>
|
||||
#Date: Tue, 25 Aug 1998 09:14:01 -0400
|
||||
#To: chet@nike.ins.cwru.edu
|
||||
#Subject: a newer version of the ksh-style 'autoload'
|
||||
|
||||
#enclosed you'll find 'autoload.v3', a version of the autoloader
|
||||
#that emulates the ksh semantics of delaying the resolution (and loading) of the function
|
||||
#until its first use. i took the liberty of simplifying the code a bit although it still uses the
|
||||
#same functional breakdown. i recently went through the exercise of converting
|
||||
#my ksh-based environment to bash (a very, very pleasant experience)
|
||||
#and this popped out.
|
||||
|
||||
# the psuedo-ksh autoloader.
|
||||
|
||||
# The first cut of this was by Bill Trost, trost@reed.bitnet.
|
||||
# The second cut came from Chet Ramey, chet@ins.CWRU.Edu
|
||||
# The third cut came from Mark Kennedy, mtk@ny.ubs.com. 1998/08/25
|
||||
|
||||
unset _AUTOLOADS
|
||||
|
||||
_aload()
|
||||
{
|
||||
local func
|
||||
for func; do
|
||||
eval $func '()
|
||||
{
|
||||
local f=$(_autoload_resolve '$func')
|
||||
if [[ $f ]]; then
|
||||
. $f
|
||||
'$func' "$@"
|
||||
return $?
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}'
|
||||
_autoload_addlist $func
|
||||
done
|
||||
}
|
||||
|
||||
_autoload_addlist()
|
||||
{
|
||||
local func
|
||||
|
||||
for func in ${_AUTOLOADS[@]}; do
|
||||
[[ $func = "$1" ]] && return
|
||||
done
|
||||
|
||||
_AUTOLOADS[${#_AUTOLOADS[@]}]=$1
|
||||
}
|
||||
|
||||
_autoload_dump()
|
||||
{
|
||||
local func
|
||||
|
||||
for func in ${_AUTOLOADS[@]}; do
|
||||
[[ $1 ]] && echo -n "autoload "
|
||||
echo $func
|
||||
done
|
||||
}
|
||||
|
||||
_autoload_remove_one()
|
||||
{
|
||||
local func
|
||||
local -a NEW_AUTOLOADS
|
||||
|
||||
for func in ${_AUTOLOADS[@]}; do
|
||||
[[ $func != "$1" ]] && NEW_AUTOLOADS[${#NEW_AUTOLOADS[@]}]=$func
|
||||
done
|
||||
|
||||
_AUTOLOADS=( ${NEW_AUTOLOADS[@]} )
|
||||
}
|
||||
|
||||
_autoload_remove()
|
||||
{
|
||||
local victim func
|
||||
|
||||
for victim; do
|
||||
for func in ${_AUTOLOADS[@]}; do
|
||||
[[ $victim = "$func" ]] && unset -f $func && continue 2
|
||||
done
|
||||
echo "autoload: $func: not an autoloaded function" >&2
|
||||
done
|
||||
|
||||
for func; do
|
||||
_autoload_remove_one $func
|
||||
done
|
||||
}
|
||||
|
||||
_autoload_resolve()
|
||||
{
|
||||
if [[ ! "$FPATH" ]]; then
|
||||
echo "autoload: FPATH not set or null" >&2
|
||||
return
|
||||
fi
|
||||
|
||||
local p
|
||||
|
||||
for p in $( (IFS=':'; set -- ${FPATH}; echo "$@") ); do
|
||||
p=${p:-.}
|
||||
if [ -f $p/$1 ]; then echo $p/$1; return; fi
|
||||
done
|
||||
|
||||
echo "autoload: $1: function source file not found" >&2
|
||||
}
|
||||
|
||||
autoload()
|
||||
{
|
||||
if (( $# == 0 )) ; then _autoload_dump; return; fi
|
||||
|
||||
local opt OPTIND
|
||||
|
||||
while getopts pu opt
|
||||
do
|
||||
case $opt in
|
||||
p) _autoload_dump printable; return;;
|
||||
u) shift $((OPTIND-1)); _autoload_remove "$@"; return;;
|
||||
*) echo "autoload: usage: autoload [-pu] [function ...]" >&2; return;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(($OPTIND-1))
|
||||
|
||||
_aload "$@"
|
||||
}
|
556
examples/functions/autoload.v4
Normal file
556
examples/functions/autoload.v4
Normal file
|
@ -0,0 +1,556 @@
|
|||
## -*- sh -*-
|
||||
|
||||
# The psuedo-ksh autoloader.
|
||||
|
||||
# How to use:
|
||||
# o One function per file.
|
||||
# o File and function name match exactly.
|
||||
# o File is located in a directory that is in FPATH.
|
||||
# o This script (autoload) must be sourced in as early as possible. This
|
||||
# implies that any code in this script should NOT rely on any library of local
|
||||
# or self-defined functions having already been loaded.
|
||||
# o autoload must be called for each function before the function can be used. If
|
||||
# autoloads are in directories where there are nothing but autoloads, then
|
||||
# 'autoload /path/to/files/*' suffices (but see options -a and -f).
|
||||
# o The call must be made in the current environment, not a subshell.
|
||||
# o The command line suffices as "current environment". If you have autoload
|
||||
# calls in a script, that script must be dotted into the process.
|
||||
|
||||
# The first cut of this was by Bill Trost, trost@reed.bitnet.
|
||||
# The second cut came from Chet Ramey, chet@ins.CWRU.Edu
|
||||
# The third cut came from Mark Kennedy, mtk@ny.ubs.com. 1998/08/25
|
||||
# The fourth cut came from Matthew Persico, matthew.persico@gmail.com 2017/August
|
||||
|
||||
autoload_calc_shimsize ()
|
||||
{
|
||||
echo $((AUTOLOAD_SHIM_OVERHEAD + 3 * ${#1}))
|
||||
}
|
||||
|
||||
_autoload_split_fpath ()
|
||||
{
|
||||
(IFS=':'; set -- ${FPATH}; echo "$@")
|
||||
}
|
||||
|
||||
_aload()
|
||||
{
|
||||
local opt OPTIND
|
||||
local doexport=0
|
||||
local doreload=0
|
||||
local doverbose=0
|
||||
local doevalshim=0
|
||||
local loadthese
|
||||
local optimize=0
|
||||
local loaded=0
|
||||
local exported=0
|
||||
local optimized=0
|
||||
local summary=0
|
||||
local dofpath=0
|
||||
while getopts xrvla:oyf opt; do
|
||||
case $opt in
|
||||
x) doexport=1;;
|
||||
r) doreload=1;;
|
||||
v) doverbose=1;;
|
||||
l) doevalshim=1;;
|
||||
a) loadthese=$(find $OPTARG -maxdepth 1 -type f -printf '%f ');;
|
||||
o) optimize=1;;
|
||||
y) summary=1;;
|
||||
f) loadthese=$(find $(_autoload_split_fpath) -maxdepth 1 -type f -printf '%f ');;
|
||||
*) echo "_aload: usage: _aload [-xrvlyf] [-a dir] [function ...]" >&2; return;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(($OPTIND-1))
|
||||
|
||||
[ -z "$loadthese" ] && loadthese="$@"
|
||||
|
||||
local func
|
||||
for func in $loadthese; do
|
||||
local exists_fn
|
||||
exists_fn=$(declare -F $func)
|
||||
if [ -n "$exists_fn" ] && ((doreload==0)) && ((doevalshim==0))
|
||||
then
|
||||
if ((doverbose))
|
||||
then
|
||||
echo "autoload: function '$func' already exists"
|
||||
fi
|
||||
else
|
||||
local andevaled=''
|
||||
local andexported=''
|
||||
local evalstat=0
|
||||
local doshim=1
|
||||
local funcfile
|
||||
funcfile=$(_autoload_resolve $func)
|
||||
if [[ $funcfile ]] ; then
|
||||
## The file was found for $func. Process it.
|
||||
|
||||
if ((optimize)); then
|
||||
## For the first function loaded, we will not know
|
||||
## AUTOLOAD_SHIM_OVERHEAD. We can only calculate it after
|
||||
## we have loaded one function.
|
||||
if [[ $AUTOLOAD_SHIM_OVERHEAD ]]; then
|
||||
local size=$(wc -c $funcfile| sed 's/ .*//')
|
||||
local shimsize=$(autoload_calc_shimsize $func)
|
||||
if (( size <= shimsize)); then
|
||||
doshim=0
|
||||
andevaled=', optimized'
|
||||
((optimized+=1))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if ((doevalshim)); then
|
||||
doshim=0
|
||||
andevaled=', evaled'
|
||||
fi
|
||||
|
||||
## 'brand' as in branding a cow with a mark. We add a local
|
||||
## variable to each function we autoload so that we can tell
|
||||
## later on it is an autoloaded function without having to
|
||||
## maintain some bash array or hash that cannot be passed to
|
||||
## and used by subshells.
|
||||
local brandtext
|
||||
brandtext="eval \"\$(type $func | sed -e 1d -e 4ilocal\\ AUTOLOADED=\'$func\')\""
|
||||
if ((doshim)); then
|
||||
## Don't bother trying to save space by shoving all the
|
||||
## eval text below onto one unreadable line; new lines will
|
||||
## be added at your semicolons and any indentation below
|
||||
## seems to be ignored anyway if you export the function;
|
||||
## look at its BASH_FUNCTION representation.
|
||||
eval $func '()
|
||||
{
|
||||
local IS_SHIM="$func"
|
||||
local file=$(_autoload_resolve '$func')
|
||||
if [[ $file ]]
|
||||
then
|
||||
. $file
|
||||
'$brandtext'
|
||||
'$func' "$@"
|
||||
return $?
|
||||
else
|
||||
return 1;
|
||||
fi
|
||||
}'
|
||||
else
|
||||
. $funcfile
|
||||
eval "$brandtext"
|
||||
fi
|
||||
evalstat=$?
|
||||
if((evalstat==0))
|
||||
then
|
||||
((loaded+=1))
|
||||
((doexport)) && export -f $func && andexported=', exported' && ((exported+=1))
|
||||
((doverbose)) && echo "$func autoloaded${andexported}${andevaled}"
|
||||
if [[ ! $AUTOLOAD_SHIM_OVERHEAD ]] && ((doshim)); then
|
||||
## ...we have just loaded the first function shim into
|
||||
## memory. Let's calc the AUTOLOAD_SHIM_OVERHEAD size
|
||||
## to use going forward. In theory, we could check
|
||||
## again here to see if we should optimize and source
|
||||
## in this function, now that we now the
|
||||
## AUTOLOAD_SHIM_OVERHEAD. In practice, it's not worth
|
||||
## duping that code or creating a function to do so for
|
||||
## one function.
|
||||
AUTOLOAD_SHIM_OVERHEAD=$(type $func | grep -v -E "^$1 is a function" | sed "s/$func//g"| wc -c)
|
||||
export AUTOLOAD_SHIM_OVERHEAD
|
||||
fi
|
||||
else
|
||||
echo "$func failed to load" >&2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
((summary)) && echo "autoload: loaded:$loaded exported:$exported optimized:$optimized overhead:$AUTOLOAD_SHIM_OVERHEAD bytes"
|
||||
}
|
||||
|
||||
_autoload_dump()
|
||||
{
|
||||
local opt OPTIND
|
||||
local opt_p=''
|
||||
local opt_s=''
|
||||
while getopts ps opt
|
||||
do
|
||||
case $opt in
|
||||
p ) opt_p=1;;
|
||||
s ) opt_s=1;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(($OPTIND-1))
|
||||
|
||||
local exported=''
|
||||
local executed=''
|
||||
local func
|
||||
for func in $(declare | grep -E 'local\\{0,1} AUTOLOADED' | sed -e "s/.*AUTOLOADED=//" -e 's/\\//g' -e 's/[");]//g' -e "s/'//g")
|
||||
do
|
||||
if [ -n "$opt_p" ]; then echo -n "autoload "; fi
|
||||
if [ -n "$opt_s" ]
|
||||
then
|
||||
exported=$(declare -F | grep -E "${func}$" | sed 's/declare -f\(x\{0,1\}\).*/\1/')
|
||||
[ "$exported" = 'x' ] && exported=' exported' || exported=' not exported'
|
||||
executed=$(type $func | grep 'local IS_SHIM')
|
||||
[ -z "$executed" ] && executed=' executed' || executed=' not executed'
|
||||
fi
|
||||
echo "${func}${exported}${executed}"
|
||||
done
|
||||
}
|
||||
|
||||
_autoload_resolve()
|
||||
{
|
||||
if [[ ! "$FPATH" ]]; then
|
||||
echo "autoload: FPATH not set or null" >&2
|
||||
return
|
||||
fi
|
||||
|
||||
local p # for 'path'. The $() commands in the for loop split the FPATH
|
||||
# string into its constituents so that each one may be processed.
|
||||
|
||||
for p in $( _autoload_split_fpath ); do
|
||||
p=${p:-.}
|
||||
if [ -f $p/$1 ]; then echo $p/$1; return; fi
|
||||
done
|
||||
|
||||
echo "autoload: $1: function source file not found" >&2
|
||||
}
|
||||
|
||||
_autoload_edit()
|
||||
{
|
||||
[ -z "$EDITOR" ] && echo "Error: no EDITOR defined" && return 1
|
||||
local toedit
|
||||
local func
|
||||
for func in "$@"
|
||||
do
|
||||
local file=$(_autoload_resolve $func)
|
||||
if [[ $file ]]
|
||||
then
|
||||
toedit="$toedit $file"
|
||||
else
|
||||
echo "$funcname not found in FPATH funcfile. Skipping."
|
||||
fi
|
||||
done
|
||||
|
||||
[ -z "$toedit" ] && return 1
|
||||
|
||||
local timemarker=$(mktemp)
|
||||
|
||||
$EDITOR $toedit
|
||||
|
||||
local i
|
||||
for i in $toedit
|
||||
do
|
||||
if [ $i -nt $timemarker ]
|
||||
then
|
||||
local f=$(basename $i)
|
||||
echo Reloading $f
|
||||
autoload -r $f
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
_autoload_page()
|
||||
{
|
||||
[ -z "$PAGER" ] && echo "Error: no PAGER defined" && return 1
|
||||
local topage
|
||||
local func
|
||||
for func in "$@"
|
||||
do
|
||||
local file=$(_autoload_resolve $func)
|
||||
if [[ $file ]]
|
||||
then
|
||||
topage="$topage $file"
|
||||
else
|
||||
echo "$funcname not found in FPATH funcfile. Skipping."
|
||||
fi
|
||||
done
|
||||
|
||||
[ -z "$topage" ] && return 1
|
||||
|
||||
$PAGER $topage
|
||||
}
|
||||
|
||||
_autoload_remove()
|
||||
{
|
||||
unset -f "$@"
|
||||
}
|
||||
|
||||
_autoload_help()
|
||||
{
|
||||
cat <<EOH
|
||||
NAME
|
||||
autoload
|
||||
|
||||
SYNOPSIS
|
||||
autoload [-ps]
|
||||
autoload [-xuremloyv] [function ...]
|
||||
autoload -a directory [-oyv]
|
||||
autoload -f [-oyv]
|
||||
autoload [-h]
|
||||
|
||||
autoreload [function ...]
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
An implementation of the 'autoload' functionality built into other
|
||||
shells, of which 'ksh' is the most prominent. It allows for a keeping
|
||||
the process environment small by loading small 'shim' functions into
|
||||
memory that will, on first call, load the full text of the given
|
||||
function and run it. Subsequent calls to the function just run the
|
||||
function.
|
||||
|
||||
'autoreload' is a synonym for 'autoload -r'. See below.
|
||||
|
||||
USAGE
|
||||
|
||||
o Each function to be autoloaded should be defined in a single file,
|
||||
named exactly the same as the function.
|
||||
|
||||
o In order to avoid side effects, do NOT put code other than the
|
||||
function definition in the file. Unless of course you want to do some
|
||||
one-time initialization. But beware that if you reload the function
|
||||
for any reason, you will rerun the initialization code. Make sure
|
||||
your initialization is re-entrant. Or, better yet,
|
||||
|
||||
*** do NOT put code other than the function definition in the file ***
|
||||
|
||||
o These function definition files should be placed in a directory that
|
||||
is in the FPATH environment variable. Subdirectories are NOT scanned.
|
||||
|
||||
o The autoload script should be sourced into the current process as
|
||||
early as possible in process start up. See NOTES below for
|
||||
suggestions.
|
||||
|
||||
o The calls to the autoload function must be made in the current
|
||||
process. If your calls are in their own script, that script must be
|
||||
sourced in. Command line invocations are also sufficient. (But see
|
||||
'-l' below.)
|
||||
|
||||
o The first time the function is called, the shim function that was
|
||||
created by the 'autoload' call is what is executed. This function
|
||||
then goes and finds the appropriate file in FPATH, sources it in and
|
||||
then calls the actual function with any arguments you just passed in
|
||||
to the shim function. Subsequent calls just run the function.
|
||||
|
||||
OPTIONS
|
||||
|
||||
-a Autoload (a)ll the functions found in the given directory.
|
||||
|
||||
-f Autoload all the functions found in all the directories on the
|
||||
FPATH.
|
||||
|
||||
-p Print all the autoloaded functions.
|
||||
|
||||
-s Print all the autoloaded functions and add their export status.
|
||||
|
||||
-x Export the specified functions to the environment for use in
|
||||
subshells.
|
||||
|
||||
-u Unset the function, so it can be reloaded.
|
||||
|
||||
-r Reload the shims of the specified functions, even if the functions
|
||||
have been already been executed. This will allow you to modify the
|
||||
functions' source and have the new version executed next time the
|
||||
function is called.
|
||||
|
||||
It would be very easy to modify a function's script, run the
|
||||
function and scratch your head for a long time trying to figure out
|
||||
why your changes are not being executed. That's why we provide the
|
||||
'-e' flag described below for modifications.
|
||||
|
||||
Reloads, of course, only apply in the context of the current session
|
||||
and any future subshell you start from the current session. Existing
|
||||
sessions will need to have the same 'autoload -r' command run in
|
||||
them.
|
||||
|
||||
-e Find the scripts in which the specified functions are defined and
|
||||
start up \$EDITOR on those scripts. Reload the ones that were
|
||||
modified when you exit \$EDITOR. (Note: If you use 'autoload -e foo'
|
||||
to edit function 'foo', and then in your editor you separately load
|
||||
up function 'bar', 'autoload' has no way of knowing that you edited
|
||||
'bar' and will NOT reload 'bar' for you.)
|
||||
|
||||
Reloads, of course, only apply in the context of the current session
|
||||
and any future subshell you start from the current session. Existing
|
||||
sessions will need to have the same 'autoload -r' command run in
|
||||
them.
|
||||
|
||||
-m Find the scripts in which the specified functions are defined and
|
||||
run \$PAGER on them ('m' is for 'more', because 'p' (page) and 'l'
|
||||
(load) are already used as options in 'autoload').
|
||||
|
||||
-l When autoloading a function, eval the shim immediately in order to
|
||||
load the true function code. See "Using '-l'" in the NOTES below for
|
||||
details.
|
||||
|
||||
-o Optimize. When autoloading, take the time to execute
|
||||
|
||||
'theCharCount=\$(wc -c \$theFuncFile)'
|
||||
|
||||
for each function and
|
||||
|
||||
if \$theCharCount < \$AUTOLOAD_SHIM_OVERHEAD
|
||||
|
||||
don't shim it, just eval directly.
|
||||
|
||||
-y Summar(y). Print the number of loaded, exported and optimized
|
||||
functions.
|
||||
|
||||
-v Turns up the chattiness.
|
||||
|
||||
NOTES
|
||||
|
||||
o Calling 'autoload' on a function that already exists (either shimmed
|
||||
or expanded) silently ignores the request to load the shim unless it
|
||||
has been previously removed (-u) or you force the reload (-r).
|
||||
|
||||
o Changing and reloading a function that has been exported does not
|
||||
require it be re-exported; the modifications will appear in
|
||||
subsequent subshells.
|
||||
|
||||
o Using '-1'
|
||||
|
||||
If you are running under set -x and/or set -v, you may see that the
|
||||
shim does not appear to "work"; instead of seeing the shim first and
|
||||
the real code subsequently, you may see the shim evaluated multiple
|
||||
times.
|
||||
|
||||
This may not be an error; review your code. What is most likely
|
||||
happening is that you are calling the function in subshells via
|
||||
backticks or $(), or in a script that is not being sourced into the
|
||||
current environment. If you have not previously called the function
|
||||
in question at your command line or in a script that was sourced into
|
||||
the current environment, then the various subshells are going to
|
||||
encounter the shim and replace with the real code before executing.
|
||||
|
||||
Remember, however, that environment modifications that occur in a
|
||||
subshell are NOT propagated back to the calling shell or over to any
|
||||
sibling shells. So, if you call an autoloaded function in a very
|
||||
tight loop of very many subshells, you may want to make an 'autoload
|
||||
-l' call before you start your loop. '-l' will instruct 'autoload' to
|
||||
bypass the shim creation and just source in the function's file
|
||||
directly. For a few calls, the overhead of repeatedly running the
|
||||
shim is not expensive, but in a tight loop, it might be. Caveat
|
||||
Programmer.
|
||||
|
||||
o Although the number of functions in the environment does not change
|
||||
by using 'autoload', the amount of memory they take up can be greatly
|
||||
reduced, depending on the size of your functions. If you have a lot
|
||||
of small functions, then it is possible that the shim text will be
|
||||
larger than your actual functions, rendering the memory savings moot.
|
||||
|
||||
'small' in this case can be determined by calling the function
|
||||
'autoload_calc_shimsize' with the name of the function to determine
|
||||
its shim size.
|
||||
|
||||
o In order to support the -p and -s options, we need a way to determine
|
||||
if a function 'func' has been autoloaded or if it was loaded
|
||||
diredctly. In order to do that, we modify the function's code by
|
||||
adding the text
|
||||
|
||||
local AUTOLOADED='func';
|
||||
|
||||
to the shim and to the actual function text, just after the opening
|
||||
brace. Then supporting -p and -s is just a matter of grepping through
|
||||
all the function text in memory. Even though grepping through the
|
||||
environment may not be the most efficient way to support this, it is
|
||||
the simplest to implement for -p and -s operations that are not
|
||||
heavily used.
|
||||
|
||||
As a consequence of this (and other reasons), the AUTOLOAD* namespace
|
||||
is reserved for autoloading. Make sure you check any functions that
|
||||
you bring under autoload for use of variables or functions that start
|
||||
with AUTOLOAD and change them.
|
||||
|
||||
o The easiest way to load shims for all functions on the FPATH is to run
|
||||
|
||||
autoload -f -x
|
||||
|
||||
in the profile that gets run for login shells.
|
||||
|
||||
When called in the profile of a login shell where no definitions
|
||||
exist, -f will load all functions it can find on FPATH and -x will
|
||||
export all of those functions to be available in subshells when this
|
||||
is called in a login shell. Using this option will relieve you of the
|
||||
need to call 'autoload' after Every Single Function Definition, nor
|
||||
will you need to call it in subshells.
|
||||
|
||||
The only thing left to do is to load up the autoload function itself
|
||||
and its helper functions. That needs to happen in your profile:
|
||||
|
||||
export FPATH=~/functions # or wherever you stash them
|
||||
if [ -z $(declare -F autoload) ]
|
||||
then
|
||||
. ~/bin/autoload # or wherever you've put it
|
||||
fi
|
||||
|
||||
The 'if' statement is used to make sure we don't reload autoload
|
||||
needlessly. Sourcing in the autoload script loads the 'autoload'
|
||||
function and all of its support functions. Additionally, we export
|
||||
all of these functions so that they are available in subshells; you
|
||||
do not have to re-source the autoload file in '.bashrc'.
|
||||
|
||||
o Even with all of these shenanigans, you will find cases where no
|
||||
matter how hard you try, your autoloaded functions will be
|
||||
unavailable to you, even if you run 'autoload -x -f'. The typical
|
||||
condition for this is starting up not a subshell, but a brand new
|
||||
DIFFERENT shell. And the typical example of this is git extensions.
|
||||
|
||||
At the time of this writing, git extensions work by taking a command
|
||||
'git foo' and looking for a file 'git-foo' on the path. 'git' then
|
||||
executes 'git-foo' in a new shell - it executes your command in
|
||||
/bin/sh. That's not a subshell of your process. It will not get your
|
||||
exported shell functions. Ballgame over.
|
||||
|
||||
If you find that you want your functions to be available in such
|
||||
circumstances, convert them back to plain old scripts, make sure they
|
||||
are 'sh' compliant and take the read/parse hit every time they are
|
||||
run.
|
||||
|
||||
EOH
|
||||
}
|
||||
|
||||
autoload()
|
||||
{
|
||||
if (( $# == 0 )) ; then _autoload_dump; return; fi
|
||||
|
||||
local opt OPTIND OPTARG
|
||||
local passthru
|
||||
local dumpopt
|
||||
while getopts psuema:yxrvlohf opt
|
||||
do
|
||||
case $opt in
|
||||
p|s) dumpopt="$dumpopt -${opt}";;
|
||||
u) shift $((OPTIND-1)); _autoload_remove "$@"; return;;
|
||||
e) shift $((OPTIND-1)); _autoload_edit "$@"; return;;
|
||||
m) shift $((OPTIND-1)); _autoload_page "$@"; return;;
|
||||
x|r|v|l|y|f|o) passthru="$passthru -$opt";;
|
||||
a) passthru="$passthru -$opt $OPTARG";;
|
||||
h) _autoload_help; return;;
|
||||
*) echo "autoload: usage: autoload [-puUx] [function ...]" >&2; return;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(($OPTIND-1))
|
||||
if [ -n "$dumpopt" ]
|
||||
then
|
||||
_autoload_dump $dumpopt
|
||||
else
|
||||
_aload $passthru "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
autoreload ()
|
||||
{
|
||||
autoload -r "$@"
|
||||
}
|
||||
|
||||
## When we source in autoload, we export (but NOT autoload) the autoload
|
||||
## functions so that they are available in subshells and you don't have to
|
||||
## source in the autoload file in subshells.
|
||||
export -f _aload \
|
||||
_autoload_dump \
|
||||
_autoload_edit \
|
||||
_autoload_help \
|
||||
_autoload_page \
|
||||
_autoload_resolve \
|
||||
_autoload_split_fpath \
|
||||
autoload \
|
||||
autoload_calc_shimsize \
|
||||
autoreload
|
184
examples/functions/autoload.v4.t
Normal file
184
examples/functions/autoload.v4.t
Normal file
|
@ -0,0 +1,184 @@
|
|||
#!/bin/bash
|
||||
|
||||
workdir=$(mktemp -d)
|
||||
|
||||
cp autoload $workdir
|
||||
|
||||
cd $workdir
|
||||
pwd
|
||||
|
||||
. ./autoload
|
||||
|
||||
funclist='ALTEST_func1 ALTEST_funcexport ALTEST_funcu'
|
||||
for funcname in $funclist; do
|
||||
cat <<EOFFUNC > $funcname
|
||||
$funcname ()
|
||||
{
|
||||
echo this is $funcname
|
||||
|
||||
}
|
||||
EOFFUNC
|
||||
|
||||
done
|
||||
|
||||
export FPATH=$workdir
|
||||
|
||||
autoload ALTEST_func1 ALTEST_funcu
|
||||
autoload -x ALTEST_funcexport
|
||||
|
||||
ok=0
|
||||
failed=0
|
||||
|
||||
for funcname in $funclist; do
|
||||
|
||||
testname="$funcname loaded"
|
||||
got=$(type $funcname 2>&1)
|
||||
if [[ $got =~ "$funcname: not found" ]]; then
|
||||
echo "## Failed $testname"
|
||||
((failed+=1))
|
||||
else
|
||||
echo "ok - $testname"
|
||||
((ok+=1))
|
||||
|
||||
testname="$funcname is a shim"
|
||||
if [[ ! $got =~ "IS_SHIM" ]]; then
|
||||
echo "## Failed $testname"
|
||||
((failed+=1))
|
||||
else
|
||||
echo "ok - $testname"
|
||||
((ok+=1))
|
||||
|
||||
testname="$funcname shim executed"
|
||||
$funcname > /dev/null
|
||||
got=$(type $funcname 2>&1)
|
||||
if [[ $got =~ "IS_SHIM" ]]; then
|
||||
echo "## Failed $testname"
|
||||
((failed+=1))
|
||||
else
|
||||
echo "ok - $testname"
|
||||
((ok+=1))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
funcname=ALTEST_func1
|
||||
testname="$funcname shim reloaded"
|
||||
autoload -r $funcname
|
||||
got=$(type $funcname 2>&1)
|
||||
if [[ ! $got =~ "IS_SHIM" ]]; then
|
||||
echo "## Failed $testname"
|
||||
((failed+=1))
|
||||
else
|
||||
echo "ok - $testname"
|
||||
((ok+=1))
|
||||
fi
|
||||
|
||||
funcname=ALTEST_funcu
|
||||
testname="$funcname shim unloaded"
|
||||
autoload -u $funcname
|
||||
got=$(type $funcname 2>&1)
|
||||
if [[ ! $got =~ "$funcname: not found" ]]; then
|
||||
echo "## Failed $testname"
|
||||
((failed+=1))
|
||||
else
|
||||
echo "ok - $testname"
|
||||
((ok+=1))
|
||||
fi
|
||||
|
||||
testname="autoload -p"
|
||||
got=$(autoload -p | grep ALTEST)
|
||||
if [[ ! $got =~ "autoload ALTEST_func1" ]] || \
|
||||
[[ ! $got =~ "autoload ALTEST_funcexport" ]] ; then
|
||||
echo "## Failed $testname"
|
||||
((failed+=1))
|
||||
else
|
||||
echo "ok - $testname"
|
||||
((ok+=1))
|
||||
fi
|
||||
|
||||
testname="autoload -s"
|
||||
echo "Executing $testname, could take a long time..."
|
||||
got=$(autoload -s | grep ALTEST)
|
||||
if [[ ! $got =~ "ALTEST_func1 not exported not executed" ]] || \
|
||||
[[ ! $got =~ "ALTEST_funcexport exported executed" ]] ; then
|
||||
echo "## Failed $testname"
|
||||
echo "## got: $got"
|
||||
((failed+=1))
|
||||
else
|
||||
echo "ok - $testname"
|
||||
((ok+=1))
|
||||
fi
|
||||
|
||||
testname="autoload -r -a $FPATH"
|
||||
autoload -r -a $FPATH
|
||||
localfailed=0
|
||||
localok=0
|
||||
for funcname in $funclist; do
|
||||
got=$(type $funcname 2>&1)
|
||||
if [[ $got =~ "$funcname: not found" ]]; then
|
||||
echo "## Failed $testname - $funcname"
|
||||
((localfailed+=1))
|
||||
else
|
||||
((localok+=1))
|
||||
if [[ ! $got =~ "IS_SHIM" ]]; then
|
||||
((localfailed+=1))
|
||||
else
|
||||
((localok+=1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if ((localfailed==0)); then
|
||||
echo "ok - $testname"
|
||||
((ok+=1))
|
||||
else
|
||||
((failed+=1))
|
||||
fi
|
||||
|
||||
testname="autoload -u $funclist"
|
||||
autoload -u $funclist
|
||||
localfailed=0
|
||||
localok=0
|
||||
for funcname in $funclist; do
|
||||
got=$(type $funcname 2>&1)
|
||||
if [[ ! $got =~ "$funcname: not found" ]]; then
|
||||
echo "## Failed $testname - $funcname"
|
||||
((localfailed+=1))
|
||||
else
|
||||
((localok+=1))
|
||||
fi
|
||||
done
|
||||
if ((localfailed==0)); then
|
||||
echo "ok - $testname"
|
||||
((ok+=1))
|
||||
else
|
||||
((failed+=1))
|
||||
fi
|
||||
|
||||
testname="autoload -r -f"
|
||||
autoload -r -f
|
||||
localfailed=0
|
||||
localok=0
|
||||
for funcname in $funclist; do
|
||||
got=$(type $funcname 2>&1)
|
||||
if [[ $got =~ "$funcname: not found" ]]; then
|
||||
echo "## Failed $testname - $funcname"
|
||||
((localfailed+=1))
|
||||
else
|
||||
((localok+=1))
|
||||
if [[ ! $got =~ "IS_SHIM" ]]; then
|
||||
((localfailed+=1))
|
||||
else
|
||||
((localok+=1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if ((localfailed==0)); then
|
||||
echo "ok - $testname"
|
||||
((ok+=1))
|
||||
else
|
||||
((failed+=1))
|
||||
fi
|
||||
|
||||
echo $ok passed, $failed failed
|
||||
exit $failed
|
23
examples/functions/basename
Normal file
23
examples/functions/basename
Normal file
|
@ -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.
|
||||
}
|
||||
|
48
examples/functions/csh-compat
Normal file
48
examples/functions/csh-compat
Normal file
|
@ -0,0 +1,48 @@
|
|||
# C-shell compatibility package.
|
||||
# setenv VAR VALUE
|
||||
function setenv ()
|
||||
{
|
||||
export $1="$2"
|
||||
}
|
||||
|
||||
function unsetenv ()
|
||||
{
|
||||
unset $1
|
||||
}
|
||||
|
||||
# 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 "$@"
|
||||
}
|
||||
|
||||
# alias - convert csh alias commands to bash functions
|
||||
# from Mohit Aron <aron@cs.rice.edu>
|
||||
# posted to usenet as <4i5p17$bnu@larry.rice.edu>
|
||||
function alias ()
|
||||
{
|
||||
if [ "x$2" = "x" ]
|
||||
then
|
||||
declare -f $1
|
||||
else
|
||||
case $2 in
|
||||
*[#\!]*)
|
||||
comm=$(echo $2 | sed 's/\\!\*/\"$\@\"/g
|
||||
s/\\!:\([1-9]\)/\"$\1\"/g
|
||||
s/#/\\#/g')
|
||||
;;
|
||||
*)
|
||||
comm="$2 \"\$@\"" ;;
|
||||
esac
|
||||
|
||||
eval function $1 \(\) "{" command "$comm" "; }"
|
||||
fi
|
||||
}
|
21
examples/functions/dirname
Normal file
21
examples/functions/dirname
Normal file
|
@ -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%/*}"
|
||||
}
|
160
examples/functions/dirstack
Normal file
160
examples/functions/dirstack
Normal file
|
@ -0,0 +1,160 @@
|
|||
#!/bin/bash
|
||||
# @(#) dirstack
|
||||
|
||||
###
|
||||
# Another implementation of the directory manipulation functions
|
||||
# published in the Bolsky & Korn book : "The new Korn shell" :
|
||||
# cd, to change current directory
|
||||
# d, to display the stack content
|
||||
# Eric Sanchis (eric.sanchis@iut-rodez.fr), 2012
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###
|
||||
|
||||
|
||||
shopt -s expand_aliases
|
||||
shopt -s extglob
|
||||
shopt -s cdable_vars
|
||||
|
||||
alias integer='declare -i'
|
||||
|
||||
integer MAX=32
|
||||
integer INDMAX=MAX-1
|
||||
integer INDTOP=0
|
||||
|
||||
unalias cd 2>/dev/null
|
||||
alias cd=cdir
|
||||
|
||||
unset tab
|
||||
tab[INDTOP]="$(pwd)"
|
||||
|
||||
|
||||
function cdir
|
||||
{
|
||||
local -i ind
|
||||
local dir
|
||||
|
||||
dir="${1:-$HOME}"
|
||||
case "$dir" in
|
||||
- ) # cd - => equivalent to : cd -1
|
||||
ind=INDTOP-1
|
||||
cd_by_number $ind
|
||||
;;
|
||||
-+([[:digit:]]) ) # cd -n
|
||||
ind=$INDTOP-${dir#-}
|
||||
cd_by_number $ind
|
||||
;;
|
||||
*) # cd ~ or cd dir_name
|
||||
cd_by_name "$dir"
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
function cd_by_number
|
||||
{
|
||||
local -i k=$1
|
||||
local -i j
|
||||
local dirtmp
|
||||
|
||||
if (( k < 0 ))
|
||||
then
|
||||
echo Impossible to change directory >&2
|
||||
return 1
|
||||
else
|
||||
dirtmp="${tab[k]}"
|
||||
j=k+1
|
||||
while (( j <= INDTOP ))
|
||||
do
|
||||
tab[j-1]="${tab[j]}"
|
||||
j=j+1
|
||||
done
|
||||
tab[INDTOP]="$dirtmp"
|
||||
\cd "${tab[INDTOP]}"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function cd_by_name
|
||||
{
|
||||
local -i i
|
||||
local rep
|
||||
|
||||
rep=$( \cd "$1" &>/dev/null && pwd)
|
||||
if [[ -z "$rep" ]]
|
||||
then
|
||||
echo cd : "$1" unknown >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
i=$INDTOP
|
||||
while (( i >= 0 ))
|
||||
do
|
||||
if [[ "${tab[i]}" == "$rep" ]]
|
||||
then break
|
||||
fi
|
||||
i=i-1
|
||||
done
|
||||
|
||||
if (( i == INDTOP ))
|
||||
then # cd -0 => we do nothing !
|
||||
return 0
|
||||
elif (( i == -1 ))
|
||||
then # the directory isn't in the stack
|
||||
if (( INDTOP == INDMAX ))
|
||||
then # the stack is FULL
|
||||
# the oldest directory is removed
|
||||
local -i m
|
||||
|
||||
m=1
|
||||
while (( m <= INDMAX ))
|
||||
do
|
||||
tab[m-1]="${tab[m]}"
|
||||
m=m+1
|
||||
done
|
||||
else # the new directory is added to the top of the stack
|
||||
INDTOP=INDTOP+1
|
||||
fi
|
||||
tab[INDTOP]="$rep"
|
||||
\cd "${tab[INDTOP]}"
|
||||
return 0
|
||||
|
||||
else # the directory is already in the stack
|
||||
# $i gives its index
|
||||
cd_by_number $i
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function d # display the directory stack
|
||||
{
|
||||
local -i i
|
||||
local rep
|
||||
|
||||
i=0
|
||||
while (( $i <= $INDTOP ))
|
||||
do
|
||||
rep="${tab[INDTOP-i]#$HOME/}"
|
||||
case "$rep" in
|
||||
$HOME) rep="~" ;;
|
||||
/* ) : ;;
|
||||
* ) rep="~/$rep"
|
||||
esac
|
||||
|
||||
echo "$i ) $rep"
|
||||
i=i+1
|
||||
done
|
||||
}
|
||||
|
||||
|
22
examples/functions/exitstat
Normal file
22
examples/functions/exitstat
Normal file
|
@ -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 ] && [ ${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
|
50
examples/functions/external
Normal file
50
examples/functions/external
Normal file
|
@ -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
|
||||
}
|
13
examples/functions/fact
Normal file
13
examples/functions/fact
Normal file
|
@ -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 )) ) ))
|
||||
}
|
77
examples/functions/fstty
Normal file
77
examples/functions/fstty
Normal file
|
@ -0,0 +1,77 @@
|
|||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 2011 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#
|
||||
# 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
|
||||
}
|
43
examples/functions/func
Normal file
43
examples/functions/func
Normal file
|
@ -0,0 +1,43 @@
|
|||
#
|
||||
# func -- print out definitions for functions named by arguments
|
||||
#
|
||||
# usage: func name [name ...]
|
||||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 1991 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
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
|
||||
}
|
79
examples/functions/inetaddr
Normal file
79
examples/functions/inetaddr
Normal file
|
@ -0,0 +1,79 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 2002 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#
|
||||
# inet2hex - Internet address conversion, dotted-decimal to hex
|
||||
#
|
||||
inet2hex ()
|
||||
{
|
||||
local IFS
|
||||
|
||||
IFS=.
|
||||
set -- $1
|
||||
|
||||
if (( $# != 4 )); then
|
||||
echo "inet2hex: incorrect input format: $1" >&2
|
||||
echo "inet2hex: usage: inet2hex XX.XX.XX.XX" >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
printf "0x%02x%02x%02x%02x\n" $1 $2 $3 $4
|
||||
}
|
||||
|
||||
#
|
||||
# hex2inet - Internet address conversion, hex to dotted-decimal
|
||||
#
|
||||
hex2inet ()
|
||||
{
|
||||
local x1 x2 x3 x4
|
||||
local rev
|
||||
|
||||
OPTIND=1
|
||||
while getopts "r" o
|
||||
do
|
||||
case "$o" in
|
||||
r) rev=true;;
|
||||
*) echo "hex2inet: usage: hex2inet [-r] [0x]XXXXXXXX" >&2 ; exit 2;;
|
||||
esac
|
||||
done
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
case "$1" in
|
||||
0x*) h=${1#??} ;;
|
||||
*) h=$1 ;;
|
||||
esac
|
||||
|
||||
if (( ${#h} != 8 )); then
|
||||
echo "hex2inet: $h not in inet format" >&2
|
||||
echo "hex2inet: usage: hex2inet [0x]XXXXXXXX" >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
x1=$(( 0x${h:0:2} ))
|
||||
x2=$(( 0x${h:2:2} ))
|
||||
x3=$(( 0x${h:4:2} ))
|
||||
x4=$(( 0x${h:6:2} ))
|
||||
|
||||
if [ -z "$rev" ] ; then
|
||||
printf "%d.%d.%d.%d\n" $x1 $x2 $x3 $x4
|
||||
else
|
||||
printf "%d.%d.%d.%d\n" $x4 $x3 $x2 $x1
|
||||
fi
|
||||
return 0
|
||||
}
|
14
examples/functions/inpath
Normal file
14
examples/functions/inpath
Normal file
|
@ -0,0 +1,14 @@
|
|||
inpath()
|
||||
{
|
||||
local PROG
|
||||
path=$(echo $PATH | sed 's/^:/.:/
|
||||
s/::/:.:/g
|
||||
s/:$/:./
|
||||
s/:/ /g')
|
||||
|
||||
for x in $path
|
||||
do
|
||||
[ -x $x/$1 ] && { PROG=$x/$1; break; }
|
||||
done
|
||||
[ -n "$PROG" ]
|
||||
}
|
41
examples/functions/isnum2
Normal file
41
examples/functions/isnum2
Normal file
|
@ -0,0 +1,41 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 1998 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
isnum2()
|
||||
{
|
||||
case "$1" in
|
||||
[-+] | '') return 1;; # empty or bare `-' or `+'
|
||||
[-+]*[!0-9]*) return 1;; # non-digit with leading sign
|
||||
[-+]*) return 0;; # OK
|
||||
*[!0-9]*) return 1;; # non-digit
|
||||
*) return 0;; # OK
|
||||
esac
|
||||
}
|
||||
|
||||
# this one handles floating point
|
||||
isnum3()
|
||||
{
|
||||
case "$1" in
|
||||
'') return 1;; # empty
|
||||
*[!0-9.+-]*) return 1;; # non-digit, +, -, or .
|
||||
*?[-+]*) return 1;; # sign as second or later char
|
||||
*.*.*) return 1;; # multiple decimal points
|
||||
*) return 0;; # OK
|
||||
esac
|
||||
}
|
14
examples/functions/isvalidip
Normal file
14
examples/functions/isvalidip
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Thanks to Chris F. A. Johnson <c.f.a.johnson@rogers.com> for this one
|
||||
is_validip()
|
||||
{
|
||||
case "$*" in
|
||||
""|*[!0-9.]*|*[!0-9]) return 1 ;;
|
||||
esac
|
||||
|
||||
local IFS=.
|
||||
set -- $*
|
||||
|
||||
[ $# -eq 4 ] &&
|
||||
[ ${1:-666} -le 255 ] && [ ${2:-666} -le 255 ] &&
|
||||
[ ${3:-666} -le 255 ] && [ ${4:-666} -le 254 ]
|
||||
}
|
54
examples/functions/ksh-cd
Normal file
54
examples/functions/ksh-cd
Normal file
|
@ -0,0 +1,54 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 2001 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#
|
||||
# ksh-like `cd': cd [-LP] [dir [change]]
|
||||
#
|
||||
cd()
|
||||
{
|
||||
OPTIND=1
|
||||
while getopts "LP" opt
|
||||
do
|
||||
case $opt in
|
||||
L|P) CDOPTS="$CDOPTS -$opt" ;;
|
||||
*) echo "$FUNCNAME: usage: $FUNCNAME [-LP] [dir] [change]" >&2
|
||||
return 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
case $# in
|
||||
0) builtin cd $CDOPTS "$HOME" ;;
|
||||
1) builtin cd $CDOPTS "$@" ;;
|
||||
2) old="$1" new="$2"
|
||||
case "$PWD" in
|
||||
*$old*) ;;
|
||||
*) echo "${0##*/}: $FUNCNAME: bad substitution" >&2 ; return 1 ;;
|
||||
esac
|
||||
|
||||
dir=${PWD//$old/$new}
|
||||
|
||||
builtin cd $CDOPTS "$dir" && echo "$PWD"
|
||||
|
||||
;;
|
||||
*) echo "${0##*/}: $FUNCNAME: usage: $FUNCNAME [-LP] [dir] [change]" >&2
|
||||
return 2 ;;
|
||||
esac
|
||||
}
|
58
examples/functions/ksh-compat-test
Normal file
58
examples/functions/ksh-compat-test
Normal file
|
@ -0,0 +1,58 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 1999 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# replacements for test/[ that do arithmetic expansion on the operands to
|
||||
# the arithmetic operators, like ksh.
|
||||
#
|
||||
function test()
|
||||
{
|
||||
local -i n1 n3
|
||||
case "$#" in
|
||||
3) case "$2" in
|
||||
-lt|-gt|-eq|-ne|-le|-ge) n1=$(( $1 ))
|
||||
n3=$(( $3 ))
|
||||
builtin test "$n1" $2 "$n3"
|
||||
return $?;;
|
||||
*) builtin test "$@" ;;
|
||||
esac;;
|
||||
*) builtin test "$@" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
function [()
|
||||
{
|
||||
local -i n1 n3
|
||||
case "$#" in
|
||||
4) case "$2" in
|
||||
-lt|-gt|-eq|-ne|-le|-ge) n1=$(( $1 ))
|
||||
n3=$(( $3 ))
|
||||
builtin [ "$n1" $2 "$n3" ]
|
||||
return $?;;
|
||||
*) builtin [ "$@" ;;
|
||||
esac;;
|
||||
*) builtin [ "$@" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
q=7
|
||||
|
||||
[ q -lt 10 ]
|
||||
echo $?
|
||||
[ $q -lt 10 ]
|
||||
echo $?
|
246
examples/functions/kshenv
Normal file
246
examples/functions/kshenv
Normal file
|
@ -0,0 +1,246 @@
|
|||
#
|
||||
# .kshenv -- functions and aliases to provide the beginnings of a ksh
|
||||
# environment for bash.
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@ins.CWRU.Edu
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright 2002 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#
|
||||
# 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 -s"
|
||||
alias functions="typeset -f"
|
||||
alias integer="typeset -i"
|
||||
alias nohup="nohup "
|
||||
alias command="command "
|
||||
alias stop="kill -s STOP"
|
||||
alias redirect="command exec"
|
||||
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 pflag fflag defarg c
|
||||
local path
|
||||
|
||||
vflag= aflag= pflag= fflag=
|
||||
path=
|
||||
if [ "$#" = "0" ] ; then
|
||||
echo "whence: usage: whence [-afpv] name..." >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
OPTIND=1
|
||||
while getopts "avfp" c
|
||||
do
|
||||
case "$c" in
|
||||
a) defarg=-a ;;
|
||||
f) fflag=1 ;; # no-op
|
||||
p) pflag=1 ;;
|
||||
v) vflag=1 ;;
|
||||
?) echo "whence: $1: unknown option" >&2
|
||||
echo "whence: usage: whence [-afpv] name..." >&2
|
||||
return 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
if [ "$#" = "0" ] ; then
|
||||
echo "whence: usage: whence [-afpv] name..." >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
for cmd
|
||||
do
|
||||
if [ "$vflag" ] ; then
|
||||
if [ -z "$defarg" ]; then
|
||||
builtin type $cmd | sed 1q
|
||||
else
|
||||
if builtin type $defarg -t $cmd | grep 'function$' >/dev/null 2>&1; then
|
||||
# HAIRY awk script to suppress
|
||||
# printing of function body -- could
|
||||
# do it with sed, but I don't have
|
||||
# that kind of time
|
||||
builtin type $defarg $cmd | awk '
|
||||
BEGIN {printit = 1;}
|
||||
$1 == "'$cmd'" && $2 == "()" {printit=0; next; }
|
||||
/^}$/ { if (printit == 0) printit=1 ; else print $0; next ; }
|
||||
/.*/ { if (printit) print $0; }'
|
||||
else
|
||||
builtin type $defarg $cmd
|
||||
fi
|
||||
fi
|
||||
else
|
||||
path=$(builtin type $defarg -p $cmd)
|
||||
if [ "$path" ] ; then
|
||||
echo $path
|
||||
else
|
||||
case "$cmd" in
|
||||
/*) echo "" ;;
|
||||
*) case "$(builtin type -t $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 "$*"
|
||||
#}
|
||||
|
||||
#
|
||||
# ksh-like `cd': cd [-LP] [dir [change]]
|
||||
#
|
||||
cd()
|
||||
{
|
||||
OPTIND=1
|
||||
while getopts "LP" opt
|
||||
do
|
||||
case $opt in
|
||||
L|P) CDOPTS="$CDOPTS -$opt" ;;
|
||||
*) echo "$FUNCNAME: usage: $FUNCNAME [-LP] [dir] [change]" >&2
|
||||
return 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
case $# in
|
||||
0) builtin cd $CDOPTS "$HOME" ;;
|
||||
1) builtin cd $CDOPTS "$@" ;;
|
||||
2) old="$1" new="$2"
|
||||
case "$PWD" in
|
||||
*$old*) ;;
|
||||
*) echo "${0##*/}: $FUNCNAME: bad substitution" >&2 ; return 1 ;;
|
||||
esac
|
||||
|
||||
dir=${PWD//$old/$new}
|
||||
|
||||
builtin cd $CDOPTS "$dir" && echo "$PWD"
|
||||
|
||||
;;
|
||||
*) echo "${0##*/}: $FUNCNAME: usage: $FUNCNAME [-LP] [dir] [change]" >&2
|
||||
return 2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
#
|
||||
# ksh print emulation
|
||||
#
|
||||
# print [-Rnprsu[n]] [-f format] [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 print to the history file
|
||||
# -u n redirect output to fd n
|
||||
# -f format printf "$format" "$@"
|
||||
#
|
||||
|
||||
print()
|
||||
{
|
||||
local eflag=-e
|
||||
local nflag= fflag= c
|
||||
local fd=1
|
||||
|
||||
OPTIND=1
|
||||
while getopts "fRnprsu:" c
|
||||
do
|
||||
case $c in
|
||||
R) eflag= ;;
|
||||
r) eflag= ;;
|
||||
n) nflag=-n ;;
|
||||
s) sflag=y ;;
|
||||
f) fflag=y ;;
|
||||
u) fd=$OPTARG ;;
|
||||
p) ;;
|
||||
esac
|
||||
done
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
if [ -n "$fflag" ]; then
|
||||
builtin printf "$@" >&$fd
|
||||
return
|
||||
fi
|
||||
|
||||
case "$sflag" in
|
||||
y) builtin history -s "$*" ;;
|
||||
*) builtin echo $eflag $nflag "$@" >&$fd
|
||||
esac
|
||||
}
|
||||
|
||||
# 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 ] || [ $# -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
|
||||
}
|
11
examples/functions/login
Normal file
11
examples/functions/login
Normal file
|
@ -0,0 +1,11 @@
|
|||
# replace the `login' and `newgrp' builtins in old bourne shells
|
||||
|
||||
login()
|
||||
{
|
||||
exec login "$@"
|
||||
}
|
||||
|
||||
newgrp()
|
||||
{
|
||||
exec newgrp "$@"
|
||||
}
|
77
examples/functions/notify.bash
Normal file
77
examples/functions/notify.bash
Normal file
|
@ -0,0 +1,77 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 1992 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
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
|
||||
}
|
48
examples/functions/seq
Normal file
48
examples/functions/seq
Normal file
|
@ -0,0 +1,48 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 1995 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
# Generate a sequence from m to n, m defaults to 1.
|
||||
|
||||
seq ()
|
||||
{
|
||||
declare -i lo hi i # makes local
|
||||
local _SEQ
|
||||
|
||||
case $# in
|
||||
1) seq 1 "$1" ; return $? ;;
|
||||
2) lo=$1 hi=$2
|
||||
i=$lo _SEQ=""
|
||||
while let "i <= hi"; do
|
||||
_SEQ="${_SEQ}$i "
|
||||
let i+=1
|
||||
done
|
||||
echo "${_SEQ# }"
|
||||
return 0 ;;
|
||||
*) echo seq: usage: seq [low] high 1>&2 ; return 2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# like the APL `iota' function (or at least how I remember it :-)
|
||||
iota()
|
||||
{
|
||||
case $# in
|
||||
1) seq 1 "$1"; return $?;;
|
||||
*) echo "iota: usage: iota high" 1>&2; return 2;;
|
||||
esac
|
||||
}
|
56
examples/functions/seq2
Normal file
56
examples/functions/seq2
Normal file
|
@ -0,0 +1,56 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 1998 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
# Generate a sequence from m to n, m defaults to 1.
|
||||
|
||||
seq ()
|
||||
{
|
||||
declare -i lo hi i # makes local
|
||||
local _SEQ INIT COMPARE STEP
|
||||
|
||||
case "$1" in
|
||||
-r) INIT='i=$hi _SEQ=""' COMPARE='let "i >= $lo"' STEP='let i-=1' ; shift ;;
|
||||
*) INIT='i=$lo _SEQ=""' COMPARE='let "i <= $hi"' STEP='let i+=1' ;;
|
||||
esac
|
||||
|
||||
case $# in
|
||||
1) lo=1 hi="$1" ;;
|
||||
2) lo=$1 hi=$2 ;;
|
||||
*) echo seq: usage: seq [-r] [low] high 1>&2 ; return 2 ;;
|
||||
esac
|
||||
|
||||
# equivalent to the as-yet-unimplemented
|
||||
# for (( "$INIT" ; "$COMPARE" ; "$STEP" )); do _SEQ="${_SEQ}$i "; done
|
||||
eval "$INIT"
|
||||
while eval "$COMPARE"; do
|
||||
_SEQ="${_SEQ}$i "
|
||||
eval "$STEP"
|
||||
done
|
||||
echo "${_SEQ# }"
|
||||
return 0
|
||||
}
|
||||
|
||||
# like the APL `iota' function (or at least how I remember it :-)
|
||||
iota()
|
||||
{
|
||||
case $# in
|
||||
1) seq 1 "$1"; return $?;;
|
||||
*) echo "iota: usage: iota high" 1>&2; return 2;;
|
||||
esac
|
||||
}
|
7
examples/functions/shcat
Normal file
7
examples/functions/shcat
Normal file
|
@ -0,0 +1,7 @@
|
|||
shcat()
|
||||
{
|
||||
while IFS= read -r line
|
||||
do
|
||||
echo "$line"
|
||||
done
|
||||
}
|
19
examples/functions/shcat2
Normal file
19
examples/functions/shcat2
Normal file
|
@ -0,0 +1,19 @@
|
|||
shcat()
|
||||
{
|
||||
while read -r
|
||||
do
|
||||
echo "$REPLY"
|
||||
done
|
||||
}
|
||||
|
||||
shcat2()
|
||||
{
|
||||
while [ $# -ge 1 ]; do
|
||||
case "$1" in
|
||||
-) shcat ;;
|
||||
*) shcat < "$1" ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
exit 0
|
||||
}
|
69
examples/functions/sort-pos-params
Normal file
69
examples/functions/sort-pos-params
Normal file
|
@ -0,0 +1,69 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 2001 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
# Sort the positional parameters.
|
||||
# Make sure the positional parameters are passed as arguments to the function.
|
||||
# If -u is the first arg, remove duplicate array members.
|
||||
sort_posparams()
|
||||
{
|
||||
local -a R
|
||||
local u
|
||||
|
||||
case "$1" in
|
||||
-u) u=-u ; shift ;;
|
||||
esac
|
||||
|
||||
# if you want the case of no positional parameters to return success,
|
||||
# remove the error message and return 0
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "$FUNCNAME: argument expected" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# make R a copy of the positional parameters
|
||||
R=( "${@}" )
|
||||
|
||||
# sort R.
|
||||
R=( $( printf "%s\n" "${R[@]}" | sort $u) )
|
||||
|
||||
printf "%s\n" "${R[@]}"
|
||||
return 0
|
||||
}
|
||||
|
||||
# will print everything on separate lines
|
||||
set -- 3 1 4 1 5 9 2 6 5 3 2
|
||||
sort_posparams "$@"
|
||||
|
||||
# sets without preserving quoted parameters
|
||||
set -- $( sort_posparams "$@" )
|
||||
echo "$@"
|
||||
echo $#
|
||||
|
||||
# sets preserving quoted parameters, beware pos params with embedded newlines
|
||||
set -- 'a b' 'a c' 'x z'
|
||||
|
||||
oifs=$IFS
|
||||
IFS=$'\n'
|
||||
set -- $( sort_posparams "$@" )
|
||||
IFS="$oifs"
|
||||
|
||||
echo "$@"
|
||||
echo $#
|
||||
|
||||
sort_posparams
|
97
examples/functions/substr
Normal file
97
examples/functions/substr
Normal file
|
@ -0,0 +1,97 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 2002 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# 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 ] || [ "$#" -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
|
||||
}
|
99
examples/functions/substr2
Normal file
99
examples/functions/substr2
Normal file
|
@ -0,0 +1,99 @@
|
|||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 2002 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# 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 ] || [ "$#" -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
|
||||
}
|
71
examples/functions/whatis
Normal file
71
examples/functions/whatis
Normal file
|
@ -0,0 +1,71 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 1994 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
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
|
||||
}
|
78
examples/functions/whence
Normal file
78
examples/functions/whence
Normal file
|
@ -0,0 +1,78 @@
|
|||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 1994 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
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
|
||||
}
|
62
examples/functions/which
Normal file
62
examples/functions/which
Normal file
|
@ -0,0 +1,62 @@
|
|||
#
|
||||
# which - emulation of `which' as it appears in FreeBSD
|
||||
#
|
||||
# usage: which [-as] command [command...]
|
||||
#
|
||||
#
|
||||
# Chet Ramey <chet.ramey@case.edu>
|
||||
#
|
||||
# Copyright 1999 Chester Ramey
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# TThis program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
which()
|
||||
{
|
||||
local aflag sflag ES a opt
|
||||
|
||||
OPTIND=1
|
||||
while builtin getopts as opt ; do
|
||||
case "$opt" in
|
||||
a) aflag=-a ;;
|
||||
s) sflag=1 ;;
|
||||
?) echo "which: usage: which [-as] command [command ...]" >&2
|
||||
exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
(( $OPTIND > 1 )) && shift $(( $OPTIND - 1 ))
|
||||
|
||||
# without command arguments, exit with status 1
|
||||
ES=1
|
||||
|
||||
# exit status is 0 if all commands are found, 1 if any are not found
|
||||
for command; do
|
||||
# if $command is a function, make sure we add -a so type
|
||||
# will look in $PATH after finding the function
|
||||
a=$aflag
|
||||
case "$(builtin type -t $command)" in
|
||||
"function") a=-a;;
|
||||
esac
|
||||
|
||||
if [ -n "$sflag" ]; then
|
||||
builtin type -p $a $command >/dev/null 2>&1
|
||||
else
|
||||
builtin type -p $a $command
|
||||
fi
|
||||
ES=$?
|
||||
done
|
||||
|
||||
return $ES
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue