home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 15 / hacker15 / 15_H4CK3R#15.ISO / linux_security / engarde / ENGARDE_COMMUNITY_FEINT.ISO / etc / bash_completion next >
Encoding:
Text File  |  2002-05-30  |  29.5 KB  |  1,138 lines

  1. #   bash_completion - some programmable completion functions for bash 2.04
  2. #
  3. #   <![CDATA[
  4. #
  5. #   $Id: bash_completion,v 1.13 2001/01/11 00:09:48 ianmacd Exp $
  6. #
  7. #   Copyright (C) Ian Macdonald <ian@caliban.org>
  8. #                <ian@linuxcare.com>
  9. #
  10. #   This program is free software; you can redistribute it and/or modify
  11. #   it under the terms of the GNU General Public License as published by
  12. #   the Free Software Foundation; either version 2, or (at your option)
  13. #   any later version.
  14. #
  15. #   This program is distributed in the hope that it will be useful,
  16. #   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. #   GNU General Public License for more details.
  19. #
  20. #   You should have received a copy of the GNU General Public License
  21. #   along with this program; if not, write to the Free Software Foundation,
  22. #   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23.  
  24. # Turn on extended globbing and programmable completion
  25. shopt -s extglob progcomp
  26.  
  27. # A lot of the following one-liners were taken directly from the
  28. # completion examples provided with the bash 2.04 source distribution
  29.  
  30. # Make directory commands see only directories
  31. complete -d cd mkdir rmdir pushd
  32.  
  33. # Make file commands see only files
  34. complete -f cat less more ln strip
  35. complete -f -X '*.bz2' bzip2
  36. complete -f -X '!*.bz2' bunzip2
  37. complete -f -X '!*.zip' unzip
  38. complete -f -X '*.gz' gzip
  39. complete -f -X '*.Z' compress
  40. complete -f -X '!*.+(Z|gz|tgz|Gz)' gunzip zcat zmore
  41. complete -f -X '!*.Z' uncompress zmore zcat
  42. complete -f -X '!*.+(gif|jpg|jpeg|GIF|JPG|bmp)' ee xv
  43. complete -f -X '!*.+(ps|PS|ps.gz)' gv
  44. complete -f -X '!*.+(dvi|DVI)' dvips xdvi dviselect dvitype
  45. complete -f -X '!*.+(pdf|PDF)' acroread xpdf
  46. complete -f -X '!*.texi*' makeinfo texi2dvi texi2html
  47. complete -f -X '!*.+(tex|TEX)' tex latex slitex
  48.  
  49. # kill sees only signals
  50. complete -A signal kill -P '%'
  51.  
  52. # user commands see only users
  53. complete -u finger su usermod userdel passwd
  54.  
  55. # bg completes with stopped jobs
  56. complete -A stopped -P '%' bg
  57.  
  58. # other job commands
  59. complete -j -P '%' fg jobs disown
  60.  
  61. # network commands complete with hostname
  62. complete -A hostname ssh rsh telnet rlogin ftp ping fping host traceroute \
  63.         nslookup
  64.  
  65. # export and others complete with shell variables
  66. complete -v export local readonly unset
  67.  
  68. # set completes with set options
  69. complete -A setopt set
  70.  
  71. # shopt completes with shopt options
  72. complete -A shopt shopt
  73.  
  74. # helptopics
  75. complete -A helptopic help
  76.  
  77. # unalias completes with aliases
  78. complete -a unalias
  79.  
  80. # various commands complete with commands
  81. complete -c command type nohup exec nice eval strace gdb sudo
  82.  
  83. # bind completes with readline bindings (make this more intelligent)
  84. complete -A binding bind
  85.  
  86. # Now we get to the meat of the file, the functions themselves. Some
  87. # of these are works in progress. Most assume GNU versions of the
  88. # tools in question and may require modifications for use on vanilla
  89. # UNIX systems.
  90. #
  91. # A couple of functions may have non-portable, Linux specific code in
  92. # them, but this will be noted where applicable
  93.  
  94.  
  95. # GNU chown(1) completion. This should be expanded to allow the use of
  96. # ':' as well as '.' as the user.group separator.
  97. #
  98. _chown()
  99. {
  100.     local cur prev user group
  101.  
  102.         COMPREPLY=()
  103.         cur=${COMP_WORDS[COMP_CWORD]}
  104.         prev=${COMP_WORDS[COMP_CWORD-1]}
  105.  
  106.     # do not attempt completion if we're specifying an option
  107.     if [ "$cur" == -* ]; then return 0; fi
  108.  
  109.     # first parameter on line or first since an option?
  110.     if [ $COMP_CWORD -eq 1 ] || [[ "$prev" == -* ]]; then
  111.         if [[ "$cur" == [a-zA-Z]*.* ]]; then
  112.             user=${cur%.*}
  113.             group=${cur#*.}
  114.             COMPREPLY=( $( awk 'BEGIN {FS=":"} \
  115.                     {if ($1 ~ /^'$group'/) print $1}' \
  116.                     /etc/group ) )
  117.             for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
  118.                 COMPREPLY[i]=$user.${COMPREPLY[i]}
  119.             done
  120.         else
  121.             COMPREPLY=( $( compgen -u $cur -S '.' ) )
  122.         fi
  123.     else
  124.         COMPREPLY=( $( compgen -f $cur ) )
  125.     fi
  126.  
  127.     return 0
  128. }
  129. complete -F _chown chown
  130.  
  131. # umount(8) completion. This relies on the mount point being the third
  132. # space-delimited field in the output of mount(8)
  133. #
  134. _umount()
  135. {
  136.     local cur
  137.  
  138.         COMPREPLY=()
  139.         cur=${COMP_WORDS[COMP_CWORD]}
  140.  
  141.     # could rewrite the cut | grep to be a sed command, but this is
  142.     # clearer and doesn't result in much overhead
  143.     COMPREPLY=( $( mount | cut -d' ' -f 3 | grep ^$cur) )
  144.  
  145.     return 0
  146. }
  147. complete -F _umount umount
  148.  
  149. # GID completion. This will get a list of all valid group names from
  150. # /etc/group and should work anywhere.
  151. #
  152. _gid_func()
  153. {
  154.     local cur
  155.  
  156.         COMPREPLY=()
  157.         cur=${COMP_WORDS[COMP_CWORD]}
  158.     COMPREPLY=( $( awk 'BEGIN {FS=":"} {if ($1 ~ /^'$cur'/) print $1}' \
  159.                /etc/group ) )
  160.     return 0
  161. }
  162. complete -F _gid_func groupdel groupmod
  163.  
  164. # mount(8) completion. This will pull a list of possible mounts out of
  165. # /etc/fstab, unless the word being completed contains a ':', which
  166. # would indicate the specification of an NFS server. In that case, we
  167. # query the server for a list of all available exports and complete on
  168. # that instead.
  169. #
  170. _mount()
  171.  
  172. {       local cur
  173.  
  174.         COMPREPLY=()
  175.         cur=${COMP_WORDS[COMP_CWORD]}
  176.  
  177.     if [[ "$cur" == *:* ]]; then
  178.         COMPREPLY=( $( /usr/sbin/showmount -e --no-headers ${cur%%:*} |\
  179.                    grep ^${cur#*:} | awk '{print $1}' ) )
  180.     else
  181.         COMPREPLY=( $( awk '{if ($2 ~ /\//) print $2}' /etc/fstab | \
  182.                    grep ^$cur ) )
  183.         # default to filename completion if all else failed
  184.         if [ ${#COMPREPLY[@]} = 0 ]; then
  185.                 COMPREPLY=( $( compgen -f $cur ) )
  186.         fi
  187.     fi
  188.  
  189.     return 0
  190. }
  191. complete -F _mount mount
  192.  
  193. # Linux rmmod(1) completion. This completes on a list of all currently
  194. # installed kernel modules.
  195. #
  196. _rmmod()
  197. {
  198.     local cur
  199.  
  200.         COMPREPLY=()
  201.         cur=${COMP_WORDS[COMP_CWORD]}
  202.  
  203.     COMPREPLY=( $( /sbin/lsmod | \
  204.                awk '{if (NR != 1 && $1 ~ /^'$cur'/) print $1}') )
  205.     return 0
  206. }
  207. complete -F _rmmod rmmod
  208.  
  209. # Linux insmod(1) completion. This completes on a list of all
  210. # available modules for the version of the kernel currently running.
  211. #
  212. _insmod()
  213. {
  214.     local cur prev modpath
  215.  
  216.         COMPREPLY=()
  217.         cur=${COMP_WORDS[COMP_CWORD]}
  218.         prev=${COMP_WORDS[COMP_CWORD-1]}
  219.     modpath=/lib/modules/`uname -r`
  220.  
  221.     if [ $COMP_CWORD -gt 1 ]; then
  222.         COMPREPLY=( $( /sbin/modinfo -p $prev | cut -f 1 -d ' ' ) )
  223.     else
  224.         COMPREPLY=($( ls -R $modpath | sed -ne 's/^\('$cur'.*\)\.o$/\1/p'))
  225.     fi
  226.  
  227.     return 0
  228. }
  229. complete -F _insmod insmod modprobe modinfo
  230.  
  231. # man(1) completion. This relies on the security enhanced version of
  232. # GNU locate(1). UNIX variants having non-numeric man page sections
  233. # other than l, m and n should add the appropriate sections to the
  234. # first clause of the case statement.
  235. #
  236. # This is Linux specific, in that 'man <section> <page>' is the
  237. # expected syntax. This allows one to do something like
  238. # 'man 3 str<tab>' to obtain a list of all string handling syscalls on
  239. # the system.
  240. #
  241. _man()
  242. {
  243.     [ -f /etc/man.config ] || return 0
  244.         local cur prev cmd
  245.  
  246.         COMPREPLY=()
  247.         cur=${COMP_WORDS[COMP_CWORD]}
  248.         prev=${COMP_WORDS[COMP_CWORD-1]}
  249.  
  250.         # filename completion if parameter contains /
  251.         if [[ "$cur" == /* ]]; then
  252.                 COMPREPLY=( $( compgen -f $cur ) )
  253.                 return 0
  254.         fi
  255.  
  256.         if [[ "$prev" == [0-9n] ]]; then
  257.                 # churn out a string of paths to search, with * appended to $cur
  258.                 cmd=`awk '{if ($1 ~ /^MANPATH/) \
  259.                      print $(NF)"/man'$prev'/'$cur'*"}' /etc/man.config | \
  260.                      sort -u`
  261.                 # strip off * from paths ending in /*
  262.                 cmd=${cmd//\/\\*/\/}
  263.                 # redirect stderr for when path doesn't exist
  264.                 cmd="ls $cmd 2>/dev/null"
  265.                 COMPREPLY=( $( eval $cmd ) )
  266.                 # get basename of man pages
  267.                 COMPREPLY=( ${COMPREPLY[@]##*/} )
  268.                 # strip suffix from man pages
  269.                 COMPREPLY=( ${COMPREPLY[@]%.gz} )
  270.                 COMPREPLY=( ${COMPREPLY[@]%.*} )
  271.     else
  272.                 cmd=`awk '{if ($1 ~ /^MANPATH/) \
  273.                      print $(NF)"/man?/'$cur'*"}' /etc/man.config | sort -u`
  274.                 cmd=${cmd//\/\\*/\/}
  275.                 cmd="ls $cmd 2>/dev/null"
  276.                 COMPREPLY=( $( eval $cmd ) )
  277.                 COMPREPLY=( ${COMPREPLY[@]##*/} )
  278.                 COMPREPLY=( ${COMPREPLY[@]%.gz} )
  279.                 COMPREPLY=( ${COMPREPLY[@]%.*} $( compgen -G $cur\*.[0-9n] ) )
  280.         fi
  281.  
  282.     return 0
  283. }
  284. complete -F _man man
  285.  
  286. # Linux killall(1) completion. This wouldn't be much use on, say,
  287. # Solaris, where killall does exactly that: kills ALL processes.
  288. #
  289. # This could be improved. For example, it currently doesn't take
  290. # command line options into account
  291. #
  292. _killall()
  293. {
  294.     local cur prev
  295.  
  296.         COMPREPLY=()
  297.         cur=${COMP_WORDS[COMP_CWORD]}
  298.         prev=${COMP_WORDS[COMP_CWORD-1]}
  299.  
  300.     if [[ "$prev" == -[A-Z0-9]* ]]; then
  301.         # get a list of processes (the gensub() in the awk takes care
  302.         # of getting the basename of the process, the first sed
  303.         # evaluation takes care of swapped out processes, and the
  304.         # second takes care of getting the basename of the process)
  305.             COMPREPLY=( $( ps ahx | sed -e 's#[]\[()]##g' | \
  306.            awk '{if (gensub("^.*/","",1,$5) ~ /^'$cur'/) print $5}' | \
  307.            sed  -e 's#^.*/##' ) )
  308.         return 0
  309.     fi
  310.  
  311.     # first parameter can be either a signal or a process
  312.     if [ $COMP_CWORD -eq 1 ]; then
  313.         # standard signal completion is rather braindead, so we need
  314.         # to hack around to get what we want here, which is to
  315.         # complete on a dash, followed by the signal name minus
  316.         # the SIG prefix
  317.         COMPREPLY=( $( compgen -A signal SIG${cur#-} ))
  318.         for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
  319.             COMPREPLY[i]=-${COMPREPLY[i]#SIG}
  320.         done
  321.     fi
  322.  
  323.     # get processes, adding to signals if applicable
  324.     COMPREPLY=( ${COMPREPLY[*]} $( ps ahx | sed -e 's#[]\[()]##g' | \
  325.            awk '{if (gensub("^.*/","",1,$5) ~ /^'$cur'/) print $5}' | \
  326.            sed -e 's#^.*/##' ))
  327.     return 0
  328. }
  329. complete -F _killall killall
  330.  
  331. # GNU find(1) completion. This makes heavy use of ksh style extended
  332. # globs and contains Linux specific code for completing the parameter
  333. # to the -fstype option.
  334. #
  335. _find()
  336. {
  337.     local cur prev
  338.  
  339.         COMPREPLY=()
  340.         cur=${COMP_WORDS[COMP_CWORD]#-}
  341.         prev=${COMP_WORDS[COMP_CWORD-1]}
  342.  
  343.     case "$prev" in
  344.     -@(max|min)depth)
  345.         COMPREPLY=( $( compgen -W '0 1 2 3 4 5 6 7 8 9' ) )
  346.         return 0
  347.         ;;
  348.     -?(a)newer|-fls|-fprint?(0|f))
  349.         COMPREPLY=( $( compgen -f $cur ) )
  350.         return 0
  351.         ;;
  352.     -fstype)
  353.         # this is highly non-portable (the option to -d is a tab)
  354.         COMPREPLY=( $( cut -d'    ' -f 2 /proc/filesystems | grep ^$cur ) )
  355.         return 0
  356.         ;;
  357.     -gid)
  358.         COMPREPLY=( $( awk 'BEGIN {FS=":"} \
  359.                 {if ($3 ~ /^'$cur'/) print $3}' /etc/group ) )
  360.         return 0
  361.         ;;
  362.     -group)
  363.         COMPREPLY=( $( awk 'BEGIN {FS=":"} \
  364.                 {if ($1 ~ /^'$cur'/) print $1}' /etc/group ) )
  365.         return 0
  366.         ;;
  367.     -?(x)type)
  368.         COMPREPLY=( $( compgen -W 'b c d p f l s' $cur ) )
  369.         return 0
  370.         ;;
  371.     -uid)
  372.         COMPREPLY=( $( awk 'BEGIN {FS=":"} \
  373.                 {if ($3 ~ /^'$cur'/) print $3}' /etc/passwd ) )
  374.         return 0
  375.         ;;
  376.     -user)
  377.         COMPREPLY=( $( compgen -u $cur ) )
  378.         return 0
  379.         ;;
  380.     -[acm]min|-[acm]time|-?(i)?(l)name|-inum|-?(i)path|-?(i)regex| \
  381.     -links|-perm|-size|-used|-exec|-ok|-printf)
  382.         # do nothing, just wait for a parameter to be given
  383.         return 0
  384.         ;;
  385.     esac
  386.  
  387.     # complete using basic options ($cur has had its dash removed here,
  388.     # as otherwise compgen will bomb out with an error, since it thinks
  389.     # the dash is an option to itself)
  390.     COMPREPLY=( $( compgen -W 'daystart depth follow help maxdepth \
  391.             mindepth mount noleaf version xdev amin anewer atime \
  392.             cmin cnewer ctime empty false fstype gid group ilname \
  393.             iname inum ipath iregex links lname mmin mtime name \
  394.             newer nouser nogroup perm regex size true type uid \
  395.             used user xtype exec fls fprint fprint0 fprintf ok \
  396.             print print0 printf prune ls' $cur ) )
  397.  
  398.     # this removes any options from the list of completions that have
  399.     # already been specified somewhere on the command line.
  400.     COMPREPLY=( $( echo "${COMP_WORDS[@]}-" | \
  401.                (while read -d '-' i; do
  402.                 [ "$i" == "" ] && continue
  403.                 # flatten array with spaces on either side,
  404.                 # otherwise we cannot grep on word boundaries of
  405.                 # first and last word
  406.                 COMPREPLY=" ${COMPREPLY[@]} "
  407.                 # remove word from list of completions
  408.                 COMPREPLY=( ${COMPREPLY/ ${i%% *} / } )
  409.                 done
  410.                 echo ${COMPREPLY[@]})
  411.           ) )
  412.     
  413.     # put dashes back
  414.     for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
  415.         COMPREPLY[i]=-${COMPREPLY[i]}
  416.     done
  417.  
  418.     # default to filename completion if all else failed
  419.     if [ ${#COMPREPLY[@]} = 0 ]; then
  420.         COMPREPLY=( $( compgen -f $cur ) )
  421.     fi
  422.  
  423.     return 0
  424. }
  425. complete -F _find find
  426.  
  427. # Linux ifconfig(8) completion
  428. #
  429. _ifconfig()
  430. {
  431.     local cur
  432.  
  433.         COMPREPLY=()
  434.         cur=${COMP_WORDS[COMP_CWORD]}
  435.  
  436.     case "${COMP_WORDS[1]}" in
  437.     -|*[0-9]*)
  438.         COMPREPLY=( $( compgen -W '-a up down arp promisc allmulti \
  439.                        metric mtu dstaddr netmask add del \
  440.                        tunnel irq io_addr mem_start media \
  441.                        broadcast pointopoint hw multicast \
  442.                        address txqueuelen' $cur ))
  443.         COMPREPLY=( $( echo " ${COMP_WORDS[@]}" | \
  444.                    (while read -d ' ' i; do
  445.                    [ "$i" == "" ] && continue
  446.                    # flatten array with spaces on either side,
  447.                    # otherwise we cannot grep on word
  448.                    # boundaries of first and last word
  449.                    COMPREPLY=" ${COMPREPLY[@]} "
  450.                    # remove word from list of completions
  451.                    COMPREPLY=( ${COMPREPLY/ $i / } )
  452.                 done
  453.                     echo ${COMPREPLY[@]})
  454.               ) )
  455.         return 0
  456.         ;;
  457.     esac
  458.  
  459.     COMPREPLY=( $( ifconfig -a | sed -ne 's/^\('$cur'[^ ]*\).*$/\1/p' ))
  460. }
  461. complete -F _ifconfig ifconfig
  462.  
  463. # Linux ipsec(8) completion (for FreeS/WAN). Basic.
  464. #
  465. _ipsec()
  466. {
  467.     local cur
  468.  
  469.         COMPREPLY=()
  470.         cur=${COMP_WORDS[COMP_CWORD]}
  471.  
  472.     
  473.     if [ $COMP_CWORD = 1 ]; then
  474.         COMPREPLY=( $( compgen -W 'auto barf eroute klipsdebug look manual \
  475.                    pluto ranbits rsasigkey setup showdefaults \
  476.                    showhostkey spi spigrp tncfg whack' $cur ))
  477.         return 0
  478.     fi
  479.  
  480.     case ${COMP_WORDS[1]} in
  481.     auto)
  482.         COMPREPLY=( $( compgen -W '--asynchronous --up --add --delete \
  483.                        --replace --down --route --unroute \
  484.                        --ready --status --rereadsecrets' $cur ) )
  485.         return 0
  486.         ;;
  487.     manual)
  488.         COMPREPLY=( $( compgen -W '--up --down --route --unroute \
  489.                        --union' $cur ) )
  490.         return 0
  491.         ;;
  492.     ranbits)
  493.         COMPREPLY=( $( compgen -W '--quick --continuous --bytes' $cur ) )
  494.         return 0
  495.         ;;
  496.     setup)
  497.         COMPREPLY=( $( compgen -W '--start --stop --restart' $cur ) )
  498.         return 0
  499.         ;;
  500.  
  501.     *)
  502.         return 0
  503.         ;;
  504.     esac
  505.  
  506.     return 0
  507. }
  508. complete -F _ipsec ipsec
  509.  
  510. # cvs(1) completion
  511. #
  512. _cvs()
  513. {
  514.     local cur prev
  515.  
  516.         COMPREPLY=()
  517.         cur=${COMP_WORDS[COMP_CWORD]}
  518.         prev=${COMP_WORDS[COMP_CWORD-1]}
  519.  
  520.     if [ $COMP_CWORD -eq 1 ] || [[ "$prev" == -* ]]; then
  521.         COMPREPLY=( $( compgen -W 'add admin checkout commit diff \
  522.         export history import log rdiff release remove rtag status \
  523.         tag update' $cur ))
  524.     else
  525.         COMPREPLY=( $( compgen -f $cur ))
  526.     fi
  527.  
  528.     return 0
  529. }
  530. complete -F _cvs cvs
  531.  
  532. # rpm(8) completion. This is quite comprehensive now and covers rpm 4.x
  533. _rpm()
  534. {
  535.     dashify()
  536.     {
  537.         local i
  538.  
  539.         for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
  540.             if [ ${#COMPREPLY[i]} -le 2 ]; then
  541.                 COMPREPLY[i]=-${COMPREPLY[i]}
  542.             else
  543.                 COMPREPLY[i]=--${COMPREPLY[i]}
  544.             fi
  545.         done
  546.     }
  547.  
  548.     add_package_list()
  549.     {
  550.         COMPREPLY=( ${COMPREPLY[@]} $( rpm -qa | \
  551.            sed -ne 's/^\('$cur'.*\)-[0-9a-zA-Z._]\+-[0-9a-z.]\+$/\1/p' ) )
  552.     }
  553.  
  554.     file_glob()
  555.     {
  556.         local suffix
  557.  
  558.         # get extension of current word, if relevant
  559.         suffix=${cur##*.}
  560.         # nullify it if it's not a substring of the extension we're
  561.         # completing on
  562.         [ "$suffix" != "${1:0:${#suffix}}" ] && suffix=""
  563.         COMPREPLY=( ${COMPREPLY[@]} $( compgen -G $cur\*${1:${#suffix}} ) )
  564.         # directory completion if all else fails and current word
  565.         # contains a slash
  566.         if [ ${#COMPREPLY[@]} = 0 ] && [[ $cur == */* ]]; then
  567.                 COMPREPLY=( $( compgen -d $cur ) )
  568.         fi
  569.     }
  570.  
  571.     local cur cur_nodash prev
  572.  
  573.         COMPREPLY=()
  574.         cur=${COMP_WORDS[COMP_CWORD]}
  575.     cur_nodash=${cur#-}
  576.         prev=${COMP_WORDS[COMP_CWORD-1]}
  577.  
  578.     if [ $COMP_CWORD = 1 ]; then
  579.         # first parameter on line
  580.         case "$cur" in
  581.         -b*)
  582.             COMPREPLY=( $( compgen -W 'ba bb bc bi bl bp bs' \
  583.                        $cur_nodash ) )
  584.             dashify
  585.             return 0
  586.             ;;
  587.         -t*)
  588.             COMPREPLY=( $( compgen -W 'ta tb tc ti tl tp ts' \
  589.                        $cur_nodash ) )
  590.             dashify
  591.             return 0
  592.             ;;
  593.         --*)
  594.             COMPREPLY=( $( compgen -W 'help version initdb \
  595.             checksig recompile rebuild resign addsign rebuilddb \
  596.             showrc setperms setgids tarbuild eval install \
  597.             upgrade query freshen erase verify querytags rmsource' \
  598.             ${cur_nodash#-} ) )
  599.             dashify
  600.             return 0
  601.             ;;
  602.         *)
  603.             COMPREPLY=( $( compgen -W 'b e F i q t U V' \
  604.                        $cur_nodash ) )
  605.             dashify
  606.             return 0
  607.             ;;
  608.         esac
  609.     fi
  610.  
  611.     case "$prev" in
  612.     --@(db|exclude)path|prefix|relocate|root)
  613.         COMPREPLY=( $( compgen -d $cur ) )
  614.         return 0
  615.         ;;
  616.     --eval)
  617.         # get a list of macros (char class contains a space and tab)
  618.         COMPREPLY=( $( sed -ne 's/^\(%'${cur#\%}'[^     ]*\).*$/\1/p' \
  619.                    /usr/lib/rpm/macros ) )
  620.         return 0
  621.         ;;
  622.     --pipe)
  623.         COMPREPLY=( $( compgen -c $cur ) )
  624.         return 0
  625.         ;;
  626.     --rcfile)
  627.         COMPREPLY=( $( compgen -f $cur ) )
  628.         return 0
  629.         ;;
  630.     esac
  631.  
  632.     case "${COMP_WORDS[1]}" in
  633.     -@([iFU]*|-install|-freshen|-upgrade))
  634.         # complete on list of relevant options
  635.         COMPREPLY=( $( compgen -W 'percent force test replacepkgs \
  636.         replacefiles root excludedocs includedocs noscripts rcfile \
  637.         ignorearch dbpath prefix ignoreos nodeps allfiles ftpproxy \
  638.         ftpport justdb httpproxy httpport noorder relocate badreloc \
  639.         notriggers excludepath ignoresize oldpackage define eval \
  640.         pipe queryformat' ${cur_nodash#-} ))
  641.         dashify
  642.         # return if $cur is an option
  643.         [[ "$cur" == -* ]] && return 0
  644.         # add a list of RPMS to possible completions
  645.         file_glob rpm
  646.         return 0
  647.         ;;
  648.     -qp*)
  649.         # complete on list of relevant options
  650.         COMPREPLY=( $( compgen -W 'scripts root rcfile whatprovides \
  651.         whatrequires requires triggeredby ftpport ftpproxy httpproxy \
  652.         httpport provides triggers dump changelog dbpath filesbypkg \
  653.         define eval pipe showrc info list state docfiles \
  654.         configfiles queryformat' ${cur_nodash#-} ) )
  655.         dashify
  656.         # return if $cur is an option
  657.         [[ "$cur" == -* ]] && return 0
  658.         # add a list of RPMS to possible completions
  659.         file_glob rpm
  660.         return 0
  661.         ;;
  662.     -*f)
  663.         # standard filename completion
  664.         COMPREPLY=( $( compgen -f $cur ) )
  665.         return 0
  666.         ;;
  667.     -*g)
  668.         # package group completion
  669.         local IFS=$(echo -e "\t")
  670.         # remove trailing backslash, or grep will complain
  671.         cur=${cur%'\'}
  672.         COMPREPLY=( $( rpm -qa --queryformat '%{group}\n' | \
  673.                    grep ^$cur ) )
  674.         # backslash escape spaces and translate newlines to tabs
  675.         COMPREPLY=( $( echo ${COMPREPLY[@]} | sed 's/ /\\ /g' | \
  676.                    tr '\n' '\t' ) )
  677.         return 0
  678.         ;;
  679.     -@(e|-erase))
  680.         # complete on list of relevant options
  681.         COMPREPLY=( $( compgen -W 'allmatches noscripts notriggers \
  682.         nodeps test' ${cur_nodash#-} ) )
  683.         dashify
  684.         # return if $cur is an option
  685.         [[ "$cur" == -* ]] && return 0
  686.         add_package_list
  687.         return 0
  688.         ;;
  689.     -q*)
  690.         # complete on list of relevant options
  691.         COMPREPLY=( $( compgen -W 'scripts root rcfile whatprovides \
  692.         whatrequires requires triggeredby ftpport ftpproxy httpproxy \
  693.         httpport provides triggers dump changelog dbpath specfile \
  694.         querybynumber last filesbypkg define eval pipe showrc info \
  695.         list state docfiles configfiles queryformat' \
  696.         ${cur_nodash#-} ) )
  697.         dashify
  698.         # return if $cur is an option
  699.         [[ "$cur" == -* ]] && return 0
  700.         # don't complete on packages if we are querying all packages
  701.         [[ ${COMP_WORDS[1]} == -qa* ]] && return 0
  702.         add_package_list
  703.         return 0
  704.         ;;
  705.     -@(K|-checksig))
  706.         # complete on list of relevant options
  707.         COMPREPLY=( $( compgen -W 'nopgp nogpg nomd5' \
  708.         ${cur_nodash#-} ) )
  709.         dashify
  710.         # return if $cur is an option
  711.         [[ "$cur" == -* ]] && return 0
  712.         # add a list of RPMS to possible completions
  713.         file_glob rpm
  714.         return 0
  715.         ;;
  716.     -@([Vy]*|-verify))
  717.         # complete on list of relevant options
  718.         COMPREPLY=( $( compgen -W 'root rcfile dbpath nodeps nofiles \
  719.         noscripts nomd5' ${cur_nodash#-} ) )
  720.         dashify
  721.         # return if $cur is an option
  722.         [[ "$cur" == -* ]] && return 0
  723.         add_package_list
  724.         return 0
  725.         ;;
  726.     -[bt]*)
  727.         # complete on list of relevant options
  728.         COMPREPLY=( $( compgen -W 'short-circuit timecheck clean \
  729.         rmsource test sign buildroot target buildarch buildos \
  730.         nobuild' ${cur_nodash#-} ) )
  731.         dashify
  732.         # return if $cur is an option
  733.         [[ "$cur" == -* ]] && return 0
  734.         if [[ ${COMP_WORDS[1]} == -b* ]]; then
  735.             # complete on .spec files
  736.             file_glob spec
  737.         else
  738.             # complete on .tar files
  739.             COMPREPLY=( $( compgen -G $cur\*.+(tgz|tar.+(gz|bz2)) ) )
  740.         fi
  741.         return 0
  742.         ;;
  743.     --re@(build|compile))
  744.         # complete on source RPMs
  745.         COMPREPLY=( $( compgen -G $cur\*.src.rpm ) )
  746.         return 0
  747.         ;;
  748.     --tarbuild)
  749.         # complete on tarred sources
  750.         COMPREPLY=( $( compgen -G $cur\*.+(tgz|tar.+(gz|bz2)) ) )
  751.         return 0
  752.         ;;
  753.     --@(re|add)sign)
  754.         # complete on RPMs
  755.         file_glob rpm
  756.         return 0
  757.         ;;
  758.     --set@(perms|gids))
  759.         add_package_list
  760.         return 0
  761.         ;;
  762.     --rmsource)
  763.         file_glob spec
  764.         return 0
  765.         ;;
  766.     esac
  767.  
  768.     return 0
  769. }
  770. complete -F _rpm rpm
  771.  
  772. # Debian Linux apt-get(8) completion.
  773. #
  774. _apt-get()
  775. {
  776.     local cur prev special
  777.  
  778.         COMPREPLY=()
  779.         cur=${COMP_WORDS[COMP_CWORD]}
  780.         prev=${COMP_WORDS[COMP_CWORD-1]}
  781.  
  782.     for (( i=0; i < ${#COMP_WORDS}-1; i++ )); do
  783.         if [[ ${COMP_WORDS[i]} == @(install|remove|source) ]]; then
  784.             special=${COMP_WORDS[i]}
  785.         fi
  786.     done
  787.     if [ -n "$special" ]; then
  788.         case $special in
  789.         @(install|remove|source))
  790.             COMPREPLY=( $( apt-cache pkgnames $cur ) )
  791.             return 0
  792.             ;;
  793.         esac
  794.     fi
  795.  
  796.     if [[ "$prev" == -*c ]] || [ "$prev" = --config-file ]; then
  797.         COMPREPLY=( $( compgen -f $cur ) )
  798.     else
  799.         COMPREPLY=( $( compgen -W 'update upgrade dselect-upgrade \
  800.                   dist-upgrade install remove source check \
  801.                   clean autoclean -d -f -h -v -m -q -s -y -u \
  802.                   -b -c -o --download-only --fix-broken --help \
  803.                   --version --ignore-missing --fix-missing \
  804.                   --no-download --quiet --simulate \
  805.                   --just-print --dry-run --recon --no-act \
  806.                   --yes --assume-yes --show-upgraded \
  807.                   --compile --build --ignore-hold \
  808.                   --no-upgrade --force-yes --print-uris \
  809.                   --purge --reinstall --list-cleanup \
  810.                   --trivial-only --no-remove --diff-only \
  811.                   --tar-only --config-file --option ' | \
  812.                   grep ^$cur ) )
  813.     fi
  814.  
  815.     return 0
  816. }
  817. complete -F _apt-get apt-get
  818.  
  819. # Debian Linux apt-cache(8) completion.
  820. #
  821. _apt-cache()
  822. {
  823.     local cur prev special
  824.  
  825.         COMPREPLY=()
  826.         cur=${COMP_WORDS[COMP_CWORD]}
  827.         prev=${COMP_WORDS[COMP_CWORD-1]}
  828.  
  829.     
  830.     for (( i=0; i < ${#COMP_WORDS}-1; i++ )); do
  831.         if [[ ${COMP_WORDS[i]} == @(add|showpkg) ]]; then
  832.             special=${COMP_WORDS[i]}
  833.         fi
  834.     done
  835.     if [ -n "$special" ]; then
  836.         case $special in
  837.         add)
  838.             COMPREPLY=( $( compgen -f $cur ) )
  839.             return 0
  840.             ;;
  841.         showpkg)
  842.             COMPREPLY=( $( apt-cache pkgnames $cur ) )
  843.             return 0
  844.             ;;
  845.         esac
  846.     fi
  847.  
  848.  
  849.     if [[ "$prev" == -*c ]] || [ "$prev" = --config-file ]; then
  850.         COMPREPLY=( $( compgen -f $cur ) )
  851.     else
  852.         COMPREPLY=( $( compgen -W 'add gencaches showpkg stats dump \
  853.                 dumpavail unmet check search show showpkg \
  854.                 depends pkgnames -h -v -p -s -q -i -f -a -g -c \
  855.                 -o --help --version --pkg-cache --src-cache \
  856.                 --quiet --important --full --all-versions \
  857.                 --no-generate --names-only --all-names \
  858.                 --config-file --option' | grep ^$cur ) )
  859.     fi
  860.  
  861.     return 0
  862. }
  863. complete -F _apt-cache apt-cache
  864.  
  865. # chsh(1) completion
  866. #
  867. _chsh()
  868. {
  869.     local cur prev
  870.  
  871.         COMPREPLY=()
  872.         cur=${COMP_WORDS[COMP_CWORD]}
  873.         prev=${COMP_WORDS[COMP_CWORD-1]}
  874.  
  875.     if [ "$prev" = "-s" ]; then
  876.         COMPREPLY=( $( chsh -l | grep ^$cur ) )
  877.     else
  878.         COMPREPLY=( $( compgen -u $cur ) )
  879.     fi
  880.  
  881.     return 0
  882. }
  883. complete -F _chsh chsh
  884.  
  885. # chkconfig(8) completion
  886. #
  887. _chkconfig()
  888. {
  889.     local cur prev
  890.  
  891.         COMPREPLY=()
  892.         cur=${COMP_WORDS[COMP_CWORD]}
  893.     cur_nodash=${cur#--}
  894.         prev=${COMP_WORDS[COMP_CWORD-1]}
  895.  
  896.     if [ $COMP_CWORD -eq 1 ]; then
  897.         COMPREPLY=( $( compgen -W 'list add del level' $cur_nodash ) )
  898.         for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
  899.             COMPREPLY[i]=--${COMPREPLY[i]}
  900.         done
  901.         return 0
  902.     fi
  903.  
  904.     if [ $COMP_CWORD -eq 4 ]; then
  905.         COMPREPLY=( $( compgen -W 'on off reset' $cur ) )
  906.         return 0
  907.     fi
  908.  
  909.     case "$prev" in
  910.     @([1-6]|--@(list|add|del)))
  911.         COMPREPLY=( $( compgen -W "`(cd /etc/rc.d/init.d; echo *)`" \
  912.                    $cur) )
  913.         return 0
  914.         ;;
  915.     --level)
  916.         COMPREPLY=( $( compgen -W '1 2 3 4 5 6' $cur ) )
  917.         return 0
  918.         ;;
  919.     esac
  920.  
  921.     return 0
  922. }
  923. complete -F _chkconfig chkconfig
  924.  
  925. # This function performs host completion based on ssh's known_hosts files, defaulting
  926. # to standard host completion if they don't exist.
  927. #
  928. _known_hosts()
  929. {
  930.     local cur kh
  931.  
  932.     kh=()
  933.         COMPREPLY=()
  934.         cur=${COMP_WORDS[COMP_CWORD]}
  935.  
  936.     [ -r /etc/known_hosts ]   && kh[0]=/etc/known_hosts
  937.     [ -r ~/.ssh/known_hosts ] && kh[1]=~/.ssh/known_hosts
  938.  
  939.     # If we have known_hosts files to use
  940.     if [ ${#kh[@]} -gt 0 ]; then
  941.         if [[ $cur == [0-9]*.* ]]; then
  942.         # Digits followed by a dot - just search for that
  943.         cur="^$cur.*"
  944.         elif [[ $cur == [0-9]* ]]; then
  945.         # Digits followed by no dot - search for digits followed
  946.         # by a dot
  947.         cur="^$cur.*\."
  948.         elif [ -z $cur ]; then
  949.         # A blank - search for a dot or an alpha character
  950.         cur="[a-z.]"
  951.         else
  952.         cur="^$cur"
  953.         fi
  954.         # FS needs to look for a comma separated list
  955.         COMPREPLY=( $( awk 'BEGIN {FS="[ ,]"}
  956.                 {for (i=1; i<=NR; ++i) { \
  957.                        if ($i ~ /'$cur'/) {print $i} \
  958.                 }}' ${kh[@]} ) )
  959.     else
  960.         # Just do normal hostname completion
  961.         COMPREPLY=( $( compgen -A hostname $cur ) )
  962.     fi
  963.  
  964.     return 0
  965. }
  966. complete -F _known_hosts traceroute ping fping telnet host nslookup
  967.  
  968. # ssh(1) completion. Should be able to improve this with user@host notation,
  969. # but the '@' seems to trigger some kind of bug in bash's completion.
  970. #
  971. _ssh()
  972. {
  973.     local cur prev
  974.  
  975.         COMPREPLY=()
  976.         cur=${COMP_WORDS[COMP_CWORD]}
  977.         prev=${COMP_WORDS[COMP_CWORD-1]}
  978.  
  979.     case "$prev" in
  980.     -*c)
  981.         COMPREPLY=( $( compgen -W 'blowfish 3des 3des-cbc blowfish-cbc \
  982.                arcfour cast128-cbc' $cur ) )
  983.         return 0
  984.         ;;
  985.     -*l)
  986.         COMPREPLY=( $( compgen -u $cur ) )
  987.         return 0
  988.         ;;
  989.     esac
  990.  
  991.     # Host has been specified, so now do simple command completion
  992.     if [ $COMP_CWORD -gt 1 ]; then
  993.         COMPREPLY=( $( compgen -c $cur ) )
  994.         return 0
  995.     fi
  996.  
  997.     # Otherwise, check for known hosts
  998.     _known_hosts
  999.  
  1000.     return 0
  1001. }
  1002. complete -F _ssh ssh slogin
  1003.  
  1004. # Linux route(8) completion. This could be improved by adding address family
  1005. # completion for -A, etc.
  1006. #
  1007. _route()
  1008. {
  1009.     local cur prev
  1010.  
  1011.         COMPREPLY=()
  1012.         cur=${COMP_WORDS[COMP_CWORD]}
  1013.         prev=${COMP_WORDS[COMP_CWORD-1]}
  1014.  
  1015.     if [ "$prev" = dev ]; then
  1016.         COMPREPLY=( $( ifconfig -a | sed -ne 's/^\('$cur'[^ ]*\).*$/\1/p' ))
  1017.         return 0
  1018.     fi
  1019.  
  1020.     # Must use grep here, otherwise $cur will cause compgen to barf, if
  1021.     # it begins with a hyphen
  1022.     COMPREPLY=( $( compgen -W 'add del -host -net netmask metric mss \
  1023.                   window irtt reject mod dyn reinstate dev' | \
  1024.                grep ^$cur ) )
  1025.  
  1026.     COMPREPLY=( $( echo " ${COMP_WORDS[@]}" | \
  1027.                (while read -d ' ' i; do
  1028.                [ "$i" == "" ] && continue
  1029.                # flatten array with spaces on either side,
  1030.                # otherwise we cannot grep on word
  1031.                # boundaries of first and last word
  1032.                COMPREPLY=" ${COMPREPLY[@]} "
  1033.                # remove word from list of completions
  1034.                COMPREPLY=( ${COMPREPLY/ $i / } )
  1035.             done
  1036.                echo ${COMPREPLY[@]})
  1037.           ) )
  1038.     return 0
  1039. }
  1040. complete -F _route route
  1041.  
  1042. # GNU make(1) completion (adapted from the example supplied with the bash 2.04
  1043. # source code)
  1044. #
  1045. _make()
  1046. {
  1047.         local mdef makef gcmd cur prev i
  1048.  
  1049.         COMPREPLY=()
  1050.         cur=${COMP_WORDS[COMP_CWORD]}
  1051.         prev=${COMP_WORDS[COMP_CWORD-1]}
  1052.  
  1053.         # if prev argument is -f, return possible filename completions.
  1054.         # we could be a little smarter here and return matches against
  1055.         # `makefile Makefile *.mk', whatever exists
  1056.         if [[ "$prev" == -*f ]]; then
  1057.         COMPREPLY=( $( compgen -f $cur ) )
  1058.         return 0
  1059.     fi
  1060.  
  1061.         # if we want an option, return the possible posix options
  1062.         if [[ "$cur" == - ]]; then
  1063.             COMPREPLY=( $( compgen -W '-e -f -i -k -n -p -q -r -S -s -t' | grep ^$cur ) )
  1064.         return 0
  1065.         fi
  1066.  
  1067.         # make reads `makefile' before `Makefile'
  1068.         if [ -f makefile ]; then
  1069.                 mdef=makefile
  1070.         elif [ -f Makefile ]; then
  1071.                 mdef=Makefile
  1072.         else
  1073.                 mdef=*.mk               # local convention
  1074.         fi
  1075.  
  1076.         # before we scan for targets, see if a makefile name was specified
  1077.         # with -f
  1078.         for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
  1079.                 if [[ ${COMP_WORDS[i]} == -*f ]]; then
  1080.                         eval makef=${COMP_WORDS[i+1]}   # eval for tilde expansion
  1081.                         break
  1082.                 fi
  1083.         done
  1084.  
  1085.         [ -z "$makef" ] && makef=$mdef
  1086.  
  1087.         # if we have a partial word to complete, restrict completions to
  1088.         # matches of that word
  1089.         if [ -n "$2" ]; then
  1090.         gcmd='grep "^$2"'
  1091.     else
  1092.         gcmd=cat
  1093.     fi
  1094.  
  1095.         # if we don't want to use *.mk, we can take out the cat and use
  1096.         # test -f $makef and input redirection  
  1097.         COMPREPLY=( $( cat $makef 2>/dev/null | \
  1098.                awk 'BEGIN {FS=":"} /^[^.#    ][^=]*:/ {print $1}' | \
  1099.                eval $gcmd ) )
  1100.  
  1101.     # default to filename completion if all else failed
  1102.     if [ ${#COMPREPLY[@]} = 0 ]; then
  1103.         COMPREPLY=( $( compgen -f $cur ) )
  1104.     fi
  1105.  
  1106.     return 0
  1107. }
  1108. complete -F _make -X '+($*|*.[cho])' make gmake pmake
  1109.  
  1110. # Red Hat Linux service completion. This completes on a list of all available
  1111. # service scripts in the SysV init.d directory, followed by that script's
  1112. # available commands
  1113. #
  1114. _service()
  1115. {
  1116.     local cur sysvdir
  1117.  
  1118.         COMPREPLY=()
  1119.         cur=${COMP_WORDS[COMP_CWORD]}
  1120.  
  1121.     [ -d /etc/rc.d/initi.d ] && sysvdir=/etc/rc.d/init.d \
  1122.                  || sysvdir=/etc/init.d
  1123.  
  1124.     #[[ "$cur" == -* ]] && return 0
  1125.     if [ $COMP_CWORD = 1 ]; then
  1126.         COMPREPLY=( $( compgen -W '`echo $sysvdir/!(*.rpmsave|*.rpmorig)`' ) )
  1127.         COMPREPLY=( $( compgen -W '${COMPREPLY[@]#$sysvdir/}' $cur ) )
  1128.     else
  1129.         COMPREPLY=( $( compgen -W '`sed -ne "y/|/ /; \
  1130.                         s/^.*Usage.*{\(.*\)}.*$/\1/p" \
  1131.                         $sysvdir/${COMP_WORDS[1]}' $cur ) )
  1132.     fi
  1133.  
  1134.     return 0
  1135. }
  1136. complete -F _service service
  1137.