# **** License **** # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # This code was originally developed by Vyatta, Inc. # Portions created by Vyatta are Copyright (C) 2006, 2007 Vyatta, Inc. # All Rights Reserved. # # Author: Tom Grennan # Date: 2007 # Description: setup bash completion for Vyatta operational commands # # **** End License **** test -z "$_vyatta_default_pager" && \ declare -r _vyatta_default_pager="less\ --QUIT-AT-EOF\ --quit-if-one-screen\ --LONG-PROMPT\ --RAW-CONTROL-CHARS\ --squeeze-blank-lines\ --buffers=64\ --auto-buffers\ --no-init\ --no-lessopen" declare -x VYATTA_PAGER=$_vyatta_default_pager _vyatta_op_do_key_bindings () { if [ "$SHELL" == "/bin/vbash" ]; then # only do this if vbash bind '"?": possible-completions' fi nullglob_save=$(shopt -p nullglob) shopt -u nullglob bind_cmds=$(grep '^bind .* # vyatta key binding$' $HOME/.bashrc) eval $bind_cmds eval $nullglob_save } _vyatta_op_do_key_bindings test -f /etc/default/vyatta && \ source /etc/default/vyatta test ! -d "$vyatta_op_templates" && \ return 0 declare -r _vyatta_op_last_comp_init='>>>>>>LASTCOMP<<<<<<' declare _vyatta_op_last_comp=${_vyatta_op_last_comp_init} declare _vyatta_op_node_path declare -a _vyatta_op_noncompletions _vyatta_op_completions declare -x -a _vyatta_pipe_noncompletions _vyatta_pipe_completions # $1: label # #2...: strings _vyatta_op_debug () { echo -ne \\n$1: shift for s ; do echo -ne " \"$s\"" done } _vyatta_op_init () { complete -F _vyatta_op_expand '' for xd in $vyatta_op_templates/* ; do if [ -d $xd ] ; then cmd=${xd##*/} complete -F _vyatta_op_expand $cmd eval alias $cmd=\'_vyatta_op_run $cmd\' fi done bind 'set show-all-if-ambiguous on' shopt -s histverify } _vyatta_op_get_node_def_field () { local file=$1 field=$2 sed -n '/^'"$field"':/,$ { # strip field name and hold rest of line s/[a-z]*: *// h :b # at EOF, print hold buffer and quit $ { x; p; q } # input next line n # if start of another field def, print hold buf and quit /^[a-z]*:/ { x; p; q } # add to hold buf and branch to input next line H bb }' $file } # $1: label # $2...: help _vyatta_op_print_help () { local label=$1 help=$2 if [ ${#help} -eq 0 ] ; then echo -ne "\n $label" elif [ ${#label} -lt 6 ] ; then echo -ne "\n $label\t\t$help" elif [ ${#label} -lt 14 ] ; then echo -ne "\n $label\t$help" else echo -ne "\n $label\n\t\t$help" fi } # $1: $cur # $2...: possible completions _vyatta_op_help () { local cur=$1; shift local ndef node_tag_help node_run help last_help ndef=${_vyatta_op_node_path}/node.tag/node.def [ -f $ndef ] && \ node_tag_help=$( _vyatta_op_get_node_def_field $ndef help ) ndef=${_vyatta_op_node_path}/node.def [ -f $ndef ] && \ node_run=$( _vyatta_op_get_node_def_field $ndef run ) echo -en "\nPossible completions:" if [ -z "$cur" -a -n "$node_run" ]; then _vyatta_op_print_help '' "Execute the current command" fi for comp ; do if [ -z "$comp" ] ; then if [ "X$node_tag_help" == "X$last_help" ] ; then help="" else last_help=$node_tag_help help=$node_tag_help fi _vyatta_op_print_help '*' "$help" elif [[ -z "$cur" || $comp == ${cur}* ]] ; then ndef=${_vyatta_op_node_path}/$comp/node.def if [ -f $ndef ] ; then help=$( _vyatta_op_get_node_def_field $ndef help ) else help=$node_tag_help fi if [ "X$help" == "X$last_help" ] ; then help="" else last_help=$help fi _vyatta_op_print_help "$comp" "$help" fi done } _vyatta_op_set_node_path () { _vyatta_op_node_path=$vyatta_op_templates for (( i=0 ; i or _vyatta_op_noncompletions=( ) completions=( ) for (( i=0 ; i<${#allowed[@]} ; i++ )) ; do if [[ "${allowed[i]}" == \<*\> ]] ; then _vyatta_op_noncompletions+=( ${allowed[i]} ) else completions+=( ${allowed[i]} ) fi done _vyatta_op_completions=($( printf "%s\n" ${completions[@]} | sort -u )) } _vyatta_op_comprely_needs_ambiguity () { local -a uniq [ ${#COMPREPLY[@]} -eq 1 ] && return uniq=( `printf "%s\n" ${COMPREPLY[@]} | cut -c1 | sort -u` ) [ ${#uniq[@]} -eq 1 ] && return false } _vyatta_op_expand () { local restore_shopts=$( shopt -p extglob nullglob | tr \\n \; ) shopt -s extglob nullglob local cur="" if (( ${#COMP_WORDS[@]} > 0 )); then cur=${COMP_WORDS[COMP_CWORD]} else (( COMP_CWORD = ${#COMP_WORDS[@]} )) fi if _vyatta_pipe_completion "${COMP_WORDS[@]}"; then if [ "${COMP_WORDS[*]}" == "$_vyatta_op_last_comp" ] ; then _vyatta_do_pipe_help COMPREPLY=( "" " " ) _vyatta_op_last_comp=${_vyatta_op_last_comp_init} else COMPREPLY=( "${_vyatta_pipe_completions[@]}" ) _vyatta_op_last_comp="${COMP_WORDS[*]}" fi eval "$restore_shopts" return fi if [ "${COMP_WORDS[*]}" != "$_vyatta_op_last_comp" ] ; then if ! _vyatta_op_set_node_path ; then echo -e \\a COMPREPLY=( "" " " ) eval "$restore_shopts" return 1 fi _vyatta_op_set_completions fi COMPREPLY=($( compgen -W "${_vyatta_op_completions[*]}" -- $cur )) # if the last command line arg is empty and we have # an empty completion option (meaning wild card), # append a blank(s) to the completion array to force ambiguity if [ -z "$cur" ] ; then for comp ; do if [ -z "$comp" ] ; then if [ ${#COMPREPLY[@]} -eq 0 ] ; then COMPREPLY+=( " " "" ) elif _vyatta_op_comprely_needs_ambiguity ; then COMPREPLY+=( " " ) fi fi done fi if [ "${COMP_WORDS[*]}" == "$_vyatta_op_last_comp" ] ; then _vyatta_op_help "$cur" \ ${_vyatta_op_noncompletions[@]} \ ${_vyatta_op_completions[@]} \ | eval ${VYATTA_PAGER:-cat} COMPREPLY=( "" " " ) _vyatta_op_last_comp=${_vyatta_op_last_comp_init} else _vyatta_op_last_comp="${COMP_WORDS[*]}" fi eval "$restore_shopts" } _vyatta_op_run () { local -i estat local tpath=$vyatta_op_templates local restore_shopts=$( shopt -p extglob nullglob | tr \\n \; ) shopt -s extglob nullglob _vyatta_op_last_comp=${_vyatta_op_last_comp_init} false; estat=$? for arg ; do if [ -f "$tpath/$arg/node.def" ] ; then tpath+=/$arg elif [ -f $tpath/node.tag/node.def ] ; then tpath+=/node.tag else echo "Invalid command" >&2 eval $restore_shopts return 1 fi done local run_cmd=$(_vyatta_op_get_node_def_field $tpath/node.def run) local ret=0 if [ -n "$run_cmd" ]; then if [[ -t 1 && "$1" == "show" ]] ; then ( eval "$run_cmd" ) | eval "${VYATTA_PAGER:-cat}" else eval "$run_cmd" fi else echo "Incomplete command" >&2 ret=1 fi eval $restore_shopts return $ret } # "pipe" functions count () { wc -l } match () { grep -E -e "$1" } no-match () { grep -E -v -e "$1" } no-more () { cat } # pipe command help # $1: command _vyatta_pipe_help () { local help="No help text available" case "$1" in count) help="Count the number of lines in the output";; match) help="Only output lines that match specified pattern";; no-match) help="Only output lines that do not match specified pattern";; more) help="Paginate the output";; no-more) help="Do not paginate the output";; '') help="Pattern for matching";; esac echo -n "$help" } _vyatta_do_pipe_help () { local help='' if (( ${#_vyatta_pipe_completions[@]} + ${#_vyatta_pipe_noncompletions[@]} == 0 )); then return fi echo -en "\nPossible completions:" for comp in "${_vyatta_pipe_completions[@]}" \ "${_vyatta_pipe_noncompletions[@]}"; do _vyatta_op_print_help "$comp" "$(_vyatta_pipe_help "$comp")" done } # pipe completion # $@: words _vyatta_pipe_completion () { local -a pipe_cmd=() local -a all_cmds=( 'count' 'match' 'no-match' 'more' 'no-more' ) local found=0 _vyatta_pipe_completions=() _vyatta_pipe_noncompletions=() for word in "$@"; do if [ "$found" == "1" -o "$word" == "|" ]; then pipe_cmd+=( "$word" ) found=1 fi done if (( found == 0 )); then return 1 fi if (( ${#pipe_cmd[@]} == 1 )); then # "|" only _vyatta_pipe_completions=( "${all_cmds[@]}" ) return 0 fi if (( ${#pipe_cmd[@]} == 2 )); then # "|" _vyatta_pipe_completions=($(compgen -W "${all_cmds[*]}" -- ${pipe_cmd[1]})) return 0 fi if (( ${#pipe_cmd[@]} == 3 )); then # "|" case "${pipe_cmd[1]}" in match|no-match) _vyatta_pipe_noncompletions=( '' );; esac return 0 fi return 0 } vtysh () { if [ -S /var/run/vyatta/quagga/zebra.vty ] ; then vyatta-vtysh "$@" elif [ ! -S /var/run/quagga/zebra.vty ] ; then /usr/bin/vtysh "$@" else echo "Can't connect with zebra daemon" fi } # don't initialize if we are in configure mode if [ "$_OFR_CONFIGURE" == "ok" ]; then return 0 fi nullglob_save=$( shopt -p nullglob ) shopt -s nullglob for f in ${vyatta_datadir}/vyatta-op/functions/allowed/* ; do source $f done eval $nullglob_save unset nullglob_save _vyatta_op_init $@ ### Local Variables: ### mode: shell-script ### End: