Imported from ../bash-2.05.tar.gz.

This commit is contained in:
Jari Aalto 2001-04-06 19:14:31 +00:00
commit 28ef6c316f
251 changed files with 22319 additions and 12413 deletions

View file

@ -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
#

View 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

View 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
#########################################################################

View 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
###

View 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
}

View 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
}

View file

@ -9,5 +9,5 @@ fact ()
echo 1
return ;
fi;
echo $[ $num * $(fact $[ $num - 1 ])]
echo $(( $num * $(fact $(( $num - 1 )) ) ))
}

View 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
View 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
}

View file

@ -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
}

View file

@ -11,7 +11,7 @@ lowercase()
for file; do
[ -f "$file" ] || continue
filename=${file##*/}
case "$filename" in
case "$file" in
*/*) dirname=${file%/*} ;;
*) dirname=.;;
esac

View 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"'

View 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

View file

@ -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
View 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
};

View file

@ -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);

View file

@ -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
View 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
};

View 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 */
};

View file

@ -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
View 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
View 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