Imported from ../bash-2.05.tar.gz.
This commit is contained in:
parent
bb70624e96
commit
28ef6c316f
251 changed files with 22319 additions and 12413 deletions
|
|
@ -352,7 +352,7 @@ _complete_meta_func()
|
|||
|
||||
if [[ $prev == -A ]]; then
|
||||
COMPREPLY=(alias arrayvar binding builtin command directory \
|
||||
disabled enabled export file function helptopic hostname job keyword \
|
||||
disabled enabled export file 'function' helptopic hostname job keyword \
|
||||
running setopt shopt signal stopped variable)
|
||||
return 0
|
||||
elif [[ $prev == -F ]]; then
|
||||
|
|
@ -400,7 +400,11 @@ _make_targets ()
|
|||
esac
|
||||
|
||||
# make reads `makefile' before `Makefile'
|
||||
if [ -f makefile ]; then
|
||||
# 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
|
||||
|
|
@ -458,11 +462,13 @@ 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 '!*.+(gif|jpg|jpeg|GIF|JPG|bmp)' xv
|
||||
complete -f -X '!*.bz2' bunzip2
|
||||
complete -f -X '!*.zip' unzip
|
||||
complete -f -X '!*.+(gif|jpg|jpeg|GIF|JPG|JPEG|bmp)' xv
|
||||
|
||||
complete -f -X '!*.pl' perl perl5
|
||||
|
||||
|
|
@ -472,11 +478,14 @@ complete -A hostname rxterm rxterm3 rxvt2
|
|||
complete -u su
|
||||
|
||||
complete -f -X '!*.+(ps|PS)' gs gv ghostview psselect pswrap
|
||||
complete -f -X '!*.+(dvi|DVI)' dvips xdvi dviselect dvitype
|
||||
complete -f -X '!*.+(pdf|PDF)' acroread
|
||||
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
|
||||
#
|
||||
|
|
|
|||
31
examples/complete/complete.freebsd
Normal file
31
examples/complete/complete.freebsd
Normal file
|
|
@ -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
|
||||
433
examples/complete/complete.ianmac
Normal file
433
examples/complete/complete.ianmac
Normal file
|
|
@ -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
|
||||
#########################################################################
|
||||
271
examples/complete/complete2.ianmac
Normal file
271
examples/complete/complete2.ianmac
Normal file
|
|
@ -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
|
||||
###
|
||||
15
examples/functions/array-to-string
Normal file
15
examples/functions/array-to-string
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#! /bin/bash
|
||||
|
||||
# Format: array_to_string vname_of_array vname_of_string separator
|
||||
array_to_string()
|
||||
{
|
||||
(( ($# < 2) || ($# > 3) )) && {
|
||||
"$FUNCNAME: usage: $FUNCNAME arrayname stringname [separator]"
|
||||
return 2
|
||||
}
|
||||
|
||||
local array=$1 string=$2
|
||||
((3==$#)) && [[ $3 = ? ]] && local IFS="${3}${IFS}"
|
||||
eval $string="\"\${$array[*]}\""
|
||||
return 0
|
||||
}
|
||||
28
examples/functions/emptydir
Normal file
28
examples/functions/emptydir
Normal file
|
|
@ -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
|
||||
}
|
||||
|
|
@ -9,5 +9,5 @@ fact ()
|
|||
echo 1
|
||||
return ;
|
||||
fi;
|
||||
echo $[ $num * $(fact $[ $num - 1 ])]
|
||||
echo $(( $num * $(fact $(( $num - 1 )) ) ))
|
||||
}
|
||||
|
|
|
|||
35
examples/functions/gethtml
Normal file
35
examples/functions/gethtml
Normal file
|
|
@ -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 "$@"
|
||||
35
examples/functions/ksh-cd
Normal file
35
examples/functions/ksh-cd
Normal file
|
|
@ -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
|
||||
}
|
||||
|
|
@ -109,27 +109,39 @@ $1 == "'$cmd'" && $2 == "()" {printit=0; next; }
|
|||
# whence -v "$*"
|
||||
#}
|
||||
|
||||
#
|
||||
# ksh-like `cd': cd [-LP] [dir [change]]
|
||||
#
|
||||
cd()
|
||||
{
|
||||
case $# in
|
||||
0) builtin cd "$HOME" ;;
|
||||
1) builtin cd "$@" ;;
|
||||
2) old="$1"
|
||||
new="$2"
|
||||
# dir=$(echo "$PWD" | sed "s:$old:$new:g")
|
||||
dir=${PWD//$old/$new}
|
||||
case "$dir" in
|
||||
"$PWD") case "$PWD" in
|
||||
*$old*) ;;
|
||||
*) echo "$FUNCNAME: bad substitution" >&2 ; return 1 ;;
|
||||
esac ;;
|
||||
*) echo "$dir"
|
||||
builtin cd "$dir"
|
||||
;;
|
||||
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 "$FUNCNAME: usage: $FUNCNAME [-LP] [dir] [change]" >&2
|
||||
return 1 ;;
|
||||
*) echo "${0##*/}: $FUNCNAME: usage: $FUNCNAME [-LP] [dir] [change]" >&2
|
||||
return 2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ lowercase()
|
|||
for file; do
|
||||
[ -f "$file" ] || continue
|
||||
filename=${file##*/}
|
||||
case "$filename" in
|
||||
case "$file" in
|
||||
*/*) dirname=${file%/*} ;;
|
||||
*) dirname=.;;
|
||||
esac
|
||||
|
|
|
|||
64
examples/functions/recurse
Normal file
64
examples/functions/recurse
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#!/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" -o -d "$file" ]; then
|
||||
eval "$3"
|
||||
fi
|
||||
done
|
||||
for file in .* * ; do
|
||||
if [ "$file" = "." -o "$file" = ".." ] ; then
|
||||
continue
|
||||
fi
|
||||
if [ -d "$file" -a ! -L "$file" ]; then
|
||||
recurse "$file" "$2" "$3" "$path"
|
||||
fi
|
||||
done
|
||||
cd ..
|
||||
fi
|
||||
}
|
||||
|
||||
recurse "$1" "$2" 'echo "$path$file"'
|
||||
|
||||
50
examples/functions/sort-pos-params
Normal file
50
examples/functions/sort-pos-params
Normal file
|
|
@ -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
|
||||
|
|
@ -67,7 +67,7 @@ INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \
|
|||
|
||||
ALLPROG = print truefalse sleep pushd finfo logname basename dirname \
|
||||
tty pathchk tee head mkdir rmdir sprintf printenv id whoami \
|
||||
uname sync push ln unlink
|
||||
uname sync push ln unlink cut realpath
|
||||
OTHERPROG = necho getconf hello cat
|
||||
|
||||
all: $(SHOBJ_STATUS)
|
||||
|
|
@ -164,6 +164,11 @@ ln: ln.o
|
|||
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)
|
||||
|
||||
# pushd is a special case. We use the same source that the builtin version
|
||||
# uses, with special compilation options.
|
||||
|
|
@ -214,3 +219,4 @@ uname.o: uname.c
|
|||
sync.o: sync.c
|
||||
push.o: push.c
|
||||
mkdir.o: mkdir.c
|
||||
realpath.o: realpath.c
|
||||
|
|
|
|||
376
examples/loadables/cut.c
Normal file
376
examples/loadables/cut.c
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
#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 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
|
||||
};
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "common.h"
|
||||
|
|
@ -17,7 +18,6 @@
|
|||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern char *strrchr();
|
||||
extern char **make_builtin_argv ();
|
||||
|
||||
static int printst();
|
||||
|
|
@ -137,7 +137,11 @@ char *f;
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
struct conf_variable
|
||||
{
|
||||
const char *name;
|
||||
enum { SYSCONF, CONFSTR, PATHCONF, CONSTANT } type;
|
||||
enum { SYSCONF, CONFSTR, PATHCONF, CONSTANT, G_UNDEF } type;
|
||||
long value;
|
||||
};
|
||||
|
||||
|
|
@ -105,19 +105,55 @@ static const struct conf_variable conf_table[] =
|
|||
#endif /* _CS_XBS5_ILP32_OFF32_CFLAGS */
|
||||
|
||||
/* POSIX.2 Utility Limit Minimum Values */
|
||||
#ifdef _POSIX2_BC_BASE_MAX
|
||||
{ "POSIX2_BC_BASE_MAX", CONSTANT, _POSIX2_BC_BASE_MAX },
|
||||
#else
|
||||
{ "POSIX2_BC_BASE_MAX", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _POSIX2_BC_DIM_MAX
|
||||
{ "POSIX2_BC_DIM_MAX", CONSTANT, _POSIX2_BC_DIM_MAX },
|
||||
#else
|
||||
{ "POSIX2_BC_DIM_MAX", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _POSIX2_BC_SCALE_MAX
|
||||
{ "POSIX2_BC_SCALE_MAX", CONSTANT, _POSIX2_BC_SCALE_MAX },
|
||||
#else
|
||||
{ "POSIX2_BC_SCALE_MAX", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _POSIX2_BC_STRING_MAX
|
||||
{ "POSIX2_BC_STRING_MAX", CONSTANT, _POSIX2_BC_STRING_MAX },
|
||||
#else
|
||||
{ "POSIX2_BC_STRING_MAX", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _POSIX2_COLL_WEIGHTS_MAX
|
||||
{ "POSIX2_COLL_WEIGHTS_MAX", CONSTANT, _POSIX2_COLL_WEIGHTS_MAX },
|
||||
#else
|
||||
{ "POSIX2_COLL_WEIGHTS_MAX", G_UNDEF, -1 },
|
||||
#endif
|
||||
#if defined (_POSIX2_EQUIV_CLASS_MAX)
|
||||
{ "POSIX2_EQUIV_CLASS_MAX", CONSTANT, _POSIX2_EQUIV_CLASS_MAX },
|
||||
#endif
|
||||
#ifdef _POSIX2_EXPR_NEST_MAX
|
||||
{ "POSIX2_EXPR_NEST_MAX", CONSTANT, _POSIX2_EXPR_NEST_MAX },
|
||||
#else
|
||||
{ "POSIX2_EXPR_NEST_MAX", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _POSIX2_LINE_MAX
|
||||
{ "POSIX2_LINE_MAX", CONSTANT, _POSIX2_LINE_MAX },
|
||||
#else
|
||||
{ "POSIX2_LINE_MAX", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _POSIX2_RE_DUP_MAX
|
||||
{ "POSIX2_RE_DUP_MAX", CONSTANT, _POSIX2_RE_DUP_MAX },
|
||||
#else
|
||||
{ "POSIX2_RE_DUP_MAX", G_UNDEF, -1 },
|
||||
#endif
|
||||
#if defined (_POSIX2_VERSION)
|
||||
{ "POSIX2_VERSION", CONSTANT, _POSIX2_VERSION },
|
||||
#else
|
||||
# if !defined (_SC_2_VERSION)
|
||||
{ "POSIX2_VERSION", G_UNDEF, -1 },
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* POSIX.1 Minimum Values */
|
||||
|
|
@ -146,20 +182,50 @@ static const struct conf_variable conf_table[] =
|
|||
{ "RE_DUP_MAX", SYSCONF, _SC_RE_DUP_MAX },
|
||||
|
||||
/* POSIX.2 Optional Facility Configuration Values */
|
||||
#ifdef _SC_2_C_BIND
|
||||
{ "POSIX2_C_BIND", SYSCONF, _SC_2_C_BIND },
|
||||
#else
|
||||
{ "POSIX2_C_BIND", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _SC_2_C_DEV
|
||||
{ "POSIX2_C_DEV", SYSCONF, _SC_2_C_DEV },
|
||||
#else
|
||||
{ "POSIX2_C_DEV", G_UNDEF, -1 },
|
||||
#endif
|
||||
#if defined (_SC_2_C_VERSION)
|
||||
{ "POSIX2_C_VERSION", SYSCONF, _SC_2_C_VERSION },
|
||||
#else
|
||||
{ "POSIX2_C_VERSION", G_UNDEF, -1 },
|
||||
#endif
|
||||
#if defined (_SC_2_CHAR_TERM)
|
||||
{ "POSIX2_CHAR_TERM", SYSCONF, _SC_2_CHAR_TERM },
|
||||
#else
|
||||
{ "POSIX2_CHAR_TERM", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _SC_2_FORT_DEV
|
||||
{ "POSIX2_FORT_DEV", SYSCONF, _SC_2_FORT_DEV },
|
||||
#else
|
||||
{ "POSIX2_FORT_DEV", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _SC_2_FORT_RUN
|
||||
{ "POSIX2_FORT_RUN", SYSCONF, _SC_2_FORT_RUN },
|
||||
#else
|
||||
{ "POSIX2_FORT_RUN", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _SC_2_LOCALEDEF
|
||||
{ "POSIX2_LOCALEDEF", SYSCONF, _SC_2_LOCALEDEF },
|
||||
#else
|
||||
{ "POSIX2_LOCALEDEF", G_UNDEF, -1 },
|
||||
#endif
|
||||
#ifdef _SC_2_SW_DEV
|
||||
{ "POSIX2_SW_DEV", SYSCONF, _SC_2_SW_DEV },
|
||||
#else
|
||||
{ "POSIX2_SW_DEV", G_UNDEF, -1 },
|
||||
#endif
|
||||
#if defined (_SC2_UPE)
|
||||
{ "POSIX2_UPE", SYSCONF, _SC_2_UPE },
|
||||
#else
|
||||
{ "POSIX2_UPE", G_UNDEF, -1 },
|
||||
#endif
|
||||
#if !defined (_POSIX2_VERSION) && defined (_SC_2_VERSION)
|
||||
{ "POSIX2_VERSION" SYSCONF, _SC_2_VERSION },
|
||||
|
|
@ -449,6 +515,10 @@ int all;
|
|||
size_t slen;
|
||||
|
||||
switch (cp->type) {
|
||||
case G_UNDEF:
|
||||
printf("undefined\n");
|
||||
break;
|
||||
|
||||
case CONSTANT:
|
||||
printf("%ld\n", cp->value);
|
||||
break;
|
||||
|
|
@ -508,7 +578,8 @@ int all;
|
|||
break;
|
||||
}
|
||||
|
||||
return (ferror(stdout) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
||||
return ((ferror(stdout) || cp->type == G_UNDEF) ? EXECUTION_FAILURE
|
||||
: EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
95
examples/loadables/push.c
Normal file
95
examples/loadables/push.c
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* push - anyone remember TOPS-20?
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "jobs.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern int dollar_dollar_pid;
|
||||
extern int last_command_exit_value;
|
||||
|
||||
int
|
||||
push_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
pid_t pid;
|
||||
int xstatus, opt;
|
||||
|
||||
xstatus = EXECUTION_SUCCESS;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
pid = make_child (savestring ("push"), 0);
|
||||
if (pid == -1)
|
||||
{
|
||||
builtin_error ("cannot fork: %s", strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
/* Shell variable adjustments: $SHLVL, $$, $PPID, $! */
|
||||
adjust_shell_level (1);
|
||||
dollar_dollar_pid = getpid ();
|
||||
set_ppid ();
|
||||
|
||||
/* Clean up job control stuff. */
|
||||
stop_making_children ();
|
||||
cleanup_the_pipeline ();
|
||||
delete_all_jobs (0);
|
||||
|
||||
last_asynchronous_pid = NO_PID;
|
||||
|
||||
/* Make sure the job control code has the right values for
|
||||
the shell's process group and tty process group, and that
|
||||
the signals are set correctly for job control. */
|
||||
initialize_job_control (0);
|
||||
initialize_job_signals ();
|
||||
|
||||
/* And read commands until exit. */
|
||||
reader_loop ();
|
||||
exit_shell (last_command_exit_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
stop_pipeline (0, (COMMAND *)NULL);
|
||||
xstatus = wait_for (pid);
|
||||
return (xstatus);
|
||||
}
|
||||
}
|
||||
|
||||
char *push_doc[] = {
|
||||
"Create a child that is an exact duplicate of the running shell",
|
||||
"and wait for it to exit. The $SHLVL, $!, $$, and $PPID variables",
|
||||
"are adjusted in the child. The return value is the exit status",
|
||||
"of the child.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin push_struct = {
|
||||
"push",
|
||||
push_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
push_doc,
|
||||
"push",
|
||||
0
|
||||
};
|
||||
119
examples/loadables/realpath.c
Normal file
119
examples/loadables/realpath.c
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* realpath -- canonicalize pathnames, resolving symlinks
|
||||
*
|
||||
* usage: realpath [-csv] pathname [pathname...]
|
||||
*
|
||||
* options: -c check whether or not each resolved path exists
|
||||
* -s no output, exit status determines whether path is valid
|
||||
* -v produce verbose output
|
||||
*
|
||||
*
|
||||
* exit status: 0 if all pathnames resolved
|
||||
* 1 if any of the pathname arguments could not be resolved
|
||||
*
|
||||
*
|
||||
* Bash loadable builtin version
|
||||
*
|
||||
* Chet Ramey
|
||||
* chet@po.cwru.edu
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include "bashansi.h"
|
||||
#include <maxpath.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern char *sh_realpath();
|
||||
|
||||
realpath_builtin(list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int opt, cflag, vflag, sflag, es;
|
||||
char *r, realbuf[PATH_MAX], *p;
|
||||
struct stat sb;
|
||||
|
||||
if (list == 0) {
|
||||
builtin_usage();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
vflag = cflag = sflag = 0;
|
||||
reset_internal_getopt();
|
||||
while ((opt = internal_getopt (list, "csv")) != -1) {
|
||||
switch (opt) {
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
case 'v':
|
||||
vflag = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
list = loptend;
|
||||
|
||||
if (list == 0)
|
||||
usage();
|
||||
|
||||
for (es = EXECUTION_SUCCESS; list; list = list->next) {
|
||||
p = list->word->word;
|
||||
r = sh_realpath(p, realbuf);
|
||||
if (r == 0) {
|
||||
es = EXECUTION_FAILURE;
|
||||
if (sflag == 0)
|
||||
builtin_error("%s: cannot resolve: %s", p, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (cflag && (stat(realbuf, &sb) < 0)) {
|
||||
es = EXECUTION_FAILURE;
|
||||
if (sflag == 0)
|
||||
builtin_error("%s: %s", p, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (sflag == 0) {
|
||||
if (vflag)
|
||||
printf ("%s -> ", p);
|
||||
printf("%s\n", realbuf);
|
||||
}
|
||||
}
|
||||
return es;
|
||||
}
|
||||
|
||||
char *realpath_doc[] = {
|
||||
"Display the canonicalized version of each PATHNAME argument, resolving",
|
||||
"symbolic links. The -c option checks whether or not each resolved name",
|
||||
"exists. The -s option produces no output; the exit status determines the",
|
||||
"valididty of each PATHNAME. The -v option produces verbose output. The",
|
||||
"exit status is 0 if each PATHNAME was resolved; non-zero otherwise.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin realpath_struct = {
|
||||
"realpath", /* builtin name */
|
||||
realpath_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
realpath_doc, /* array of long documentation strings */
|
||||
"realpath [-csv] pathname [pathname...]", /* usage synopsis */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
|
|
@ -99,7 +99,7 @@ set -o emacs
|
|||
cd
|
||||
LIM=.limbo # $HOME/$LIM contains "destroyed" objects
|
||||
mkdir $LIM || {
|
||||
echo "ash: cannot mkdir $LIM: exiting
|
||||
echo "ash: cannot mkdir $LIM: exiting"
|
||||
exit 1
|
||||
}
|
||||
KNAP=.knapsack # $HOME/$KNAP contains objects being "carried"
|
||||
|
|
|
|||
12
examples/scripts/cat.sh
Normal file
12
examples/scripts/cat.sh
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
shcat()
|
||||
{
|
||||
while read -r ; do
|
||||
echo "$REPLY"
|
||||
done
|
||||
}
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
shcat < "$1"
|
||||
else
|
||||
shcat
|
||||
fi
|
||||
476
examples/scripts/dd-ex.sh
Normal file
476
examples/scripts/dd-ex.sh
Normal file
|
|
@ -0,0 +1,476 @@
|
|||
#!/bin/sh
|
||||
|
||||
# this is a line editor using only /bin/sh, /bin/dd and /bin/rm
|
||||
|
||||
# /bin/rm is not really required, but it is nice to clean up temporary files
|
||||
|
||||
PATH=
|
||||
dd=/bin/dd
|
||||
rm=/bin/rm
|
||||
|
||||
# temporary files we might need
|
||||
tmp=/tmp/silly.$$
|
||||
ed=/tmp/ed.$$
|
||||
trap "$rm -f $tmp $tmp.1 $tmp.2 $tmp.3 $tmp.4 $tmp.5 $tmp.6 $ed.a $ed.b $ed.c; exit" 0 1 2 3
|
||||
|
||||
# from now on, no more rm - the above trap is enough
|
||||
unset rm
|
||||
|
||||
# we do interesting things with IFS, but better save it...
|
||||
saveIFS="$IFS"
|
||||
|
||||
# in case "echo" is not a shell builtin...
|
||||
|
||||
Echo () {
|
||||
case "$1" in
|
||||
-n) shift
|
||||
$dd of=$tmp 2>/dev/null <<EOF
|
||||
$@
|
||||
EOF
|
||||
IFS="+"
|
||||
set `$dd if=$tmp bs=1 of=/dev/null skip=1 2>&1`
|
||||
IFS="$saveIFS"
|
||||
$dd if=$tmp bs=1 count=$1 2>/dev/null
|
||||
;;
|
||||
*) $dd 2>/dev/null <<EOF
|
||||
$@
|
||||
EOF
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# this is used to generate garbage files
|
||||
|
||||
true () {
|
||||
return 0
|
||||
}
|
||||
|
||||
false () {
|
||||
return 1
|
||||
}
|
||||
|
||||
zero () {
|
||||
( trap 'go=false' 13
|
||||
go=true
|
||||
while $go
|
||||
do
|
||||
$dd "if=$0"
|
||||
case "$?" in
|
||||
0) ;;
|
||||
*) go=false ;;
|
||||
esac
|
||||
done
|
||||
) 2>/dev/null
|
||||
}
|
||||
|
||||
# arithmetic using dd!
|
||||
|
||||
# add variable n1 n2 n3...
|
||||
# assigns n1+n2+n3+... to variable
|
||||
|
||||
add () {
|
||||
result="$1"
|
||||
shift
|
||||
$dd if=/dev/null of=$tmp bs=1 2>/dev/null
|
||||
for n in "$@"
|
||||
do
|
||||
case "$n" in
|
||||
0) ;;
|
||||
*) zero | $dd of=$tmp.1 bs=1 "count=$n" 2>/dev/null
|
||||
( $dd if=$tmp; $dd if=$tmp.1 ) 2>/dev/null | $dd of=$tmp.2 2>/dev/null
|
||||
$dd if=$tmp.2 of=$tmp 2>/dev/null
|
||||
;;
|
||||
esac
|
||||
done
|
||||
IFS="+"
|
||||
set `$dd if=$tmp bs=1 of=/dev/null 2>&1`
|
||||
IFS="$saveIFS"
|
||||
eval $result='$1'
|
||||
}
|
||||
|
||||
# subtract variable n1 n2
|
||||
# subtracts n2 from n1, assigns result to variable
|
||||
|
||||
subtract () {
|
||||
result="$1"
|
||||
zero | $dd of=$tmp bs=1 "count=$2" 2>/dev/null
|
||||
IFS="+"
|
||||
set `$dd if=$tmp bs=1 of=/dev/null "skip=$3" 2>&1`
|
||||
IFS="$saveIFS"
|
||||
case "$1" in
|
||||
dd*) set 0 ;;
|
||||
esac
|
||||
eval $result='$1'
|
||||
}
|
||||
|
||||
# multiply variable n1 n2
|
||||
# variable = n1 * n2
|
||||
|
||||
multiply () {
|
||||
result="$1"
|
||||
zero | $dd "bs=$2" of=$tmp "count=$3" 2>/dev/null
|
||||
IFS="+"
|
||||
set `$dd if=$tmp bs=1 of=/dev/null 2>&1`
|
||||
IFS="$saveIFS"
|
||||
eval $result='$1'
|
||||
}
|
||||
|
||||
# divide variable n1 n2
|
||||
# variable = int( n1 / n2 )
|
||||
|
||||
divide () {
|
||||
result="$1"
|
||||
zero | $dd bs=1 of=$tmp "count=$2" 2>/dev/null
|
||||
IFS="+"
|
||||
set `$dd if=$tmp "bs=$3" of=/dev/null 2>&1`
|
||||
IFS="$saveIFS"
|
||||
eval $result='$1'
|
||||
}
|
||||
|
||||
# compare variable n1 n2 sets variable to lt if n1<n2, gt if n1>n2, eq if n1==n2
|
||||
|
||||
compare () {
|
||||
res="$1"
|
||||
n1="$2"
|
||||
n2="$3"
|
||||
subtract somename "$n1" "$n2"
|
||||
case "$somename" in
|
||||
0) ;;
|
||||
*) eval $res=gt; return;
|
||||
esac
|
||||
subtract somename "$n2" "$n1"
|
||||
case "$somename" in
|
||||
0) ;;
|
||||
*) eval $res=lt; return;
|
||||
esac
|
||||
eval $res=eq
|
||||
}
|
||||
|
||||
# lt n1 n2 returns true if n1 < n2
|
||||
|
||||
lt () {
|
||||
n1="$1"
|
||||
n2="$2"
|
||||
subtract somename "$n2" "$n1"
|
||||
case "$somename" in
|
||||
0) return 1 ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
# le n1 n2 returns true if n1 <= n2
|
||||
|
||||
le () {
|
||||
n1="$1"
|
||||
n2="$2"
|
||||
subtract somename "$n1" "$n2"
|
||||
case "$somename" in
|
||||
0) return 0 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
# gt n1 n2 returns true if n1 > n2
|
||||
|
||||
gt () {
|
||||
n1="$1"
|
||||
n2="$2"
|
||||
subtract somename "$n1" "$n2"
|
||||
case "$somename" in
|
||||
0) return 1 ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
# ge n1 n2 returns true if n1 >= n2
|
||||
|
||||
ge () {
|
||||
n1="$1"
|
||||
n2="$2"
|
||||
subtract somename "$n2" "$n1"
|
||||
case "$somename" in
|
||||
0) return 0 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
# useful functions for the line editor
|
||||
|
||||
# open a file - copy it to the buffers
|
||||
|
||||
open () {
|
||||
file="$1"
|
||||
set `$dd "if=$file" of=/dev/null 2>&1`
|
||||
case "$1" in
|
||||
dd*) return 1
|
||||
esac
|
||||
# copy the first line to $ed.c
|
||||
go=true
|
||||
len=0
|
||||
while $go
|
||||
do
|
||||
case "`$dd "if=$file" bs=1 skip=$len count=1 2>/dev/null`" in
|
||||
?*) go=true ;;
|
||||
*) go=false ;;
|
||||
esac
|
||||
add len 1 $len
|
||||
done
|
||||
# now $len is the length of the first line (including newline)
|
||||
$dd "if=$file" bs=1 count=$len of=$ed.c 2>/dev/null
|
||||
$dd "if=$file" bs=1 skip=$len of=$ed.b 2>/dev/null
|
||||
$dd if=/dev/null of=$ed.a 2>/dev/null
|
||||
lineno=1
|
||||
}
|
||||
|
||||
# save a file - copy the buffers to the file
|
||||
|
||||
save () {
|
||||
# make a backup copy of the original
|
||||
$dd "if=$1" "of=$1.bak" 2>/dev/null
|
||||
# and save
|
||||
( $dd if=$ed.a; $dd if=$ed.c; $dd if=$ed.b ) > "$1" 2>/dev/null
|
||||
}
|
||||
|
||||
# replace n1 n2 bla replaces n2 chars of current line, starting n1-th
|
||||
|
||||
replace () {
|
||||
$dd if=$ed.c of=$tmp.1 bs=1 "count=$1" 2>/dev/null
|
||||
( $dd if=$ed.c "skip=$1" bs=1 | $dd of=$tmp.2 bs=1 "skip=$2" ) 2>/dev/null
|
||||
shift
|
||||
shift
|
||||
( $dd if=$tmp.1; Echo -n "$@"; $dd if=$tmp.2 ) > $tmp.3 2>/dev/null
|
||||
$dd if=$tmp.3 of=$ed.c 2>/dev/null
|
||||
}
|
||||
|
||||
# rstring n s bla
|
||||
# replace the n-th occurence of s with bla
|
||||
|
||||
rstring () {
|
||||
n="$1"
|
||||
shift;
|
||||
# first we have to find it - this is fun!
|
||||
# we have $tmp.4 => text before string, $tmp.5 => text after
|
||||
$dd if=/dev/null of=$tmp.4 2>/dev/null
|
||||
$dd if=$ed.c of=$tmp.5 2>/dev/null
|
||||
string="$1"
|
||||
shift
|
||||
$dd of=$tmp.6 2>/dev/null <<EOF
|
||||
$@
|
||||
EOF
|
||||
while :
|
||||
do
|
||||
case "`$dd if=$tmp.5 2>/dev/null`" in
|
||||
$string*)
|
||||
if lt $n 2
|
||||
then
|
||||
# now we want to replace the string
|
||||
Echo -n "$@" > $tmp.2
|
||||
Echo -n "$string" > $tmp.1
|
||||
IFS="+"
|
||||
set `$dd bs=1 if=$tmp.1 of=/dev/null 2>&1`
|
||||
IFS="$saveIFS"
|
||||
slen=$1
|
||||
IFS="+"
|
||||
( $dd if=$tmp.4; $dd if=$tmp.2; $dd if=$tmp.5 bs=1 skip=$slen ) \
|
||||
2>/dev/null > $tmp
|
||||
$dd if=$tmp of=$ed.c 2>/dev/null
|
||||
return 0
|
||||
else
|
||||
subtract n $n 1
|
||||
( $dd if=$tmp.4; $dd if=$tmp.5 bs=1 count=1 ) > $tmp 2>/dev/null
|
||||
$dd if=$tmp of=$tmp.4 2>/dev/null
|
||||
# and remove it from $tmp.5
|
||||
$dd if=$tmp.5 of=$tmp bs=1 skip=1 2>/dev/null
|
||||
$dd if=$tmp of=$tmp.5 2>/dev/null
|
||||
fi
|
||||
;;
|
||||
?*) # add one more byte...
|
||||
( $dd if=$tmp.4; $dd if=$tmp.5 bs=1 count=1 ) > $tmp 2>/dev/null
|
||||
$dd if=$tmp of=$tmp.4 2>/dev/null
|
||||
# and remove it from $tmp.5
|
||||
$dd if=$tmp.5 of=$tmp bs=1 skip=1 2>/dev/null
|
||||
$dd if=$tmp of=$tmp.5 2>/dev/null
|
||||
;;
|
||||
*) # not found
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# skip to next line
|
||||
next () {
|
||||
add l $lineno 1
|
||||
( $dd if=$ed.a; $dd if=$ed.c ) 2>/dev/null > $tmp.3
|
||||
$dd if=$ed.b of=$tmp.4 2>/dev/null
|
||||
open $tmp.4
|
||||
$dd if=$tmp.3 of=$ed.a 2>/dev/null
|
||||
lineno=$l
|
||||
}
|
||||
|
||||
# delete current line
|
||||
delete () {
|
||||
l=$lineno
|
||||
$dd if=$ed.a 2>/dev/null > $tmp.1
|
||||
$dd if=$ed.b of=$tmp.2 2>/dev/null
|
||||
open $tmp.2
|
||||
$dd if=$tmp.1 of=$ed.a 2>/dev/null
|
||||
lineno=$l
|
||||
}
|
||||
|
||||
# insert before current line (without changing current)
|
||||
insert () {
|
||||
( $dd if=$ed.a; Echo "$@" ) 2>/dev/null > $tmp.1
|
||||
$dd if=$tmp.1 of=$ed.a 2>/dev/null
|
||||
add lineno $lineno 1
|
||||
}
|
||||
|
||||
# previous line
|
||||
prev () {
|
||||
case "$lineno" in
|
||||
1) ;;
|
||||
*) subtract lineno $lineno 1
|
||||
# read last line of $ed.a
|
||||
IFS='+'
|
||||
set `$dd if=$ed.a of=/dev/null bs=1 2>&1`
|
||||
IFS="$saveIFS"
|
||||
size=$1
|
||||
# empty?
|
||||
case "$size" in
|
||||
0) return ;;
|
||||
esac
|
||||
subtract size $size 1
|
||||
# skip final newline
|
||||
case "$size" in
|
||||
0) ;;
|
||||
*) subtract size1 $size 1
|
||||
case "`$dd if=$ed.a bs=1 skip=$size count=1 2>/dev/null`" in
|
||||
?*) ;;
|
||||
*) size=$size1 ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
go=true
|
||||
while $go
|
||||
do
|
||||
case "$size" in
|
||||
0) go=false ;;
|
||||
*) case "`$dd if=$ed.a bs=1 skip=$size count=1 2>/dev/null`" in
|
||||
?*) go=true; subtract size $size 1 ;;
|
||||
*) go=false; add size $size 1 ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# now $size is the size of the first n-1 lines
|
||||
# add $ed.c to $ed.b
|
||||
( $dd if=$ed.c; $dd if=$ed.b ) 2>/dev/null > $tmp.5
|
||||
$dd if=$tmp.5 of=$ed.b 2>/dev/null
|
||||
# move line to ed.c
|
||||
case "$size" in
|
||||
0) $dd if=$ed.a of=$ed.c 2>/dev/null
|
||||
$dd if=/dev/null of=$tmp.5 2>/dev/null
|
||||
;;
|
||||
*) $dd if=$ed.a of=$ed.c bs=1 skip=$size 2>/dev/null
|
||||
$dd if=$ed.a of=$tmp.5 bs=1 count=$size 2>/dev/null
|
||||
;;
|
||||
esac
|
||||
# move rest to ed.a
|
||||
$dd if=$tmp.5 of=$ed.a 2>/dev/null
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# goes to a given line
|
||||
goto () {
|
||||
rl="$1"
|
||||
compare bla "$rl" $lineno
|
||||
case "$bla" in
|
||||
eq) return
|
||||
;;
|
||||
gt) while gt "$rl" $lineno
|
||||
do
|
||||
next
|
||||
done
|
||||
;;
|
||||
lt) while lt "$rl" $lineno
|
||||
do
|
||||
prev
|
||||
done
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
lineout () {
|
||||
Echo -n "$lineno: "
|
||||
$dd if=$ed.c 2>/dev/null
|
||||
}
|
||||
|
||||
state=closed
|
||||
name=
|
||||
autoprint=true
|
||||
|
||||
while true
|
||||
do
|
||||
Echo -n '> '
|
||||
read cmd arg
|
||||
case "$cmd:$state" in
|
||||
open:open) Echo "There is a file open already" ;;
|
||||
open:*) if open "$arg"
|
||||
then state=open; name="$arg"; $autoprint
|
||||
else Echo "Cannot open $arg"
|
||||
fi
|
||||
;;
|
||||
new:open) Echo "There is a file open already" ;;
|
||||
new:*) open "$arg"
|
||||
state=open
|
||||
name="$arg"
|
||||
$autoprint
|
||||
;;
|
||||
close:changed) Echo "Use 'discard' or 'save'" ;;
|
||||
close:closed) Echo "Closed already" ;;
|
||||
close:*) state=closed ;;
|
||||
save:closed) Echo "There isn't a file to save" ;;
|
||||
save:*) case "$arg" in
|
||||
?*) save "$arg" ;;
|
||||
*) save "$name" ;;
|
||||
esac
|
||||
state=open
|
||||
;;
|
||||
discard:changed) Echo "Your problem!"; state=closed ;;
|
||||
discard:*) state=closed ;;
|
||||
print:closed) Echo "No current file" ;;
|
||||
print:*) lineout ;;
|
||||
goto:closed) Echo "No current file" ;;
|
||||
goto:*) goto "$arg"; $autoprint ;;
|
||||
next:closed) Echo "No current file" ;;
|
||||
next:*) next; $autoprint ;;
|
||||
prev:closed) Echo "No current file" ;;
|
||||
prev:*) prev; $autoprint ;;
|
||||
name:closed) Echo "No current file" ;;
|
||||
name:*) name="$arg" ;;
|
||||
replace:closed) Echo "No current file" ;;
|
||||
replace:*) if rstring 1 $arg
|
||||
then state=changed; $autoprint
|
||||
else Echo "Not found"
|
||||
fi
|
||||
;;
|
||||
nreplace:closed) Echo "No current file" ;;
|
||||
nreplace:*) if rstring $arg
|
||||
then state=changed; $autoprint
|
||||
else Echo "Not found"
|
||||
fi
|
||||
;;
|
||||
delete:closed) Echo "No current file" ;;
|
||||
delete:*) delete; state=changed; $autoprint ;;
|
||||
insert:closed) Echo "No current file" ;;
|
||||
insert:*) insert "$arg"; prev; state=changed; $autoprint ;;
|
||||
quit:changed) Echo "Use 'save' or 'discard'" ;;
|
||||
quit:*) Echo "bye"; exit;;
|
||||
autoprint:*) autoprint="lineout" ;;
|
||||
noprint:*) autoprint="" ;;
|
||||
:*) ;;
|
||||
*) Echo "Command not understood" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue