mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-29 08:29:54 +02:00
commit bash-20130301 snapshot
This commit is contained in:
@@ -1,4 +1,25 @@
|
||||
# based on the cd completion function from the bash_completion package
|
||||
# cdfunc - example completion function for cd
|
||||
#
|
||||
# based on the cd completion function from the bash_completion package
|
||||
#
|
||||
# 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.
|
||||
|
||||
_comp_cd()
|
||||
{
|
||||
local IFS=$' \t\n' # normalize IFS
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# based on the cd completion function from the bash_completion package
|
||||
_comp_cd()
|
||||
{
|
||||
local IFS=$' \t\n' # normalize IFS
|
||||
local cur _skipdot _cdpath
|
||||
local i j k
|
||||
|
||||
# Tilde expansion, with side effect of expanding tilde to full pathname
|
||||
case "$2" in
|
||||
\~*) eval cur="$2" ;;
|
||||
*) cur=$2 ;;
|
||||
esac
|
||||
|
||||
# no cdpath or absolute pathname -- straight directory completion
|
||||
if [[ -z "${CDPATH:-}" ]] || [[ "$cur" == @(./*|../*|/*) ]]; then
|
||||
# compgen prints paths one per line; could also use while loop
|
||||
IFS=$'\n'
|
||||
COMPREPLY=( $(compgen -d -- "$cur") )
|
||||
IFS=$' \t\n'
|
||||
# CDPATH+directories in the current directory if not in CDPATH
|
||||
else
|
||||
IFS=$'\n'
|
||||
_skipdot=false
|
||||
# preprocess CDPATH to convert null directory names to .
|
||||
_cdpath=${CDPATH/#:/.:}
|
||||
_cdpath=${_cdpath//::/:.:}
|
||||
_cdpath=${_cdpath/%:/:.}
|
||||
for i in ${_cdpath//:/$'\n'}; do
|
||||
if [[ $i -ef . ]]; then _skipdot=true; fi
|
||||
k="${#COMPREPLY[@]}"
|
||||
for j in $( compgen -d -- "$i/$cur" ); do
|
||||
COMPREPLY[k++]=${j#$i/} # cut off directory
|
||||
done
|
||||
done
|
||||
$_skipdot || COMPREPLY+=( $(compgen -d -- "$cur") )
|
||||
IFS=$' \t\n'
|
||||
fi
|
||||
|
||||
# variable names if appropriate shell option set and no completions
|
||||
if shopt -q cdable_vars && [[ ${#COMPREPLY[@]} -eq 0 ]]; then
|
||||
COMPREPLY=( $(compgen -v -- "$cur") )
|
||||
fi
|
||||
|
||||
# append slash to passed directory name that is the only completion.
|
||||
# readline will not do this if we complete from CDPATH
|
||||
if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
|
||||
i=${COMPREPLY[0]} # shorthand
|
||||
if [[ "$cur" == "$i" ]] && [[ "$i" != "*/" ]]; then
|
||||
COMPREPLY[0]+=/
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -o filenames -o nospace -o bashdefault -F _comp_cd cd
|
||||
@@ -1,6 +1,23 @@
|
||||
#
|
||||
# Completion examples
|
||||
#
|
||||
# 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.
|
||||
|
||||
#
|
||||
# This encapsulates the default bash completion code
|
||||
|
||||
@@ -0,0 +1,495 @@
|
||||
#
|
||||
# Completion examples
|
||||
#
|
||||
|
||||
#
|
||||
# This encapsulates the default bash completion code
|
||||
# call with the word to be completed as $1
|
||||
#
|
||||
# Since programmable completion does not use the bash default completions
|
||||
# or the readline default of filename completion when the compspec does
|
||||
# not generate any matches, this may be used as a `last resort' in a
|
||||
# completion function to mimic the default bash completion behavior.
|
||||
#
|
||||
_bash_def_completion ()
|
||||
{
|
||||
local h t
|
||||
COMPREPLY=()
|
||||
|
||||
# command substitution
|
||||
if [[ "$1" == \$\(* ]]; then
|
||||
t=${1#??}
|
||||
COMPREPLY=( $(compgen -c -P '$(' $t) )
|
||||
fi
|
||||
# variables with a leading `${'
|
||||
if [ ${#COMPREPLY[@]} -eq 0 ] && [[ "$1" == \$\{* ]]; then
|
||||
t=${1#??}
|
||||
COMPREPLY=( $(compgen -v -P '${' -S '}' $t) )
|
||||
fi
|
||||
# variables with a leading `$'
|
||||
if [ ${#COMPREPLY[@]} -eq 0 ] && [[ "$1" == \$* ]]; then
|
||||
t=${1#?}
|
||||
COMPREPLY=( $(compgen -v -P '$' $t ) )
|
||||
fi
|
||||
# username expansion
|
||||
if [ ${#COMPREPLY[@]} -eq 0 ] && [[ "$1" == ~* ]] && [[ "$1" != */* ]]; then
|
||||
t=${1#?}
|
||||
COMPREPLY=( $( compgen -u -P '~' $t ) )
|
||||
fi
|
||||
# hostname
|
||||
if [ ${#COMPREPLY[@]} -eq 0 ] && [[ "$1" == *@* ]]; then
|
||||
h=${1%%@*}
|
||||
t=${1#*@}
|
||||
COMPREPLY=( $( compgen -A hostname -P "${h}@" $t ) )
|
||||
fi
|
||||
# glob pattern
|
||||
if [ ${#COMPREPLY[@]} -eq 0 ]; then
|
||||
# sh-style glob pattern
|
||||
if [[ $1 == *[*?[]* ]]; then
|
||||
COMPREPLY=( $( compgen -G "$1" ) )
|
||||
# ksh-style extended glob pattern - must be complete
|
||||
elif shopt -q extglob && [[ $1 == *[?*+\!@]\(*\)* ]]; then
|
||||
COMPREPLY=( $( compgen -G "$1" ) )
|
||||
fi
|
||||
fi
|
||||
|
||||
# final default is filename completion
|
||||
if [ ${#COMPREPLY[@]} -eq 0 ]; then
|
||||
COMPREPLY=( $(compgen -f "$1" ) )
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Return 1 if $1 appears to contain a redirection operator. Handles backslash
|
||||
# quoting (barely).
|
||||
#
|
||||
_redir_op()
|
||||
{
|
||||
case "$1" in
|
||||
*\\'[\<\>]'*) return 1;;
|
||||
*[\<\>]*) return 0;;
|
||||
*) return 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
# _redir_test tests the current word ($1) and the previous word ($2) for
|
||||
# redirection operators and does filename completion on the current word
|
||||
# if either one contains a redirection operator
|
||||
_redir_test()
|
||||
{
|
||||
if _redir_op "$1" ; then
|
||||
COMPREPLY=( $( compgen -f "$1" ) )
|
||||
return 0
|
||||
elif _redir_op "$2" ; then
|
||||
COMPREPLY=( $( compgen -f "$1" ) )
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# optional, but without this you can't use extended glob patterns
|
||||
shopt -s extglob
|
||||
|
||||
#
|
||||
# Easy ones for the shell builtins
|
||||
#
|
||||
# nothing for: alias, break, continue, dirs, echo, eval, exit, getopts,
|
||||
# let, logout, popd, printf, pwd, return, shift, suspend, test, times,
|
||||
# umask
|
||||
#
|
||||
|
||||
complete -f -- . source
|
||||
complete -A enabled builtin
|
||||
complete -d cd
|
||||
|
||||
# this isn't exactly right yet -- needs to skip shell functions and
|
||||
# do $PATH lookup (or do compgen -c and filter out matches that also
|
||||
# appear in compgen -A function)
|
||||
complete -c command
|
||||
|
||||
# could add -S '=', but that currently screws up because readline appends
|
||||
# a space unconditionally
|
||||
|
||||
complete -v export local readonly
|
||||
complete -A helptopic help # currently same as builtins
|
||||
|
||||
complete -d pushd
|
||||
|
||||
complete -A shopt shopt
|
||||
|
||||
complete -c type
|
||||
|
||||
complete -a unalias
|
||||
complete -v unset
|
||||
|
||||
#
|
||||
# Job control builtins: fg, bg, disown, kill, wait
|
||||
# kill not done yet
|
||||
#
|
||||
|
||||
complete -A stopped -P '%' bg
|
||||
complete -j -P '%' fg jobs disown
|
||||
|
||||
# this is not quite right at this point
|
||||
|
||||
_wait_func ()
|
||||
{
|
||||
local cur
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
|
||||
case "$cur" in
|
||||
%*) COMPREPLY=( $(compgen -A running -P '%' ${cur#?} ) ) ;;
|
||||
[0-9]*) COMPREPLY=( $(jobs -p | grep ^${cur}) ) ;;
|
||||
*) COMPREPLY=( $(compgen -A running -P '%') $(jobs -p) )
|
||||
;;
|
||||
esac
|
||||
}
|
||||
complete -F _wait_func wait
|
||||
|
||||
#
|
||||
# more complicated things, several as yet unimplemented
|
||||
#
|
||||
|
||||
#complete -F _bind_func bind
|
||||
|
||||
_declare_func()
|
||||
{
|
||||
local cur prev nflag opts
|
||||
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
COMPREPLY=()
|
||||
if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
|
||||
COMPREPLY=(-a -f -F -i -p -r -t -x)
|
||||
return 0;
|
||||
fi
|
||||
if [[ $cur == '+' ]]; then
|
||||
COMPREPLY=(+i +t +x)
|
||||
return 0;
|
||||
fi
|
||||
if [[ $prev == '-p' ]]; then
|
||||
COMPREPLY=( $(compgen -v $cur) )
|
||||
return 0;
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
complete -F _declare_func declare typeset
|
||||
|
||||
_enable_func()
|
||||
{
|
||||
local cur prev nflag opts
|
||||
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
COMPREPLY=()
|
||||
if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
|
||||
COMPREPLY=(-a -d -f -n -p -s)
|
||||
return 0;
|
||||
fi
|
||||
if [[ $prev == '-f' ]]; then
|
||||
COMPREPLY=( $( compgen -f $cur ) )
|
||||
return 0;
|
||||
fi
|
||||
for opts in "${COMP_WORDS[@]}" ; do
|
||||
if [[ $opts == -*n* ]]; then nflag=1; fi
|
||||
done
|
||||
|
||||
if [ -z "$nflag" ] ; then
|
||||
COMPREPLY=( $( compgen -A enabled $cur ) )
|
||||
else
|
||||
COMPREPLY=( $( compgen -A disabled $cur ) )
|
||||
fi
|
||||
return 0;
|
||||
}
|
||||
complete -F _enable_func enable
|
||||
|
||||
_exec_func()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
|
||||
COMPREPLY=(-a -c -l)
|
||||
return 0;
|
||||
fi
|
||||
if [[ $prev != -*a* ]]; then
|
||||
COMPREPLY=( $( compgen -c $cur ) )
|
||||
return 0
|
||||
fi
|
||||
return 1;
|
||||
}
|
||||
complete -F _exec_func exec
|
||||
|
||||
_fc_func()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
|
||||
COMPREPLY=(-e -n -l -r -s)
|
||||
return 0;
|
||||
fi
|
||||
if [[ $prev == -*e ]]; then
|
||||
COMPREPLY=( $(compgen -c $cur) )
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
complete -F _fc_func fc
|
||||
|
||||
_hash_func()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
|
||||
COMPREPLY=(-p -r -t)
|
||||
return 0;
|
||||
fi
|
||||
|
||||
if [[ $prev == '-p' ]]; then
|
||||
COMPREPLY=( $( compgen -f $cur ) )
|
||||
return 0;
|
||||
fi
|
||||
COMPREPLY=( $( compgen -c $cur ) )
|
||||
return 0
|
||||
}
|
||||
complete -F _hash_func hash
|
||||
|
||||
_history_func()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
COMPREPLY=()
|
||||
if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
|
||||
COMPREPLY=(-a -c -d -n -r -w -p -s)
|
||||
return 0;
|
||||
fi
|
||||
if [[ $prev == -[anrw] ]]; then
|
||||
COMPREPLY=( $( compgen -f $cur ) )
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
complete -F _history_func history
|
||||
|
||||
#complete -F _read_func read
|
||||
|
||||
_set_func ()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
_redir_test "$cur" "$prev" && return 0;
|
||||
|
||||
if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
|
||||
COMPREPLY=(-a -b -e -f -k -m -n -o -p -t -u -v -x -B -C -H -P --)
|
||||
return 0;
|
||||
fi
|
||||
if [[ $cur == '+' ]]; then
|
||||
COMPREPLY=(+a +b +e +f +k +m +n +o +p +t +u +v +x +B +C +H +P)
|
||||
return 0;
|
||||
fi
|
||||
if [[ $prev == [+-]o ]]; then
|
||||
COMPREPLY=( $(compgen -A setopt $cur) )
|
||||
return 0;
|
||||
fi
|
||||
return 1;
|
||||
}
|
||||
complete -F _set_func set
|
||||
|
||||
_trap_func ()
|
||||
{
|
||||
local cur
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
|
||||
if (( $COMP_CWORD <= 1 )) || [[ $cur == '-' ]]; then
|
||||
COMPREPLY=(-l -p)
|
||||
return 0;
|
||||
fi
|
||||
COMPREPLY=( $( compgen -A signal ${cur}) )
|
||||
return 0
|
||||
}
|
||||
complete -F _trap_func trap
|
||||
|
||||
#
|
||||
# meta-completion (completion for complete/compgen)
|
||||
#
|
||||
_complete_meta_func()
|
||||
{
|
||||
local cur prev cmd
|
||||
COMPREPLY=()
|
||||
|
||||
cmd=$1
|
||||
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
_redir_test "$cur" "$prev" && return 0;
|
||||
|
||||
if (( $COMP_CWORD <= 1 )) || [[ "$cur" == '-' ]]; then
|
||||
case "$cmd" in
|
||||
complete) COMPREPLY=(-a -b -c -d -e -f -j -k -s -v -u -r -p -A -G -W -P -S -X -F -C);;
|
||||
compgen) COMPREPLY=(-a -b -c -d -e -f -j -k -s -v -u -A -G -W -P -S -X -F -C);;
|
||||
esac
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ $prev == -A ]]; then
|
||||
COMPREPLY=(alias arrayvar binding builtin command directory \
|
||||
disabled enabled export file 'function' helptopic hostname job keyword \
|
||||
running service setopt shopt signal stopped variable)
|
||||
return 0
|
||||
elif [[ $prev == -F ]]; then
|
||||
COMPREPLY=( $( compgen -A function $cur ) )
|
||||
elif [[ $prev == -C ]]; then
|
||||
COMPREPLY=( $( compgen -c $cur ) )
|
||||
else
|
||||
COMPREPLY=( $( compgen -c $cur ) )
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
complete -F _complete_meta_func complete compgen
|
||||
|
||||
#
|
||||
# some completions for shell reserved words
|
||||
#
|
||||
#complete -c -k time do if then else elif '{'
|
||||
|
||||
#
|
||||
# external commands
|
||||
#
|
||||
|
||||
complete -e printenv
|
||||
|
||||
complete -c nohup exec nice eval trace truss strace sotruss gdb
|
||||
|
||||
_make_targets ()
|
||||
{
|
||||
local mdef makef gcmd cur prev i
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
# if prev argument is -f, return possible filename completions.
|
||||
# we could be a little smarter here and return matches against
|
||||
# `makefile Makefile *.mk', whatever exists
|
||||
case "$prev" in
|
||||
-*f) COMPREPLY=( $(compgen -f $cur ) ); return 0;;
|
||||
esac
|
||||
|
||||
# if we want an option, return the possible posix options
|
||||
case "$cur" in
|
||||
-) COMPREPLY=(-e -f -i -k -n -p -q -r -S -s -t); return 0;;
|
||||
esac
|
||||
|
||||
# make reads `makefile' before `Makefile'
|
||||
# GNU make reads `GNUmakefile' before all other makefiles, but we
|
||||
# check that we're completing `gmake' before checking for it
|
||||
if [ -f GNUmakefile ] && [ ${COMP_WORDS[0]} == gmake ]; then
|
||||
mdef=GNUmakefile
|
||||
elif [ -f makefile ]; then
|
||||
mdef=makefile
|
||||
elif [ -f Makefile ]; then
|
||||
mdef=Makefile
|
||||
else
|
||||
mdef=*.mk # local convention
|
||||
fi
|
||||
|
||||
# before we scan for targets, see if a makefile name was specified
|
||||
# with -f
|
||||
for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
|
||||
if [[ ${COMP_WORDS[i]} == -*f ]]; then
|
||||
eval makef=${COMP_WORDS[i+1]} # eval for tilde expansion
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
[ -z "$makef" ] && makef=$mdef
|
||||
|
||||
# if we have a partial word to complete, restrict completions to
|
||||
# matches of that word
|
||||
if [ -n "$2" ]; then gcmd='grep "^$2"' ; else gcmd=cat ; fi
|
||||
|
||||
# if we don't want to use *.mk, we can take out the cat and use
|
||||
# test -f $makef and input redirection
|
||||
COMPREPLY=( $(cat $makef 2>/dev/null | awk 'BEGIN {FS=":"} /^[^.# ][^=]*:/ {print $1}' | tr -s ' ' '\012' | sort -u | eval $gcmd ) )
|
||||
}
|
||||
complete -F _make_targets -X '+($*|*.[cho])' make gmake pmake
|
||||
|
||||
_umount_func ()
|
||||
{
|
||||
COMPREPLY=( $(mount | awk '{print $1}') )
|
||||
}
|
||||
complete -F _umount_func umount
|
||||
|
||||
_configure_func ()
|
||||
{
|
||||
case "$2" in
|
||||
-*) ;;
|
||||
*) return ;;
|
||||
esac
|
||||
|
||||
case "$1" in
|
||||
\~*) eval cmd=$1 ;;
|
||||
*) cmd="$1" ;;
|
||||
esac
|
||||
|
||||
COMPREPLY=( $("$cmd" --help | awk '{if ($1 ~ /--.*/) print $1}' | grep ^"$2" | sort -u) )
|
||||
}
|
||||
complete -F _configure_func configure
|
||||
|
||||
complete -W '"${GROUPS[@]}"' newgrp
|
||||
|
||||
complete -f chown ln more cat
|
||||
complete -d mkdir rmdir
|
||||
complete -f strip
|
||||
|
||||
complete -f -X '*.gz' gzip
|
||||
complete -f -X '*.bz2' bzip2
|
||||
complete -f -X '*.Z' compress
|
||||
complete -f -X '!*.+(gz|tgz|Gz)' gunzip gzcat zcat zmore
|
||||
complete -f -X '!*.Z' uncompress zmore zcat
|
||||
complete -f -X '!*.bz2' bunzip2 bzcat
|
||||
complete -f -X '!*.zip' unzip
|
||||
complete -f -X '!*.+(gif|jpg|jpeg|GIF|JPG|JPEG|bmp)' xv
|
||||
|
||||
complete -f -X '!*.pl' perl perl5
|
||||
|
||||
complete -A hostname rsh telnet rlogin ftp ping xping host traceroute nslookup
|
||||
complete -A hostname rxterm rxterm3 rxvt2
|
||||
|
||||
complete -u su
|
||||
complete -g newgrp groupdel groupmod
|
||||
|
||||
complete -f -X '!*.+(ps|PS)' gs gv ghostview psselect pswrap
|
||||
complete -f -X '!*.+(dvi|DVI)' dvips xdvi dviselect dvitype catdvi
|
||||
complete -f -X '!*.+(pdf|PDF)' acroread4
|
||||
complete -f -X '!*.texi*' makeinfo texi2dvi texi2html
|
||||
complete -f -X '!*.+(tex|TEX)' tex latex slitex
|
||||
|
||||
complete -f -X '!*.+(mp3|MP3)' mpg123
|
||||
complete -f -X '!*.+(htm|html)' links w3m lynx
|
||||
|
||||
#
|
||||
# other possibilities, left as exercises
|
||||
#
|
||||
#complete -F _find_func find
|
||||
#complete -F _man_func man
|
||||
#complete -F _stty_func stty
|
||||
@@ -1,3 +1,21 @@
|
||||
# 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.
|
||||
|
||||
# from zsh, just for testing
|
||||
complete -A stopped -P '%' bg
|
||||
complete -j -P '%' fg jobs disown
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# from zsh, just for testing
|
||||
complete -A stopped -P '%' bg
|
||||
complete -j -P '%' fg jobs disown
|
||||
# this is wrong at this point
|
||||
complete -j -P '%' -W '$(ps -x | tail +2 | cut -c1-5)' wait
|
||||
complete -c type
|
||||
complete -a unalias
|
||||
complete -v getopts read unset
|
||||
complete -v -S '=' declare export local readonly typeset
|
||||
complete -f -- . source
|
||||
complete -A shopt shopt
|
||||
complete -e printenv
|
||||
|
||||
complete -A helptopic help
|
||||
|
||||
complete -c nohup exec nice eval
|
||||
complete -c -k time
|
||||
|
||||
complete -A signal trap kill
|
||||
|
||||
complete -f chown ln more cat
|
||||
complete -d mkdir rmdir
|
||||
|
||||
complete -f -X '!*.+(gz|tgz)' gunzip gzcat zcat zmore
|
||||
complete -f -X '!*.Z' uncompress zmore zcat
|
||||
complete -f gzip
|
||||
|
||||
complete -d cd pushd popd
|
||||
|
||||
complete -A hostname rsh telnet rlogin ftp
|
||||
|
||||
complete -u su
|
||||
complete -W '"${GROUPS[@]}"' newgrp
|
||||
complete -g groupdel groupmod
|
||||
|
||||
complete -f -X '!*.+(ps|PS)' gs gv ghostview
|
||||
complete -f -X '!*.dvi' dvips xdvi
|
||||
complete -f -X '!*.pdf' acroread
|
||||
|
||||
complete -f -X '!*.texi*' makeinfo texi2dvi texi2html
|
||||
|
||||
complete -c gdb make
|
||||
|
||||
complete -p gs
|
||||
complete -p
|
||||
|
||||
complete -r xdvi
|
||||
complete -r notthere
|
||||
complete -r
|
||||
complete
|
||||
@@ -0,0 +1,31 @@
|
||||
#Date: Wed, 31 Jan 2001 12:53:56 -0800
|
||||
#From: Aaron Smith <aaron@mutex.org>
|
||||
#To: freebsd-ports@freebsd.org
|
||||
#Subject: useful bash completion function for pkg commands
|
||||
#Message-ID: <20010131125356.G52003@gelatinous.com>
|
||||
|
||||
#hi all. i just wanted to share this bash completion function i wrote that
|
||||
#completes package names for pkg_info and pkg_delete. i find this a great
|
||||
#help when dealing with port management. programmed completion requires
|
||||
#bash-2.04.
|
||||
|
||||
_pkg_func ()
|
||||
{
|
||||
local cur
|
||||
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
|
||||
if [[ $cur == '-' ]]; then
|
||||
if [[ ${COMP_WORDS[0]} == 'pkg_info' ]]; then
|
||||
COMPREPLY=(-a -c -d -D -i -k -r -R -p -L -q -I -m -v -e -l)
|
||||
return 0;
|
||||
elif [[ ${COMP_WORDS[0]} == 'pkg_delete' ]]; then
|
||||
COMPREPLY=(-v -D -d -n -f -p)
|
||||
return 0;
|
||||
fi
|
||||
fi
|
||||
|
||||
COMPREPLY=( $(compgen -d /var/db/pkg/$cur | sed sN/var/db/pkg/NNg) )
|
||||
return 0
|
||||
}
|
||||
complete -F _pkg_func pkg_delete pkg_info
|
||||
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# Originally from:
|
||||
#
|
||||
#Message-ID: <3B13EC65.179451AE@wanadoo.fr>
|
||||
#Date: Tue, 29 May 2001 20:37:25 +0200
|
||||
#From: Manu Rouat <emmanuel.rouat@wanadoo.fr>
|
||||
#Subject: [bash] Universal command options completion?
|
||||
#
|
||||
#
|
||||
#In the recent versions of bash (after 2.04) programmable
|
||||
#completion is available. A useful completion function
|
||||
#is , for a particular command, to enumerate all flags
|
||||
#that can be used in the command. Now, most GNU unix
|
||||
#commands have so-called 'long options' for example:
|
||||
#
|
||||
#ls --color=always --no-group --size
|
||||
#
|
||||
#and these are all listed when you issue a '--help' flag.
|
||||
#So the idea is to use that, then parse the output of the
|
||||
#'--help' and reinject this to compgen. The basis of the
|
||||
#following 'universal' completion funtion was the _configure_func'
|
||||
#written by Ian McDonnald (or is it Chet Ramey ?)
|
||||
#A dedicated function will always be better, but this is quite
|
||||
#convenient. I chose to use 'long options' because they are
|
||||
#easy to parse and explicit too (it's the point I guess...)
|
||||
#Lots of room for improvement !
|
||||
|
||||
_longopt_func ()
|
||||
{
|
||||
case "$2" in
|
||||
-*) ;;
|
||||
*) return ;;
|
||||
esac
|
||||
|
||||
case "$1" in
|
||||
\~*) eval cmd=$1 ;;
|
||||
*) cmd="$1" ;;
|
||||
esac
|
||||
COMPREPLY=( $("$cmd" --help | sed -e '/--/!d' -e 's/.*--\([^ ]*\).*/--\1/'| \
|
||||
grep ^"$2" |sort -u) )
|
||||
}
|
||||
|
||||
complete -o default -F _longopt_func ldd wget bash id info # some examples that work
|
||||
@@ -0,0 +1,433 @@
|
||||
#####
|
||||
#To: chet@po.cwru.edu, sarahmckenna@lucent.com
|
||||
#Message-Id: <slrn8mqioc.msb.ian@lovelorn.linuxcare.com>
|
||||
#Posted-To: comp.unix.shell, gnu.bash.bug
|
||||
#Subject: bash 2.04 programmable completion examples
|
||||
#Reply-To: ian@linuxcare.com, ian@caliban.org
|
||||
#Summary: examples of programmable completion for bash 2.04
|
||||
#Date: Thu, 13 Jul 2000 00:52:33 -0400 (EDT)
|
||||
#From: ianmacd@linuxcare.com (Ian Macdonald)
|
||||
#####
|
||||
|
||||
#########################################################################
|
||||
# Turn on extended globbing
|
||||
shopt -s extglob
|
||||
|
||||
# A lot of the following one-liners were taken directly from the
|
||||
# completion examples provided with the bash 2.04 source distribution
|
||||
|
||||
# Make directory commands see only directories
|
||||
complete -d cd mkdir rmdir pushd
|
||||
|
||||
# Make file commands see only files
|
||||
complete -f cat less more chown ln strip
|
||||
complete -f -X '*.gz' gzip
|
||||
complete -f -X '*.Z' compress
|
||||
complete -f -X '!*.+(Z|gz|tgz|Gz)' gunzip zcat zmore
|
||||
complete -f -X '!*.Z' uncompress zmore zcat
|
||||
complete -f -X '!*.+(gif|jpg|jpeg|GIF|JPG|bmp)' ee xv
|
||||
complete -f -X '!*.+(ps|PS|ps.gz)' gv
|
||||
complete -f -X '!*.+(dvi|DVI)' dvips xdvi dviselect dvitype
|
||||
complete -f -X '!*.+(pdf|PDF)' acroread xpdf
|
||||
complete -f -X '!*.texi*' makeinfo texi2dvi texi2html
|
||||
complete -f -X '!*.+(tex|TEX)' tex latex slitex
|
||||
complete -f -X '!*.+(mp3|MP3)' mpg123
|
||||
|
||||
# kill sees only signals
|
||||
complete -A signal kill -P '%'
|
||||
|
||||
# user commands see only users
|
||||
complete -u finger su usermod userdel passwd
|
||||
|
||||
# bg completes with stopped jobs
|
||||
complete -A stopped -P '%' bg
|
||||
|
||||
# other job commands
|
||||
complete -j -P '%' fg jobs disown
|
||||
|
||||
# network commands complete with hostname
|
||||
complete -A hostname ssh rsh telnet rlogin ftp ping fping host traceroute \
|
||||
nslookup
|
||||
|
||||
# export and others complete with shell variables
|
||||
complete -v export local readonly unset
|
||||
|
||||
# set completes with set options
|
||||
complete -A setopt set
|
||||
|
||||
# shopt completes with shopt options
|
||||
complete -A shopt shopt
|
||||
|
||||
# helptopics
|
||||
complete -A helptopic help
|
||||
|
||||
# unalias completes with aliases
|
||||
complete -a unalias
|
||||
|
||||
# various commands complete with commands
|
||||
complete -c command type nohup exec nice eval strace gdb
|
||||
|
||||
# bind completes with readline bindings (make this more intelligent)
|
||||
complete -A binding bind
|
||||
|
||||
# Now we get to the meat of the file, the functions themselves. Some
|
||||
# of these are works in progress. Most assume GNU versions of the
|
||||
# tools in question and may require modifications for use on vanilla
|
||||
# UNIX systems.
|
||||
#
|
||||
# A couple of functions may have non-portable, Linux specific code in
|
||||
# them, but this will be noted where applicable
|
||||
|
||||
|
||||
# GNU chown(1) completion. This should be expanded to allow the use of
|
||||
# ':' as well as '.' as the user.group separator.
|
||||
#
|
||||
_chown ()
|
||||
{
|
||||
local cur prev user group
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
# do not attempt completion if we're specifying an option
|
||||
if [ "${cur:0:1}" = "-" ]; then return 0; fi
|
||||
|
||||
# first parameter on line or first since an option?
|
||||
if [ $COMP_CWORD -eq 1 ] || [ "${prev:0:1}" = "-" ]; then
|
||||
case "$cur" in
|
||||
[a-zA-Z]*.*)
|
||||
user=${cur%.*}
|
||||
group=${cur#*.}
|
||||
COMPREPLY=( $( awk 'BEGIN {FS=":"} \
|
||||
{if ($1 ~ /^'$group'/) print $1}' \
|
||||
/etc/group ) )
|
||||
for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
|
||||
COMPREPLY[i]=$user.${COMPREPLY[i]}
|
||||
done
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -u $cur -S '.' ) )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
else
|
||||
COMPREPLY=( $( compgen -f $cur ) )
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
complete -F _chown chown
|
||||
|
||||
# umount(8) completion. This relies on the mount point being the third
|
||||
# space-delimited field in the output of mount(8)
|
||||
#
|
||||
_umount ()
|
||||
{
|
||||
local cur
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
|
||||
# could rewrite the cut | grep to be a sed command, but this is
|
||||
# clearer and doesn't result in much overhead
|
||||
COMPREPLY=( $( mount | cut -d' ' -f 3 | grep ^$cur) )
|
||||
return 0
|
||||
}
|
||||
complete -F _umount umount
|
||||
|
||||
# GID completion. This will get a list of all valid group names from
|
||||
# /etc/group and should work anywhere.
|
||||
#
|
||||
_gid_func ()
|
||||
{
|
||||
local cur
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
COMPREPLY=( $( awk 'BEGIN {FS=":"} {if ($1 ~ /^'$cur'/) print $1}' \
|
||||
/etc/group ) )
|
||||
return 0
|
||||
}
|
||||
complete -F _gid_func groupdel groupmod
|
||||
|
||||
# mount(8) completion. This will pull a list of possible mounts out of
|
||||
# /etc/fstab, unless the word being completed contains a ':', which
|
||||
# would indicate the specification of an NFS server. In that case, we
|
||||
# query the server for a list of all available exports and complete on
|
||||
# that instead.
|
||||
#
|
||||
_mount ()
|
||||
|
||||
{ local cur
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
|
||||
case "$cur" in
|
||||
*:*)
|
||||
COMPREPLY=( $( /usr/sbin/showmount -e --no-headers ${cur%%:*} |\
|
||||
grep ^${cur#*:} | awk '{print $1}'))
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( awk '{if ($2 ~ /\//) print $2}' /etc/fstab | \
|
||||
grep ^$cur ))
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
complete -F _mount mount
|
||||
|
||||
# Linux rmmod(1) completion. This completes on a list of all currently
|
||||
# installed kernel modules.
|
||||
#
|
||||
_rmmod ()
|
||||
{
|
||||
local cur
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
|
||||
COMPREPLY=($( lsmod | awk '{if (NR != 1 && $1 ~ /^'$cur'/) print $1}'))
|
||||
return 0
|
||||
}
|
||||
complete -F _rmmod rmmod
|
||||
|
||||
# Linux insmod(1) completion. This completes on a list of all
|
||||
# available modules for the version of the kernel currently running.
|
||||
#
|
||||
_insmod ()
|
||||
{
|
||||
local cur modpath
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
modpath=/lib/modules/`uname -r`
|
||||
|
||||
COMPREPLY=($( ls -R $modpath | sed -ne 's/^\('$cur'.*\)\.o$/\1/p'))
|
||||
return 0
|
||||
}
|
||||
complete -F _insmod insmod depmod modprobe
|
||||
|
||||
# man(1) completion. This relies on the security enhanced version of
|
||||
# GNU locate(1). UNIX variants having non-numeric man page sections
|
||||
# other than l, m and n should add the appropriate sections to the
|
||||
# first clause of the case statement.
|
||||
#
|
||||
# This is Linux specific, in that 'man <section> <page>' is the
|
||||
# expected syntax. This allows one to do something like
|
||||
# 'man 3 str<tab>' to obtain a list of all string handling syscalls on
|
||||
# the system.
|
||||
#
|
||||
_man ()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
case "$prev" in
|
||||
[0-9lmn])
|
||||
COMPREPLY=($( slocate -ql 0 -r '/man/man'$prev'/'$cur | \
|
||||
sed -ne 's/^.*\/\('$cur'[^.\/]*\)\..*$/\1/p' ))
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=($( slocate -ql 0 -r '/man/man./'$cur | \
|
||||
sed -ne 's/^.*\/\('$cur'[^.\/]*\)\..*$/\1/p' ))
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
complete -F _man man
|
||||
|
||||
# Linux killall(1) completion. This wouldn't be much use on, say,
|
||||
# Solaris, where killall does exactly that: kills ALL processes.
|
||||
#
|
||||
# This could be improved. For example, it currently doesn't take
|
||||
# command line options into account
|
||||
#
|
||||
_killall ()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
case "$prev" in
|
||||
-[A-Z0-9]*)
|
||||
# get a list of processes (the first sed evaluation
|
||||
# takes care of swapped out processes, the second
|
||||
# takes care of getting the basename of the process)
|
||||
COMPREPLY=( $( ps ahx | awk '{if ($5 ~ /^'$cur'/) print $5}' | \
|
||||
sed -e 's#[]\[]##g' -e 's#^.*/##' ))
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# first parameter can be either a signal or a process
|
||||
if [ $COMP_CWORD -eq 1 ]; then
|
||||
# standard signal completion is rather braindead, so we need
|
||||
# to hack around to get what we want here, which is to
|
||||
# complete on a dash, followed by the signal name minus
|
||||
# the SIG prefix
|
||||
COMPREPLY=( $( compgen -A signal SIG${cur#-} ))
|
||||
for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
|
||||
COMPREPLY[i]=-${COMPREPLY[i]#SIG}
|
||||
done
|
||||
fi
|
||||
|
||||
# get processes, adding to signals if applicable
|
||||
COMPREPLY=( ${COMPREPLY[*]} $( ps ahx | \
|
||||
awk '{if ($5 ~ /^'$cur'/) print $5}' | \
|
||||
sed -e 's#[]\[]##g' -e 's#^.*/##' ))
|
||||
return 0
|
||||
}
|
||||
complete -F _killall killall
|
||||
|
||||
# GNU find(1) completion. This makes heavy use of ksh style extended
|
||||
# globs and contains Linux specific code for completing the parameter
|
||||
# to the -fstype option.
|
||||
#
|
||||
_find ()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]#-}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
case "$prev" in
|
||||
-@(max|min)depth)
|
||||
COMPREPLY=( $( compgen -W '0 1 2 3 4 5 6 7 8 9' ) )
|
||||
return 0
|
||||
;;
|
||||
-?(a)newer|-fls|-fprint?(0|f))
|
||||
COMPREPLY=( $( compgen -f $cur ) )
|
||||
return 0
|
||||
;;
|
||||
-fstype)
|
||||
# this is highly non-portable (the option to -d is a tab)
|
||||
COMPREPLY=( $( cut -d' ' -f 2 /proc/filesystems | grep ^$cur ) )
|
||||
return 0
|
||||
;;
|
||||
-gid)
|
||||
COMPREPLY=( $( awk 'BEGIN {FS=":"} \
|
||||
{if ($3 ~ /^'$cur'/) print $3}' /etc/group ) )
|
||||
return 0
|
||||
;;
|
||||
-group)
|
||||
COMPREPLY=( $( awk 'BEGIN {FS=":"} \
|
||||
{if ($1 ~ /^'$cur'/) print $1}' /etc/group ) )
|
||||
return 0
|
||||
;;
|
||||
-?(x)type)
|
||||
COMPREPLY=( $( compgen -W 'b c d p f l s' $cur ) )
|
||||
return 0
|
||||
;;
|
||||
-uid)
|
||||
COMPREPLY=( $( awk 'BEGIN {FS=":"} \
|
||||
{if ($3 ~ /^'$cur'/) print $3}' /etc/passwd ) )
|
||||
return 0
|
||||
;;
|
||||
-user)
|
||||
COMPREPLY=( $( compgen -u $cur ) )
|
||||
return 0
|
||||
;;
|
||||
-[acm]min|-[acm]time|-?(i)?(l)name|-inum|-?(i)path|-?(i)regex| \
|
||||
-links|-perm|-size|-used|-exec|-ok|-printf)
|
||||
# do nothing, just wait for a parameter to be given
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# complete using basic options ($cur has had its dash removed here,
|
||||
# as otherwise compgen will bomb out with an error, since it thinks
|
||||
# the dash is an option to itself)
|
||||
COMPREPLY=( $( compgen -W 'daystart depth follow help maxdepth \
|
||||
mindepth mount noleaf version xdev amin anewer atime \
|
||||
cmin cnewer ctime empty false fstype gid group ilname \
|
||||
iname inum ipath iregex links lname mmin mtime name \
|
||||
newer nouser nogroup perm regex size true type uid \
|
||||
used user xtype exec fls fprint fprint0 fprintf ok \
|
||||
print print0 printf prune ls' $cur ) )
|
||||
|
||||
# this removes any options from the list of completions that have
|
||||
# already been specified somewhere on the command line.
|
||||
COMPREPLY=( $( echo "${COMP_WORDS[@]}-" | \
|
||||
(while read -d '-' i; do
|
||||
[ "$i" == "" ] && continue
|
||||
# flatten array with spaces on either side,
|
||||
# otherwise we cannot grep on word boundaries of
|
||||
# first and last word
|
||||
COMPREPLY=" ${COMPREPLY[@]} "
|
||||
# remove word from list of completions
|
||||
COMPREPLY=( ${COMPREPLY/ ${i%% *} / } )
|
||||
done
|
||||
echo ${COMPREPLY[@]})
|
||||
) )
|
||||
|
||||
# put dashes back
|
||||
for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
|
||||
COMPREPLY[i]=-${COMPREPLY[i]}
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
complete -F _find find
|
||||
|
||||
# Linux ifconfig(8) completion
|
||||
#
|
||||
_ifconfig ()
|
||||
{
|
||||
local cur
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
|
||||
case "${COMP_WORDS[1]}" in
|
||||
-|*[0-9]*)
|
||||
COMPREPLY=( $( compgen -W '-a up down arp promisc allmulti \
|
||||
metric mtu dstaddr netmask add del \
|
||||
tunnel irq io_addr mem_start media \
|
||||
broadcast pointopoint hw multicast \
|
||||
address txqueuelen' $cur ))
|
||||
COMPREPLY=( $( echo " ${COMP_WORDS[@]}" | \
|
||||
(while read -d ' ' i; do
|
||||
[ "$i" == "" ] && continue
|
||||
# flatten array with spaces on either side,
|
||||
# otherwise we cannot grep on word
|
||||
# boundaries of first and last word
|
||||
COMPREPLY=" ${COMPREPLY[@]} "
|
||||
# remove word from list of completions
|
||||
COMPREPLY=( ${COMPREPLY/ $i / } )
|
||||
done
|
||||
echo ${COMPREPLY[@]})
|
||||
) )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
COMPREPLY=( $( ifconfig -a | sed -ne 's/^\('$cur'[^ ]*\).*$/\1/p' ))
|
||||
}
|
||||
complete -F _ifconfig ifconfig
|
||||
|
||||
# Linux ipsec(8) completion (for FreeS/WAN). Very basic.
|
||||
#
|
||||
_ipsec ()
|
||||
{
|
||||
local cur
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
|
||||
COMPREPLY=( $( compgen -W 'auto barf eroute klipsdebug look manual \
|
||||
pluto ranbits rsasigkey setup showdefaults \
|
||||
showhostkey spi spigrp tncfg whack' $cur ))
|
||||
}
|
||||
complete -F _ipsec ipsec
|
||||
#########################################################################
|
||||
@@ -0,0 +1,271 @@
|
||||
#####
|
||||
#From: ian@linuxcare.com (Ian Macdonald)
|
||||
#Newsgroups: comp.unix.shell
|
||||
#Subject: More bash 2.04 completions
|
||||
#Date: 12 Aug 2000 09:53:40 GMT
|
||||
#Organization: Linuxcare, Inc.
|
||||
#Lines: 274
|
||||
#Message-ID: <slrn8pa7l2.jgm.ian@lovelorn.linuxcare.com>
|
||||
#Reply-To: ian@linuxcare.com
|
||||
#####
|
||||
|
||||
# Turn on extended globbing
|
||||
shopt -s extglob
|
||||
|
||||
# cvs(1) completion
|
||||
#
|
||||
_cvs ()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
if [ $COMP_CWORD -eq 1 ] || [ "${prev:0:1}" = "-" ]; then
|
||||
COMPREPLY=( $( compgen -W 'add admin checkout commit diff \
|
||||
export history import log rdiff release remove rtag status \
|
||||
tag update' $cur ))
|
||||
else
|
||||
COMPREPLY=( $( compgen -f $cur ))
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
complete -F _cvs cvs
|
||||
|
||||
# rpm(8) completion. This isn't exhaustive yet, but still provides
|
||||
# quite a lot of functionality.
|
||||
#
|
||||
_rpm()
|
||||
{
|
||||
dashify()
|
||||
{
|
||||
local i
|
||||
|
||||
for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
|
||||
if [ ${#COMPREPLY[i]} -le 2 ]; then
|
||||
COMPREPLY[i]=-${COMPREPLY[i]}
|
||||
else
|
||||
COMPREPLY[i]=--${COMPREPLY[i]}
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
local cur cur_nodash prev
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
cur_nodash=${cur#-}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
if [ $COMP_CWORD = 1 ]; then
|
||||
# first parameter on line
|
||||
case "$cur" in
|
||||
-b*)
|
||||
COMPREPLY=( $( compgen -W 'ba bb bc bi bl bp bs' \
|
||||
$cur_nodash ) )
|
||||
dashify
|
||||
return 0
|
||||
;;
|
||||
-t*)
|
||||
COMPREPLY=( $( compgen -W 'ta tb tc ti tl tp ts' \
|
||||
$cur_nodash ) )
|
||||
dashify
|
||||
return 0
|
||||
;;
|
||||
--*)
|
||||
COMPREPLY=( $( compgen -W 'help version initdb \
|
||||
checksig recompile rebuild resign addsign rebuilddb \
|
||||
showrc setperms setgids' ${cur_nodash#-} ) )
|
||||
dashify;
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=( $( compgen -W 'b e F i q t U V' \
|
||||
$cur_nodash ) )
|
||||
dashify
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
case "${COMP_WORDS[1]}" in
|
||||
-[iFU]*)
|
||||
# complete on list of relevant options
|
||||
COMPREPLY=( $( compgen -W 'percent force test replacepkgs \
|
||||
replacefiles root excludedocs includedocs noscripts rcfile \
|
||||
ignorearch dbpath prefix ignoreos nodeps allfiles ftpproxy \
|
||||
ftpport justdb httpproxy httpport noorder relocate badreloc \
|
||||
notriggers excludepath ignoresize oldpackage' ${cur_nodash#-} ))
|
||||
dashify;
|
||||
# return if $cur is an option
|
||||
[ "${cur:0:1}" = "-" ] && return 0
|
||||
# add a list of RPMS to possible completions
|
||||
COMPREPLY=( ${COMPREPLY[@]} $( compgen -G $cur\*.rpm ) )
|
||||
return 0
|
||||
;;
|
||||
-qp*)
|
||||
# complete on list of relevant options
|
||||
COMPREPLY=( $( compgen -W 'scripts root rcfile whatprovides \
|
||||
whatrequires requires triggeredby ftpport ftpproxy httpproxy \
|
||||
httpport provides triggers dump changelog dbpath filesbypkg' \
|
||||
${cur_nodash#-} ) )
|
||||
dashify;
|
||||
# return if $cur is an option
|
||||
[ "${cur:0:1}" = "-" ] && return 0
|
||||
# add a list of RPMS to possible completions
|
||||
COMPREPLY=( ${COMPREPLY[@]} $( compgen -G $cur\*.rpm ) )
|
||||
return 0
|
||||
;;
|
||||
-*f)
|
||||
# standard filename completion
|
||||
COMPREPLY=( $( compgen -f $cur ) )
|
||||
return 0
|
||||
;;
|
||||
-e)
|
||||
# complete on list of relevant options
|
||||
COMPREPLY=( $( compgen -W 'allmatches noscripts notriggers \
|
||||
nodeps test' ${cur_nodash#-} ) )
|
||||
dashify;
|
||||
# return if $cur is an option
|
||||
[ "${cur:0:1}" = "-" ] && return 0
|
||||
# complete on basename of installed RPMs
|
||||
COMPREPLY=( $( rpm -qa | \
|
||||
sed -ne 's/^\('$cur'.*\)-[0-9a-zA-Z._]\+-[0-9.]\+$/\1/p' ) )
|
||||
return 0
|
||||
;;
|
||||
-qa*)
|
||||
# complete on list of relevant options
|
||||
COMPREPLY=( $( compgen -W 'scripts root rcfile whatprovides \
|
||||
whatrequires requires triggeredby ftpport ftpproxy httpproxy \
|
||||
httpport provides triggers dump changelog dbpath specfile \
|
||||
querybynumber last filesbypkg' ${cur_nodash#-} ) )
|
||||
dashify;
|
||||
return 0
|
||||
;;
|
||||
-q*)
|
||||
# complete on list of relevant options
|
||||
COMPREPLY=( $( compgen -W 'scripts root rcfile whatprovides \
|
||||
whatrequires requires triggeredby ftpport ftpproxy httpproxy \
|
||||
httpport provides triggers dump changelog dbpath specfile \
|
||||
querybynumber last filesbypkg' ${cur_nodash#-} ) )
|
||||
dashify;
|
||||
# return if $cur is an option
|
||||
[ "${cur:0:1}" = "-" ] && return 0
|
||||
# add a list of RPMS to possible completions
|
||||
COMPREPLY=( ${COMPREPLY[@]} $( rpm -qa | \
|
||||
sed -ne 's/^\('$cur'.*\)-[0-9a-zA-Z._]\+-[0-9.]\+$/\1/p' ) )
|
||||
return 0
|
||||
;;
|
||||
-[Vy]*)
|
||||
# complete on list of relevant options
|
||||
COMPREPLY=( $( compgen -W 'root rcfile dbpath nodeps nofiles \
|
||||
noscripts nomd5 nopgp' ${cur_nodash#-} ) )
|
||||
dashify;
|
||||
# return if $cur is an option
|
||||
[ "${cur:0:1}" = "-" ] && return 0
|
||||
# add a list of RPMS to possible completions
|
||||
COMPREPLY=( ${COMPREPLY[@]} $( rpm -qa | \
|
||||
sed -ne 's/^\('$cur'.*\)-[0-9a-zA-Z._]\+-[0-9.]\+$/\1/p' ) )
|
||||
return 0
|
||||
;;
|
||||
-b*)
|
||||
# complete on list of relevant options
|
||||
COMPREPLY=( $( compgen -W 'short-circuit timecheck clean \
|
||||
rmsource test sign buildroot target buildarch buildos' \
|
||||
${cur_nodash#-} ) )
|
||||
dashify;
|
||||
# return if $cur is an option
|
||||
[ "${cur:0:1}" = "-" ] && return 0
|
||||
# complete on .spec files
|
||||
COMPREPLY=( $( compgen -G $cur\*.spec ) )
|
||||
return 0
|
||||
;;
|
||||
-t*)
|
||||
# complete on list of relevant options
|
||||
COMPREPLY=( $( compgen -W 'short-circuit timecheck clean \
|
||||
rmsource test sign buildroot target buildarch buildos' \
|
||||
${cur_nodash#-} ) )
|
||||
dashify;
|
||||
# return if $cur is an option
|
||||
[ "${cur:0:1}" = "-" ] && return 0
|
||||
# complete on .tar.gz files
|
||||
COMPREPLY=( $( compgen -G $cur\*.tar.gz ) )
|
||||
return 0
|
||||
;;
|
||||
--re@(build|compile))
|
||||
# complete on source RPMs
|
||||
COMPREPLY=( $( compgen -G $cur\*.src.rpm ) )
|
||||
return 0
|
||||
;;
|
||||
--@(checksig|@(re|add)sign))
|
||||
# complete on RPMs
|
||||
COMPREPLY=( $( compgen -G $cur\*.rpm ) )
|
||||
return 0
|
||||
;;
|
||||
--set@(perms|gids))
|
||||
# complete on installed RPMs
|
||||
COMPREPLY=( ${COMPREPLY[@]} $( rpm -qa | \
|
||||
sed -ne 's/^\('$cur'.*\)-[0-9a-zA-Z._]\+-[0-9.]\+$/\1/p' ) )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
complete -F _rpm rpm
|
||||
|
||||
# chsh(1) completion
|
||||
#
|
||||
_chsh()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
if [ "$prev" = "-s" ]; then
|
||||
COMPREPLY=( $( chsh -l | grep ^$cur ) )
|
||||
else
|
||||
COMPREPLY=( $( compgen -u $cur ) )
|
||||
fi
|
||||
}
|
||||
complete -F _chsh chsh
|
||||
|
||||
# chkconfig(8) completion
|
||||
#
|
||||
_chkconfig()
|
||||
{
|
||||
local cur prev
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
cur_nodash=${cur#--}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
if [ $COMP_CWORD -eq 1 ]; then
|
||||
COMPREPLY=( $( compgen -W 'list add del level' $cur_nodash ) )
|
||||
for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
|
||||
COMPREPLY[i]=--${COMPREPLY[i]}
|
||||
done
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ $COMP_CWORD -eq 4 ]; then
|
||||
COMPREPLY=( $( compgen -W 'on off reset' $cur ) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$prev" in
|
||||
@([1-6]|--@(list|add|del)))
|
||||
COMPREPLY=( $( compgen -W "`(cd /etc/rc.d/init.d; echo *)`" \
|
||||
$cur) )
|
||||
return 0
|
||||
;;
|
||||
--level)
|
||||
COMPREPLY=( $( compgen -W '1 2 3 4 5 6' $cur ) )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
complete -F _chkconfig chkconfig
|
||||
###
|
||||
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# 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.
|
||||
@@ -0,0 +1,76 @@
|
||||
# cdfunc - example completion function for cd
|
||||
#
|
||||
# based on the cd completion function from the bash_completion package
|
||||
#
|
||||
# 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.
|
||||
|
||||
_comp_cd()
|
||||
{
|
||||
local IFS=$' \t\n' # normalize IFS
|
||||
local cur _skipdot _cdpath
|
||||
local i j k
|
||||
|
||||
# Tilde expansion, with side effect of expanding tilde to full pathname
|
||||
case "$2" in
|
||||
\~*) eval cur="$2" ;;
|
||||
*) cur=$2 ;;
|
||||
esac
|
||||
|
||||
# no cdpath or absolute pathname -- straight directory completion
|
||||
if [[ -z "${CDPATH:-}" ]] || [[ "$cur" == @(./*|../*|/*) ]]; then
|
||||
# compgen prints paths one per line; could also use while loop
|
||||
IFS=$'\n'
|
||||
COMPREPLY=( $(compgen -d -- "$cur") )
|
||||
IFS=$' \t\n'
|
||||
# CDPATH+directories in the current directory if not in CDPATH
|
||||
else
|
||||
IFS=$'\n'
|
||||
_skipdot=false
|
||||
# preprocess CDPATH to convert null directory names to .
|
||||
_cdpath=${CDPATH/#:/.:}
|
||||
_cdpath=${_cdpath//::/:.:}
|
||||
_cdpath=${_cdpath/%:/:.}
|
||||
for i in ${_cdpath//:/$'\n'}; do
|
||||
if [[ $i -ef . ]]; then _skipdot=true; fi
|
||||
k="${#COMPREPLY[@]}"
|
||||
for j in $( compgen -d -- "$i/$cur" ); do
|
||||
COMPREPLY[k++]=${j#$i/} # cut off directory
|
||||
done
|
||||
done
|
||||
$_skipdot || COMPREPLY+=( $(compgen -d -- "$cur") )
|
||||
IFS=$' \t\n'
|
||||
fi
|
||||
|
||||
# variable names if appropriate shell option set and no completions
|
||||
if shopt -q cdable_vars && [[ ${#COMPREPLY[@]} -eq 0 ]]; then
|
||||
COMPREPLY=( $(compgen -v -- "$cur") )
|
||||
fi
|
||||
|
||||
# append slash to passed directory name that is the only completion.
|
||||
# readline will not do this if we complete from CDPATH
|
||||
if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
|
||||
i=${COMPREPLY[0]} # shorthand
|
||||
if [[ "$cur" == "$i" ]] && [[ "$i" != "*/" ]]; then
|
||||
COMPREPLY[0]+=/
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -o filenames -o nospace -o bashdefault -F _comp_cd cd
|
||||
@@ -1,3 +1,22 @@
|
||||
#
|
||||
# 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()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
# 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[@]}"
|
||||
@@ -0,0 +1,43 @@
|
||||
#From: "Grigoriy Strokin" <grg@philol.msu.ru>
|
||||
#Newsgroups: comp.unix.shell
|
||||
#Subject: fast basename and dirname functions for BASH/SH
|
||||
#Date: Sat, 27 Dec 1997 21:18:40 +0300
|
||||
#
|
||||
#Please send your comments to grg@philol.msu.ru
|
||||
|
||||
function basename()
|
||||
{
|
||||
local name="${1##*/}"
|
||||
echo "${name%$2}"
|
||||
}
|
||||
|
||||
function dirname()
|
||||
{
|
||||
local dir="${1%${1##*/}}"
|
||||
[ "${dir:=./}" != "/" ] && dir="${dir%?}"
|
||||
echo "$dir"
|
||||
}
|
||||
|
||||
# Two additional functions:
|
||||
# 1) namename prints the basename without extension
|
||||
# 2) ext prints extension of a file, including "."
|
||||
|
||||
function namename()
|
||||
{
|
||||
local name=${1##*/}
|
||||
local name0="${name%.*}"
|
||||
echo "${name0:-$name}"
|
||||
}
|
||||
function ext()
|
||||
{
|
||||
local name=${1##*/}
|
||||
local name0="${name%.*}"
|
||||
local ext=${name0:+${name#$name0}}
|
||||
echo "${ext:-.}"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
# coprocess.bash
|
||||
#
|
||||
# vi:set sts=2 sw=2 ai:
|
||||
#
|
||||
|
||||
coprocess_pid=
|
||||
|
||||
#
|
||||
# coprocess - Start, control, and end coprocesses.
|
||||
#
|
||||
function coprocess ()
|
||||
{
|
||||
while (( $# > 0 )) ; do
|
||||
case "$1" in
|
||||
#
|
||||
# coprocess close
|
||||
#
|
||||
c|cl|clo|clos|close)
|
||||
shift
|
||||
exec 61>&- 62<&-
|
||||
coprocess_pid=
|
||||
if [ "$1" = "-SIGPIPE" ] ; then
|
||||
# Only print message in an interactive shell
|
||||
case "$-" in
|
||||
*i*)
|
||||
echo 'SIGPIPE' >&2
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
|
||||
#
|
||||
# coprocess open
|
||||
#
|
||||
o|op|ope|open)
|
||||
shift
|
||||
local fifo="/var/tmp/coprocess.$$.$RANDOM"
|
||||
|
||||
local cmd="/bin/bash"
|
||||
if (( $# > 0 )) ; then
|
||||
cmd="$@"
|
||||
fi
|
||||
|
||||
mkfifo "$fifo.in" || return $?
|
||||
mkfifo "$fifo.out" || {
|
||||
ret=$?
|
||||
rm -f "$fifo.in"
|
||||
return $?
|
||||
}
|
||||
|
||||
( "$@" <$fifo.in >$fifo.out ; rm -f "$fifo.in" "$fifo.out" ) &
|
||||
coprocess_pid=$!
|
||||
exec 61>$fifo.in 62<$fifo.out
|
||||
return 0
|
||||
;;
|
||||
|
||||
#
|
||||
# coprocess print - write to the coprocess
|
||||
#
|
||||
p|pr|pri|prin|print)
|
||||
shift
|
||||
local old_trap=$(trap -p SIGPIPE)
|
||||
trap 'coprocess close -SIGPIPE' SIGPIPE
|
||||
if [ $# -eq 1 ] && [ "$1" = "--stdin" ] ; then
|
||||
cat >&61
|
||||
else
|
||||
echo "$@" >&61
|
||||
fi
|
||||
local ret=$?
|
||||
eval "$old_trap"
|
||||
return $ret
|
||||
;;
|
||||
|
||||
#
|
||||
# coprocess read - read from the coprocess
|
||||
#
|
||||
r|re|rea|read)
|
||||
shift
|
||||
local old_trap=$(trap -p SIGPIPE)
|
||||
trap '_coprocess_close -SIGPIPE' SIGPIPE
|
||||
builtin read "$@" <&62
|
||||
local ret=$?
|
||||
eval "$old_trap"
|
||||
return $ret
|
||||
;;
|
||||
|
||||
s|st|sta|stat|statu|status)
|
||||
if [ -z "$coprocess_pid" ] ; then
|
||||
echo 'no active coprocess'
|
||||
return 1
|
||||
else
|
||||
echo " coprocess is active [$coprocess_pid]"
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
coprocess print "$@"
|
||||
return $?
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
coprocess status
|
||||
return $?
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
Date: Fri, 21 Sep 2001 14:50:29 -0400
|
||||
From: "Jason M. Felice" <jfelice@cronosys.com>
|
||||
To: bash-maintainers@gnu.org, chet@po.cwru.edu
|
||||
Subject: Bash co-processes functions
|
||||
Message-ID: <20010921145029.A6093@argo.eraserhead.net>
|
||||
Mime-Version: 1.0
|
||||
|
||||
Attached to this message you will find coprocess.bash and coshell.bash.
|
||||
Here's a brief synopsis of use:
|
||||
|
||||
coprocess open telnet localhost
|
||||
while coprocess read il ; do
|
||||
echo "$il"
|
||||
case "$il" in
|
||||
*ogin:*)
|
||||
coprocess print 'user'
|
||||
;;
|
||||
*ord:*)
|
||||
echo 'pass' |coprocess print --stdin
|
||||
;;
|
||||
*$ *)
|
||||
coprocess print 'exit'
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
coprocess close
|
||||
|
||||
And here's an example of the coshell function:
|
||||
|
||||
coshell open ssh -l root otherbox
|
||||
coshell eval hostname
|
||||
coshell ls -l
|
||||
if coshell test -d /tmp ; then echo 'otherbox has a /tmp!' ; fi
|
||||
|
||||
coshell sendfile /var/lib/upgrade.rpm /tmp/test.rpm || exit $?
|
||||
coshell eval rpm -ivh /tmp/test.rpm || exit $?
|
||||
coshell eval rm -f /tmp/test.rpm || exit $?
|
||||
coshell close
|
||||
exit 0
|
||||
|
||||
There are a few minor issues that I'd like to work out, but it works well
|
||||
enough for me ;-) The issues are:
|
||||
|
||||
- Shell quoting issue with 'coshell eval' commands - need to somehow
|
||||
re-quote words.
|
||||
- Interactive commands hang 'coshell eval', tried redirecting in </dev/null
|
||||
to executed command, but it caused strange shell exit problems.
|
||||
- Some way to copy stdin from local coshell eval to remote shell. Probably
|
||||
logically impossible, but would be wonderfully useful.
|
||||
|
||||
I'm using it for writing scripts to publish websites and other scripts to
|
||||
co-located servers.
|
||||
@@ -0,0 +1,127 @@
|
||||
# vi:set sts=2 sw=2 ai:
|
||||
#
|
||||
# coshell.bash - Control shell coprocesses (see coprocess.bash).
|
||||
#
|
||||
|
||||
function coshell ()
|
||||
{
|
||||
while (( $# > 0 )) ; do
|
||||
case "$1" in
|
||||
#
|
||||
# coshell open
|
||||
#
|
||||
o|op|ope|open)
|
||||
shift
|
||||
coprocess open "$@"
|
||||
local ret=$?
|
||||
|
||||
# This should eat any ssh error messages or what not.
|
||||
coshell eval : >/dev/null 2>&1
|
||||
return $ret
|
||||
;;
|
||||
|
||||
#
|
||||
# coshell close
|
||||
#
|
||||
c|cl|clo|close)
|
||||
shift
|
||||
coprocess close "$@"
|
||||
return $?
|
||||
;;
|
||||
|
||||
#
|
||||
# coshell eval
|
||||
#
|
||||
e|ev|eva|eval)
|
||||
shift
|
||||
local cookie=$RANDOM
|
||||
if (( $# == 0 )) ; then
|
||||
echo "coshell eval: no argumentsl" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ x$coprocess_pid = x ] ; then
|
||||
echo "coshell eval: no active coshell" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
coprocess print "$@"
|
||||
coprocess print "coprocess_rc=\$?"
|
||||
coprocess print "printf 'coprocess-$cookie----\n%d\n' \$coprocess_rc"
|
||||
if [ x$coprocess_pid = x ] ; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local ol
|
||||
while coprocess read ol ; do
|
||||
case "$ol" in
|
||||
*coprocess-$cookie----*)
|
||||
ol="${ol%coprocess-$cookie----}"
|
||||
echo -n "$ol"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
echo "$ol"
|
||||
done
|
||||
coprocess read ol
|
||||
return $ol
|
||||
;;
|
||||
|
||||
#
|
||||
# coshell sendfile
|
||||
#
|
||||
s|se|sen|send|sendf|sendfi|sendfil|sendfile)
|
||||
shift
|
||||
if (( $# != 2 )) ; then
|
||||
echo "coshell sendfile: syntax is 'coshell sendfile SRC TARGET'" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ x$coprocess_pid = x ] ; then
|
||||
echo "coshell sendfile: no active coshell" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local target=$2
|
||||
if coshell test -d "$target" ; then
|
||||
target="$target/${1##*/}"
|
||||
fi
|
||||
|
||||
coprocess print "uudecode <<END_OF_FILE"
|
||||
uuencode -m "$target" <$1 |coprocess print --stdin
|
||||
coshell eval "END_OF_FILE"
|
||||
return $?
|
||||
;;
|
||||
|
||||
#
|
||||
# coshell getfile
|
||||
#
|
||||
g|ge|get|getf|getfi|getfil|getfile)
|
||||
shift
|
||||
if (( $# != 2 )) ; then
|
||||
echo "coshell getfile: syntax is 'coshell getfile SRC TARGET'" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ x$coprocess_pid = x ] ; then
|
||||
echo "coshell getfile: no active coshell" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local target=$2
|
||||
if test -d "$target" ; then
|
||||
target="$target/${1##*/}"
|
||||
fi
|
||||
|
||||
coshell eval uuencode -m "$target" "<" "$1" |uudecode
|
||||
return $?
|
||||
;;
|
||||
|
||||
*)
|
||||
coshell eval "$@"
|
||||
return $?
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
coprocess status
|
||||
return $?
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
#
|
||||
# Directory manipulation functions from the book 'The Korn Shell'
|
||||
# Modified for use with bash Mon Apr 18 08:37 1994 by
|
||||
# Ken Konecki (kenk@wfg.com)
|
||||
#
|
||||
# Modified by Chet Ramey
|
||||
#
|
||||
# This could stand to have calls to `select' added back in
|
||||
#
|
||||
|
||||
alias integer="declare -i"
|
||||
|
||||
integer _push_max=${CDSTACK-31} _push_top=${CDSTACK-31}
|
||||
|
||||
unalias cd
|
||||
# alias cd=_cd
|
||||
|
||||
# Display directory stack -- $HOME display as ~
|
||||
dirs()
|
||||
{
|
||||
dir="${PWD#$HOME/}"
|
||||
case $dir in
|
||||
$HOME) dir=\~ ;;
|
||||
/*) ;;
|
||||
*) dir=\~/$dir ;;
|
||||
esac
|
||||
|
||||
integer i=_push_top
|
||||
integer n=1
|
||||
|
||||
echo "$n) $dir"
|
||||
while let "i < $_push_max"
|
||||
do
|
||||
n=n+1
|
||||
eval "echo \$n\) \$_push_stack_$i"
|
||||
i=i+1
|
||||
done
|
||||
}
|
||||
|
||||
# Change directory and put directory on front of stack
|
||||
cd()
|
||||
{
|
||||
typeset dir=
|
||||
integer n=0 type=4 i
|
||||
case $1 in
|
||||
-|-1|2) # cd -
|
||||
n=_push_top type=1
|
||||
;;
|
||||
-[1-9]|-[1-9][0-9]) # cd -n
|
||||
n=_push_top+${1#-}-1 type=2
|
||||
;;
|
||||
|
||||
1) # keep present directory
|
||||
echo "$PWD"
|
||||
return
|
||||
;;
|
||||
|
||||
[2-9]|[1-9][0-9]) # cd n
|
||||
n=_push_top+${1}-2 type=2
|
||||
;;
|
||||
|
||||
*)
|
||||
if let "_push_top <= 0"; then
|
||||
type=3 n=_push_max
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if let "type < 3"; then
|
||||
if let "n >= _push_max"; then
|
||||
echo cd: Directory stack not that deep
|
||||
return 1
|
||||
else
|
||||
eval dir=\${_push_stack_$n}
|
||||
fi
|
||||
fi
|
||||
|
||||
case $dir in
|
||||
~*) dir=$HOME${dir#\~} ;;
|
||||
esac
|
||||
|
||||
cd2 ${dir:-$@} > /dev/null || return 1
|
||||
dir=${OLDPWD#$HOME/}
|
||||
case $dir in
|
||||
$HOME) dir=\~ ;;
|
||||
/*) ;;
|
||||
*) dir=\~/$dir ;;
|
||||
esac
|
||||
|
||||
case $type in
|
||||
1) # swap first two elements
|
||||
eval _push_stack_$_push_top=\$dir ;;
|
||||
|
||||
2|3) # put $dir on top and shift down by one until top
|
||||
i=_push_top
|
||||
unset _dirlist
|
||||
while let "i < $_push_max" ; do
|
||||
eval _dirlist=\"\$_dirlist \$_push_stack_$i\"
|
||||
i=i+1
|
||||
done
|
||||
|
||||
i=_push_top
|
||||
for dir in "$dir" ${_dirlist} ; do
|
||||
let "i > n" && break
|
||||
eval _push_stack_$i=\$dir
|
||||
i=i+1
|
||||
done
|
||||
;;
|
||||
4) # push name
|
||||
_push_top=_push_top-1;
|
||||
eval _push_stack_$_push_top=\$dir
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$PWD"
|
||||
|
||||
}
|
||||
|
||||
# Menu-driven change directory command
|
||||
function mcd
|
||||
{
|
||||
dirs
|
||||
echo -n "Select by number or enter a name: "
|
||||
read
|
||||
cd $REPLY
|
||||
}
|
||||
|
||||
|
||||
# Emulate ksh cd substitution
|
||||
cd2()
|
||||
{
|
||||
case "$#" in
|
||||
0) builtin cd "$HOME" ;;
|
||||
1) builtin cd "$1" ;;
|
||||
2) newDir=$(echo $PWD | sed -e "s:$1:$2:g")
|
||||
case "$newDir" in
|
||||
$PWD) echo "bash:: cd: bad substitution" >&2 ; return 1 ;;
|
||||
*) builtin cd "$newDir" ;;
|
||||
esac ;;
|
||||
*) echo "bash: cd: wrong arg count" 1>&2 ; return 1 ;;
|
||||
esac
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
#Derived from:
|
||||
#
|
||||
#From: damercer@mmm.com (Dan Mercer)
|
||||
#Newsgroups: comp.unix.admin,comp.unix.shell,comp.unix.programmer,comp.sys.sun.admin
|
||||
#Subject: Re: Command to find out if a directory is empty
|
||||
#Date: 17 Aug 2000 14:35:56 GMT
|
||||
#Message-ID: <8ngt8c$fmr$1@magnum.mmm.com>
|
||||
|
||||
# usage: emptydir [dirname] ; default dirname is "."
|
||||
|
||||
emptydir()
|
||||
{
|
||||
typeset file dir=${1:-.}
|
||||
[[ -d $dir ]] || {
|
||||
echo "$FUNCNAME: $dir is not a directory" >&2
|
||||
return 2
|
||||
}
|
||||
for file in $dir/.* $dir/*
|
||||
do
|
||||
case ${file#$dir/} in
|
||||
.|..) ;;
|
||||
\*) [[ -e $file ]];let $?;return;;
|
||||
*) return 1;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
@@ -2,6 +2,24 @@
|
||||
# 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
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#
|
||||
# A function that works as a front end for both stty and the `bind'
|
||||
# builtin, so the tty driver and readline see the same changes
|
||||
#
|
||||
|
||||
#
|
||||
# Convert between the stty ^H control character form and the readline \C-H
|
||||
# form
|
||||
#
|
||||
cvt()
|
||||
{
|
||||
echo "$@" | cat -v | sed 's/\^/\\C-/'
|
||||
}
|
||||
|
||||
#
|
||||
# stty front-end. Parses the argument list and creates two command strings,
|
||||
# one for stty, another for bind.
|
||||
#
|
||||
fstty()
|
||||
{
|
||||
local cmd="" bargs=""
|
||||
local e
|
||||
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
-a) cmd="$cmd everything"
|
||||
;;
|
||||
erase) shift;
|
||||
e=$(cvt "$1")
|
||||
cmd="$cmd erase $1"
|
||||
bargs="$bargs '\"$e\": backward-delete-char'"
|
||||
;;
|
||||
kill) shift
|
||||
e=$(cvt "$1")
|
||||
cmd="$cmd kill $1"
|
||||
bargs="$bargs '\"$e\": unix-line-discard'"
|
||||
;;
|
||||
werase) shift;
|
||||
e=$(cvt "$1")
|
||||
cmd="$cmd erase $1"
|
||||
bargs="$bargs '\"$e\": backward-kill-word'"
|
||||
;;
|
||||
lnext) shift;
|
||||
e=$(cvt "$1")
|
||||
cmd="$cmd erase $1"
|
||||
bargs="$bargs '\"$e\": quoted-insert'"
|
||||
;;
|
||||
*) cmd="$cmd $1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
command stty $cmd
|
||||
if [ -n "$bargs" ]; then
|
||||
builtin bind $bargs
|
||||
fi
|
||||
}
|
||||
+18
-2
@@ -3,8 +3,24 @@
|
||||
#
|
||||
# usage: func name [name ...]
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@ins.CWRU.Edu
|
||||
# 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
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# func -- print out definitions for functions named by arguments
|
||||
#
|
||||
# usage: func name [name ...]
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@ins.CWRU.Edu
|
||||
func()
|
||||
{
|
||||
local status=0
|
||||
|
||||
if [ $# -eq 0 ] ; then
|
||||
echo "usage: func name [name...]" 1>&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
for f
|
||||
do
|
||||
if [ "$(builtin type -type $f)" != "function" ] ; then
|
||||
echo "func: $f: not a function" 1>&2
|
||||
status=1 # one failed
|
||||
continue
|
||||
fi
|
||||
builtin type $f | sed 1d
|
||||
done
|
||||
return $status
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# get_html -- get a web page from a remote server
|
||||
#
|
||||
# Original Author: Jeff Korn <jlk@cs.princeton.edu>
|
||||
# Modified for bash by Chet Ramey <chet@po.cwru.edu>
|
||||
#
|
||||
# Example: get_html cnswww.cns.cwru.edu /~chet/ | more
|
||||
|
||||
get_html()
|
||||
{
|
||||
local host port
|
||||
|
||||
(($# < 2)) && {
|
||||
echo "usage: $FUNCNAME hostname path [port]" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
host="$1"
|
||||
port="${3:-80}"
|
||||
|
||||
exec 3<> /dev/tcp/$host/$port || {
|
||||
echo "$FUNCNAME: $host/$port: cannot connect" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo -e "GET $2 HTTP/1.0\n" >&3
|
||||
|
||||
cat <&3
|
||||
|
||||
exec 3<&-
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
get_html "$@"
|
||||
@@ -0,0 +1,301 @@
|
||||
#From: "Grigoriy Strokin" <grg@philol.msu.ru>
|
||||
#Newsgroups: comp.unix.shell
|
||||
#Subject: BASH: getopt function that parses long-named options
|
||||
#Date: Mon, 22 Dec 1997 20:35:18 +0300
|
||||
|
||||
#Hi, I have written a BASH function named getoptex, that is like bash builtin
|
||||
#"getopts", but does parse long-named options and optional arguments. It only
|
||||
#uses builtin bash commands, so it is very fast. In order to use it in your
|
||||
#bash scripts, include a command ". getopt.sh" (<dot> getopt.sh) to the file
|
||||
#containing your script, and that will define functions getopt, getoptex, and
|
||||
#optlistex (the file getopt.sh with its detailed description is listed
|
||||
#below).
|
||||
|
||||
#*** file getopt.sh ***
|
||||
|
||||
#! /bin/bash
|
||||
#
|
||||
# getopt.sh:
|
||||
# functions like getopts but do long-named options parsing
|
||||
# and support optional arguments
|
||||
#
|
||||
# Version 1.0 1997 by Grigoriy Strokin (grg@philol.msu.ru), Public Domain
|
||||
# Date created: December 21, 1997
|
||||
# Date modified: December 21, 1997
|
||||
#
|
||||
# IMPORTANT FEATURES
|
||||
#
|
||||
# 1) Parses both short and long-named options
|
||||
# 2) Supports optional arguments
|
||||
# 3) Only uses bash builtins, thus no calls to external
|
||||
# utilities such as expr or sed is done. Therefore,
|
||||
# parsing speed is high enough
|
||||
#
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# FUNCTION getopt
|
||||
# Usage: getopt OPTLIST {"$@"|ALTERNATIVE_PARAMETERS}
|
||||
#
|
||||
# like getopts, but parse options with both required and optional arguments,
|
||||
# Options with optional arguments must have "." instead of ":" after them.
|
||||
# Furthemore, a variable name to place option name cannot be specified
|
||||
# and is always placed in OPTOPT variable
|
||||
#
|
||||
# This function is provided for compatibility with getopts()
|
||||
# OPTLIST style, and it actually calls getoptex (see bellow)
|
||||
#
|
||||
# NOTE that a list of parameters is required and must be either "$@",
|
||||
# if processing command line arguments, or some alternative parameters.
|
||||
#
|
||||
# FUNCTION getoptex
|
||||
# Usage: getoptex OPTION_LIST {"$@"|ALTERNATIVE_PARAMETERS}
|
||||
#
|
||||
# like getopts, but parse long-named options.
|
||||
#
|
||||
# Both getopt and getoptex return 0 if an option has been parsed,
|
||||
# and 1 if all options are already parsed or an error occured
|
||||
#
|
||||
# Both getopt and getoptex set or test the following variables:
|
||||
#
|
||||
# OPTERR -- tested for whether error messages must be given for invalid
|
||||
options
|
||||
#
|
||||
# OPTOPT -- set to the name of an option parsed,
|
||||
# or to "?" if no more options or error
|
||||
# OPTARG -- set to the option argument, if any;
|
||||
# unset if ther is no argument;
|
||||
# on error, set to the erroneous option name
|
||||
#
|
||||
# OPTIND -- Initialized to 1.
|
||||
# Then set to the number of the next parameter to be parsed
|
||||
# when getopt or getoptex will be called next time.
|
||||
# When all options are parsed, contains a number of
|
||||
# the first non-option argument.
|
||||
#
|
||||
#
|
||||
# OPTOFS -- If a parameter number $OPTIND containg an option parsed
|
||||
# does not contain any more options, OPTOFS is unset;
|
||||
# otherwise, OPTOFS is set to such a number of "?" signs
|
||||
# which is equal to the number of options parsed
|
||||
#
|
||||
# You might not set variables OPTIND and OPTOFS yourself
|
||||
# unless you want to parse a list of parameters more than once.
|
||||
# Otherwise, you whould unset OPTIND (or set it to 1)
|
||||
# and unset OPTOFS each time you want to parse a new parameters
|
||||
list
|
||||
#
|
||||
# Option list format is DIFFERENT from one for getopts or getopt.
|
||||
getopts-style
|
||||
# option list can be converted to getoptex-style using a function optlistex
|
||||
# (see bellow)
|
||||
#
|
||||
# DESCRIPTION of option list used with getoptex:
|
||||
# Option names are separated by whitespace. Options consiting of
|
||||
# more than one character are treated as long-named (--option)
|
||||
#
|
||||
# Special characters can appear at the and of option names specifying
|
||||
# whether an argument is required (default is ";"):
|
||||
# ";" (default) -- no argument
|
||||
# ":" -- required argument
|
||||
# "," -- optional argument
|
||||
#
|
||||
# For example, an option list "a b c help version f: file: separator."
|
||||
# defines the following options:
|
||||
# -a, -b, -c, --help, --version -- no argument
|
||||
# -f, --file -- argument required
|
||||
# --separator -- optional argument
|
||||
#
|
||||
# FUNCTION optlistex
|
||||
# Usage new_style_optlist=`optlistex OLD_STYLE_OPTLIST`
|
||||
#
|
||||
# Converts getopts-style option list in a format suitable for use with getoptex
|
||||
# Namely, it inserts spaces after each option name.
|
||||
#
|
||||
#
|
||||
# HOW TO USE
|
||||
#
|
||||
# In order o use in your bash scripts the functions described,
|
||||
# include a command ". getopt.sh" to the file containing the script,
|
||||
# which will define functions getopt, getoptex, and optlistex
|
||||
#
|
||||
# EXAMPLES
|
||||
#
|
||||
# See files 'getopt1' and 'getopt2' that contain sample scripts that use
|
||||
# getopt and getoptex functions respectively
|
||||
#
|
||||
#
|
||||
# Please send your comments to grg@philol.msu.ru
|
||||
|
||||
function getoptex()
|
||||
{
|
||||
let $# || return 1
|
||||
local optlist="${1#;}"
|
||||
let OPTIND || OPTIND=1
|
||||
[ $OPTIND -lt $# ] || return 1
|
||||
shift $OPTIND
|
||||
if [ "$1" != "-" ] && [ "$1" != "${1#-}" ]
|
||||
then OPTIND=$(( OPTIND+1 )); if [ "$1" != "--" ]
|
||||
then
|
||||
local o
|
||||
o="-${1#-$OPTOFS}"
|
||||
for opt in ${optlist#;}
|
||||
do
|
||||
OPTOPT="${opt%[;.:]}"
|
||||
unset OPTARG
|
||||
local opttype="${opt##*[^;:.]}"
|
||||
[ -z "$opttype" ] && opttype=";"
|
||||
if [ ${#OPTOPT} -gt 1 ]
|
||||
then # long-named option
|
||||
case $o in
|
||||
"--$OPTOPT")
|
||||
if [ "$opttype" != ":" ]; then return 0; fi
|
||||
OPTARG="$2"
|
||||
if [ -z "$OPTARG" ];
|
||||
then # error: must have an agrument
|
||||
let OPTERR && echo "$0: error: $OPTOPT must have an argument" >&2
|
||||
OPTARG="$OPTOPT";
|
||||
OPTOPT="?"
|
||||
return 1;
|
||||
fi
|
||||
OPTIND=$(( OPTIND+1 )) # skip option's argument
|
||||
return 0
|
||||
;;
|
||||
"--$OPTOPT="*)
|
||||
if [ "$opttype" = ";" ];
|
||||
then # error: must not have arguments
|
||||
let OPTERR && echo "$0: error: $OPTOPT must not have arguments" >&2
|
||||
OPTARG="$OPTOPT"
|
||||
OPTOPT="?"
|
||||
return 1
|
||||
fi
|
||||
OPTARG=${o#"--$OPTOPT="}
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
else # short-named option
|
||||
case "$o" in
|
||||
"-$OPTOPT")
|
||||
unset OPTOFS
|
||||
[ "$opttype" != ":" ] && return 0
|
||||
OPTARG="$2"
|
||||
if [ -z "$OPTARG" ]
|
||||
then
|
||||
echo "$0: error: -$OPTOPT must have an argument" >&2
|
||||
OPTARG="$OPTOPT"
|
||||
OPTOPT="?"
|
||||
return 1
|
||||
fi
|
||||
OPTIND=$(( OPTIND+1 )) # skip option's argument
|
||||
return 0
|
||||
;;
|
||||
"-$OPTOPT"*)
|
||||
if [ $opttype = ";" ]
|
||||
then # an option with no argument is in a chain of options
|
||||
OPTOFS="$OPTOFS?" # move to the next option in the chain
|
||||
OPTIND=$(( OPTIND-1 )) # the chain still has other options
|
||||
return 0
|
||||
else
|
||||
unset OPTOFS
|
||||
OPTARG="${o#-$OPTOPT}"
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
echo "$0: error: invalid option: $o"
|
||||
fi; fi
|
||||
OPTOPT="?"
|
||||
unset OPTARG
|
||||
return 1
|
||||
}
|
||||
function optlistex
|
||||
{
|
||||
local l="$1"
|
||||
local m # mask
|
||||
local r # to store result
|
||||
while [ ${#m} -lt $(( ${#l}-1 )) ]; do m="$m?"; done # create a "???..." mask
|
||||
while [ -n "$l" ]
|
||||
do
|
||||
r="${r:+"$r "}${l%$m}" # append the first character of $l to $r
|
||||
l="${l#?}" # cut the first charecter from $l
|
||||
m="${m#?}" # cut one "?" sign from m
|
||||
if [ -n "${l%%[^:.;]*}" ]
|
||||
then # a special character (";", ".", or ":") was found
|
||||
r="$r${l%$m}" # append it to $r
|
||||
l="${l#?}" # cut the special character from l
|
||||
m="${m#?}" # cut one more "?" sign
|
||||
fi
|
||||
done
|
||||
echo $r
|
||||
}
|
||||
function getopt()
|
||||
{
|
||||
local optlist=`optlistex "$1"`
|
||||
shift
|
||||
getoptex "$optlist" "$@"
|
||||
return $?
|
||||
}
|
||||
|
||||
#**************************************
|
||||
# cut here
|
||||
#**************************************
|
||||
#*** (end of getopt.sh) ***
|
||||
|
||||
|
||||
#*** file getopt1 ***
|
||||
|
||||
#! /bin/bash
|
||||
# getopt1:
|
||||
# Sample script using the function getopt
|
||||
#
|
||||
# Type something like "getopt1 -ab -d 10 -e20 text1 text2"
|
||||
# on the command line to see how it works
|
||||
#
|
||||
# See getopt.sh for more information
|
||||
#. getopt.sh
|
||||
#echo Using getopt to parse arguments:
|
||||
#while getopt "abcd:e." "$@"
|
||||
#do
|
||||
# echo "Option <$OPTOPT> ${OPTARG:+has an arg <$OPTARG>}"
|
||||
#done
|
||||
#shift $(( OPTIND-1 ))
|
||||
#for arg in "$@"
|
||||
#do
|
||||
# echo "Non option argument <$arg>"
|
||||
#done
|
||||
#
|
||||
#**************************************
|
||||
# cut here
|
||||
#**************************************
|
||||
#*** (end of getopt1) ***
|
||||
#
|
||||
#
|
||||
#*** file getopt2 ***
|
||||
#
|
||||
#! /bin/bash
|
||||
# getopt2:
|
||||
# Sample script using the function getoptex
|
||||
#
|
||||
# Type something like "getopt2 -ab -d 10 -e20 --opt1 --opt4=100 text1 text2"
|
||||
# to see how it works
|
||||
#
|
||||
# See getopt.sh for more information
|
||||
. getopt.sh
|
||||
#echo Using getoptex to parse arguments:
|
||||
#while getoptex "a; b; c; d: e. opt1 opt2 opt3 opt4: opt5." "$@"
|
||||
#do
|
||||
# echo "Option <$OPTOPT> ${OPTARG:+has an arg <$OPTARG>}"
|
||||
#done
|
||||
#shift $(( OPTIND-1 ))
|
||||
#for arg in "$@"
|
||||
#do
|
||||
# echo "Non option argument <$arg>"
|
||||
#done
|
||||
#
|
||||
#**************************************
|
||||
# cut here
|
||||
#**************************************
|
||||
#*** (end of getopt2) ***
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#
|
||||
# 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
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#From: jrmartin@rainey.blueneptune.com (James R. Martin)
|
||||
#Newsgroups: comp.unix.shell
|
||||
#Subject: Re: testing user input on numeric or character value
|
||||
#Date: 26 Nov 1997 01:28:43 GMT
|
||||
|
||||
# isnum returns True if its argument is a valid number,
|
||||
# and False (retval=1) if it is any other string.
|
||||
# The first pattern requires a digit before the decimal
|
||||
# point, and the second after the decimal point.
|
||||
|
||||
# BASH NOTE: make sure you have executed `shopt -s extglob' before
|
||||
# trying to use this function, or it will not work
|
||||
|
||||
isnum() # string
|
||||
{
|
||||
case $1 in
|
||||
?([-+])+([0-9])?(.)*([0-9])?([Ee]?([-+])+([0-9])) )
|
||||
return 0;;
|
||||
?([-+])*([0-9])?(.)+([0-9])?([Ee]?([-+])+([0-9])) )
|
||||
return 0;;
|
||||
*) return 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
isnum2() # string
|
||||
{
|
||||
case $1 in
|
||||
?([-+])+([[:digit:]])?(.)*([[:digit:]])?([Ee]?([-+])+([[:digit:]])) )
|
||||
return 0;;
|
||||
?([-+])*([[:digit:]])?(.)+([[:digit:]])?([Ee]?([-+])+([[:digit:]])) )
|
||||
return 0;;
|
||||
*) return 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
isint() # string
|
||||
{
|
||||
case $1 in
|
||||
?([-+])+([0-9]) )
|
||||
return 0;;
|
||||
*) return 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
isint2() # string
|
||||
{
|
||||
case $1 in
|
||||
?([-+])+([[:digit:]]) )
|
||||
return 0;;
|
||||
*) return 1;;
|
||||
esac
|
||||
}
|
||||
@@ -1,3 +1,22 @@
|
||||
#
|
||||
# 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
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#From: damatex@CAM.ORG (Mario Boudreault)
|
||||
#Newsgroups: comp.unix.shell
|
||||
#Subject: JULIAN DATE CONVERSION SUB
|
||||
#Date: 4 Aug 1995 10:23:28 -0400
|
||||
#Message-ID: <3vtah0$jb3@ocean.CAM.ORG>
|
||||
|
||||
#For those using shells and who want to convert dates to a julian number
|
||||
#here is a shell script (wihtout validation) that can be used as a base
|
||||
#program for your shell scripts.
|
||||
|
||||
#Special thanks to Ed Ferguson@ti.com who sent me the algorithm to compute
|
||||
#that date.
|
||||
|
||||
#
|
||||
# MODIFIED BY CHET RAMEY TO CONVERT TO bash v2 SYNTAX
|
||||
#
|
||||
|
||||
# cnvdate - Conversion de dates en julienne et vice et versa...
|
||||
#
|
||||
# Par : Mario Boudreault Damatex Inc Montreal, Canada
|
||||
# Date: 2 Aout 1995
|
||||
# Rev.: 2 Aout 1995
|
||||
#
|
||||
# Usage:
|
||||
# cvdate [-j] YYYMMDD pour convertir en nbre de jours
|
||||
# cvdate -d {julian number} pour convertir en AAAAMMJJ
|
||||
#
|
||||
|
||||
jul_date()
|
||||
{
|
||||
#
|
||||
# Separe ANNEE, MOIS et JOUR...
|
||||
#
|
||||
YEAR=`echo $DATE | awk ' { print substr($0,1,4) } '`
|
||||
MONTH=`echo $DATE | awk ' { print substr($0,5,2) } '`
|
||||
DAY=`echo $DATE | awk ' { print substr($0,7,2) } '`
|
||||
#
|
||||
# Execute la formule magique...
|
||||
#
|
||||
A=$(( $DAY - 32075 + 1461 * ( $YEAR + 4800 - ( 14 - $MONTH ) / 12 ) \
|
||||
/ 4 + 367 * ( $MONTH - 2 + ( 14 - $MONTH ) / 12 * 12 ) / 12 - \
|
||||
3 * ( ( $YEAR + 4900 - ( 14 - $MONTH ) / 12 ) / 100 ) / 4 ))
|
||||
echo $A
|
||||
}
|
||||
|
||||
day_date()
|
||||
{
|
||||
TEMP1=$(( $DATE + 68569 ))
|
||||
TEMP2=$(( 4 * $TEMP1 / 146097 ))
|
||||
TEMP1=$(( $TEMP1 - ( 146097 * $TEMP2 + 3 ) / 4 ))
|
||||
Y=$(( 4000 * ( $TEMP1 + 1 ) / 1461001 ))
|
||||
TEMP1=$(( $TEMP1 - 1461 * $Y / 4 + 31 ))
|
||||
M=$(( 80 * $TEMP1 / 2447 ))
|
||||
D=$(( $TEMP1 - 2447 * $M / 80 ))
|
||||
TEMP1=$(( $M / 11 ))
|
||||
M=$(( $M + 2 - 12 * $TEMP1 ))
|
||||
Y=$(( 100 * ( $TEMP2 - 49 ) + $Y + $TEMP1 ))
|
||||
M=`echo $M | awk ' { M=$0 ; if ( length($0) == 1 ) M="0"$0 } END { print M } '`
|
||||
D=`echo $D | awk ' { D=$0 ; if ( length($0) == 1 ) D="0"$0 } END { print D } '`
|
||||
echo $Y$M$D
|
||||
}
|
||||
|
||||
# main()
|
||||
|
||||
if [ $# -eq 1 ]; then
|
||||
DATE=$1
|
||||
jul_date
|
||||
elif [ "$1" = '-j' ]; then
|
||||
DATE=$2
|
||||
jul_date
|
||||
elif [ "$1" = '-d' ]; then
|
||||
DATE=$2
|
||||
day_date
|
||||
fi
|
||||
#
|
||||
# Termine
|
||||
#
|
||||
exit 0
|
||||
@@ -0,0 +1,12 @@
|
||||
jj ()
|
||||
{
|
||||
p=$(jobs $1);
|
||||
echo $p
|
||||
|
||||
case "$p" in
|
||||
[*) echo matches '[*'
|
||||
;;
|
||||
*) echo not a match\?
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
# From: Seth Chaiklin <psykseth@aau.dk>
|
||||
# To: chet@ins.CWRU.Edu
|
||||
# Subject: bash functions (sorta)
|
||||
|
||||
#
|
||||
# keep:
|
||||
# usage: keep program
|
||||
# declare the a program should be "kept". i.e. try to fg a stopped one
|
||||
# and only when that fails start a fresh program.
|
||||
#
|
||||
|
||||
keep()
|
||||
{
|
||||
case $# in
|
||||
1|2) ;;
|
||||
*) echo "usage: keep [alias] program" 1>&2 ; return 1;;
|
||||
esac
|
||||
|
||||
# progname
|
||||
pn=${1##*/}
|
||||
|
||||
# set up an alias for the kept program
|
||||
if [ $# = 1 ]; then
|
||||
alias "$pn=fg $1 2>/dev/null || $1"
|
||||
else
|
||||
alias "$1=fg $2 2>/dev/null || $2"
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# unkeep:
|
||||
# usage: unkeep program
|
||||
# unset the alias set up by the keep function
|
||||
#
|
||||
|
||||
unkeep()
|
||||
{
|
||||
if [ $# != 1 ]; then
|
||||
echo "usage: unkeep program"
|
||||
return 2
|
||||
fi
|
||||
|
||||
# unset the alias for the kept program
|
||||
unalias "${1##*/}"
|
||||
}
|
||||
|
||||
#
|
||||
# kept:
|
||||
# lists all kept programs in 'alias: program' form
|
||||
#
|
||||
|
||||
kept()
|
||||
{
|
||||
alias | grep "fg.*2>" | sed "s/alias \(.*\)='fg.*||\(.*\)'$/\1:\2/"
|
||||
}
|
||||
|
||||
|
||||
# some things that should be kept
|
||||
#keep /usr/local/bin/emacs
|
||||
#keep e ${EDITOR:-/usr/local/bin/emacs}
|
||||
#keep edit ${EDITOR:-/usr/local/bin/emacs}
|
||||
#keep /usr/local/bin/emm
|
||||
@@ -1,3 +1,22 @@
|
||||
#
|
||||
# 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]]
|
||||
#
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# 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
|
||||
}
|
||||
@@ -1,4 +1,22 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# 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 $?
|
||||
@@ -5,6 +5,24 @@
|
||||
# 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",
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
#
|
||||
# .kshenv -- functions and aliases to provide the beginnings of a ksh
|
||||
# environment for bash.
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@ins.CWRU.Edu
|
||||
#
|
||||
#
|
||||
# These are definitions for the ksh compiled-in `exported aliases'. There
|
||||
# are others, but we already have substitutes for them: "history", "type",
|
||||
# and "hash".
|
||||
#
|
||||
alias r="fc -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
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from
|
||||
# @(#) lowercase.ksh 1.0 92/10/08
|
||||
# 92/10/08 john h. dubois iii (john@armory.com)
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
lowercase()
|
||||
{
|
||||
for file; do
|
||||
[ -f "$file" ] || continue
|
||||
filename=${file##*/}
|
||||
case "$file" in
|
||||
*/*) dirname=${file%/*} ;;
|
||||
*) dirname=.;;
|
||||
esac
|
||||
nf=$(echo $filename | tr A-Z a-z)
|
||||
newname="${dirname}/${nf}"
|
||||
if [ "$nf" != "$filename" ]; then
|
||||
mv "$file" "$newname"
|
||||
echo "lowercase: $file -> $newname"
|
||||
else
|
||||
echo "lowercase: $file not changed."
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
# Written from scratch by Tom Tromey (tromey@cns.caltech.edu)
|
||||
#
|
||||
# manpage -- find and print a manual page.
|
||||
# usage: manpage section name [printing]
|
||||
#
|
||||
function manpage ()
|
||||
{
|
||||
local i h cmd zot sec
|
||||
local num="$1"
|
||||
local page="$2"
|
||||
local printing="$3"
|
||||
local mp
|
||||
|
||||
mp="${MANPATH:-/usr/man}"
|
||||
if [ "$#" -lt 2 ]; then return 1; fi # should print usage
|
||||
if [ "$num" != "" ]; then
|
||||
sec="${num%%[a-zA-Z]*}"
|
||||
else
|
||||
sec='[168234571lnpo]'
|
||||
num="$sec"
|
||||
fi
|
||||
for i in $(echo "$mp" | tr : ' '); do
|
||||
if [ ! -d "$i" ]; then continue; fi
|
||||
file="$i"/man"$sec"/"$page"."$num"*
|
||||
set $file
|
||||
file="$1"
|
||||
if [ -f "$file" ]; then
|
||||
zot=$(sed 1q "$file")
|
||||
cmd=${MANROFF:-"nroff -man - | col | cat -s"}
|
||||
h=${zot##"'"'\"'}
|
||||
if [ "$h" != "$zot" ]; then
|
||||
while [ "$h" != "" ]; do
|
||||
case "$h" in
|
||||
*e) cmd="${MANEQN:-neqn} | $cmd";;
|
||||
*r) cmd="refer | $cmd";;
|
||||
*t) cmd="tbl | $cmd";;
|
||||
*v) cmd="vgrind | $cmd";;
|
||||
*) ;; # should print error
|
||||
esac
|
||||
h=${h%?}
|
||||
done
|
||||
fi
|
||||
if [ "$printing" != "" ]; then
|
||||
(cd "$i"; eval "$cmd") < "$file" | ${PAGER:-more}
|
||||
else
|
||||
(cd "$i"; eval "$cmd") < "$file" > /tmp/manpage-$$
|
||||
${PAGER:-more} /tmp/manpage-$$
|
||||
rm -f /tmp/manpage-$$
|
||||
fi
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function whatis_internal ()
|
||||
{
|
||||
local j
|
||||
for j in $(echo "$MANPATH" | tr : ' '); do
|
||||
if [ -f "$j/whatis" ]; then
|
||||
eval $2 -i -e "$1" $j/whatis
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function whatis ()
|
||||
{
|
||||
local name=$(basename "$1")
|
||||
whatis_internal "$name" "grep -w"
|
||||
}
|
||||
|
||||
function apropos ()
|
||||
{
|
||||
whatis_internal "$1" "grep -F"
|
||||
}
|
||||
|
||||
# Note: "-" and "-t" together not supported. This man could be
|
||||
# made a lot better, but it does everything I want.
|
||||
function man ()
|
||||
{
|
||||
local PAGER printing mpath MANROFF num
|
||||
mpath="${MANPATH:-/usr/man}"
|
||||
while true; do
|
||||
case "$1" in
|
||||
-) PAGER=cat
|
||||
printing= ;;
|
||||
-t)
|
||||
MANROFF=${TROFF:-"ptroff -man -t"}
|
||||
PAGER="${TCAT:-lpr}"
|
||||
printing=yes ;;
|
||||
-M)
|
||||
mpath="$2"
|
||||
shift;;
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
local MANPATH="$mpath"
|
||||
case "$1" in
|
||||
-f | -k)
|
||||
local g a
|
||||
if [ "$1" = "-f" ]; then
|
||||
g="grep -w"
|
||||
a=$(basename "$2")
|
||||
else
|
||||
g="grep -F"
|
||||
a="$2"
|
||||
fi
|
||||
whatis_internal "$a" "$g"
|
||||
;;
|
||||
[0-9npol] | [0-9][a-z]* | new | public | old | local)
|
||||
if [ "$1" = "new" ]; then
|
||||
num=n
|
||||
elif [ "$1" = "public" ]; then
|
||||
num=p
|
||||
elif [ "$1" = "old" ]; then
|
||||
num=o
|
||||
elif [ "$1" = "local" ]; then
|
||||
num=l
|
||||
else
|
||||
num="$1"
|
||||
fi
|
||||
shift
|
||||
manpage "$num" "$1" "$printing"
|
||||
;;
|
||||
*)
|
||||
manpage "$num" "$1" "$printing"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# To: chet@ins.CWRU.Edu
|
||||
# Subject: Bash functions
|
||||
# From: Sandeep Mehta <sxm@philabs.Philips.Com>
|
||||
|
||||
# print MH folders, useful only because folders(1) doesn't print
|
||||
# mod date/times
|
||||
|
||||
mhfold()
|
||||
{
|
||||
list=`folders | awk '{if (1 < NR) print $1}'`
|
||||
/bin/ls -lag ~/Mail > /tmp/fold$$
|
||||
for i in $list; do
|
||||
grep $i /tmp/fold$$
|
||||
done
|
||||
/bin/rm -f /tmp/fold$$
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
#!/bin/bash
|
||||
# @(#) newdirstack.bsh
|
||||
|
||||
# Date: Tue, 31 Jan 2012 16:28:52 +0100
|
||||
# Subject: A Bash source code example
|
||||
# From: Eric Sanchis <eric.sanchis@iut-rodez.fr>
|
||||
# To: chet.ramey@case.edu
|
||||
#
|
||||
# Using Bash everyday, I developped an enhanced implementation of the
|
||||
# cd/dir functions described in the Bolsky & Korn book, which
|
||||
# illustrates several specific Bash syntax elements.
|
||||
#
|
||||
# It works fine with a non empty CDPATH and cdable variables. In
|
||||
# addition, a directory name is indexed only once into the stack.
|
||||
#
|
||||
# If you find this code snippet useful, would it be possible to include
|
||||
# it into the bash-doc section of future bash packages ?
|
||||
#
|
||||
# Sincerely yours,
|
||||
#
|
||||
# Eric
|
||||
# IUT Rodez
|
||||
# University of Toulouse (France)
|
||||
|
||||
###
|
||||
# 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
|
||||
###
|
||||
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
#
|
||||
# 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
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
trap _notify CHLD
|
||||
NOTIFY_ALL=false
|
||||
unset NOTIFY_LIST
|
||||
unalias false
|
||||
|
||||
false()
|
||||
{
|
||||
return 1
|
||||
}
|
||||
|
||||
_notify ()
|
||||
{
|
||||
local i j
|
||||
local newlist=
|
||||
|
||||
if $NOTIFY_ALL
|
||||
then
|
||||
return # let bash take care of this itself
|
||||
elif [ -z "$NOTIFY_LIST" ]; then
|
||||
return
|
||||
else
|
||||
set -- $NOTIFY_LIST
|
||||
for i in "$@"
|
||||
do
|
||||
j=$(jobs -n %$i)
|
||||
if [ -n "$j" ]; then
|
||||
echo "$j"
|
||||
jobs -n %$i >/dev/null
|
||||
else
|
||||
newlist="newlist $i"
|
||||
fi
|
||||
done
|
||||
NOTIFY_LIST="$newlist"
|
||||
fi
|
||||
}
|
||||
|
||||
notify ()
|
||||
{
|
||||
local i j
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
NOTIFY_ALL=:
|
||||
set -b
|
||||
return
|
||||
else
|
||||
for i in "$@"
|
||||
do
|
||||
# turn a valid job spec into a job number
|
||||
j=$(jobs $i)
|
||||
case "$j" in
|
||||
[*) j=${j%%]*}
|
||||
j=${j#[}
|
||||
NOTIFY_LIST="$NOTIFY_LIST $j"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#From: "Simon J. Gerraty" <sjg@zen.void.oz.au>
|
||||
#Message-Id: <199510091130.VAA01188@zen.void.oz.au>
|
||||
#Subject: Re: a shell idea?
|
||||
#Date: Mon, 09 Oct 1995 21:30:20 +1000
|
||||
|
||||
|
||||
# NAME:
|
||||
# add_path.sh - add dir to path
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# These functions originated in /etc/profile and ksh.kshrc, but
|
||||
# are more useful in a separate file.
|
||||
#
|
||||
# SEE ALSO:
|
||||
# /etc/profile
|
||||
#
|
||||
# AUTHOR:
|
||||
# Simon J. Gerraty <sjg@zen.void.oz.au>
|
||||
|
||||
# @(#)Copyright (c) 1991 Simon J. Gerraty
|
||||
#
|
||||
# This file is provided in the hope that it will
|
||||
# be of use. There is absolutely NO WARRANTY.
|
||||
# Permission to copy, redistribute or otherwise
|
||||
# use this file is hereby granted provided that
|
||||
# the above copyright notice and this notice are
|
||||
# left intact.
|
||||
|
||||
# is $1 missing from $2 (or PATH) ?
|
||||
no_path() {
|
||||
eval "case :\$${2-PATH}: in *:$1:*) return 1;; *) return 0;; esac"
|
||||
}
|
||||
# if $1 exists and is not in path, append it
|
||||
add_path () {
|
||||
[ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}:$1"
|
||||
}
|
||||
# if $1 exists and is not in path, prepend it
|
||||
pre_path () {
|
||||
[ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2:-PATH}"
|
||||
}
|
||||
# if $1 is in path, remove it
|
||||
del_path () {
|
||||
no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: |
|
||||
sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"`
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
|
||||
#From: kaz@ashi.footprints.net (Kaz Kylheku)
|
||||
#Newsgroups: comp.os.linux.misc
|
||||
#Subject: Re: bash question: subdirectories
|
||||
#Message-ID: <slrn8a0gu9.v5n.kaz@ashi.FootPrints.net>
|
||||
#Date: Tue, 08 Feb 2000 16:24:35 GMT
|
||||
|
||||
#Actually it can be made to. That is to say, it is possible to code a recursive
|
||||
#descender function in the bash language. Here is an example.
|
||||
#
|
||||
#What is nice about this is that you can embed the function into your shell
|
||||
#script. The function changes the current working directory as it descends.
|
||||
#So it can handle arbitrarily deep paths. Whereas paths generated by the
|
||||
#find command can cause a problem when they get too long; the kernel has a
|
||||
#hard limit on the length of the string passed to the open() and other
|
||||
#system calls.
|
||||
|
||||
#There are races; what if the directory tree is blown away during the traversal?
|
||||
#The function won't be able to crawl back up using the .. link and will just
|
||||
#bail.
|
||||
|
||||
# Recursive Directory Traverser
|
||||
# Author: Kaz Kylheku
|
||||
# Date: Feb 27, 1999
|
||||
# Copyright 1999
|
||||
|
||||
# Function parameter usage:
|
||||
# $1 directory to search
|
||||
# $2 pattern to search for
|
||||
# $3 command to execute
|
||||
# $4 secret argument for passing down path
|
||||
|
||||
function recurse
|
||||
{
|
||||
local file
|
||||
local path
|
||||
|
||||
if [ "$4" = "" ] ; then
|
||||
path="${1%/}/"
|
||||
else
|
||||
path="$4$1/"
|
||||
fi
|
||||
|
||||
if cd "$1" ; then
|
||||
for file in $2; do
|
||||
if [ -f "$file" ] || [ -d "$file" ]; then
|
||||
eval "$3"
|
||||
fi
|
||||
done
|
||||
for file in .* * ; do
|
||||
if [ "$file" = "." ] || [ "$file" = ".." ] ; then
|
||||
continue
|
||||
fi
|
||||
if [ -d "$file" ] && [ ! -L "$file" ]; then
|
||||
recurse "$file" "$2" "$3" "$path"
|
||||
fi
|
||||
done
|
||||
cd ..
|
||||
fi
|
||||
}
|
||||
|
||||
recurse "$1" "$2" 'echo "$path$file"'
|
||||
@@ -0,0 +1,43 @@
|
||||
# To: chet@ins.CWRU.Edu
|
||||
# Subject: Bash functions
|
||||
# From: Sandeep Mehta <sxm@philabs.Philips.Com>
|
||||
|
||||
##########################################
|
||||
#
|
||||
# repeat - clone of C shell builtin `repeat'
|
||||
#
|
||||
# usage: repeat <count> <command>
|
||||
#
|
||||
# It has been tested inside other functions and in conditionals like
|
||||
# if [ "`repeat <count> <command>`" ]; then COMMANDS [ else COMMANDS ] fi
|
||||
# Please send me fixes/enhancements.
|
||||
#
|
||||
# Sandeep Mehta <sxm@philabs.Philips.Com>
|
||||
##########################################
|
||||
repeat()
|
||||
{
|
||||
local rcount=$1
|
||||
|
||||
if [ $# -le 1 ] || [ -z "$rcount" ]; then
|
||||
echo "usage: repeat <count> <command>" 1>&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
local acmd=("$@")
|
||||
|
||||
if [ $rcount -le 0 ]; then
|
||||
echo "count must be greater than 0"
|
||||
echo "usage: repeat <count> <command>" 1>&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
st=0
|
||||
while [ $rcount -gt 0 ]; do
|
||||
eval "${acmd[@]}"
|
||||
st=$?
|
||||
rcount=$((rcount - 1))
|
||||
done
|
||||
return $st
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
# From psamuels@jake.niar.twsu.edu (Peter Samuelson)
|
||||
# posted to usenet, Message-ID: <6rtp8j$2a0$1@jake.niar.twsu.edu>
|
||||
|
||||
repeat ()
|
||||
{
|
||||
local i max; # note that you can use \$i in the command string
|
||||
max=$1; shift;
|
||||
|
||||
i=1; while ((i <= max)); do
|
||||
eval "$@"; ((i = i + 1));
|
||||
done;
|
||||
}
|
||||
@@ -1,3 +1,22 @@
|
||||
#
|
||||
# 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 ()
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
#
|
||||
# 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 ()
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# 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
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# Generate a sequence from m to n, m defaults to 1.
|
||||
|
||||
seq ()
|
||||
{
|
||||
declare -i lo hi i # makes local
|
||||
local _SEQ
|
||||
|
||||
case $# in
|
||||
1) seq 1 "$1" ; return $? ;;
|
||||
2) lo=$1 hi=$2
|
||||
i=$lo _SEQ=""
|
||||
while let "i <= hi"; do
|
||||
_SEQ="${_SEQ}$i "
|
||||
let i+=1
|
||||
done
|
||||
echo "${_SEQ# }"
|
||||
return 0 ;;
|
||||
*) echo seq: usage: seq [low] high 1>&2 ; return 2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# like the APL `iota' function (or at least how I remember it :-)
|
||||
iota()
|
||||
{
|
||||
case $# in
|
||||
1) seq 1 "$1"; return $?;;
|
||||
*) echo "iota: usage: iota high" 1>&2; return 2;;
|
||||
esac
|
||||
}
|
||||
@@ -1,3 +1,22 @@
|
||||
#
|
||||
# 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 paramters.
|
||||
# Make sure the positional parameters are passed as arguments to the function.
|
||||
# If -u is the first arg, remove duplicate array members.
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# Sort the positional paramters.
|
||||
# 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
|
||||
@@ -0,0 +1,21 @@
|
||||
#From: Syamala Rao Tadigadapa <stadigad@us.oracle.com>
|
||||
#Subject: Re: Division in ksh(getting the exact number) Please HELP
|
||||
#Date: Mon, 25 Oct 1999 15:05:08 -0700
|
||||
#Message-ID: <3814D414.7B896084@us.oracle.com>
|
||||
|
||||
#Here is how to calculate the (integer part of the) square root
|
||||
#of a number in a much cleaner way.
|
||||
|
||||
sqroot()
|
||||
{
|
||||
let arg=$1
|
||||
let root=arg
|
||||
while :
|
||||
do
|
||||
newroot=$(( (root+arg/root)/2 ))
|
||||
(( newroot == root )) && { echo $root; return; }
|
||||
let root=newroot
|
||||
done
|
||||
}
|
||||
|
||||
sqroot "$@"
|
||||
@@ -1,4 +1,22 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#
|
||||
# substr -- a function to emulate the ancient ksh builtin
|
||||
#
|
||||
|
||||
# -l == remove shortest from left
|
||||
# -L == remove longest from left
|
||||
# -r == remove shortest from right (the default)
|
||||
# -R == remove longest from right
|
||||
|
||||
substr()
|
||||
{
|
||||
local flag pat str
|
||||
local usage="usage: substr -lLrR pat string or substr string pat"
|
||||
local options="l:L:r:R:"
|
||||
|
||||
OPTIND=1
|
||||
while getopts "$options" c
|
||||
do
|
||||
case "$c" in
|
||||
l | L | r | R)
|
||||
flag="-$c"
|
||||
pat="$OPTARG"
|
||||
;;
|
||||
'?')
|
||||
echo "$usage"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$OPTIND" -gt 1 ] ; then
|
||||
shift $(( $OPTIND -1 ))
|
||||
fi
|
||||
|
||||
if [ "$#" -eq 0 ] || [ "$#" -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
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#
|
||||
# substr -- a function to emulate the ancient ksh builtin
|
||||
#
|
||||
|
||||
#
|
||||
# -l == shortest from left
|
||||
# -L == longest from left
|
||||
# -r == shortest from right (the default)
|
||||
# -R == longest from right
|
||||
|
||||
substr()
|
||||
{
|
||||
local flag pat str
|
||||
local usage="usage: substr -lLrR pat string or substr string pat"
|
||||
|
||||
case "$1" in
|
||||
-l | -L | -r | -R)
|
||||
flag="$1"
|
||||
pat="$2"
|
||||
shift 2
|
||||
;;
|
||||
-*)
|
||||
echo "substr: unknown option: $1"
|
||||
echo "$usage"
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
flag="-r"
|
||||
pat="$2"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$#" -eq 0 ] || [ "$#" -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
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# term -- a shell function to set the terminal type interactively or not.
|
||||
#
|
||||
|
||||
term()
|
||||
{
|
||||
local t
|
||||
|
||||
if [ $# != 0 ] ; then
|
||||
eval $(tset -sQ $1)
|
||||
else # interactive
|
||||
if [ -z "$TERM" ] ; then
|
||||
TERM="unknown"
|
||||
fi
|
||||
|
||||
case "$TERM" in
|
||||
network|dialup|unknown|lat)
|
||||
TERM=unknown
|
||||
;;
|
||||
*)
|
||||
eval $(tset -sQ)
|
||||
;;
|
||||
esac
|
||||
|
||||
while [ "$TERM" = "unknown" ] ; do
|
||||
echo -n "Terminal type: "
|
||||
read t
|
||||
if [ -n "$t" ] ; then
|
||||
eval $(tset -sQ $t)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,25 @@
|
||||
# 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()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#
|
||||
# whatis -- and implementation of the 10th Edition Unix sh builtin `whatis'
|
||||
# command.
|
||||
#
|
||||
# usage: whatis arg [...]
|
||||
#
|
||||
# For each argument, whatis prints the associated value as a parameter,
|
||||
# builtin, function, alias, or executable file as appropriate. In each
|
||||
# case, the value is printed in a form which would yield the same value
|
||||
# if typed as input to the shell itself.
|
||||
#
|
||||
|
||||
whatis()
|
||||
{
|
||||
local wusage='usage: whatis arg [arg...]'
|
||||
local fail=0
|
||||
|
||||
if [ $# -eq 0 ] ; then
|
||||
echo "$wusage"
|
||||
return 1
|
||||
fi
|
||||
|
||||
for arg
|
||||
do
|
||||
case $(builtin type -type $arg 2>/dev/null) in
|
||||
"alias")
|
||||
builtin alias "$arg"
|
||||
;;
|
||||
"function")
|
||||
builtin type "$arg" | sed 1d
|
||||
;;
|
||||
"builtin")
|
||||
echo builtin "$arg"
|
||||
;;
|
||||
"file")
|
||||
builtin type -path "$arg"
|
||||
;;
|
||||
*)
|
||||
# OK, we could have a variable, or we could have nada
|
||||
if [ "$(eval echo \${$arg+set})" = "set" ] ; then
|
||||
# It is a variable, and it is set
|
||||
echo -n "$arg="
|
||||
eval echo '\"'\$$arg'\"'
|
||||
else
|
||||
echo whatis: $arg: not found
|
||||
fail=1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
return $fail
|
||||
}
|
||||
@@ -8,6 +8,25 @@
|
||||
# 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=
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#
|
||||
# An almost-ksh compatible `whence' command. This is as hairy as it is
|
||||
# because of the desire to exactly mimic ksh.
|
||||
#
|
||||
# This depends somewhat on knowing the format of the output of the bash
|
||||
# `builtin type' command.
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@ins.CWRU.Edu
|
||||
#
|
||||
whence()
|
||||
{
|
||||
local vflag= path=
|
||||
|
||||
if [ "$#" = "0" ] ; then
|
||||
echo "whence: argument expected"
|
||||
return 1
|
||||
fi
|
||||
case "$1" in
|
||||
-v) vflag=1
|
||||
shift 1
|
||||
;;
|
||||
-*) echo "whence: bad option: $1"
|
||||
return 1
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
if [ "$#" = "0" ] ; then
|
||||
echo "whence: bad argument count"
|
||||
return 1
|
||||
fi
|
||||
|
||||
for cmd
|
||||
do
|
||||
if [ "$vflag" ] ; then
|
||||
echo $(builtin type $cmd | sed 1q)
|
||||
else
|
||||
path=$(builtin type -path $cmd)
|
||||
if [ "$path" ] ; then
|
||||
echo $path
|
||||
else
|
||||
case "$cmd" in
|
||||
/*) if [ -x "$cmd" ]; then
|
||||
echo "$cmd"
|
||||
fi
|
||||
;;
|
||||
*) case "$(builtin type -type $cmd)" in
|
||||
"") ;;
|
||||
*) echo "$cmd"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
@@ -3,6 +3,24 @@
|
||||
#
|
||||
# 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()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#
|
||||
# which - emulation of `which' as it appears in FreeBSD
|
||||
#
|
||||
# usage: which [-as] command [command...]
|
||||
#
|
||||
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
# xalias - convert csh alias commands to bash functions
|
||||
# from Mohit Aron <aron@cs.rice.edu>
|
||||
# posted to usenet as <4i5p17$bnu@larry.rice.edu>
|
||||
function xalias ()
|
||||
{
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#! /bin/bash
|
||||
#From: kaz@cafe.net (Kaz Kylheku)
|
||||
#Newsgroups: comp.unix.shell
|
||||
#Subject: Why not roll your own @#$% find! (was: splitting directory off from filename)
|
||||
#Message-ID: <6n1117$tp1@espresso.cafe.net>
|
||||
#Date: Fri, 26 Jun 1998 20:47:34 GMT
|
||||
|
||||
# $1 = dirname, $2 = pattern, optional $3 = action
|
||||
xfind()
|
||||
{
|
||||
local x
|
||||
local dir="$1"
|
||||
|
||||
# descend into specified directory
|
||||
|
||||
builtin cd -L "$1" || {
|
||||
echo "${FUNCNAME}: cannot change dir to $1" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
#
|
||||
# default action is to print the filename
|
||||
#
|
||||
if [ -n "$3" ]; then
|
||||
action="$3"
|
||||
else
|
||||
action='printf -- "%s\n"'
|
||||
fi
|
||||
|
||||
# process ordinary files that match pattern
|
||||
|
||||
for x in $2 ; do
|
||||
if [ -f "$x" ] ; then
|
||||
eval "$action" "$x"
|
||||
fi
|
||||
done
|
||||
|
||||
# now descend into subdirectories, avoiding symbolic links
|
||||
# and directories that start with a period.
|
||||
|
||||
for x in * ; do
|
||||
if [ -d "$x" ] && [ ! -L "$x" ] ; then
|
||||
$FUNCNAME "$x" "$2" "$action"
|
||||
fi
|
||||
done
|
||||
|
||||
# finally, pop back up
|
||||
|
||||
builtin cd -L ..
|
||||
}
|
||||
|
||||
#xfind "$@"
|
||||
@@ -0,0 +1,238 @@
|
||||
#
|
||||
# Simple makefile for the sample loadable builtins
|
||||
#
|
||||
# Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
# 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.
|
||||
|
||||
# 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, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
# Include some boilerplate Gnu makefile definitions.
|
||||
prefix = @prefix@
|
||||
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
includedir = @includedir@
|
||||
|
||||
topdir = @top_srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
|
||||
@SET_MAKE@
|
||||
CC = @CC@
|
||||
RM = rm -f
|
||||
|
||||
SHELL = @MAKE_SHELL@
|
||||
|
||||
host_os = @host_os@
|
||||
host_cpu = @host_cpu@
|
||||
host_vendor = @host_vendor@
|
||||
|
||||
CFLAGS = @CFLAGS@
|
||||
LOCAL_CFLAGS = @LOCAL_CFLAGS@
|
||||
DEFS = @DEFS@
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
|
||||
BASHINCDIR = ${topdir}/include
|
||||
|
||||
LIBBUILD = ${BUILD_DIR}/lib
|
||||
|
||||
INTL_LIBSRC = ${topdir}/lib/intl
|
||||
INTL_BUILDDIR = ${LIBBUILD}/intl
|
||||
INTL_INC = @INTL_INC@
|
||||
LIBINTL_H = @LIBINTL_H@
|
||||
|
||||
CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS)
|
||||
|
||||
#
|
||||
# These values are generated for configure by ${topdir}/support/shobj-conf.
|
||||
# If your system is not supported by that script, but includes facilities for
|
||||
# dynamic loading of shared objects, please update the script and send the
|
||||
# changes to bash-maintainers@gnu.org.
|
||||
#
|
||||
SHOBJ_CC = @SHOBJ_CC@
|
||||
SHOBJ_CFLAGS = @SHOBJ_CFLAGS@
|
||||
SHOBJ_LD = @SHOBJ_LD@
|
||||
SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@
|
||||
SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@
|
||||
SHOBJ_LIBS = @SHOBJ_LIBS@
|
||||
SHOBJ_STATUS = @SHOBJ_STATUS@
|
||||
|
||||
INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \
|
||||
-I$(BASHINCDIR) -I$(BUILD_DIR) -I$(LIBBUILD) \
|
||||
-I$(BUILD_DIR)/builtins $(INTL_INC)
|
||||
|
||||
.c.o:
|
||||
$(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $<
|
||||
|
||||
|
||||
ALLPROG = print truefalse sleep pushd finfo logname basename dirname \
|
||||
tty pathchk tee head mkdir rmdir printenv id whoami \
|
||||
uname sync push ln unlink cut realpath getconf strftime
|
||||
OTHERPROG = necho hello cat
|
||||
|
||||
all: $(SHOBJ_STATUS)
|
||||
|
||||
supported: $(ALLPROG)
|
||||
others: $(OTHERPROG)
|
||||
|
||||
unsupported:
|
||||
@echo "Your system (${host_os}) is not supported by the"
|
||||
@echo "${topdir}/support/shobj-conf script."
|
||||
@echo "If your operating system provides facilities for dynamic"
|
||||
@echo "loading of shared objects using the dlopen(3) interface,"
|
||||
@echo "please update the script and re-run configure.
|
||||
@echo "Please send the changes you made to bash-maintainers@gnu.org"
|
||||
@echo "for inclusion in future bash releases."
|
||||
|
||||
everything: supported others
|
||||
|
||||
print: print.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ print.o $(SHOBJ_LIBS)
|
||||
|
||||
necho: necho.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ necho.o $(SHOBJ_LIBS)
|
||||
|
||||
getconf: getconf.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ getconf.o $(SHOBJ_LIBS)
|
||||
|
||||
hello: hello.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ hello.o $(SHOBJ_LIBS)
|
||||
|
||||
truefalse: truefalse.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ truefalse.o $(SHOBJ_LIBS)
|
||||
|
||||
sleep: sleep.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sleep.o $(SHOBJ_LIBS)
|
||||
|
||||
finfo: finfo.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ finfo.o $(SHOBJ_LIBS)
|
||||
|
||||
cat: cat.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS)
|
||||
|
||||
logname: logname.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS)
|
||||
|
||||
basename: basename.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ basename.o $(SHOBJ_LIBS)
|
||||
|
||||
dirname: dirname.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ dirname.o $(SHOBJ_LIBS)
|
||||
|
||||
tty: tty.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tty.o $(SHOBJ_LIBS)
|
||||
|
||||
pathchk: pathchk.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pathchk.o $(SHOBJ_LIBS)
|
||||
|
||||
tee: tee.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tee.o $(SHOBJ_LIBS)
|
||||
|
||||
mkdir: mkdir.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mkdir.o $(SHOBJ_LIBS)
|
||||
|
||||
rmdir: rmdir.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rmdir.o $(SHOBJ_LIBS)
|
||||
|
||||
head: head.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ head.o $(SHOBJ_LIBS)
|
||||
|
||||
printenv: printenv.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ printenv.o $(SHOBJ_LIBS)
|
||||
|
||||
id: id.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ id.o $(SHOBJ_LIBS)
|
||||
|
||||
whoami: whoami.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ whoami.o $(SHOBJ_LIBS)
|
||||
|
||||
uname: uname.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ uname.o $(SHOBJ_LIBS)
|
||||
|
||||
sync: sync.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sync.o $(SHOBJ_LIBS)
|
||||
|
||||
push: push.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ push.o $(SHOBJ_LIBS)
|
||||
|
||||
ln: ln.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ ln.o $(SHOBJ_LIBS)
|
||||
|
||||
unlink: unlink.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ unlink.o $(SHOBJ_LIBS)
|
||||
|
||||
cut: cut.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cut.o $(SHOBJ_LIBS)
|
||||
|
||||
realpath: realpath.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ realpath.o $(SHOBJ_LIBS)
|
||||
|
||||
strftime: strftime.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ strftime.o $(SHOBJ_LIBS)
|
||||
|
||||
# pushd is a special case. We use the same source that the builtin version
|
||||
# uses, with special compilation options.
|
||||
#
|
||||
pushd.c: ${topdir}/builtins/pushd.def
|
||||
$(RM) $@
|
||||
${BUILD_DIR}/builtins/mkbuiltins -D ${topdir}/builtins ${topdir}/builtins/pushd.def
|
||||
|
||||
pushd.o: pushd.c
|
||||
$(RM) $@
|
||||
$(SHOBJ_CC) -DHAVE_CONFIG_H -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INC) -c -o $@ $<
|
||||
|
||||
pushd: pushd.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pushd.o $(SHOBJ_LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) $(ALLPROG) $(OTHERPROG) *.o
|
||||
-( cd perl && ${MAKE} ${MFLAGS} $@ )
|
||||
|
||||
mostlyclean: clean
|
||||
-( cd perl && ${MAKE} ${MFLAGS} $@ )
|
||||
|
||||
distclean maintainer-clean: clean
|
||||
$(RM) Makefile pushd.c
|
||||
-( cd perl && ${MAKE} ${MFLAGS} $@ )
|
||||
|
||||
print.o: print.c
|
||||
truefalse.o: truefalse.c
|
||||
sleep.o: sleep.c
|
||||
finfo.o: finfo.c
|
||||
logname.o: logname.c
|
||||
basename.o: basename.c
|
||||
dirname.o: dirname.c
|
||||
tty.o: tty.c
|
||||
pathchk.o: pathchk.c
|
||||
tee.o: tee.c
|
||||
head.o: head.c
|
||||
rmdir.o: rmdir.c
|
||||
necho.o: necho.c
|
||||
getconf.o: getconf.c
|
||||
hello.o: hello.c
|
||||
cat.o: cat.c
|
||||
printenv.o: printenv.c
|
||||
id.o: id.c
|
||||
whoami.o: whoami.c
|
||||
uname.o: uname.c
|
||||
sync.o: sync.c
|
||||
push.o: push.c
|
||||
mkdir.o: mkdir.c
|
||||
realpath.o: realpath.c
|
||||
strftime.o: strftime.c
|
||||
@@ -2,6 +2,24 @@
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
/*
|
||||
Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/* basename - return nondirectory portion of pathname */
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "common.h"
|
||||
|
||||
basename_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int slen, sufflen, off;
|
||||
char *string, *suffix, *fn;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
if (no_options (list))
|
||||
return (EX_USAGE);
|
||||
|
||||
string = list->word->word;
|
||||
suffix = (char *)NULL;
|
||||
if (list->next)
|
||||
{
|
||||
list = list->next;
|
||||
suffix = list->word->word;
|
||||
}
|
||||
|
||||
if (list->next)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
slen = strlen (string);
|
||||
|
||||
/* Strip trailing slashes */
|
||||
while (slen > 0 && string[slen - 1] == '/')
|
||||
slen--;
|
||||
|
||||
/* (2) If string consists entirely of slash characters, string shall be
|
||||
set to a single slash character. In this case, skip steps (3)
|
||||
through (5). */
|
||||
if (slen == 0)
|
||||
{
|
||||
fputs ("/\n", stdout);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* (3) If there are any trailing slash characters in string, they
|
||||
shall be removed. */
|
||||
string[slen] = '\0';
|
||||
|
||||
/* (4) If there are any slash characters remaining in string, the prefix
|
||||
of string up to an including the last slash character in string
|
||||
shall be removed. */
|
||||
while (--slen >= 0)
|
||||
if (string[slen] == '/')
|
||||
break;
|
||||
|
||||
fn = string + slen + 1;
|
||||
|
||||
/* (5) If the suffix operand is present, is not identical to the
|
||||
characters remaining in string, and is identical to a suffix
|
||||
of the characters remaining in string, the suffix suffix
|
||||
shall be removed from string. Otherwise, string shall not be
|
||||
modified by this step. */
|
||||
if (suffix)
|
||||
{
|
||||
sufflen = strlen (suffix);
|
||||
slen = strlen (fn);
|
||||
if (sufflen < slen)
|
||||
{
|
||||
off = slen - sufflen;
|
||||
if (strcmp (fn + off, suffix) == 0)
|
||||
fn[off] = '\0';
|
||||
}
|
||||
}
|
||||
printf ("%s\n", fn);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
char *basename_doc[] = {
|
||||
"Return non-directory portion of pathname.",
|
||||
"",
|
||||
"The STRING is converted to a filename corresponding to the last",
|
||||
"pathname component in STRING. If the suffix string SUFFIX is",
|
||||
"supplied, it is removed.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
/* The standard structure describing a builtin command. bash keeps an array
|
||||
of these structures. */
|
||||
struct builtin basename_struct = {
|
||||
"basename", /* builtin name */
|
||||
basename_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
basename_doc, /* array of long documentation strings. */
|
||||
"basename string [suffix]", /* usage synopsis */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)cut.c 8.3 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if !defined (_POSIX2_LINE_MAX)
|
||||
# define _POSIX2_LINE_MAX 2048
|
||||
#endif
|
||||
|
||||
static int cflag;
|
||||
static char dchar;
|
||||
static int dflag;
|
||||
static int fflag;
|
||||
static int sflag;
|
||||
|
||||
static int autostart, autostop, maxval;
|
||||
static char positions[_POSIX2_LINE_MAX + 1];
|
||||
|
||||
static int c_cut __P((FILE *, char *));
|
||||
static int f_cut __P((FILE *, char *));
|
||||
static int get_list __P((char *));
|
||||
static char *_cut_strsep __P((char **, const char *));
|
||||
|
||||
int
|
||||
cut_builtin(list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
FILE *fp;
|
||||
int (*fcn) __P((FILE *, char *)) = NULL;
|
||||
int ch;
|
||||
|
||||
fcn = NULL;
|
||||
dchar = '\t'; /* default delimiter is \t */
|
||||
|
||||
/* Since we don't support multi-byte characters, the -c and -b
|
||||
options are equivalent, and the -n option is meaningless. */
|
||||
reset_internal_getopt ();
|
||||
while ((ch = internal_getopt (list, "b:c:d:f:sn")) != -1)
|
||||
switch(ch) {
|
||||
case 'b':
|
||||
case 'c':
|
||||
fcn = c_cut;
|
||||
if (get_list(list_optarg) < 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dchar = *list_optarg;
|
||||
dflag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
fcn = f_cut;
|
||||
if (get_list(list_optarg) < 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
fflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
case 'n':
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
builtin_usage();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
list = loptend;
|
||||
|
||||
if (fflag) {
|
||||
if (cflag) {
|
||||
builtin_usage();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
} else if (!cflag || dflag || sflag) {
|
||||
builtin_usage();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
if (list) {
|
||||
while (list) {
|
||||
fp = fopen(list->word->word, "r");
|
||||
if (fp == 0) {
|
||||
builtin_error("%s", list->word->word);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
ch = (*fcn)(fp, list->word->word);
|
||||
(void)fclose(fp);
|
||||
if (ch < 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
list = list->next;
|
||||
}
|
||||
} else {
|
||||
ch = (*fcn)(stdin, "stdin");
|
||||
if (ch < 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
get_list(list)
|
||||
char *list;
|
||||
{
|
||||
int setautostart, start, stop;
|
||||
char *pos;
|
||||
char *p;
|
||||
|
||||
/*
|
||||
* set a byte in the positions array to indicate if a field or
|
||||
* column is to be selected; use +1, it's 1-based, not 0-based.
|
||||
* This parser is less restrictive than the Draft 9 POSIX spec.
|
||||
* POSIX doesn't allow lists that aren't in increasing order or
|
||||
* overlapping lists. We also handle "-3-5" although there's no
|
||||
* real reason too.
|
||||
*/
|
||||
for (; (p = _cut_strsep(&list, ", \t")) != NULL;) {
|
||||
setautostart = start = stop = 0;
|
||||
if (*p == '-') {
|
||||
++p;
|
||||
setautostart = 1;
|
||||
}
|
||||
if (isdigit((unsigned char)*p)) {
|
||||
start = stop = strtol(p, &p, 10);
|
||||
if (setautostart && start > autostart)
|
||||
autostart = start;
|
||||
}
|
||||
if (*p == '-') {
|
||||
if (isdigit((unsigned char)p[1]))
|
||||
stop = strtol(p + 1, &p, 10);
|
||||
if (*p == '-') {
|
||||
++p;
|
||||
if (!autostop || autostop > stop)
|
||||
autostop = stop;
|
||||
}
|
||||
}
|
||||
if (*p) {
|
||||
builtin_error("[-cf] list: illegal list value");
|
||||
return -1;
|
||||
}
|
||||
if (!stop || !start) {
|
||||
builtin_error("[-cf] list: values may not include zero");
|
||||
return -1;
|
||||
}
|
||||
if (stop > _POSIX2_LINE_MAX) {
|
||||
builtin_error("[-cf] list: %d too large (max %d)",
|
||||
stop, _POSIX2_LINE_MAX);
|
||||
return -1;
|
||||
}
|
||||
if (maxval < stop)
|
||||
maxval = stop;
|
||||
for (pos = positions + start; start++ <= stop; *pos++ = 1);
|
||||
}
|
||||
|
||||
/* overlapping ranges */
|
||||
if (autostop && maxval > autostop)
|
||||
maxval = autostop;
|
||||
|
||||
/* set autostart */
|
||||
if (autostart)
|
||||
memset(positions + 1, '1', autostart);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
c_cut(fp, fname)
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
{
|
||||
int ch, col;
|
||||
char *pos;
|
||||
|
||||
ch = 0;
|
||||
for (;;) {
|
||||
pos = positions + 1;
|
||||
for (col = maxval; col; --col) {
|
||||
if ((ch = getc(fp)) == EOF)
|
||||
return;
|
||||
if (ch == '\n')
|
||||
break;
|
||||
if (*pos++)
|
||||
(void)putchar(ch);
|
||||
}
|
||||
if (ch != '\n') {
|
||||
if (autostop)
|
||||
while ((ch = getc(fp)) != EOF && ch != '\n')
|
||||
(void)putchar(ch);
|
||||
else
|
||||
while ((ch = getc(fp)) != EOF && ch != '\n');
|
||||
}
|
||||
(void)putchar('\n');
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
f_cut(fp, fname)
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
{
|
||||
int ch, field, isdelim;
|
||||
char *pos, *p, sep;
|
||||
int output;
|
||||
char lbuf[_POSIX2_LINE_MAX + 1];
|
||||
|
||||
for (sep = dchar; fgets(lbuf, sizeof(lbuf), fp);) {
|
||||
output = 0;
|
||||
for (isdelim = 0, p = lbuf;; ++p) {
|
||||
if (!(ch = *p)) {
|
||||
builtin_error("%s: line too long.", fname);
|
||||
return -1;
|
||||
}
|
||||
/* this should work if newline is delimiter */
|
||||
if (ch == sep)
|
||||
isdelim = 1;
|
||||
if (ch == '\n') {
|
||||
if (!isdelim && !sflag)
|
||||
(void)printf("%s", lbuf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isdelim)
|
||||
continue;
|
||||
|
||||
pos = positions + 1;
|
||||
for (field = maxval, p = lbuf; field; --field, ++pos) {
|
||||
if (*pos) {
|
||||
if (output++)
|
||||
(void)putchar(sep);
|
||||
while ((ch = *p++) != '\n' && ch != sep)
|
||||
(void)putchar(ch);
|
||||
} else {
|
||||
while ((ch = *p++) != '\n' && ch != sep)
|
||||
continue;
|
||||
}
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
if (ch != '\n') {
|
||||
if (autostop) {
|
||||
if (output)
|
||||
(void)putchar(sep);
|
||||
for (; (ch = *p) != '\n'; ++p)
|
||||
(void)putchar(ch);
|
||||
} else
|
||||
for (; (ch = *p) != '\n'; ++p);
|
||||
}
|
||||
(void)putchar('\n');
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get next token from string *stringp, where tokens are possibly-empty
|
||||
* strings separated by characters from delim.
|
||||
*
|
||||
* Writes NULs into the string at *stringp to end tokens.
|
||||
* delim need not remain constant from call to call.
|
||||
* On return, *stringp points past the last NUL written (if there might
|
||||
* be further tokens), or is NULL (if there are definitely no more tokens).
|
||||
*
|
||||
* If *stringp is NULL, strsep returns NULL.
|
||||
*/
|
||||
static char *
|
||||
_cut_strsep(stringp, delim)
|
||||
register char **stringp;
|
||||
register const char *delim;
|
||||
{
|
||||
register char *s;
|
||||
register const char *spanp;
|
||||
register int c, sc;
|
||||
char *tok;
|
||||
|
||||
if ((s = *stringp) == NULL)
|
||||
return (NULL);
|
||||
for (tok = s;;) {
|
||||
c = *s++;
|
||||
spanp = delim;
|
||||
do {
|
||||
if ((sc = *spanp++) == c) {
|
||||
if (c == 0)
|
||||
s = NULL;
|
||||
else
|
||||
s[-1] = 0;
|
||||
*stringp = s;
|
||||
return (tok);
|
||||
}
|
||||
} while (sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static char *cut_doc[] = {
|
||||
"Select portions of lines.",
|
||||
"",
|
||||
"Select portions of each line (as specified by LIST) from each FILE",
|
||||
"(by default, the standard input), and write them to the standard output.",
|
||||
"Items specified by LIST are either column positions or fields delimited",
|
||||
"by a special character. Column numbering starts at 1.",
|
||||
(char *)0
|
||||
};
|
||||
|
||||
struct builtin cut_struct = {
|
||||
"cut",
|
||||
cut_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
cut_doc,
|
||||
"cut -b list [-n] [file ...] OR cut -c list [file ...] OR cut -f list [-s] [-d delim] [file ...]",
|
||||
0
|
||||
};
|
||||
@@ -5,6 +5,24 @@
|
||||
* chet@po.cwru.edu
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
* finfo - print file info
|
||||
*
|
||||
* Chet Ramey
|
||||
* chet@po.cwru.edu
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "posixstat.h"
|
||||
#include <stdio.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
#include "posixtime.h"
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern char **make_builtin_argv ();
|
||||
|
||||
static int printst();
|
||||
static int printsome();
|
||||
static int printfinfo();
|
||||
static int finfo_main();
|
||||
|
||||
extern int sh_optind;
|
||||
extern char *sh_optarg;
|
||||
extern char *this_command_name;
|
||||
|
||||
static char *prog;
|
||||
static int pmask;
|
||||
|
||||
#define OPT_UID 0x00001
|
||||
#define OPT_GID 0x00002
|
||||
#define OPT_DEV 0x00004
|
||||
#define OPT_INO 0x00008
|
||||
#define OPT_PERM 0x00010
|
||||
#define OPT_LNKNAM 0x00020
|
||||
#define OPT_FID 0x00040
|
||||
#define OPT_NLINK 0x00080
|
||||
#define OPT_RDEV 0x00100
|
||||
#define OPT_SIZE 0x00200
|
||||
#define OPT_ATIME 0x00400
|
||||
#define OPT_MTIME 0x00800
|
||||
#define OPT_CTIME 0x01000
|
||||
#define OPT_BLKSIZE 0x02000
|
||||
#define OPT_BLKS 0x04000
|
||||
#define OPT_FTYPE 0x08000
|
||||
#define OPT_PMASK 0x10000
|
||||
#define OPT_OPERM 0x20000
|
||||
|
||||
#define OPT_ASCII 0x1000000
|
||||
|
||||
#define OPTIONS "acdgiflmnopsuACGMP:U"
|
||||
|
||||
static int
|
||||
octal(s)
|
||||
char *s;
|
||||
{
|
||||
int r;
|
||||
|
||||
r = *s - '0';
|
||||
while (*++s >= '0' && *s <= '7')
|
||||
r = (r * 8) + (*s - '0');
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
finfo_main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register int i;
|
||||
int mode, flags, opt;
|
||||
|
||||
sh_optind = 0; /* XXX */
|
||||
prog = base_pathname(argv[0]);
|
||||
if (argc == 1) {
|
||||
builtin_usage();
|
||||
return(1);
|
||||
}
|
||||
flags = 0;
|
||||
while ((opt = sh_getopt(argc, argv, OPTIONS)) != EOF) {
|
||||
switch(opt) {
|
||||
case 'a': flags |= OPT_ATIME; break;
|
||||
case 'A': flags |= OPT_ATIME|OPT_ASCII; break;
|
||||
case 'c': flags |= OPT_CTIME; break;
|
||||
case 'C': flags |= OPT_CTIME|OPT_ASCII; break;
|
||||
case 'd': flags |= OPT_DEV; break;
|
||||
case 'i': flags |= OPT_INO; break;
|
||||
case 'f': flags |= OPT_FID; break;
|
||||
case 'g': flags |= OPT_GID; break;
|
||||
case 'G': flags |= OPT_GID|OPT_ASCII; break;
|
||||
case 'l': flags |= OPT_LNKNAM; break;
|
||||
case 'm': flags |= OPT_MTIME; break;
|
||||
case 'M': flags |= OPT_MTIME|OPT_ASCII; break;
|
||||
case 'n': flags |= OPT_NLINK; break;
|
||||
case 'o': flags |= OPT_OPERM; break;
|
||||
case 'p': flags |= OPT_PERM; break;
|
||||
case 'P': flags |= OPT_PMASK; pmask = octal(sh_optarg); break;
|
||||
case 's': flags |= OPT_SIZE; break;
|
||||
case 'u': flags |= OPT_UID; break;
|
||||
case 'U': flags |= OPT_UID|OPT_ASCII; break;
|
||||
default: builtin_usage (); return(1);
|
||||
}
|
||||
}
|
||||
|
||||
argc -= sh_optind;
|
||||
argv += sh_optind;
|
||||
|
||||
if (argc == 0) {
|
||||
builtin_usage();
|
||||
return(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
opt = flags ? printsome (argv[i], flags) : printfinfo(argv[i]);
|
||||
|
||||
return(opt);
|
||||
}
|
||||
|
||||
static struct stat *
|
||||
getstat(f)
|
||||
char *f;
|
||||
{
|
||||
static struct stat st;
|
||||
int fd, r;
|
||||
intmax_t lfd;
|
||||
|
||||
if (strncmp(f, "/dev/fd/", 8) == 0) {
|
||||
if ((legal_number(f + 8, &lfd) == 0) || (int)lfd != lfd) {
|
||||
builtin_error("%s: invalid fd", f + 8);
|
||||
return ((struct stat *)0);
|
||||
}
|
||||
fd = lfd;
|
||||
r = fstat(fd, &st);
|
||||
} else
|
||||
#ifdef HAVE_LSTAT
|
||||
r = lstat(f, &st);
|
||||
#else
|
||||
r = stat(f, &st);
|
||||
#endif
|
||||
if (r < 0) {
|
||||
builtin_error("%s: cannot stat: %s", f, strerror(errno));
|
||||
return ((struct stat *)0);
|
||||
}
|
||||
return (&st);
|
||||
}
|
||||
|
||||
static int
|
||||
printfinfo(f)
|
||||
char *f;
|
||||
{
|
||||
struct stat *st;
|
||||
|
||||
st = getstat(f);
|
||||
return (st ? printst(st) : 1);
|
||||
}
|
||||
|
||||
static int
|
||||
getperm(m)
|
||||
int m;
|
||||
{
|
||||
return (m & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID));
|
||||
}
|
||||
|
||||
static int
|
||||
perms(m)
|
||||
int m;
|
||||
{
|
||||
char ubits[4], gbits[4], obits[4]; /* u=rwx,g=rwx,o=rwx */
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
if (m & S_IRUSR)
|
||||
ubits[i++] = 'r';
|
||||
if (m & S_IWUSR)
|
||||
ubits[i++] = 'w';
|
||||
if (m & S_IXUSR)
|
||||
ubits[i++] = 'x';
|
||||
ubits[i] = '\0';
|
||||
|
||||
i = 0;
|
||||
if (m & S_IRGRP)
|
||||
gbits[i++] = 'r';
|
||||
if (m & S_IWGRP)
|
||||
gbits[i++] = 'w';
|
||||
if (m & S_IXGRP)
|
||||
gbits[i++] = 'x';
|
||||
gbits[i] = '\0';
|
||||
|
||||
i = 0;
|
||||
if (m & S_IROTH)
|
||||
obits[i++] = 'r';
|
||||
if (m & S_IWOTH)
|
||||
obits[i++] = 'w';
|
||||
if (m & S_IXOTH)
|
||||
obits[i++] = 'x';
|
||||
obits[i] = '\0';
|
||||
|
||||
if (m & S_ISUID)
|
||||
ubits[2] = (m & S_IXUSR) ? 's' : 'S';
|
||||
if (m & S_ISGID)
|
||||
gbits[2] = (m & S_IXGRP) ? 's' : 'S';
|
||||
if (m & S_ISVTX)
|
||||
obits[2] = (m & S_IXOTH) ? 't' : 'T';
|
||||
|
||||
printf ("u=%s,g=%s,o=%s", ubits, gbits, obits);
|
||||
}
|
||||
|
||||
static int
|
||||
printmode(mode)
|
||||
int mode;
|
||||
{
|
||||
if (S_ISBLK(mode))
|
||||
printf("S_IFBLK ");
|
||||
if (S_ISCHR(mode))
|
||||
printf("S_IFCHR ");
|
||||
if (S_ISDIR(mode))
|
||||
printf("S_IFDIR ");
|
||||
if (S_ISREG(mode))
|
||||
printf("S_IFREG ");
|
||||
if (S_ISFIFO(mode))
|
||||
printf("S_IFIFO ");
|
||||
if (S_ISLNK(mode))
|
||||
printf("S_IFLNK ");
|
||||
if (S_ISSOCK(mode))
|
||||
printf("S_IFSOCK ");
|
||||
#ifdef S_ISWHT
|
||||
if (S_ISWHT(mode))
|
||||
printf("S_ISWHT ");
|
||||
#endif
|
||||
perms(getperm(mode));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int
|
||||
printst(st)
|
||||
struct stat *st;
|
||||
{
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
char *owner;
|
||||
int ma, mi, d;
|
||||
|
||||
ma = major (st->st_rdev);
|
||||
mi = minor (st->st_rdev);
|
||||
#if defined (makedev)
|
||||
d = makedev (ma, mi);
|
||||
#else
|
||||
d = st->st_rdev & 0xFF;
|
||||
#endif
|
||||
printf("Device (major/minor): %d (%d/%d)\n", d, ma, mi);
|
||||
|
||||
printf("Inode: %d\n", (int) st->st_ino);
|
||||
printf("Mode: (%o) ", (int) st->st_mode);
|
||||
printmode((int) st->st_mode);
|
||||
printf("Link count: %d\n", (int) st->st_nlink);
|
||||
pw = getpwuid(st->st_uid);
|
||||
owner = pw ? pw->pw_name : "unknown";
|
||||
printf("Uid of owner: %d (%s)\n", (int) st->st_uid, owner);
|
||||
gr = getgrgid(st->st_gid);
|
||||
owner = gr ? gr->gr_name : "unknown";
|
||||
printf("Gid of owner: %d (%s)\n", (int) st->st_gid, owner);
|
||||
printf("Device type: %d\n", (int) st->st_rdev);
|
||||
printf("File size: %ld\n", (long) st->st_size);
|
||||
printf("File last access time: %s", ctime (&st->st_atime));
|
||||
printf("File last modify time: %s", ctime (&st->st_mtime));
|
||||
printf("File last status change time: %s", ctime (&st->st_ctime));
|
||||
fflush(stdout);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
printsome(f, flags)
|
||||
char *f;
|
||||
int flags;
|
||||
{
|
||||
struct stat *st;
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
int p;
|
||||
char *b;
|
||||
|
||||
st = getstat(f);
|
||||
if (st == NULL)
|
||||
return (1);
|
||||
|
||||
/* Print requested info */
|
||||
if (flags & OPT_ATIME) {
|
||||
if (flags & OPT_ASCII)
|
||||
printf("%s", ctime(&st->st_atime));
|
||||
else
|
||||
printf("%ld\n", st->st_atime);
|
||||
} else if (flags & OPT_MTIME) {
|
||||
if (flags & OPT_ASCII)
|
||||
printf("%s", ctime(&st->st_mtime));
|
||||
else
|
||||
printf("%ld\n", st->st_mtime);
|
||||
} else if (flags & OPT_CTIME) {
|
||||
if (flags & OPT_ASCII)
|
||||
printf("%s", ctime(&st->st_ctime));
|
||||
else
|
||||
printf("%ld\n", st->st_ctime);
|
||||
} else if (flags & OPT_DEV)
|
||||
printf("%d\n", st->st_dev);
|
||||
else if (flags & OPT_INO)
|
||||
printf("%d\n", st->st_ino);
|
||||
else if (flags & OPT_FID)
|
||||
printf("%d:%ld\n", st->st_dev, st->st_ino);
|
||||
else if (flags & OPT_NLINK)
|
||||
printf("%d\n", st->st_nlink);
|
||||
else if (flags & OPT_LNKNAM) {
|
||||
#ifdef S_ISLNK
|
||||
b = xmalloc(4096);
|
||||
p = readlink(f, b, 4096);
|
||||
if (p >= 0 && p < 4096)
|
||||
b[p] = '\0';
|
||||
else {
|
||||
p = errno;
|
||||
strcpy(b, prog);
|
||||
strcat(b, ": ");
|
||||
strcat(b, strerror(p));
|
||||
}
|
||||
printf("%s\n", b);
|
||||
free(b);
|
||||
#else
|
||||
printf("%s\n", f);
|
||||
#endif
|
||||
} else if (flags & OPT_PERM) {
|
||||
perms(st->st_mode);
|
||||
printf("\n");
|
||||
} else if (flags & OPT_OPERM)
|
||||
printf("%o\n", getperm(st->st_mode));
|
||||
else if (flags & OPT_PMASK)
|
||||
printf("%o\n", getperm(st->st_mode) & pmask);
|
||||
else if (flags & OPT_UID) {
|
||||
pw = getpwuid(st->st_uid);
|
||||
if (flags & OPT_ASCII)
|
||||
printf("%s\n", pw ? pw->pw_name : "unknown");
|
||||
else
|
||||
printf("%d\n", st->st_uid);
|
||||
} else if (flags & OPT_GID) {
|
||||
gr = getgrgid(st->st_gid);
|
||||
if (flags & OPT_ASCII)
|
||||
printf("%s\n", gr ? gr->gr_name : "unknown");
|
||||
else
|
||||
printf("%d\n", st->st_gid);
|
||||
} else if (flags & OPT_SIZE)
|
||||
printf("%ld\n", (long) st->st_size);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifndef NOBUILTIN
|
||||
int
|
||||
finfo_builtin(list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int c, r;
|
||||
char **v;
|
||||
WORD_LIST *l;
|
||||
|
||||
v = make_builtin_argv (list, &c);
|
||||
r = finfo_main (c, v);
|
||||
free (v);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static char *finfo_doc[] = {
|
||||
"Display information about file attributes.",
|
||||
"",
|
||||
"Display information about each FILE. Only single operators should",
|
||||
"be supplied. If no options are supplied, a summary of the info",
|
||||
"available about each FILE is printed. If FILE is of the form",
|
||||
"/dev/fd/XX, file descriptor XX is described. Operators, if supplied,",
|
||||
"have the following meanings:",
|
||||
"",
|
||||
" -a last file access time",
|
||||
" -A last file access time in ctime format",
|
||||
" -c last file status change time",
|
||||
" -C last file status change time in ctime format",
|
||||
" -m last file modification time",
|
||||
" -M last file modification time in ctime format",
|
||||
" -d device",
|
||||
" -i inode",
|
||||
" -f composite file identifier (device:inode)",
|
||||
" -g gid of owner",
|
||||
" -G group name of owner",
|
||||
" -l name of file pointed to by symlink",
|
||||
" -n link count",
|
||||
" -o permissions in octal",
|
||||
" -p permissions in ascii",
|
||||
" -P mask permissions ANDed with MASK (like with umask)",
|
||||
" -s file size in bytes",
|
||||
" -u uid of owner",
|
||||
" -U user name of owner",
|
||||
(char *)0
|
||||
};
|
||||
|
||||
struct builtin finfo_struct = {
|
||||
"finfo",
|
||||
finfo_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
finfo_doc,
|
||||
"finfo [-acdgiflmnopsuACGMPU] file [file...]",
|
||||
0
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef NOBUILTIN
|
||||
#if defined (PREFER_STDARG)
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# if defined (PREFER_VARARGS)
|
||||
# include <varargs.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
char *this_command_name;
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
this_command_name = argv[0];
|
||||
exit(finfo_main(argc, argv));
|
||||
}
|
||||
|
||||
void
|
||||
builtin_usage()
|
||||
{
|
||||
fprintf(stderr, "%s: usage: %s [-%s] [file ...]\n", prog, OPTIONS);
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
char *
|
||||
strerror(e)
|
||||
int e;
|
||||
{
|
||||
static char ebuf[40];
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
|
||||
if (e < 0 || e > sys_nerr) {
|
||||
sprintf(ebuf,"Unknown error code %d", e);
|
||||
return (&ebuf[0]);
|
||||
}
|
||||
return (sys_errlist[e]);
|
||||
}
|
||||
#endif
|
||||
|
||||
char *
|
||||
xmalloc(s)
|
||||
size_t s;
|
||||
{
|
||||
char *ret;
|
||||
extern char *malloc();
|
||||
|
||||
ret = malloc(s);
|
||||
if (ret)
|
||||
return (ret);
|
||||
fprintf(stderr, "%s: cannot malloc %d bytes\n", prog, s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *
|
||||
base_pathname(p)
|
||||
char *p;
|
||||
{
|
||||
char *t;
|
||||
|
||||
if (t = strrchr(p, '/'))
|
||||
return(++t);
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
legal_number (string, result)
|
||||
char *string;
|
||||
long *result;
|
||||
{
|
||||
int sign;
|
||||
long value;
|
||||
|
||||
sign = 1;
|
||||
value = 0;
|
||||
|
||||
if (result)
|
||||
*result = 0;
|
||||
|
||||
/* Skip leading whitespace characters. */
|
||||
while (whitespace (*string))
|
||||
string++;
|
||||
|
||||
if (!*string)
|
||||
return (0);
|
||||
|
||||
/* We allow leading `-' or `+'. */
|
||||
if (*string == '-' || *string == '+')
|
||||
{
|
||||
if (!digit (string[1]))
|
||||
return (0);
|
||||
|
||||
if (*string == '-')
|
||||
sign = -1;
|
||||
|
||||
string++;
|
||||
}
|
||||
|
||||
while (digit (*string))
|
||||
{
|
||||
if (result)
|
||||
value = (value * 10) + digit_value (*string);
|
||||
string++;
|
||||
}
|
||||
|
||||
/* Skip trailing whitespace, if any. */
|
||||
while (whitespace (*string))
|
||||
string++;
|
||||
|
||||
/* Error if not at end of string. */
|
||||
if (*string)
|
||||
return (0);
|
||||
|
||||
if (result)
|
||||
*result = value * sign;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int sh_optind;
|
||||
char *sh_optarg;
|
||||
int sh_opterr;
|
||||
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
int
|
||||
sh_getopt(c, v, o)
|
||||
int c;
|
||||
char **v, *o;
|
||||
{
|
||||
int r;
|
||||
|
||||
r = getopt(c, v, o);
|
||||
sh_optind = optind;
|
||||
sh_optarg = optarg;
|
||||
return r;
|
||||
}
|
||||
|
||||
#if defined (USE_VARARGS)
|
||||
void
|
||||
#if defined (PREFER_STDARG)
|
||||
builtin_error (const char *format, ...)
|
||||
#else
|
||||
builtin_error (format, va_alist)
|
||||
const char *format;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (this_command_name && *this_command_name)
|
||||
fprintf (stderr, "%s: ", this_command_name);
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
#endif
|
||||
|
||||
vfprintf (stderr, format, args);
|
||||
va_end (args);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
#else
|
||||
void
|
||||
builtin_error (format, arg1, arg2, arg3, arg4, arg5)
|
||||
char *format, *arg1, *arg2, *arg3, *arg4, *arg5;
|
||||
{
|
||||
if (this_command_name && *this_command_name)
|
||||
fprintf (stderr, "%s: ", this_command_name);
|
||||
|
||||
fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
|
||||
fprintf (stderr, "\n");
|
||||
fflush (stderr);
|
||||
}
|
||||
#endif /* !USE_VARARGS */
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,214 @@
|
||||
/* getconf.h -- replacement definitions for ones the system doesn't provide. */
|
||||
|
||||
#ifndef _GETCONF_H
|
||||
#define _GETCONF_H
|
||||
|
||||
/* Some systems do not define these; use POSIX.2 minimum recommended values. */
|
||||
#ifndef _POSIX2_COLL_WEIGHTS_MAX
|
||||
# define _POSIX2_COLL_WEIGHTS_MAX 2
|
||||
#endif
|
||||
|
||||
/* If we're on a posix system, but the system doesn't define the necessary
|
||||
constants, use posix.1 minimum values. */
|
||||
#if defined (_POSIX_VERSION)
|
||||
|
||||
#ifndef _POSIX_ARG_MAX
|
||||
# define _POSIX_ARG_MAX 4096
|
||||
#endif
|
||||
#ifndef _POSIX_CHILD_MAX
|
||||
# define _POSIX_CHILD_MAX 6
|
||||
#endif
|
||||
#ifndef _POSIX_LINK_MAX
|
||||
# define _POSIX_LINK_MAX 8
|
||||
#endif
|
||||
#ifndef _POSIX_MAX_CANON
|
||||
# define _POSIX_MAX_CANON 255
|
||||
#endif
|
||||
#ifndef _POSIX_MAX_INPUT
|
||||
# define _POSIX_MAX_INPUT 255
|
||||
#endif
|
||||
#ifndef _POSIX_NAME_MAX
|
||||
# define _POSIX_NAME_MAX 14
|
||||
#endif
|
||||
#ifndef _POSIX_NGROUPS_MAX
|
||||
# define _POSIX_NGROUPS_MAX 0
|
||||
#endif
|
||||
#ifndef _POSIX_OPEN_MAX
|
||||
# define _POSIX_OPEN_MAX 16
|
||||
#endif
|
||||
#ifndef _POSIX_PATH_MAX
|
||||
# define _POSIX_PATH_MAX 255
|
||||
#endif
|
||||
#ifndef _POSIX_PIPE_BUF
|
||||
# define _POSIX_PIPE_BUF 512
|
||||
#endif
|
||||
#ifndef _POSIX_SSIZE_MAX
|
||||
# define _POSIX_SSIZE_MAX 32767
|
||||
#endif
|
||||
#ifndef _POSIX_STREAM_MAX
|
||||
# define _POSIX_STREAM_MAX 8
|
||||
#endif
|
||||
#ifndef _POSIX_TZNAME_MAX
|
||||
# define _POSIX_TZNAME_MAX 3
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX2_BC_BASE_MAX
|
||||
# define _POSIX2_BC_BASE_MAX 99
|
||||
#endif
|
||||
#ifndef _POSIX2_BC_DIM_MAX
|
||||
# define _POSIX2_BC_DIM_MAX 2048
|
||||
#endif
|
||||
#ifndef _POSIX2_BC_SCALE_MAX
|
||||
# define _POSIX2_BC_SCALE_MAX 99
|
||||
#endif
|
||||
#ifndef _POSIX2_BC_STRING_MAX
|
||||
# define _POSIX2_BC_STRING_MAX 1000
|
||||
#endif
|
||||
#ifndef _POSIX2_EQUIV_CLASS_MAX
|
||||
# define _POSIX2_EQUIV_CLASS_MAX 2
|
||||
#endif
|
||||
#ifndef _POSIX2_EXPR_NEST_MAX
|
||||
# define _POSIX2_EXPR_NEST_MAX 32
|
||||
#endif
|
||||
#ifndef _POSIX2_LINE_MAX
|
||||
# define _POSIX2_LINE_MAX 2048
|
||||
#endif
|
||||
#ifndef _POSIX2_RE_DUP_MAX
|
||||
# define _POSIX2_RE_DUP_MAX 255
|
||||
#endif
|
||||
|
||||
/* configurable system variables */
|
||||
#if !defined (HAVE_SYSCONF)
|
||||
|
||||
#ifndef _SC_ARG_MAX
|
||||
# define _SC_ARG_MAX 1
|
||||
# define _SC_CHILD_MAX 2
|
||||
# define _SC_CLK_TCK 3
|
||||
# define _SC_NGROUPS_MAX 4
|
||||
# define _SC_OPEN_MAX 5
|
||||
# define _SC_JOB_CONTROL 6
|
||||
# define _SC_SAVED_IDS 7
|
||||
# define _SC_VERSION 8
|
||||
# define _SC_BC_BASE_MAX 9
|
||||
# define _SC_BC_DIM_MAX 10
|
||||
# define _SC_BC_SCALE_MAX 11
|
||||
# define _SC_BC_STRING_MAX 12
|
||||
# define _SC_COLL_WEIGHTS_MAX 13
|
||||
# define _SC_EXPR_NEST_MAX 14
|
||||
# define _SC_LINE_MAX 15
|
||||
# define _SC_RE_DUP_MAX 16
|
||||
#if 0
|
||||
# define _SC_2_VERSION 17
|
||||
# define _SC_2_C_BIND 18
|
||||
# define _SC_2_C_DEV 19
|
||||
# define _SC_2_CHAR_TERM 20
|
||||
# define _SC_2_FORT_DEV 21
|
||||
# define _SC_2_FORT_RUN 22
|
||||
# define _SC_2_LOCALEDEF 23
|
||||
# define _SC_2_SW_DEV 24
|
||||
# define _SC_2_UPE 25
|
||||
#endif /* 0 */
|
||||
|
||||
# define _SC_STREAM_MAX 26
|
||||
# define _SC_TZNAME_MAX 27
|
||||
#endif /* !_SC_ARG_MAX */
|
||||
|
||||
#endif /* !HAVE_SYSCONF */
|
||||
|
||||
/* configurable pathname variables */
|
||||
#if !defined (HAVE_PATHCONF)
|
||||
|
||||
#ifndef _PC_LINK_MAX
|
||||
#define _PC_LINK_MAX 1
|
||||
#define _PC_MAX_CANON 2
|
||||
#define _PC_MAX_INPUT 3
|
||||
#define _PC_NAME_MAX 4
|
||||
#define _PC_PATH_MAX 5
|
||||
#define _PC_PIPE_BUF 6
|
||||
#define _PC_CHOWN_RESTRICTED 7
|
||||
#define _PC_NO_TRUNC 8
|
||||
#define _PC_VDISABLE 9
|
||||
#endif /* !_PC_LINK_MAX */
|
||||
|
||||
#endif /* !HAVE_PATHCONF */
|
||||
|
||||
#endif /* _POSIX_VERSION */
|
||||
|
||||
#ifndef _CS_PATH
|
||||
# define _CS_PATH 1
|
||||
#endif
|
||||
|
||||
/* ANSI/ISO C, POSIX.1-200x, XPG 4.2 (and later) C language type limits.
|
||||
Defined only if the system include files don't. Assume a 32-bit
|
||||
environment with signed 8-bit characters. */
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
# define CHAR_BIT 8
|
||||
#endif
|
||||
#ifndef CHAR_MAX
|
||||
# define CHAR_MAX 127
|
||||
#endif
|
||||
#ifndef CHAR_MIN
|
||||
# define CHAR_MIN -128
|
||||
#endif
|
||||
|
||||
#ifndef INT_BIT
|
||||
# define INT_BIT (sizeof (int) * CHAR_BIT)
|
||||
#endif
|
||||
#ifndef INT_MAX
|
||||
# define INT_MAX 2147483647
|
||||
#endif
|
||||
#ifndef INT_MIN
|
||||
# define INT_MIN (-2147483647-1)
|
||||
#endif
|
||||
|
||||
#ifndef LONG_BIT
|
||||
# define LONG_BIT (sizeof (long int) * CHAR_BIT)
|
||||
#endif
|
||||
#ifndef LONG_MAX
|
||||
# define LONG_MAX 2147483647L
|
||||
#endif
|
||||
#ifndef LONG_MIN
|
||||
# define LONG_MIN (-2147483647L-1L)
|
||||
#endif
|
||||
|
||||
#ifndef SCHAR_MAX
|
||||
# define SCHAR_MAX CHAR_MAX
|
||||
#endif
|
||||
#ifndef SCHAR_MIN
|
||||
# define SCHAR_MIN CHAR_MIN
|
||||
#endif
|
||||
|
||||
#ifndef SHRT_MAX
|
||||
# define SHRT_MAX 32767
|
||||
#endif
|
||||
#ifndef SHRT_MIN
|
||||
# define SHRT_MIN (-32768)
|
||||
#endif
|
||||
|
||||
#ifndef UCHAR_MAX
|
||||
# define UCHAR_MAX 255
|
||||
#endif
|
||||
#ifndef UINT_MAX
|
||||
# define UINT_MAX 4294967295U
|
||||
#endif
|
||||
#ifndef ULONG_MAX
|
||||
# define ULONG_MAX 4294967295UL
|
||||
#endif
|
||||
#ifndef USHRT_MAX
|
||||
# define UCHAR_MAX 65535
|
||||
#endif
|
||||
|
||||
/* assume size_t is `unsigned int'; ssize_t is `int' */
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX UINT_MAX
|
||||
#endif
|
||||
#ifndef SSIZE_MAX
|
||||
# define SSIZE_MAX INT_MAX
|
||||
#endif
|
||||
|
||||
#ifndef WORD_BIT
|
||||
# define WORD_BIT (sizeof (int) * CHAR_BIT)
|
||||
#endif
|
||||
|
||||
#endif /* _GETCONF_H */
|
||||
@@ -3,6 +3,24 @@
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
/*
|
||||
Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
Bash 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.
|
||||
|
||||
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/* Sample builtin to be dynamically loaded with enable -f and create a new
|
||||
builtin. */
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
/* A builtin `xxx' is normally implemented with an `xxx_builtin' function.
|
||||
If you're converting a command that uses the normal Unix argc/argv
|
||||
calling convention, use argv = make_builtin_argv (list, &argc) and call
|
||||
the original `main' something like `xxx_main'. Look at cat.c for an
|
||||
example.
|
||||
|
||||
Builtins should use internal_getopt to parse options. It is the same as
|
||||
getopt(3), but it takes a WORD_LIST *. Look at print.c for an example
|
||||
of its use.
|
||||
|
||||
If the builtin takes no options, call no_options(list) before doing
|
||||
anything else. If it returns a non-zero value, your builtin should
|
||||
immediately return EX_USAGE. Look at logname.c for an example.
|
||||
|
||||
A builtin command returns EXECUTION_SUCCESS for success and
|
||||
EXECUTION_FAILURE to indicate failure. */
|
||||
int
|
||||
hello_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
printf("hello world\n");
|
||||
fflush (stdout);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* An array of strings forming the `long' documentation for a builtin xxx,
|
||||
which is printed by `help xxx'. It must end with a NULL. By convention,
|
||||
the first line is a short description. */
|
||||
char *hello_doc[] = {
|
||||
"Sample builtin.",
|
||||
"",
|
||||
"this is the long doc for the sample hello builtin",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
/* The standard structure describing a builtin command. bash keeps an array
|
||||
of these structures. The flags must include BUILTIN_ENABLED so the
|
||||
builtin can be used. */
|
||||
struct builtin hello_struct = {
|
||||
"hello", /* builtin name */
|
||||
hello_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
hello_doc, /* array of long documentation strings. */
|
||||
"hello", /* usage synopsis; becomes short_doc */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(BUILTIN) && !defined(SHELL)
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "stdc.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
static char sbuf[1024];
|
||||
static int sblen;
|
||||
|
||||
/* Gee, I wish sprintf could be reliably counted upon to return the
|
||||
number of characters written :-( */
|
||||
#define PF(f, func) \
|
||||
do { \
|
||||
if (fieldwidth) \
|
||||
if (precision) \
|
||||
sprintf(sbuf, f, fieldwidth, precision, func); \
|
||||
else \
|
||||
sprintf(sbuf, f, fieldwidth, func); \
|
||||
else if (precision) \
|
||||
sprintf(sbuf, f, precision, func); \
|
||||
else \
|
||||
sprintf(sbuf, f, func); \
|
||||
spaddstr (sbuf, strlen (sbuf)); \
|
||||
} while (0)
|
||||
|
||||
static int asciicode __P((void));
|
||||
static void escape __P((char *));
|
||||
static int getchr __P((void));
|
||||
static double getdouble __P((void));
|
||||
static int getint __P((int *));
|
||||
static int getlong __P((long *));
|
||||
static char *getstr __P((void));
|
||||
static char *mklong __P((char *, int));
|
||||
static void usage __P((void));
|
||||
|
||||
static char **gargv;
|
||||
|
||||
static char *outstr;
|
||||
static int outsize;
|
||||
static int outind;
|
||||
|
||||
int sprintf_builtin ();
|
||||
static int sprintf_main ();
|
||||
static void spaddstr ();
|
||||
|
||||
extern char *this_command_name;
|
||||
extern char *single_quote ();
|
||||
extern char **make_builtin_argv ();
|
||||
|
||||
static char *sprintf_doc[] = {
|
||||
"Format arguments and assign result to variable.",
|
||||
"",
|
||||
"sprintf formats and outputs its arguments, after the second, under control",
|
||||
"of the format and assigns the result to the variable named by its first",
|
||||
"argument. The format is a character string which contains three types",
|
||||
"of objects: plain characters, which are simply copied to the output string,",
|
||||
"character escape sequences which are converted and copied to the output",
|
||||
"string, and format specifications, each of which causes printing of the",
|
||||
"next successive argument. In addition to the standard sprintf(3) formats,",
|
||||
"%b means to expand escapes in the corresponding argument, and %q means",
|
||||
"to quote the argument in a way that can be reused as shell input. Each",
|
||||
"one of the format specifications must not expand to more than 1024",
|
||||
"characters, though there is no limit on the total size of the output",
|
||||
"string.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin sprintf_struct = {
|
||||
"sprintf",
|
||||
sprintf_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
sprintf_doc,
|
||||
"sprintf var format [arguments]",
|
||||
(char *)0
|
||||
};
|
||||
|
||||
int
|
||||
sprintf_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int c, r;
|
||||
char **v, *varname;
|
||||
WORD_LIST *l;
|
||||
SHELL_VAR *var;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
varname = list->word->word;
|
||||
list = list->next;
|
||||
|
||||
if (legal_identifier (varname) == 0)
|
||||
{
|
||||
builtin_error ("%s: not a legal variable name", varname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
outind = 0;
|
||||
if (outstr == 0)
|
||||
outstr = xmalloc (outsize = 64);
|
||||
outstr[0] = '\0';
|
||||
|
||||
v = make_builtin_argv (list, &c);
|
||||
r = sprintf_main (c, v);
|
||||
free (v);
|
||||
|
||||
var = bind_variable (varname, outstr, 0);
|
||||
if (readonly_p (var))
|
||||
{
|
||||
builtin_error ("%s: readonly variable", varname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
spaddstr(str, len)
|
||||
char *str;
|
||||
int len;
|
||||
{
|
||||
RESIZE_MALLOCED_BUFFER (outstr, outind, len, outsize, 64);
|
||||
strcpy (outstr + outind, str);
|
||||
outind += len;
|
||||
}
|
||||
|
||||
static int
|
||||
sprintf_main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern int optind;
|
||||
static char *skip1, *skip2;
|
||||
int ch, end, fieldwidth, precision;
|
||||
char convch, nextch, *format, *fmt, *start;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch (ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic algorithm is to scan the format string for conversion
|
||||
* specifications -- once one is found, find out if the field
|
||||
* width or precision is a '*'; if it is, gather up value. Note,
|
||||
* format strings are reused as necessary to use up the provided
|
||||
* arguments, arguments of zero/null string are provided to use
|
||||
* up the format string.
|
||||
*/
|
||||
skip1 = "#-+ 0";
|
||||
skip2 = "*0123456789";
|
||||
|
||||
escape(fmt = format = *argv); /* backslash interpretation */
|
||||
gargv = ++argv;
|
||||
for (;;) {
|
||||
end = 0;
|
||||
/* find next format specification */
|
||||
next: for (start = fmt;; ++fmt) {
|
||||
if (!*fmt) {
|
||||
/* avoid infinite loop */
|
||||
if (end == 1) {
|
||||
warnx("missing format character",
|
||||
NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
end = 1;
|
||||
if (fmt > start)
|
||||
(void)printf("%s", start);
|
||||
if (!*gargv)
|
||||
return (0);
|
||||
fmt = format;
|
||||
goto next;
|
||||
}
|
||||
/* %% prints a % */
|
||||
if (*fmt == '%') {
|
||||
if (*++fmt != '%')
|
||||
break;
|
||||
*fmt++ = '\0';
|
||||
(void)printf("%s", start);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip to field width */
|
||||
for (; strchr(skip1, *fmt); ++fmt);
|
||||
if (*fmt == '*') {
|
||||
if (getint(&fieldwidth))
|
||||
return (1);
|
||||
} else
|
||||
fieldwidth = 0;
|
||||
|
||||
/* skip to possible '.', get following precision */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (*fmt == '.')
|
||||
++fmt;
|
||||
if (*fmt == '*') {
|
||||
if (getint(&precision))
|
||||
return (1);
|
||||
} else
|
||||
precision = 0;
|
||||
|
||||
/* skip to conversion char */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (!*fmt) {
|
||||
warnx("missing format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
|
||||
convch = *fmt;
|
||||
nextch = *++fmt;
|
||||
*fmt = '\0';
|
||||
switch(convch) {
|
||||
case 'c': {
|
||||
char p;
|
||||
|
||||
p = getchr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 'b': { /* expand escapes in argument */
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
escape(p);
|
||||
PF("%s", p);
|
||||
break;
|
||||
}
|
||||
case 'q': { /* print with shell single quoting */
|
||||
char *p, *p2;
|
||||
|
||||
p = getstr();
|
||||
p2 = single_quote(p);
|
||||
PF("%s", p2);
|
||||
free(p2);
|
||||
break;
|
||||
}
|
||||
case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
|
||||
long p;
|
||||
char *f;
|
||||
|
||||
if ((f = mklong(start, convch)) == NULL)
|
||||
return (1);
|
||||
if (getlong(&p))
|
||||
return (1);
|
||||
PF(f, p);
|
||||
break;
|
||||
}
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G': {
|
||||
double p;
|
||||
|
||||
p = getdouble();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warnx("illegal format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
*fmt = nextch;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static char *
|
||||
mklong(str, ch)
|
||||
char *str;
|
||||
int ch;
|
||||
{
|
||||
static char copy[64];
|
||||
int len;
|
||||
|
||||
len = strlen(str) + 2;
|
||||
memmove(copy, str, len - 3);
|
||||
copy[len - 3] = 'l';
|
||||
copy[len - 2] = ch;
|
||||
copy[len - 1] = '\0';
|
||||
return (copy);
|
||||
}
|
||||
|
||||
static void
|
||||
escape(fmt)
|
||||
register char *fmt;
|
||||
{
|
||||
register char *store;
|
||||
register int value, c;
|
||||
|
||||
for (store = fmt; c = *fmt; ++fmt, ++store) {
|
||||
if (c != '\\') {
|
||||
*store = c;
|
||||
continue;
|
||||
}
|
||||
switch (*++fmt) {
|
||||
case '\0': /* EOS, user error */
|
||||
*store = '\\';
|
||||
*++store = '\0';
|
||||
return;
|
||||
case '\\': /* backslash */
|
||||
case '\'': /* single quote */
|
||||
*store = *fmt;
|
||||
break;
|
||||
case 'a': /* bell/alert */
|
||||
*store = '\7';
|
||||
break;
|
||||
case 'b': /* backspace */
|
||||
*store = '\b';
|
||||
break;
|
||||
case 'c':
|
||||
return;
|
||||
case 'e':
|
||||
case 'E':
|
||||
*store = '\033';
|
||||
break;
|
||||
case 'f': /* form-feed */
|
||||
*store = '\f';
|
||||
break;
|
||||
case 'n': /* newline */
|
||||
*store = '\n';
|
||||
break;
|
||||
case 'r': /* carriage-return */
|
||||
*store = '\r';
|
||||
break;
|
||||
case 't': /* horizontal tab */
|
||||
*store = '\t';
|
||||
break;
|
||||
case 'v': /* vertical tab */
|
||||
*store = '\13';
|
||||
break;
|
||||
/* octal constant */
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
for (c = 3, value = 0;
|
||||
c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
|
||||
value <<= 3;
|
||||
value += *fmt - '0';
|
||||
}
|
||||
--fmt;
|
||||
*store = value;
|
||||
break;
|
||||
default:
|
||||
*store = *fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*store = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
getchr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ('\0');
|
||||
return ((int)**gargv++);
|
||||
}
|
||||
|
||||
static char *
|
||||
getstr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ("");
|
||||
return (*gargv++);
|
||||
}
|
||||
|
||||
static char *Number = "+-.0123456789";
|
||||
static int
|
||||
getint(ip)
|
||||
int *ip;
|
||||
{
|
||||
long val;
|
||||
|
||||
if (getlong(&val))
|
||||
return (1);
|
||||
if (val > INT_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
*ip = val;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getlong(lp)
|
||||
long *lp;
|
||||
{
|
||||
long val;
|
||||
char *ep;
|
||||
|
||||
if (!*gargv) {
|
||||
*lp = 0;
|
||||
return (0);
|
||||
}
|
||||
if (strchr(Number, **gargv)) {
|
||||
errno = 0;
|
||||
val = strtol(*gargv, &ep, 0);
|
||||
if (*ep != '\0') {
|
||||
warnx("%s: illegal number", *gargv, NULL);
|
||||
return (1);
|
||||
}
|
||||
if (errno == ERANGE)
|
||||
if (val == LONG_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
if (val == LONG_MIN) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
|
||||
*lp = val;
|
||||
++gargv;
|
||||
return (0);
|
||||
}
|
||||
*lp = (long)asciicode();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static double
|
||||
getdouble()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ((double)0);
|
||||
if (strchr(Number, **gargv))
|
||||
return (atof(*gargv++));
|
||||
return ((double)asciicode());
|
||||
}
|
||||
|
||||
static int
|
||||
asciicode()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
ch = **gargv;
|
||||
if (ch == '\'' || ch == '"')
|
||||
ch = (*gargv)[1];
|
||||
++gargv;
|
||||
return (ch);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: printf format [arg ...]\n");
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Originally from
|
||||
* http://www.excessus.demon.co.uk/misc-hacks/index.html#xtitle
|
||||
*/
|
||||
|
||||
/*
|
||||
* Made into a loadable builtin by chet@po.cwru.edu.
|
||||
*/
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "bashgetopt.h"
|
||||
#endif
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
int xtitle_builtin(WORD_LIST *list)
|
||||
#else
|
||||
int main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int query = 0;
|
||||
int fd;
|
||||
int openned = 0;
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
reset_internal_getopt();
|
||||
#endif
|
||||
for (;;) {
|
||||
#ifdef BASH_BUILTIN
|
||||
int i;
|
||||
i = internal_getopt(list, "q");
|
||||
#else
|
||||
int i = getopt(argc, argv, "q");
|
||||
#endif
|
||||
if (i < 0)
|
||||
break;
|
||||
switch (i) {
|
||||
case 'q':
|
||||
query = 1;
|
||||
break;
|
||||
default:
|
||||
#ifdef BASH_BUILTIN
|
||||
builtin_usage();
|
||||
#else
|
||||
fprintf(stderr, "usage: xtitle [-q] [string]\n");
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
if (!query && loptend == 0) {
|
||||
#else
|
||||
if (!query && optind == argc) {
|
||||
#endif
|
||||
fprintf(stderr, "xtitle: no string to set\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
{
|
||||
char *t = getenv("TERM");
|
||||
if (!t || strncmp(t, "xterm", 5))
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (isatty(0))
|
||||
fd = 0;
|
||||
else {
|
||||
fd = open("/dev/tty", O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "xtitle: couldn't open terminal: %s", strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
openned = 1;
|
||||
}
|
||||
|
||||
if (!query) {
|
||||
#ifdef BASH_BUILTIN
|
||||
WORD_LIST *l = loptend;
|
||||
char sp = ' ';
|
||||
write(fd, "\33]0;", 4);
|
||||
while (l) {
|
||||
write(fd, l->word->word, strlen(l->word->word));
|
||||
if (l->next)
|
||||
write(fd, &sp, 1);
|
||||
l = l->next;
|
||||
}
|
||||
write(fd, "\33\\", 2);
|
||||
#else
|
||||
int i;
|
||||
char sp = ' ';
|
||||
write(fd, "\33]0;", 4);
|
||||
for (i = optind; i < argc; i++) {
|
||||
write(fd, argv[i], strlen(argv[i]));
|
||||
if (i < argc - 1)
|
||||
write(fd, &sp, 1);
|
||||
}
|
||||
write(fd, "\33\\", 2);
|
||||
#endif
|
||||
} else {
|
||||
struct termios o, n;
|
||||
char hack;
|
||||
int state = 0;
|
||||
|
||||
tcgetattr(fd, &o);
|
||||
n = o;
|
||||
n.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|
||||
|INLCR|IGNCR|ICRNL|IXON);
|
||||
n.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
||||
n.c_cflag &= ~(CSIZE|PARENB);
|
||||
n.c_cflag |= CS8;
|
||||
tcsetattr(fd, TCSAFLUSH, &n);
|
||||
write(fd, "\33[21t", 5);
|
||||
|
||||
while (state != -1) {
|
||||
if (read(fd, &hack, 1) < 1)
|
||||
break;
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (hack == '\33') state = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (hack == ']') state = 2; else state = 0;
|
||||
break;
|
||||
case 2:
|
||||
if (hack == 'l') state = 3; else state = 0;
|
||||
break;
|
||||
case 3:
|
||||
if (hack == '\33') state = 4; else putchar(hack);
|
||||
break;
|
||||
case 4:
|
||||
if (hack == '\\') { state = -1; putchar('\n'); }
|
||||
else { putchar('\33'); putchar(hack); state = 3; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tcsetattr(fd, TCSAFLUSH, &o);
|
||||
}
|
||||
|
||||
if (openned)
|
||||
close(fd);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
|
||||
static char *xtitle_doc[] = {
|
||||
"Set xterm window title.",
|
||||
"",
|
||||
"Either set or read the title of the current xterm window. With the",
|
||||
"-q option, writes the current xterm title to standard output. Without",
|
||||
"the -q option, sets the xterm title to be the arguments given,",
|
||||
"separated by space characters. [By Mark Wooding, mdw@nsict.org]",
|
||||
0
|
||||
};
|
||||
|
||||
struct builtin xtitle_struct = {
|
||||
"xtitle",
|
||||
xtitle_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
xtitle_doc,
|
||||
"xtitle [-q] [arguments]",
|
||||
0
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
#Posted-Date: Fri, 9 Mar 90 18:34:29 EST
|
||||
#Date: Fri, 9 Mar 90 18:34:29 EST
|
||||
#From: "Eirik Fuller" <wonton.tn.cornell.edu!eirik@ucsbcsl.UUCP>
|
||||
#To: bfox@ai.mit.edu (Brian Fox)
|
||||
#Subject: Patch to bash 1.05 for SunView
|
||||
#
|
||||
#I think this works:
|
||||
#
|
||||
Mu|sun-cmd:am:bs:km:pt:li#34:co#80:cl=^L:ce=\E[K:cd=\E[J:rs=\E[s:
|
||||
#
|
||||
#Another alternative is to send the ti string at startup time (and, I
|
||||
#guess, the te string at exit time); that is how vi works in a cmdtool.
|
||||
#The best reason to not do this is that this also disables scrolling
|
||||
#which, as I understand it, is why anyone would use cmdtool in the
|
||||
#first place. Sending the ti string at startup time would do strange
|
||||
#things on other systems too; in xterm it would use the alternate
|
||||
#screen.
|
||||
#
|
||||
#The problem with cmdtool, in case that is less than obvious, is that
|
||||
#almost none of the capabilities advertised in /etc/termcap are enabled
|
||||
#while scrolling is enabled. It has other problems too, like being
|
||||
#part of an outdated proprietary windowing system, but there's probably
|
||||
#no need to dwell on that. In a sense, though, the sun-cmd termcap
|
||||
#entry doesn't lie about the capabilities; I think the termcap man page
|
||||
#does warn about some terminals having cursor motion capabilities only
|
||||
#in the "ti/te window".
|
||||
#
|
||||
#A general solution to this problem would require a termcap capability
|
||||
#which somehow tells which features are available outside of the ti/te
|
||||
#window. There is no such capability in termcap now, of course.
|
||||
@@ -0,0 +1,27 @@
|
||||
From mikel@ora.com Tue Aug 1 12:13:20 1995
|
||||
Flags: 10
|
||||
Return-Path: mikel@ora.com
|
||||
Received: from ruby.ora.com (ruby.ora.com [198.112.208.25]) by odin.INS.CWRU.Edu with ESMTP (8.6.12+cwru/CWRU-2.1-ins)
|
||||
id MAA01565; Tue, 1 Aug 1995 12:13:18 -0400 (from mikel@ora.com for <chet@odin.INS.CWRU.Edu>)
|
||||
Received: (from fax@localhost) by ruby.ora.com (8.6.12/8.6.11) with UUCP id MAA23251; Tue, 1 Aug 1995 12:07:51 -0400
|
||||
Received: by los.ora.com (4.1/Spike-2.1)
|
||||
id AA00672; Tue, 1 Aug 95 08:57:32 EDT
|
||||
Date: Tue, 1 Aug 95 08:57:32 EDT
|
||||
From: mikel@ora.com (Michael Loukides)
|
||||
Message-Id: <9508011257.AA00672@los.ora.com>
|
||||
Subject: Re: Ksh debugger from Rosenblatt's book [for bash]
|
||||
To: Chet Ramey <chet@odin.INS.CWRU.Edu>
|
||||
Cc: cmarie@ora.com, cam@iinet.com.au, brosenblatt@tm.com
|
||||
In-Reply-To: Chet Ramey <chet@odin.INS.CWRU.Edu>, Mon, 31 Jul 1995 16:22:48 -0400
|
||||
|
||||
I've modified a (modified) version of Bill Rosenblatt's ksh debugger
|
||||
to work with bash-2.0. Does ORA have any problem with me distributing
|
||||
it with bash-2.0?
|
||||
|
||||
That's great!
|
||||
|
||||
Go ahead and circulate it; in fact, we should probably grab it and
|
||||
stick it in our ftp archive, and put a reference to it in the book.
|
||||
(Too late to actually discuss the thing, at least for this edition).
|
||||
-------
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
This is a sample implementation of a bash debugger. It is not the same
|
||||
as the project available from http://bashdb.sourceforge.net, and has been
|
||||
deprecated in favor of that implementation.
|
||||
Executable
+581
@@ -0,0 +1,581 @@
|
||||
#! /bin/bash
|
||||
# bashdb - Bash shell debugger
|
||||
#
|
||||
# Adapted from an idea in O'Reilly's `Learning the Korn Shell'
|
||||
# Copyright (C) 1993-1994 O'Reilly and Associates, Inc.
|
||||
# Copyright (C) 1998, 1999, 2001 Gary V. Vaughan <gvv@techie.com>>
|
||||
#
|
||||
# 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 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, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# NOTE:
|
||||
#
|
||||
# This program requires bash 2.x.
|
||||
# If bash 2.x is installed as "bash2", you can invoke bashdb like this:
|
||||
#
|
||||
# DEBUG_SHELL=/bin/bash2 /bin/bash2 bashdb script.sh
|
||||
|
||||
# TODO:
|
||||
#
|
||||
# break [regexp]
|
||||
# cond [break] [condition]
|
||||
# tbreak [regexp|+lines]
|
||||
# restart
|
||||
# Variable watchpoints
|
||||
# Instrument `source' and `.' files in $_potbelliedpig
|
||||
# be cleverer about lines we allow breakpoints to be set on
|
||||
# break [function_name]
|
||||
|
||||
echo 'Bash Debugger version 1.2.4'
|
||||
|
||||
export _dbname=${0##*/}
|
||||
|
||||
if test $# -lt 1; then
|
||||
echo "$_dbname: Usage: $_dbname filename" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
_guineapig=$1
|
||||
|
||||
if test ! -r $1; then
|
||||
echo "$_dbname: Cannot read file '$_guineapig'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
__debug=${TMPDIR-/tmp}/bashdb.$$
|
||||
sed -e '/^# bashdb - Bash shell debugger/,/^# -- DO NOT DELETE THIS LINE -- /d' "$0" > $__debug
|
||||
cat $_guineapig >> $__debug
|
||||
exec ${DEBUG_SHELL-bash} $__debug $_guineapig "$@"
|
||||
|
||||
exit 1
|
||||
|
||||
# -- DO NOT DELETE THIS LINE -- The program depends on it
|
||||
|
||||
#bashdb preamble
|
||||
# $1 name of the original guinea pig script
|
||||
|
||||
__debug=$0
|
||||
_guineapig=$1
|
||||
__steptrap_calls=0
|
||||
|
||||
shift
|
||||
|
||||
shopt -s extglob # turn on extglob so we can parse the debugger funcs
|
||||
|
||||
function _steptrap
|
||||
{
|
||||
local i=0
|
||||
|
||||
_curline=$1
|
||||
|
||||
if (( ++__steptrap_calls > 1 && $_curline == 1 )); then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -n "$_disps" ]; then
|
||||
while (( $i < ${#_disps[@]} ))
|
||||
do
|
||||
if [ -n "${_disps[$i]}" ]; then
|
||||
_msg "${_disps[$i]}: \c"
|
||||
eval _msg ${_disps[$i]}
|
||||
fi
|
||||
let i=$i+1
|
||||
done
|
||||
fi
|
||||
|
||||
if (( $_trace )); then
|
||||
_showline $_curline
|
||||
fi
|
||||
|
||||
if (( $_steps >= 0 )); then
|
||||
let _steps="$_steps - 1"
|
||||
fi
|
||||
|
||||
if _at_linenumbp ; then
|
||||
_msg "Reached breakpoint at line $_curline"
|
||||
_showline $_curline
|
||||
_cmdloop
|
||||
elif [ -n "$_brcond" ] && eval $_brcond; then
|
||||
_msg "Break condition $_brcond true at line $_curline"
|
||||
_showline $_curline
|
||||
_cmdloop
|
||||
elif (( $_steps == 0 )); then
|
||||
# Assuming a real script will have the "#! /bin/sh" at line 1,
|
||||
# assume that when $_curline == 1 we are inside backticks.
|
||||
if (( ! $_trace )); then
|
||||
_msg "Stopped at line $_curline"
|
||||
_showline $_curline
|
||||
fi
|
||||
_cmdloop
|
||||
fi
|
||||
}
|
||||
|
||||
function _setbp
|
||||
{
|
||||
local i f line _x
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
_listbp
|
||||
return
|
||||
fi
|
||||
|
||||
eval "$_seteglob"
|
||||
|
||||
if [[ $1 == *(\+)[1-9]*([0-9]) ]]; then
|
||||
case $1 in
|
||||
+*)
|
||||
# normalize argument, then double it (+2 -> +2 + 2 = 4)
|
||||
_x=${1##*([!1-9])} # cut off non-numeric prefix
|
||||
_x=${x%%*([!0-9])} # cut off non-numeric suffix
|
||||
f=$(( $1 + $_x ))
|
||||
;;
|
||||
*)
|
||||
f=$(( $1 ))
|
||||
;;
|
||||
esac
|
||||
|
||||
# find the next valid line
|
||||
line="${_lines[$f]}"
|
||||
while _invalidbreakp $f
|
||||
do
|
||||
(( f++ ))
|
||||
line="${_lines[$f]}"
|
||||
done
|
||||
|
||||
if (( $f != $1 ))
|
||||
then
|
||||
_msg "Line $1 is not a valid breakpoint"
|
||||
fi
|
||||
|
||||
if [ -n "${_lines[$f]}" ]; then
|
||||
_linebp[$1]=$1;
|
||||
_msg "Breakpoint set at line $f"
|
||||
else
|
||||
_msg "Breakpoints can only be set on executable lines"
|
||||
fi
|
||||
else
|
||||
_msg "Please specify a numeric line number"
|
||||
fi
|
||||
|
||||
eval "$_resteglob"
|
||||
}
|
||||
|
||||
function _listbp
|
||||
{
|
||||
local i
|
||||
|
||||
if [ -n "$_linebp" ]; then
|
||||
_msg "Breakpoints:"
|
||||
for i in ${_linebp[*]}; do
|
||||
_showline $i
|
||||
done
|
||||
else
|
||||
_msg "No breakpoints have been set"
|
||||
fi
|
||||
}
|
||||
|
||||
function _clearbp
|
||||
{
|
||||
local i
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
read -e -p "Delete all breakpoints? "
|
||||
case $REPLY in
|
||||
[yY]*)
|
||||
unset _linebp[*]
|
||||
_msg "All breakpoints have been cleared"
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
fi
|
||||
|
||||
eval "$_seteglob"
|
||||
|
||||
if [[ $1 == [1-9]*([0-9]) ]]; then
|
||||
unset _linebp[$1]
|
||||
_msg "Breakpoint cleared at line $1"
|
||||
else
|
||||
_msg "Please specify a numeric line number"
|
||||
fi
|
||||
|
||||
eval "$_resteglob"
|
||||
}
|
||||
|
||||
function _setbc
|
||||
{
|
||||
if (( $# > 0 )); then
|
||||
_brcond=$@
|
||||
_msg "Break when true: $_brcond"
|
||||
else
|
||||
_brcond=
|
||||
_msg "Break condition cleared"
|
||||
fi
|
||||
}
|
||||
|
||||
function _setdisp
|
||||
{
|
||||
if [ -z "$1" ]; then
|
||||
_listdisp
|
||||
else
|
||||
_disps[${#_disps[@]}]="$1"
|
||||
if (( ${#_disps[@]} < 10 ))
|
||||
then
|
||||
_msg " ${#_disps[@]}: $1"
|
||||
else
|
||||
_msg "${#_disps[@]}: $1"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function _listdisp
|
||||
{
|
||||
local i=0 j
|
||||
|
||||
if [ -n "$_disps" ]; then
|
||||
while (( $i < ${#_disps[@]} ))
|
||||
do
|
||||
let j=$i+1
|
||||
if (( ${#_disps[@]} < 10 ))
|
||||
then
|
||||
_msg " $j: ${_disps[$i]}"
|
||||
else
|
||||
_msg "$j: ${_disps[$i]}"
|
||||
fi
|
||||
let i=$j
|
||||
done
|
||||
else
|
||||
_msg "No displays have been set"
|
||||
fi
|
||||
}
|
||||
|
||||
function _cleardisp
|
||||
{
|
||||
if (( $# < 1 )) ; then
|
||||
read -e -p "Delete all display expressions? "
|
||||
case $REPLY in
|
||||
[Yy]*)
|
||||
unset _disps[*]
|
||||
_msg "All breakpoints have been cleared"
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
fi
|
||||
|
||||
eval "$_seteglob"
|
||||
|
||||
if [[ $1 == [1-9]*([0-9]) ]]; then
|
||||
unset _disps[$1]
|
||||
_msg "Display $i has been cleared"
|
||||
else
|
||||
_listdisp
|
||||
_msg "Please specify a numeric display number"
|
||||
fi
|
||||
|
||||
eval "$_resteglob"
|
||||
}
|
||||
|
||||
# usage _ftrace -u funcname [funcname...]
|
||||
function _ftrace
|
||||
{
|
||||
local _opt=-t _tmsg="enabled" _func
|
||||
if [[ $1 == -u ]]; then
|
||||
_opt=+t
|
||||
_tmsg="disabled"
|
||||
shift
|
||||
fi
|
||||
for _func; do
|
||||
declare -f $_opt $_func
|
||||
_msg "Tracing $_tmsg for function $_func"
|
||||
done
|
||||
}
|
||||
|
||||
function _cmdloop
|
||||
{
|
||||
local cmd args
|
||||
|
||||
while read -e -p "bashdb> " cmd args; do
|
||||
test -n "$cmd" && history -s "$cmd $args" # save on history list
|
||||
test -n "$cmd" || { set $_lastcmd; cmd=$1; shift; args=$*; }
|
||||
if [ -n "$cmd" ]
|
||||
then
|
||||
case $cmd in
|
||||
b|br|bre|brea|break)
|
||||
_setbp $args
|
||||
_lastcmd="break $args"
|
||||
;;
|
||||
co|con)
|
||||
_msg "ambiguous command: '$cmd', condition, continue?"
|
||||
;;
|
||||
cond|condi|condit|conditi|conditio|condition)
|
||||
_setbc $args
|
||||
_lastcmd="condition $args"
|
||||
;;
|
||||
c|cont|conti|contin|continu|continue)
|
||||
_lastcmd="continue"
|
||||
return
|
||||
;;
|
||||
d)
|
||||
_msg "ambiguous command: '$cmd', delete, display?"
|
||||
;;
|
||||
de|del|dele|delet|delete)
|
||||
_clearbp $args
|
||||
_lastcmd="delete $args"
|
||||
;;
|
||||
di|dis|disp|displ|displa|display)
|
||||
_setdisp $args
|
||||
_lastcmd="display $args"
|
||||
;;
|
||||
f|ft|ftr|ftra|ftrace)
|
||||
_ftrace $args
|
||||
_lastcmd="ftrace $args"
|
||||
;;
|
||||
\?|h|he|hel|help)
|
||||
_menu
|
||||
_lastcmd="help"
|
||||
;;
|
||||
l|li|lis|list)
|
||||
_displayscript $args
|
||||
# _lastcmd is set in the _displayscript function
|
||||
;;
|
||||
p|pr|pri|prin|print)
|
||||
_examine $args
|
||||
_lastcmd="print $args"
|
||||
;;
|
||||
q|qu|qui|quit)
|
||||
exit
|
||||
;;
|
||||
s|st|ste|step|n|ne|nex|next)
|
||||
let _steps=${args:-1}
|
||||
_lastcmd="next $args"
|
||||
return
|
||||
;;
|
||||
t|tr|tra|trac|trace)
|
||||
_xtrace
|
||||
;;
|
||||
u|un|und|undi|undis|undisp|undispl|undispla|undisplay)
|
||||
_cleardisp $args
|
||||
_lastcmd="undisplay $args"
|
||||
;;
|
||||
!*)
|
||||
eval ${cmd#!} $args
|
||||
_lastcmd="$cmd $args"
|
||||
;;
|
||||
*)
|
||||
_msg "Invalid command: '$cmd'"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function _at_linenumbp
|
||||
{
|
||||
[[ -n ${_linebp[$_curline]} ]]
|
||||
}
|
||||
|
||||
function _invalidbreakp
|
||||
{
|
||||
local line=${_lines[$1]}
|
||||
|
||||
# XXX - should use shell patterns
|
||||
if test -z "$line" \
|
||||
|| expr "$line" : '[ \t]*#.*' > /dev/null \
|
||||
|| expr "$line" : '[ \t]*;;[ \t]*$' > /dev/null \
|
||||
|| expr "$line" : '[ \t]*[^)]*)[ \t]*$' > /dev/null \
|
||||
|| expr "$line" : '[ \t]*;;[ \t]*#.**$' > /dev/null \
|
||||
|| expr "$line" : '[ \t]*[^)]*)[ \t]*;;[ \t]*$' > /dev/null \
|
||||
|| expr "$line" : '[ \t]*[^)]*)[ \t]*;;*[ \t]*#.*$' > /dev/null
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
function _examine
|
||||
{
|
||||
if [ -n "$*" ]; then
|
||||
_msg "$args: \c"
|
||||
eval _msg $args
|
||||
else
|
||||
_msg "Nothing to print"
|
||||
fi
|
||||
}
|
||||
|
||||
function _displayscript
|
||||
{
|
||||
local i j start end bp cl
|
||||
|
||||
if (( $# == 1 )); then # list 5 lines on either side of $1
|
||||
if [ $1 = "%" ]; then
|
||||
let start=1
|
||||
let end=${#_lines[@]}
|
||||
else
|
||||
let start=$1-5
|
||||
let end=$1+5
|
||||
fi
|
||||
elif (( $# > 1 )); then # list between start and end
|
||||
if [ $1 = "^" ]; then
|
||||
let start=1
|
||||
else
|
||||
let start=$1
|
||||
fi
|
||||
|
||||
if [ $2 = "\$" ]; then
|
||||
let end=${#_lines[@]}
|
||||
else
|
||||
let end=$2
|
||||
fi
|
||||
else # list 5 lines on either side of current line
|
||||
let start=$_curline-5
|
||||
let end=$_curline+5
|
||||
fi
|
||||
|
||||
# normalize start and end
|
||||
if (( $start < 1 )); then
|
||||
start=1
|
||||
fi
|
||||
if (( $end > ${#_lines[@]} )); then
|
||||
end=${#_lines[@]}
|
||||
fi
|
||||
|
||||
cl=$(( $end - $start ))
|
||||
if (( $cl > ${LINES-24} )); then
|
||||
pager=${PAGER-more}
|
||||
else
|
||||
pager=cat
|
||||
fi
|
||||
|
||||
i=$start
|
||||
( while (( $i <= $end )); do
|
||||
_showline $i
|
||||
let i=$i+1
|
||||
done ) 2>&1 | $pager
|
||||
|
||||
# calculate the next block of lines
|
||||
start=$(( $end + 1 ))
|
||||
end=$(( $start + 11 ))
|
||||
if (( $end > ${#_lines[@]} ))
|
||||
then
|
||||
end=${#_lines[@]}
|
||||
fi
|
||||
|
||||
_lastcmd="list $start $end"
|
||||
}
|
||||
|
||||
function _xtrace
|
||||
{
|
||||
let _trace="! $_trace"
|
||||
if (( $_trace )); then
|
||||
_msg "Execution trace on"
|
||||
else
|
||||
_msg "Execution trace off"
|
||||
fi
|
||||
}
|
||||
|
||||
function _msg
|
||||
{
|
||||
echo -e "$@" >&2
|
||||
}
|
||||
|
||||
function _showline
|
||||
{
|
||||
local i=0 bp=' ' line=$1 cl=' '
|
||||
|
||||
if [[ -n ${_linebp[$line]} ]]; then
|
||||
bp='*'
|
||||
fi
|
||||
|
||||
if (( $_curline == $line )); then
|
||||
cl=">"
|
||||
fi
|
||||
|
||||
if (( $line < 100 )); then
|
||||
_msg "${_guineapig/*\//}:$line $bp $cl${_lines[$line]}"
|
||||
elif (( $line < 10 )); then
|
||||
_msg "${_guineapig/*\//}:$line $bp $cl${_lines[$line]}"
|
||||
elif (( $line > 0 )); then
|
||||
_msg "${_guineapig/*\//}:$line $bp $cl${_lines[$line]}"
|
||||
fi
|
||||
}
|
||||
|
||||
function _cleanup
|
||||
{
|
||||
rm -f $__debug $_potbelliedpig 2> /dev/null
|
||||
}
|
||||
|
||||
function _menu
|
||||
{
|
||||
_msg 'bashdb commands:
|
||||
break N set breakpoint at line N
|
||||
break list breakpoints & break condition
|
||||
condition foo set break condition to foo
|
||||
condition clear break condition
|
||||
delete N clear breakpoint at line N
|
||||
delete clear all breakpoints
|
||||
display EXP evaluate and display EXP for each debug step
|
||||
display show a list of display expressions
|
||||
undisplay N remove display expression N
|
||||
list N M display all lines of script between N and M
|
||||
list N display 5 lines of script either side of line N
|
||||
list display 5 lines if script either side of current line
|
||||
continue continue execution upto next breakpoint
|
||||
next [N] execute [N] statements (default 1)
|
||||
print expr prints the value of an expression
|
||||
trace toggle execution trace on/off
|
||||
ftrace [-u] func make the debugger step into function FUNC
|
||||
(-u turns off tracing FUNC)
|
||||
help print this menu
|
||||
! string passes string to a shell
|
||||
quit quit'
|
||||
}
|
||||
|
||||
shopt -u extglob
|
||||
|
||||
HISTFILE=~/.bashdb_history
|
||||
set -o history
|
||||
set +H
|
||||
|
||||
# strings to save and restore the setting of `extglob' in debugger functions
|
||||
# that need it
|
||||
_seteglob='local __eopt=-u ; shopt -q extglob && __eopt=-s ; shopt -s extglob'
|
||||
_resteglob='shopt $__eopt extglob'
|
||||
|
||||
_linebp=()
|
||||
let _trace=0
|
||||
let _i=1
|
||||
|
||||
# Be careful about quoted newlines
|
||||
_potbelliedpig=${TMPDIR-/tmp}/${_guineapig/*\//}.$$
|
||||
sed 's,\\$,\\\\,' $_guineapig > $_potbelliedpig
|
||||
|
||||
_msg "Reading source from file: $_guineapig"
|
||||
while read; do
|
||||
_lines[$_i]=$REPLY
|
||||
let _i=$_i+1
|
||||
done < $_potbelliedpig
|
||||
|
||||
trap _cleanup EXIT
|
||||
# Assuming a real script will have the "#! /bin/sh" at line 1,
|
||||
# don't stop at line 1 on the first run
|
||||
let _steps=1
|
||||
LINENO=-1
|
||||
trap '_steptrap $LINENO' DEBUG
|
||||
@@ -0,0 +1,177 @@
|
||||
;;; bashdb.el --- Grand Unified Debugger mode for running bashdb
|
||||
;; Copyright (C) 2000, 2001 Masatake YAMATO
|
||||
|
||||
;; Author: Masatake YAMATO <jet@gyve.org>
|
||||
|
||||
;; 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 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, write to the Free Software Foundation,
|
||||
;; Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
;; Commentary:
|
||||
;; This program may run on Emacs 21.0.91 and XEmacs 21.1.
|
||||
;;
|
||||
;; Put
|
||||
;; (autoload 'bashdb "bashdb" "Run bashdb" t nil)
|
||||
;; to your .emacs.
|
||||
;; M-x bashdb
|
||||
;; Run bashdb (like this): bashdb target.sh
|
||||
;;
|
||||
;; About bashdb:
|
||||
;; You can get bashdb from
|
||||
;; http://www.oranda.demon.co.uk/development.html
|
||||
;;
|
||||
;; bashdb.el is based on perldb in gud.el in XEmacs 21.1.
|
||||
|
||||
;; Revision:
|
||||
;; $Revision: 1.6 $
|
||||
;; $Log: bashdb.el,v $
|
||||
;; Revision 1.6 2001/01/06 12:18:06 masata-y
|
||||
;; Write note about XEmacs.
|
||||
;;
|
||||
;;
|
||||
|
||||
|
||||
;;; Code:
|
||||
(require 'gud)
|
||||
|
||||
;; User customizable variable
|
||||
(defcustom gud-bashdb-command-name "bashdb"
|
||||
"File name for executing Bashdb."
|
||||
:type 'string
|
||||
:group 'gud)
|
||||
|
||||
;; History of argument lists passed to bashdb.
|
||||
(defvar gud-bashdb-history nil)
|
||||
|
||||
(defun gud-bashdb-massage-args (file args)
|
||||
(if xemacsp
|
||||
(cons (file-name-nondirectory file) args)
|
||||
args))
|
||||
|
||||
;; There's no guarantee that Emacs will hand the filter the entire
|
||||
;; marker at once; it could be broken up across several strings. We
|
||||
;; might even receive a big chunk with several markers in it. If we
|
||||
;; receive a chunk of text which looks like it might contain the
|
||||
;; beginning of a marker, we save it here between calls to the
|
||||
;; filter.
|
||||
(if xemacsp
|
||||
(defvar gud-bashdb-marker-acc ""))
|
||||
(defun gud-bashdb-marker-acc ()
|
||||
(if xemacsp
|
||||
gud-bashdb-marker-acc
|
||||
gud-marker-acc))
|
||||
(defun gud-bashdb-marker-acc-quote ()
|
||||
(if xemacsp
|
||||
'gud-bashdb-marker-acc
|
||||
'gud-marker-acc))
|
||||
|
||||
(defun gud-bashdb-marker-filter (string)
|
||||
(save-match-data
|
||||
(set (gud-bashdb-marker-acc-quote)
|
||||
(concat (gud-bashdb-marker-acc) string))
|
||||
(let ((output ""))
|
||||
;; Process all the complete markers in this chunk.
|
||||
(while (string-match "^\\([^:\n]+\\):\\([0-9]+\\)[ *]*>.*\n"
|
||||
(gud-bashdb-marker-acc))
|
||||
(setq
|
||||
;; Extract the frame position from the marker.
|
||||
gud-last-frame (cons
|
||||
(substring (gud-bashdb-marker-acc)
|
||||
(match-beginning 1)
|
||||
(match-end 1))
|
||||
(string-to-int
|
||||
(substring (gud-bashdb-marker-acc)
|
||||
(match-beginning 2)
|
||||
(match-end 2))))
|
||||
;; Append any text before the marker to the output we're going
|
||||
;; to return - we don't include the marker in this text.
|
||||
output (concat output
|
||||
(substring (gud-bashdb-marker-acc) 0 (match-beginning 0))))
|
||||
;; Set the accumulator to the remaining text.
|
||||
(set
|
||||
(gud-bashdb-marker-acc-quote) (substring
|
||||
(gud-bashdb-marker-acc) (match-end 0))))
|
||||
|
||||
;; Does the remaining text look like it might end with the
|
||||
;; beginning of another marker? If it does, then keep it in
|
||||
;; (gud-bashdb-marker-acc) until we receive the rest of it. Since we
|
||||
;; know the full marker regexp above failed, it's pretty simple to
|
||||
;; test for marker starts.
|
||||
(if (string-match "^\\([^:\n]+\\):\\([0-9]+\\)[ *]*>" (gud-bashdb-marker-acc))
|
||||
(progn
|
||||
;; Everything before the potential marker start can be output.
|
||||
(setq output (concat output (substring (gud-bashdb-marker-acc)
|
||||
0 (match-beginning 0))))
|
||||
;; Everything after, we save, to combine with later input.
|
||||
(set (gud-bashdb-marker-acc-quote)
|
||||
(substring (gud-bashdb-marker-acc) (match-beginning 0))))
|
||||
|
||||
(setq output (concat output (gud-bashdb-marker-acc)))
|
||||
(set (gud-bashdb-marker-acc-quote) ""))
|
||||
|
||||
output)))
|
||||
|
||||
(defun gud-bashdb-find-file (f)
|
||||
(find-file-noselect f))
|
||||
|
||||
;;;###autoload
|
||||
(defun bashdb (command-line)
|
||||
"Run bashdb on program FILE in buffer *gud-FILE*.
|
||||
The directory containing FILE becomes the initial working directory
|
||||
and source-file directory for your debugger."
|
||||
(interactive
|
||||
(if xemacsp
|
||||
(list (read-from-minibuffer "Run bashdb (like this): "
|
||||
(if (consp gud-bashdb-history)
|
||||
(car gud-bashdb-history)
|
||||
(format "%s " gud-bashdb-command-name))
|
||||
nil nil
|
||||
'(gud-bashdb-history . 1)))
|
||||
(list (gud-query-cmdline 'bashdb))
|
||||
))
|
||||
|
||||
(if xemacsp
|
||||
(progn
|
||||
(gud-overload-functions '((gud-massage-args . gud-bashdb-massage-args)
|
||||
(gud-marker-filter . gud-bashdb-marker-filter)
|
||||
(gud-find-file . gud-bashdb-find-file)))
|
||||
(gud-common-init command-line gud-bashdb-command-name))
|
||||
(gud-common-init command-line 'gud-bashdb-massage-args
|
||||
'gud-bashdb-marker-filter 'gud-bashdb-find-file)
|
||||
(set (make-local-variable 'gud-minor-mode) 'bashdb))
|
||||
|
||||
;; Unsupported commands
|
||||
;; condition foo set break condition to foo
|
||||
;; condition clear break condition
|
||||
;; display EXP evaluate and display EXP for each debug step
|
||||
;; display show a list of display expressions
|
||||
;; undisplay N remove display expression N
|
||||
;; ! string passes string to a shell
|
||||
;; quit quit
|
||||
|
||||
(gud-def gud-break "break %l" "\C-b" "Set breakpoint at current line.")
|
||||
(gud-def gud-list-break "break" "b" "List breakpoints & break condition.")
|
||||
(gud-def gud-remove "delete %l" "\C-d" "Remove breakpoint at current line")
|
||||
(gud-def gud-remove-all "delete" "d" "Clear all breakpoints")
|
||||
(gud-def gud-cont "continue" "\C-r" "Continue with display.")
|
||||
(gud-def gud-next "next" "\C-n" "Step one line (skip functions).")
|
||||
(gud-def gud-print "print %e" "\C-p" "Evaluate bash expression at point.")
|
||||
(gud-def gud-help "help" "h" "Show all commands.")
|
||||
(gud-def gud-trace "trace" "t" "Toggle execution trace on/off")
|
||||
|
||||
(setq comint-prompt-regexp "^bashdb> ")
|
||||
(setq paragraph-start comint-prompt-regexp)
|
||||
(run-hooks 'bashdb-mode-hook))
|
||||
|
||||
(provide 'bashdb)
|
||||
;; bashdb.el ends here
|
||||
@@ -0,0 +1,561 @@
|
||||
#! /bin/bash
|
||||
# bashdb - Bash shell debugger
|
||||
#
|
||||
# Adapted from an idea in O'Reilly's `Learning the Korn Shell'
|
||||
# Copyright (C) 1993-1994 O'Reilly and Associates, Inc.
|
||||
# Copyright (C) 1998, 1999, 2001 Gary V. Vaughan <gvv@techie.com>>
|
||||
#
|
||||
# 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 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, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# NOTE:
|
||||
#
|
||||
# This program requires bash 2.x.
|
||||
# If bash 2.x is installed as "bash2", you can invoke bashdb like this:
|
||||
#
|
||||
# DEBUG_SHELL=/bin/bash2 /bin/bash2 bashdb script.sh
|
||||
|
||||
# TODO:
|
||||
#
|
||||
# break [regexp]
|
||||
# cond [break] [condition]
|
||||
# tbreak [regexp|+lines]
|
||||
# restart
|
||||
# Variable watchpoints
|
||||
# Output colourization
|
||||
# History with csh ^ substitution? Or write a readline frontend?
|
||||
# Instrument shell functions with the _steptrap in $_potbelliedpig
|
||||
# Instrument `source' and `.' files in $_potbelliedpig
|
||||
# be cleverer about lines we allow breakpoints to be set on
|
||||
# break [function_name]
|
||||
|
||||
|
||||
echo 'Bash Debugger version 1.2.4'
|
||||
|
||||
export _dbname=$(echo "X$0"|sed -e 's,^X,,' -e 's,^.*/,,')
|
||||
|
||||
if test $# -lt 1; then
|
||||
echo "$_dbname: Usage: $_dbname <filename>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
_guineapig=$1
|
||||
|
||||
if test ! -r $1; then
|
||||
echo "$_dbname: Cannot read file '$_guineapig'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
__debug=${TMPDIR-/tmp}/bashdb.$$
|
||||
sed -e '/^# bashdb - Bash shell debugger/,/^# -- DO NOT DELETE THIS LINE -- /d' "$0" > $__debug
|
||||
cat $_guineapig >> $__debug
|
||||
exec ${DEBUG_SHELL-bash} $__debug $_guineapig "$@"
|
||||
|
||||
exit 1
|
||||
|
||||
# -- DO NOT DELETE THIS LINE -- The program depends on it
|
||||
|
||||
#bashdb preamble
|
||||
# $1 name of the original guinea pig script
|
||||
|
||||
__debug=$0
|
||||
_guineapig=$1
|
||||
|
||||
shift
|
||||
|
||||
function _steptrap
|
||||
{
|
||||
local i=0
|
||||
|
||||
_curline=$1
|
||||
|
||||
if [ -n "$_disps" ]
|
||||
then
|
||||
while (( $i < ${#_disps[@]} ))
|
||||
do
|
||||
if [ -n "${_disps[$i]}" ]
|
||||
then
|
||||
_msg "${_disps[$i]}: \c"
|
||||
eval _msg ${_disps[$i]}
|
||||
fi
|
||||
let i=$i+1
|
||||
done
|
||||
fi
|
||||
|
||||
if (( $_trace )); then
|
||||
_showline $_curline
|
||||
fi
|
||||
|
||||
if (( $_steps >= 0 )); then
|
||||
let _steps="$_steps - 1"
|
||||
fi
|
||||
|
||||
if _at_linenumbp ; then
|
||||
_msg "Reached breakpoint at line $_curline"
|
||||
_showline $_curline
|
||||
_cmdloop
|
||||
elif [ -n "$_brcond" ] && eval $_brcond; then
|
||||
_msg "Break condition $_brcond true at line $_curline"
|
||||
_showline $_curline
|
||||
_cmdloop
|
||||
elif (( $_steps == 0 && $_curline > 1)); then
|
||||
# Assuming a real script will have the "#! /bin/sh" at line 1,
|
||||
# assume that when $_curline == 1 we are inside backticks.
|
||||
if (( ! $_trace )); then
|
||||
_msg "Stopped at line $_curline"
|
||||
_showline $_curline
|
||||
fi
|
||||
_cmdloop
|
||||
fi
|
||||
}
|
||||
|
||||
function _setbp
|
||||
{
|
||||
local i f line
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
_listbp
|
||||
elif [ $(echo $1 | grep '^\+*[1-9][0-9]*') ]
|
||||
then
|
||||
case $1 in
|
||||
+*)
|
||||
let f="$1 + `expr $1 : '+*\([1-9][0-9]*\)'`"
|
||||
;;
|
||||
*)
|
||||
let f=$1
|
||||
;;
|
||||
esac
|
||||
|
||||
# find the next valid line
|
||||
line="${_lines[$f]}"
|
||||
while _invalidbreakp $f
|
||||
do
|
||||
let f="$f + 1"
|
||||
line="${_lines[$f]}"
|
||||
done
|
||||
|
||||
if (( $f != $1 ))
|
||||
then
|
||||
_msg "Line $1 is not a valid breakpoint"
|
||||
fi
|
||||
|
||||
if [ -n "${_lines[$f]}" ]
|
||||
then
|
||||
_linebp=($(echo $( (for i in ${_linebp[*]} $1; do
|
||||
echo $i; done) | sort -n) ))
|
||||
_msg "Breakpoint set at line $f"
|
||||
else
|
||||
_msg "Breakpoints can only be set on executable lines"
|
||||
fi
|
||||
else
|
||||
_msg "Please specify a numeric line number"
|
||||
fi
|
||||
}
|
||||
|
||||
function _listbp
|
||||
{
|
||||
local i
|
||||
|
||||
if [ -n "$_linebp" ]
|
||||
then
|
||||
_msg "Breakpoints:"
|
||||
for i in ${_linebp[*]}; do
|
||||
_showline $i
|
||||
done
|
||||
else
|
||||
_msg "No breakpoints have been set"
|
||||
fi
|
||||
}
|
||||
|
||||
function _clearbp
|
||||
{
|
||||
local i
|
||||
if [ -z "$1" ]; then
|
||||
read -e -p "Delete all breakpoints? "
|
||||
case $REPLY in
|
||||
y*)
|
||||
unset _linebp[*]
|
||||
_msg "All breakpoints have been cleared"
|
||||
;;
|
||||
esac
|
||||
elif [ $(echo $1 | grep '^[0-9]*') ]; then
|
||||
_linebp=($(echo $(for i in ${_linebp[*]}; do
|
||||
if (( $1 != $i )); then echo $1; fi; done) ))
|
||||
_msg "Breakpoint cleared at line $1"
|
||||
else
|
||||
_msg "Please specify a numeric line number"
|
||||
fi
|
||||
}
|
||||
|
||||
function _setbc
|
||||
{
|
||||
if [ -n "$*" ]
|
||||
then
|
||||
_brcond=$args
|
||||
_msg "Break when true: $_brcond"
|
||||
else
|
||||
_brcond=
|
||||
_msg "Break condition cleared"
|
||||
fi
|
||||
}
|
||||
|
||||
function _setdisp
|
||||
{
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
_listdisp
|
||||
else
|
||||
_disps[${#_disps[@]}]="$1"
|
||||
if (( ${#_disps[@]} < 10 ))
|
||||
then
|
||||
_msg " ${#_disps[@]}: $1"
|
||||
else
|
||||
_msg "${#_disps[@]}: $1"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function _listdisp
|
||||
{
|
||||
local i=0 j
|
||||
|
||||
if [ -n "$_disps" ]
|
||||
then
|
||||
while (( $i < ${#_disps[@]} ))
|
||||
do
|
||||
let j=$i+1
|
||||
if (( ${#_disps[@]} < 10 ))
|
||||
then
|
||||
_msg " $j: ${_disps[$i]}"
|
||||
else
|
||||
_msg "$j: ${_disps[$i]}"
|
||||
fi
|
||||
let i=$j
|
||||
done
|
||||
else
|
||||
_msg "No displays have been set"
|
||||
fi
|
||||
}
|
||||
|
||||
function _cleardisp
|
||||
{
|
||||
if (( $# < 1 ))
|
||||
then
|
||||
read -e -p "Delete all display expressions? "
|
||||
case $REPLY in
|
||||
y*)
|
||||
unset _disps[*]
|
||||
_msg "All breakpoints have been cleared"
|
||||
;;
|
||||
esac
|
||||
elif [ $(echo $1 | grep '^[0-9]*') ]
|
||||
then
|
||||
unset _disps[$1]
|
||||
_msg "Display $i has been cleared"
|
||||
else
|
||||
_listdisp
|
||||
_msg "Please specify a numeric display number"
|
||||
fi
|
||||
}
|
||||
|
||||
function _cmdloop
|
||||
{
|
||||
local cmd args
|
||||
|
||||
while read -e -p "bashdb> " cmd args; do
|
||||
test -n "$cmd" || { set $_lastcmd; cmd=$1; shift; args=$*; }
|
||||
if [ -n "$cmd" ]
|
||||
then
|
||||
case $cmd in
|
||||
b|br|bre|brea|break)
|
||||
_setbp $args
|
||||
_lastcmd="break $args"
|
||||
;;
|
||||
co|con)
|
||||
_msg "ambiguous command: '$cmd', condition, continue?"
|
||||
;;
|
||||
cond|condi|condit|conditi|conditio|condition)
|
||||
_setbc $args
|
||||
_lastcmd="condition $args"
|
||||
;;
|
||||
c|cont|conti|contin|continu|continue)
|
||||
_lastcmd="continue"
|
||||
return
|
||||
;;
|
||||
d)
|
||||
_msg "ambiguous command: '$cmd', delete, display?"
|
||||
;;
|
||||
de|del|dele|delet|delete)
|
||||
_clearbp $args
|
||||
_lastcmd="delete $args"
|
||||
;;
|
||||
di|dis|disp|displ|displa|display)
|
||||
_setdisp $args
|
||||
_lastcmd="display $args"
|
||||
;;
|
||||
\?|h|he|hel|help)
|
||||
_menu
|
||||
_lastcmd="help"
|
||||
;;
|
||||
l|li|lis|list)
|
||||
_displayscript $args
|
||||
# _lastcmd is set in the _displayscript function
|
||||
;;
|
||||
p|pr|pri|prin|print)
|
||||
_examine $args
|
||||
_lastcmd="print $args"
|
||||
;;
|
||||
q|qu|qui|quit)
|
||||
exit
|
||||
;;
|
||||
s|st|ste|step|n|ne|nex|next)
|
||||
let _steps=${args:-1}
|
||||
_lastcmd="next $args"
|
||||
return
|
||||
;;
|
||||
t|tr|tra|trac|trace)
|
||||
_xtrace
|
||||
;;
|
||||
u|un|und|undi|undis|undisp|undispl|undispla|undisplay)
|
||||
_cleardisp $args
|
||||
_lastcmd="undisplay $args"
|
||||
;;
|
||||
!*)
|
||||
eval ${cmd#!} $args
|
||||
_lastcmd="$cmd $args"
|
||||
;;
|
||||
*)
|
||||
_msg "Invalid command: '$cmd'"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function _at_linenumbp
|
||||
{
|
||||
local i=0
|
||||
|
||||
if [ "$_linebp" ]
|
||||
then
|
||||
while (( $i < ${#_linebp[@]} )); do
|
||||
if (( ${_linebp[$i]} == $_curline )); then
|
||||
return 0
|
||||
fi
|
||||
let i=$i+1
|
||||
done
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
function _invalidbreakp
|
||||
{
|
||||
local line=${_lines[$1]}
|
||||
|
||||
if test -z "$line" \
|
||||
|| expr "$line" : '[ \t]*#.*' > /dev/null \
|
||||
|| expr "$line" : '[ \t]*;;[ \t]*$' > /dev/null \
|
||||
|| expr "$line" : '[ \t]*[^)]*)[ \t]*$' > /dev/null \
|
||||
|| expr "$line" : '[ \t]*;;[ \t]*#.**$' > /dev/null \
|
||||
|| expr "$line" : '[ \t]*[^)]*)[ \t]*;;[ \t]*$' > /dev/null \
|
||||
|| expr "$line" : '[ \t]*[^)]*)[ \t]*;;*[ \t]*#.*$' > /dev/null
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
function _examine
|
||||
{
|
||||
if [ -n "$*" ]
|
||||
then
|
||||
_msg "$args: \c"
|
||||
eval _msg $args
|
||||
else
|
||||
_msg "Nothing to print"
|
||||
fi
|
||||
}
|
||||
|
||||
function _displayscript
|
||||
{
|
||||
local i j start end bp cl
|
||||
|
||||
if (( $# == 1 ))
|
||||
then
|
||||
if test $1 = "%"
|
||||
then
|
||||
let start=1
|
||||
let end=${#_lines[@]}
|
||||
else
|
||||
let start=$1-5
|
||||
let end=$1+5
|
||||
fi
|
||||
elif (( $# > 1 ))
|
||||
then
|
||||
if test $1 = "^"
|
||||
then
|
||||
let start=1
|
||||
else
|
||||
let start=$1
|
||||
fi
|
||||
|
||||
if test $2 = "\$"
|
||||
then
|
||||
let end=${#_lines[@]}
|
||||
else
|
||||
let end=$2
|
||||
fi
|
||||
else
|
||||
let start=$_curline-5
|
||||
let end=$_curline+5
|
||||
fi
|
||||
|
||||
if (( $start < 1 ))
|
||||
then
|
||||
start=1
|
||||
fi
|
||||
if (( $end > ${#_lines[@]} ))
|
||||
then
|
||||
end=${#_lines[@]}
|
||||
fi
|
||||
|
||||
let cl=$end-$start
|
||||
if (( $cl > ${LINES-24} ))
|
||||
then
|
||||
pager=${PAGER-more}
|
||||
else
|
||||
pager=cat
|
||||
fi
|
||||
|
||||
i=$start
|
||||
( while (( $i <= $end )); do
|
||||
_showline $i
|
||||
let i=$i+1
|
||||
done ) 2>&1 | $pager
|
||||
|
||||
# calculate the next block of lines
|
||||
let start=$end+1
|
||||
let end=$start+11
|
||||
if (( $end > ${#_lines[@]} ))
|
||||
then
|
||||
end=${#_lines[@]}
|
||||
fi
|
||||
|
||||
_lastcmd="list $start $end"
|
||||
}
|
||||
|
||||
function _xtrace
|
||||
{
|
||||
let _trace="! $_trace"
|
||||
if (( $_trace )); then
|
||||
_msg "Execution trace on"
|
||||
else
|
||||
_msg "Execution trace off"
|
||||
fi
|
||||
}
|
||||
|
||||
function _msg
|
||||
{
|
||||
echo -e "$@" >&2
|
||||
}
|
||||
|
||||
function _showline
|
||||
{
|
||||
local i=0 bp=' ' line=$1
|
||||
|
||||
while (( $i < ${#_linebp[@]} ))
|
||||
do
|
||||
if [ ${_linebp[$i]} ] && (( ${_linebp[$i]} == $line ))
|
||||
then
|
||||
bp='*'
|
||||
fi
|
||||
let i=$i+1
|
||||
done
|
||||
|
||||
if (( $_curline == $line )); then
|
||||
cl=">"
|
||||
else
|
||||
cl=" "
|
||||
fi
|
||||
|
||||
if (( $line < 100 )); then
|
||||
_msg "$_guineapig:$line $bp $cl${_lines[$line]}"
|
||||
elif (( $line < 10 )); then
|
||||
_msg "$_guineapig:$line $bp $cl${_lines[$line]}"
|
||||
elif (( $line > 0 )); then
|
||||
_msg "$_guineapig:$line $bp $cl${_lines[$line]}"
|
||||
fi
|
||||
}
|
||||
|
||||
function _cleanup
|
||||
{
|
||||
rm -f $__debug $_potbelliedpig 2> /dev/null
|
||||
}
|
||||
|
||||
function _menu
|
||||
{
|
||||
_msg 'bashdb commands:
|
||||
break N set breakpoint at line N
|
||||
break list breakpoints & break condition
|
||||
condition foo set break condition to foo
|
||||
condition clear break condition
|
||||
delete N clear breakpoint at line N
|
||||
delete clear all breakpoints
|
||||
display EXP evaluate and display EXP for each debug step
|
||||
display show a list of display expressions
|
||||
undisplay N remove display expression N
|
||||
list N M display all lines of script between N and M
|
||||
list N display 5 lines of script either side of line N
|
||||
list display 5 lines if script either side of current line
|
||||
continue continue execution upto next breakpoint
|
||||
next [N] execute [N] statements (default 1)
|
||||
print expr prints the value of an expression
|
||||
trace toggle execution trace on/off
|
||||
help print this menu
|
||||
! string passes string to a shell
|
||||
quit quit'
|
||||
}
|
||||
|
||||
|
||||
_linebp=
|
||||
let _trace=0
|
||||
let _i=1
|
||||
|
||||
# Be careful about quoted newlines
|
||||
_potbelliedpig=${TMPDIR-/tmp}/$_guineapig.$$
|
||||
sed 's,\\$,\\\\,' $_guineapig > $_potbelliedpig
|
||||
|
||||
_msg "Reading source from file: $_guineapig"
|
||||
while read; do
|
||||
_lines[$_i]=$REPLY
|
||||
let _i=$_i+1
|
||||
done < $_potbelliedpig
|
||||
|
||||
trap _cleanup EXIT
|
||||
# Assuming a real script will have the "#! /bin/sh" at line 1,
|
||||
# don't stop at line 1 on the first run
|
||||
let _steps=2
|
||||
LINENO=-2
|
||||
trap '_steptrap $LINENO' DEBUG
|
||||
:
|
||||
@@ -0,0 +1,29 @@
|
||||
From friedman@cli.com Thu May 25 12:19:06 1995
|
||||
Flags: 10
|
||||
Return-Path: friedman@cli.com
|
||||
Received: from po.cwru.edu (root@po.CWRU.Edu [129.22.4.2]) by odin.INS.CWRU.Edu with ESMTP (8.6.10+cwru/CWRU-2.1-ins)
|
||||
id MAA08685; Thu, 25 May 1995 12:19:05 -0400 (from friedman@cli.com for <chet@odin.INS.CWRU.Edu>)
|
||||
Received: from cli.com (cli.com [192.31.85.1]) by po.cwru.edu with SMTP (8.6.10+cwru/CWRU-2.3)
|
||||
id MAA11299; Thu, 25 May 1995 12:19:00 -0400 (from friedman@cli.com for <chet@po.cwru.edu>)
|
||||
Received: from tepui.cli.com by cli.com (4.1/SMI-4.1)
|
||||
id AA27213; Thu, 25 May 95 11:18:25 CDT
|
||||
Received: by tepui.cli.com (4.1) id AA16031; Thu, 25 May 95 11:18:23 CDT
|
||||
Message-Id: <9505251618.AA16031@tepui.cli.com>
|
||||
From: friedman@gnu.ai.mit.edu (Noah Friedman)
|
||||
To: chet@po.cwru.edu
|
||||
Subject: Bash scripts
|
||||
Reply-To: friedman@gnu.ai.mit.edu
|
||||
In-Reply-To: <chet@odin.ins.cwru.edu> Thu, 25 May 1995 11:19:59 -0400
|
||||
References: <9505251519.AA06424.SM@odin.INS.CWRU.Edu>
|
||||
Date: Thu, 25 May 95 11:18:21 CST
|
||||
|
||||
>Hi. I snagged some of your bash functions from your home directory on
|
||||
>the FSF machines (naughty, I know), and I was wondering if you'd let
|
||||
>me distribute them with bash-2.0. Thanks.
|
||||
|
||||
Sure. I think there's a later copy in
|
||||
~ftp/friedman/shell-inits/init-4.89.tar.gz. There are also some elisp and
|
||||
es frobs in that file.
|
||||
|
||||
It should serve as a pretty good example of how to get carried away. :-)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
This collection of scripts was originally written for older versions
|
||||
of bash by Noah Friedman (friedman@gnu.ai.mit.edu). The conversion
|
||||
to bash v2 syntax was done by Chet Ramey.
|
||||
|
||||
These scripts are as-is; there is no copyright associated with
|
||||
any of them. They exist simply as examples of bash scripting.
|
||||
|
||||
Here's a description of what's in this directory:
|
||||
|
||||
aref.bash Pseudo-arrays and substring indexing examples.
|
||||
bash.sub.bash Library functions used by require.bash.
|
||||
bash_version.bash A function to slice up $BASH_VERSION.
|
||||
meta.bash Enable and disable eight-bit readline input.
|
||||
mktmp.bash Make a temporary file with a unique name.
|
||||
number.bash A fun hack to translate numerals into English.
|
||||
PERMISSION Permissions to use the scripts in this directory.
|
||||
prompt.bash A way to set PS1 to some predefined strings.
|
||||
README README
|
||||
remap_keys.bash A front end to 'bind' to redo readline bindings.
|
||||
require.bash Lisp-like require/provide library functions for bash.
|
||||
send_mail.bash Replacement SMTP client written in bash.
|
||||
shcat.bash Bash replacement for 'cat(1)'.
|
||||
source.bash Replacement for source that uses current directory.
|
||||
string.bash The string(3) functions at the shell level.
|
||||
stty.bash Front-end to stty(1) that changes readline bindings too.
|
||||
y_or_n_p.bash Prompt for a yes/no/quit answer.
|
||||
@@ -0,0 +1,44 @@
|
||||
# aref.bash --- pseudo-array manipulating routines
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created 1992-07-01
|
||||
# Last modified: 1993-02-03
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring aref:
|
||||
# Usage: aref NAME INDEX
|
||||
#
|
||||
# In array NAME, access element INDEX (0-origin)
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function aref ()
|
||||
{
|
||||
local name="$1"
|
||||
local index="$2"
|
||||
|
||||
set -- ${!name}
|
||||
[ $index -ge 1 ] && shift $index
|
||||
echo $1
|
||||
}
|
||||
|
||||
#:docstring string_aref:
|
||||
# Usage: aref STRING INDEX
|
||||
#
|
||||
# Echo the INDEXth character in STRING (0-origin) on stdout.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function string_aref ()
|
||||
{
|
||||
local stuff=${1:$2}
|
||||
echo ${stuff:0:1}
|
||||
}
|
||||
|
||||
provide aref
|
||||
|
||||
# aref.bash ends here
|
||||
@@ -0,0 +1,28 @@
|
||||
# bash.sub.bash --- stub for standalone shell scripts using bash library
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-07-13
|
||||
# Last modified: 1993-09-29
|
||||
# Public domain
|
||||
|
||||
#:docstring bash.sub:
|
||||
# Standard subroutines for bash scripts wishing to use "require" to load
|
||||
# libraries.
|
||||
#
|
||||
# Usage: In each directory where a bash script that uses this script
|
||||
# exists, place a copy of this script. Then, at the top of such scripts,
|
||||
# put the command
|
||||
#
|
||||
# source ${0%/*}/bash.sub || exit 1
|
||||
#
|
||||
# Then you can use `require' to load packages.
|
||||
#
|
||||
#:end docstring:
|
||||
|
||||
default_FPATH="~friedman/etc/init/bash/functions/lib"
|
||||
|
||||
source "${default_FPATH}/feature"
|
||||
REQUIRE_FAILURE_FATAL=t
|
||||
|
||||
FPATH="${FPATH-${default_FPATH}}"
|
||||
|
||||
# bash.sub.bash ends here
|
||||
@@ -0,0 +1,42 @@
|
||||
# bash_version.bash --- get major and minor components of bash version number
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-01-26
|
||||
# Last modified: 1993-01-26
|
||||
# Public domain
|
||||
|
||||
# Converted to bash v2 syntax by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring bash_version:
|
||||
# Usage: bash_version {major|minor}
|
||||
#
|
||||
# Echo the major or minor number of this version of bash on stdout, or
|
||||
# just echo $BASH_VERSION if no argument is given.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function bash_version ()
|
||||
{
|
||||
local major minor
|
||||
|
||||
case "$1" in
|
||||
major) echo "${BASH_VERSION/.*/}" ;;
|
||||
minor) major="${BASH_VERSION/.*/}"
|
||||
minor="${BASH_VERSION#${major}.}"
|
||||
echo "${minor%%.*}" ;;
|
||||
patchlevel) minor="${BASH_VERSION#*.*.}"
|
||||
echo "${minor%(*}" ;;
|
||||
version) minor=${BASH_VERSION/#*.*./}
|
||||
echo ${BASH_VERSION/%.$minor/} ;;
|
||||
release) echo ${BASH_VERSION%(*} ;;
|
||||
build) minor="${BASH_VERSION#*.*.*(}"
|
||||
echo ${minor%)} ;;
|
||||
*) echo "${BASH_VERSION}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
provide bash_version
|
||||
|
||||
# bash_version.bash ends here
|
||||
@@ -0,0 +1,37 @@
|
||||
# meta.bash --- meta key frobnications
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-06-28
|
||||
# Last modified: 1993-01-26
|
||||
# Public domain
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring meta:
|
||||
# Usage: meta [on|off]
|
||||
#
|
||||
# An argument of "on" will make bash use the 8th bit of any input from
|
||||
# a terminal as a "meta" bit, i.e bash will be able to use a real meta
|
||||
# key.
|
||||
#
|
||||
# An argument of "off" causes bash to disregard the 8th bit, which is
|
||||
# assumed to be used for parity instead.
|
||||
#:end docstring:
|
||||
|
||||
function meta ()
|
||||
{
|
||||
case "$1" in
|
||||
on) bind 'set input-meta On'
|
||||
bind 'set output-meta on'
|
||||
bind 'set convert-meta off' ;;
|
||||
off) bind 'set input-meta Off'
|
||||
bind 'set output-meta off'
|
||||
bind 'set convert-meta on' ;;
|
||||
*) echo "Usage: meta [on|off]" 1>&2 ; return 1 ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
provide meta
|
||||
|
||||
# meta.bash ends here
|
||||
@@ -0,0 +1,66 @@
|
||||
# mktmp.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-02-03
|
||||
# Last modified: 1993-02-03
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring mktmp:
|
||||
# Usage: mktmp [template] {createp}
|
||||
#
|
||||
# Generate a unique filename from TEMPLATE by appending a random number to
|
||||
# the end.
|
||||
#
|
||||
# If optional 2nd arg CREATEP is non-null, file will be created atomically
|
||||
# before returning. This is to avoid the race condition that in between
|
||||
# the time that the temporary name is returned and the caller uses it,
|
||||
# someone else creates the file.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function mktmp ()
|
||||
{
|
||||
local template="$1"
|
||||
local tmpfile="${template}${RANDOM}"
|
||||
local createp="$2"
|
||||
local noclobber_status
|
||||
|
||||
case "$-" in
|
||||
*C*) noclobber_status=set;;
|
||||
esac
|
||||
|
||||
if [ "${createp:+set}" = "set" ]; then
|
||||
# Version which creates file atomically through noclobber test.
|
||||
set -o noclobber
|
||||
(> "${tmpfile}") 2> /dev/null
|
||||
while [ $? -ne 0 ] ; do
|
||||
# Detect whether file really exists or creation lost because of
|
||||
# some other permissions problem. If the latter, we don't want
|
||||
# to loop forever.
|
||||
if [ ! -e "${tmpfile}" ]; then
|
||||
# Trying to create file again creates stderr message.
|
||||
echo -n "mktmp: " 1>&2
|
||||
> "${tmpfile}"
|
||||
return 1
|
||||
fi
|
||||
tmpfile="${template}${RANDOM}"
|
||||
(> "${tmpfile}") 2> /dev/null
|
||||
done
|
||||
test "${noclobber_status}" != "set" && set +o noclobber
|
||||
else
|
||||
# Doesn't create file, so it introduces race condition for caller.
|
||||
while [ -e "${tmpfile}" ]; do
|
||||
tmpfile="${template}${RANDOM}"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "${tmpfile}"
|
||||
}
|
||||
|
||||
provide mktmp
|
||||
|
||||
# mktmp.bash ends here
|
||||
@@ -0,0 +1,185 @@
|
||||
# number.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-02-22
|
||||
# Last modified: 1993-04-01
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring number:
|
||||
# Usage: number [number]
|
||||
#
|
||||
# Converts decimal integers to english notation. Spaces and commas are
|
||||
# optional. Numbers 67 digits and larger will overflow this script.
|
||||
#
|
||||
# E.g: number 99,000,000,000,000,454
|
||||
# => ninety-nine quadrillion four hundred fifty-four
|
||||
#
|
||||
#:end docstring:
|
||||
|
||||
function number ()
|
||||
{
|
||||
local result
|
||||
local val1
|
||||
local val2
|
||||
local val3
|
||||
local d1
|
||||
local d2
|
||||
local d3
|
||||
|
||||
case "$*" in
|
||||
*[!0-9,.]* )
|
||||
echo "number: invalid character in argument." 1>&2
|
||||
return 1
|
||||
;;
|
||||
*.* )
|
||||
echo "number: fractions not supported (yet)." 1>&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
result=''
|
||||
|
||||
eval set - "`echo ${1+\"$@\"} | sed -n -e '
|
||||
s/[, ]//g;s/^00*/0/g;s/\(.\)\(.\)\(.\)$/\"\1 \2 \3\"/;
|
||||
:l
|
||||
/[0-9][0-9][0-9]/{
|
||||
s/\([^\" ][^\" ]*\)\([^\" ]\)\([^\" ]\)\([^\" ]\)/\1\"\2 \3 \4\"/g;
|
||||
t l
|
||||
}
|
||||
/^[0-9][0-9][0-9]/s/\([^\" ]\)\([^\" ]\)\([^\" ]\)/\"\1 \2 \3\"/;
|
||||
/^[0-9][0-9]/s/\([^\" ]\)\([^\" ]\)/\"\1 \2\"/;
|
||||
/^[0-9]/s/^\([^\" ][^\" ]*\)/\"\1\"/g;s/\"\"/\" \"/g;p;'`"
|
||||
|
||||
while test $# -ne 0 ; do
|
||||
eval `set - $1;
|
||||
d3='' d2='' d1=''
|
||||
case $# in
|
||||
1 ) d1=$1 ;;
|
||||
2 ) d2=$1 d1=$2 ;;
|
||||
3 ) d3=$1 d2=$2 d1=$3 ;;
|
||||
esac
|
||||
echo "d3=\"${d3}\" d2=\"${d2}\" d1=\"${d1}\""`
|
||||
|
||||
val1='' val2='' val3=''
|
||||
|
||||
case "${d3}" in
|
||||
'1' ) val3='one' ;;
|
||||
'2' ) val3='two' ;;
|
||||
'3' ) val3='three' ;;
|
||||
'4' ) val3='four' ;;
|
||||
'5' ) val3='five' ;;
|
||||
'6' ) val3='six' ;;
|
||||
'7' ) val3='seven' ;;
|
||||
'8' ) val3='eight' ;;
|
||||
'9' ) val3='nine' ;;
|
||||
esac
|
||||
|
||||
case "${d2}" in
|
||||
'1' ) val2='teen' ;;
|
||||
'2' ) val2='twenty' ;;
|
||||
'3' ) val2='thirty' ;;
|
||||
'4' ) val2='forty' ;;
|
||||
'5' ) val2='fifty' ;;
|
||||
'6' ) val2='sixty' ;;
|
||||
'7' ) val2='seventy' ;;
|
||||
'8' ) val2='eighty' ;;
|
||||
'9' ) val2='ninety' ;;
|
||||
esac
|
||||
|
||||
case "${val2}" in
|
||||
'teen')
|
||||
val2=''
|
||||
case "${d1}" in
|
||||
'0') val1='ten' ;;
|
||||
'1') val1='eleven' ;;
|
||||
'2') val1='twelve' ;;
|
||||
'3') val1='thirteen' ;;
|
||||
'4') val1='fourteen' ;;
|
||||
'5') val1='fifteen' ;;
|
||||
'6') val1='sixteen' ;;
|
||||
'7') val1='seventeen' ;;
|
||||
'8') val1='eighteen' ;;
|
||||
'9') val1='nineteen' ;;
|
||||
esac
|
||||
;;
|
||||
0 ) : ;;
|
||||
* )
|
||||
if test ".${val2}" != '.' && test ".${d1}" != '.0' ; then
|
||||
val2="${val2}-"
|
||||
fi
|
||||
case "${d1}" in
|
||||
'0') val2="${val2} " ;;
|
||||
'1') val1='one' ;;
|
||||
'2') val1='two' ;;
|
||||
'3') val1='three' ;;
|
||||
'4') val1='four' ;;
|
||||
'5') val1='five' ;;
|
||||
'6') val1='six' ;;
|
||||
'7') val1='seven' ;;
|
||||
'8') val1='eight' ;;
|
||||
'9') val1='nine' ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
if test ".${val3}" != '.' ; then
|
||||
result="${result}${val3} hundred "
|
||||
fi
|
||||
|
||||
if test ".${val2}" != '.' ; then
|
||||
result="${result}${val2}"
|
||||
fi
|
||||
|
||||
if test ".${val1}" != '.' ; then
|
||||
result="${result}${val1} "
|
||||
fi
|
||||
|
||||
if test ".${d1}${d2}${d3}" != '.000' ; then
|
||||
case $# in
|
||||
0 | 1 ) ;;
|
||||
2 ) result="${result}thousand " ;;
|
||||
3 ) result="${result}million " ;;
|
||||
4 ) result="${result}billion " ;;
|
||||
5 ) result="${result}trillion " ;;
|
||||
6 ) result="${result}quadrillion " ;;
|
||||
7 ) result="${result}quintillion " ;;
|
||||
8 ) result="${result}sextillion " ;;
|
||||
9 ) result="${result}septillion " ;;
|
||||
10 ) result="${result}octillion " ;;
|
||||
11 ) result="${result}nonillion " ;;
|
||||
12 ) result="${result}decillion " ;;
|
||||
13 ) result="${result}undecillion " ;;
|
||||
14 ) result="${result}duodecillion " ;;
|
||||
15 ) result="${result}tredecillion " ;;
|
||||
16 ) result="${result}quattuordecillion " ;;
|
||||
17 ) result="${result}quindecillion " ;;
|
||||
18 ) result="${result}sexdecillion " ;;
|
||||
19 ) result="${result}septendecillion " ;;
|
||||
20 ) result="${result}octodecillion " ;;
|
||||
21 ) result="${result}novemdecillion " ;;
|
||||
22 ) result="${result}vigintillion " ;;
|
||||
* )
|
||||
echo "Error: number too large (66 digits max)." 1>&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
set - ${result}
|
||||
case "$*" in
|
||||
'') set - 'zero' ;;
|
||||
esac
|
||||
|
||||
echo ${1+"$@"}
|
||||
}
|
||||
|
||||
provide number
|
||||
|
||||
# number.bash ends here
|
||||
@@ -0,0 +1,40 @@
|
||||
# prompt.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-01-15
|
||||
# Public domain
|
||||
|
||||
# $Id: prompt.bash,v 1.2 1994/10/18 16:34:35 friedman Exp $
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring prompt:
|
||||
# Usage: prompt [chars]
|
||||
#
|
||||
# Various preformatted prompt strings selected by argument. For a
|
||||
# list of available arguments and corresponding formats, do
|
||||
# `type prompt'.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function prompt ()
|
||||
{
|
||||
case "$1" in
|
||||
d) PS1='$(dirs) \$ ' ;;
|
||||
n) PS1='\$ ' ;;
|
||||
hsw) PS1='\h[$SHLVL]: \w \$ ' ;;
|
||||
hw) PS1='\h: \w \$ ' ;;
|
||||
sh) PS1='[$SHLVL] \h\$ ' ;;
|
||||
sw) PS1='[$SHLVL] \w \$ ' ;;
|
||||
uh) PS1='\u@\h\$ ' ;;
|
||||
uhsHw) PS1='\u@\h[$SHLVL]:\#: \w \$ ' ;;
|
||||
uhsw) PS1='\u@\h[$SHLVL]: \w \$ ' ;;
|
||||
uhw) PS1='\u@\h: \w \$ ' ;;
|
||||
uw) PS1='(\u) \w \$ ' ;;
|
||||
w) PS1='\w \$ ' ;;
|
||||
esac
|
||||
}
|
||||
|
||||
provide prompt
|
||||
|
||||
# prompt.bash ends here
|
||||
@@ -0,0 +1,71 @@
|
||||
# remap_keybindings.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-01-11
|
||||
# Last modified: 1993-02-03
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring remap_keybindings:
|
||||
# Usage: remap_keybindings old_function new_function
|
||||
#
|
||||
# Clear all readline keybindings associated with OLD_FUNCTION (a Readline
|
||||
# function) rebinding them to NEW_FUNCTION (`self-insert' by default)
|
||||
#
|
||||
# This requires bash version 1.10 or newer, since previous versions did not
|
||||
# implement the `bind' builtin.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function remap_keybindings ()
|
||||
{
|
||||
local unbind_function="$1"
|
||||
local bind_function="${2:-'self-insert'}"
|
||||
local bind_output
|
||||
local arg
|
||||
|
||||
# If they're the same thing, the work has already been done. :-)
|
||||
if [ "${unbind_function}" = "${bind_function}" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
while : ; do
|
||||
bind_output="$(bind -q ${unbind_function} 2> /dev/null)"
|
||||
|
||||
case "${bind_output}" in
|
||||
"${unbind_function} can be invoked via"* ) ;;
|
||||
"" ) return 1 ;; # probably bad argument to bind
|
||||
*) return 0 ;; # unbound
|
||||
esac
|
||||
|
||||
# Format of bind_output is like:
|
||||
# 'quoted-insert can be invoked via "\C-q", "\C-v".'
|
||||
# 'self-insert can be invoked via " ", "!", """, "$", "%", ...'
|
||||
set -- ${bind_output}
|
||||
shift 5
|
||||
|
||||
for arg in "$@" ; do
|
||||
# strip off trailing `.' or `,'
|
||||
arg=${arg%.};
|
||||
arg=${arg%,};
|
||||
|
||||
case ${arg} in
|
||||
..)
|
||||
# bind -q didn't provide whole list of key bindings; jump
|
||||
# to top loop to get more
|
||||
continue 2 ;
|
||||
;;
|
||||
*)
|
||||
bind "${arg}: ${bind_function}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
provide remap_keybindings
|
||||
|
||||
# remap_keybindings.bash ends here
|
||||
@@ -0,0 +1,182 @@
|
||||
# require.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-07-08
|
||||
# Last modified: 1993-09-29
|
||||
# Public domain
|
||||
|
||||
# Commentary:
|
||||
|
||||
# These functions provide an interface based on the lisp implementation for
|
||||
# loading libraries when they are needed and eliminating redundant loading.
|
||||
# The basic idea is that each "package" (or set of routines, even if it is
|
||||
# only one function) registers itself with a symbol that marks a "feature"
|
||||
# as being "provided". If later you "require" a given feature, you save
|
||||
# yourself the trouble of explicitly loading it again.
|
||||
#
|
||||
# At the bottom of each package, put a "provide foobar", so when another
|
||||
# package has a "require foobar", it gets loaded and registered as a
|
||||
# "feature" that won't need to get loaded again. (See warning below for
|
||||
# reasons why provide should be put at the end.)
|
||||
#
|
||||
# The list of provided features are kept in the `FEATURES' variable, which
|
||||
# is not exported. Care should be taken not to munge this in the shell.
|
||||
# The search path comes from a colon-separated `FPATH' variable. It has no
|
||||
# default value and must be set by the user.
|
||||
#
|
||||
# Require uses `fpath_search', which works by scanning all of FPATH for a
|
||||
# file named the same as the required symbol but with a `.bash' appended to
|
||||
# the name. If that is found, it is loaded. If it is not, FPATH is
|
||||
# searched again for a file name the same as the feature (i.e. without any
|
||||
# extension). Fpath_search may be useful for doing library filename
|
||||
# lookups in other functions (such as a `load' or `autoload' function).
|
||||
#
|
||||
# Warning: Because require ultimately uses the builtin `source' command to
|
||||
# read in files, it has no way of undoing the commands contained in the
|
||||
# file if there is an error or if no provide statement appeared (this
|
||||
# differs from the lisp implementation of require, which normally undoes
|
||||
# most of the forms that were loaded if the require fails). Therefore, to
|
||||
# minize the number of problems caused by requiring a faulty package (such
|
||||
# as syntax errors in the source file) it is better to put the provide at
|
||||
# the end of the file, rather than at the beginning.
|
||||
|
||||
# Code:
|
||||
|
||||
# Exporting this variable would cause considerable lossage, since none of
|
||||
# the functions are exported (or at least, they're not guaranteed to be)
|
||||
export -n FEATURES
|
||||
|
||||
#:docstring :
|
||||
# Null function. Provided only so that one can put page breaks in source
|
||||
# files without any ill effects.
|
||||
#:end docstring:
|
||||
#
|
||||
# (\\014 == C-l)
|
||||
eval "function $(echo -e \\014) () { : }"
|
||||
|
||||
|
||||
#:docstring featurep:
|
||||
# Usage: featurep argument
|
||||
#
|
||||
# Returns 0 (true) if argument is a provided feature. Returns 1 (false)
|
||||
# otherwise.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function featurep ()
|
||||
{
|
||||
local feature="$1"
|
||||
|
||||
case " ${FEATURES} " in
|
||||
*" ${feature} "* ) return 0 ;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
#:docstring provide:
|
||||
# Usage: provide symbol ...
|
||||
#
|
||||
# Register a list of symbols as provided features
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function provide ()
|
||||
{
|
||||
local feature
|
||||
|
||||
for feature in "$@" ; do
|
||||
if ! featurep "${feature}" ; then
|
||||
FEATURES="${FEATURES} ${feature}"
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
#:docstring require:
|
||||
# Usage: require feature {file}
|
||||
#
|
||||
# Load FEATURE if it is not already provided. Note that require does not
|
||||
# call `provide' to register features. The loaded file must do that
|
||||
# itself. If the package does not explicitly do a `provide' after being
|
||||
# loaded, require will complain about the feature not being provided on
|
||||
# stderr.
|
||||
#
|
||||
# Optional argument FILE means to try to load FEATURE from FILE. If no
|
||||
# file argument is given, require searches through FPATH (see fpath_search)
|
||||
# for the appropriate file.
|
||||
#
|
||||
# If the variable REQUIRE_FAILURE_FATAL is set, require will cause the
|
||||
# current shell invocation to exit, rather than merely return. This may be
|
||||
# useful for a shell script that vitally depends on a package.
|
||||
#
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function require ()
|
||||
{
|
||||
local feature="$1"
|
||||
local path="$2"
|
||||
local file
|
||||
|
||||
if ! featurep "${feature}" ; then
|
||||
file=$(fpath_search "${feature}" "${path}") && source "${file}"
|
||||
|
||||
if ! featurep "${feature}" ; then
|
||||
echo "require: ${feature}: feature was not provided." 1>&2
|
||||
if [ "${REQUIRE_FAILURE_FATAL+set}" = "set" ]; then
|
||||
exit 1
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#:docstring fpath_search:
|
||||
# Usage: fpath_search filename {path ...}
|
||||
#
|
||||
# Search $FPATH for `filename' or, if `path' (a list) is specified, search
|
||||
# those directories instead of $FPATH. First the path is searched for an
|
||||
# occurrence of `filename.bash, then a second search is made for just
|
||||
# `filename'.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function fpath_search ()
|
||||
{
|
||||
local name="$1"
|
||||
local path="$2"
|
||||
local suffix=".bash"
|
||||
local file
|
||||
|
||||
if [ -z "${path}" ]; then path="${FPATH}"; fi
|
||||
|
||||
for file in "${name}${suffix}" "${name}" ; do
|
||||
set -- $(IFS=':'
|
||||
set -- ${path}
|
||||
for p in "$@" ; do
|
||||
echo -n "${p:-.} "
|
||||
done)
|
||||
|
||||
while [ $# -ne 0 ]; do
|
||||
test -f "${1}/${file}" && { file="${1}/${file}"; break 2 }
|
||||
shift
|
||||
done
|
||||
done
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "fpath_search: ${name}: file not found in fpath" 1>&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "${file}"
|
||||
return 0
|
||||
}
|
||||
|
||||
provide require
|
||||
|
||||
# require.bash ends here
|
||||
@@ -0,0 +1,140 @@
|
||||
# send_mail.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-07-02
|
||||
# Public domain
|
||||
|
||||
# Commentary:
|
||||
|
||||
# TODO: implement Fcc headers (see emacs manual)
|
||||
|
||||
# Code:
|
||||
|
||||
#:docstring send_mail:
|
||||
# Usage: send_mail
|
||||
#
|
||||
# This function serves as a simple replacement for sendmail as a client
|
||||
# interface on those systems where it is not available. It does assume
|
||||
# that one can talk to an SMTP mailer on port 25 either on the local host
|
||||
# or on the host specified by the MAILHOST environment variable. If you
|
||||
# have access to sendmail, it's better to use 'sendmail -t' instead of this
|
||||
# script (which probably isn't as robust).
|
||||
#
|
||||
# Message is read from stdin, and headers are parsed to determine
|
||||
# recipients.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function send_mail ()
|
||||
{
|
||||
# Need gawk, since several extensions are taken advantage of (like
|
||||
# IGNORECASE for regexps).
|
||||
local awk="${GAWK_LOCATION:-gawk}"
|
||||
local DefaultFrom="${USER:-${LOGNAME}}"
|
||||
local From
|
||||
local To
|
||||
local Cc
|
||||
local Bcc
|
||||
local tmpfile="/tmp/send_mail$$"
|
||||
|
||||
while [ -e "${tmpfile}" ]; do
|
||||
tmpfile="/tmp/send_mail${RANDOM}"
|
||||
done
|
||||
|
||||
# Lines consisting only of dots need one more dot appended. SMTP
|
||||
# servers eat one of the dots (and if only 1 dot appears, it signifies
|
||||
# the end of the message).
|
||||
sed '/^\.\.*/s/^\(\.\.*\)$/\1./' > "${tmpfile}"
|
||||
|
||||
# Parse mail headers in message to extract recipients list.
|
||||
# This doesn't affect what the user sees---it's only used to generate
|
||||
# the rcpt-to lines for SMTP.
|
||||
eval $(${awk} -f - "${tmpfile}" <<- '__EOF__'
|
||||
# Try to extract email address from amidst random data
|
||||
function parse_address (data)
|
||||
{
|
||||
# From: "real name" <foobar@host>
|
||||
# From: "" <foobar@host>
|
||||
if (match(data, /^\"[^\"]*\"[ \t]*<.*>/)) {
|
||||
data_idx = match(data, /^\"[^\"]*\"[ \t]*</)
|
||||
data = substr(data, RSTART + RLENGTH);
|
||||
if (data_idx = match(data, ">.*"))
|
||||
data = substr(data, 1, RSTART - 1);
|
||||
return data
|
||||
}
|
||||
# From: real name <foobar@host>
|
||||
if (match(data, /<.*>/)) {
|
||||
data_idx = match(data, /</)
|
||||
data = substr(data, RSTART + RLENGTH);
|
||||
if (data_idx = match(data, ">"))
|
||||
data = substr(data, 1, RSTART - 1);
|
||||
return data
|
||||
}
|
||||
# From: foobar@host (real name)
|
||||
if (match(data, /\(.*\)/)) {
|
||||
data_idx = match(data, /\(/);
|
||||
data = substr(data, 1, RSTART - 1);
|
||||
return data
|
||||
}
|
||||
# (hopefully) From: foobar@host
|
||||
return data
|
||||
}
|
||||
|
||||
BEGIN { IGNORECASE = 1; }
|
||||
|
||||
# Blank line signifies end of headers, so we can stop looking.
|
||||
/^$/ { exit(0) }
|
||||
|
||||
/^from:|^to:|^cc:|^bcc:/ {
|
||||
header_idx = match($0, /^[^:]*:/)
|
||||
if (header_idx) {
|
||||
# Capitalize header name
|
||||
header_firstchar = toupper(substr($0, RSTART, 1));
|
||||
header_rest = tolower(substr($0, RSTART + 1, RLENGTH - 2));
|
||||
header = header_firstchar header_rest
|
||||
|
||||
$0 = substr($0, RSTART + RLENGTH + 1);
|
||||
addresses = ""
|
||||
# parse addresses
|
||||
while ($0) {
|
||||
# Strip leading whitespace
|
||||
if (idx = match($0, /[ \t]*/))
|
||||
$0 = substr($0, RSTART + RLENGTH);
|
||||
|
||||
# Find everything up to a nonquoted comma
|
||||
# FIXME: doesnt handle quoting yet
|
||||
if (idx = match($0, /,/)) {
|
||||
data = substr($0, 1, RSTART);
|
||||
$0 = substr($0, RSTART + 1);
|
||||
} else {
|
||||
data = $0
|
||||
$0 = ""
|
||||
}
|
||||
addresses = addresses " " parse_address(data)
|
||||
}
|
||||
|
||||
printf("%s='%s'\n", header, addresses);
|
||||
}
|
||||
}
|
||||
__EOF__)
|
||||
|
||||
# Not sure if an address is *required* after the HELO.. every sendmail
|
||||
# I tried talking to didn't seem to care. Some sendmails don't care
|
||||
# if there's a HELO at all.
|
||||
cat <<- __EOF__ | telnet ${MAILHOST:-localhost} 25 > /dev/null 2>&1
|
||||
HELO
|
||||
mail from: ${From:-${DefaultFrom}}
|
||||
$(for name in ${To} ${Cc} ${Bcc} ; do
|
||||
echo "rcpt to: ${name}"
|
||||
done)
|
||||
data
|
||||
$(cat "${tmpfile}")
|
||||
.
|
||||
quit
|
||||
__EOF__
|
||||
|
||||
rm -f "${tmpfile}"
|
||||
}
|
||||
|
||||
provide send_mail
|
||||
|
||||
# send_mail.bash ends here
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user