diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | debian/vyatta-cfg.install | 1 | ||||
-rwxr-xr-x | etc/bash_completion.d/vyatta-cfg | 669 | ||||
-rw-r--r-- | functions/interpreter/vyatta-cfg-run | 621 |
4 files changed, 637 insertions, 657 deletions
diff --git a/Makefile.am b/Makefile.am index f01ea8f..ec2dbaf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,6 +20,9 @@ initd_SCRIPTS = etc/init.d/vyatta-router dhcphook_SCRIPTS = scripts/vyatta-dhclient-hook logrotate_DATA = etc/logrotate.d/vyatta-config-logs +interpdir = $(datadir)/vyatta-cfg/functions/interpreter/ +interp_DATA = functions/interpreter/vyatta-cfg-run + src/cparse/cparse.cpp: src/cparse/cparse.ypp src/cparse/cparse_def.h bison -p cparse_ --defines=src/cparse/cparse.h -o $@ $< diff --git a/debian/vyatta-cfg.install b/debian/vyatta-cfg.install index b2385da..8c9aca2 100644 --- a/debian/vyatta-cfg.install +++ b/debian/vyatta-cfg.install @@ -1,5 +1,6 @@ etc opt/vyatta/share/enumeration +opt/vyatta/share/vyatta-cfg/functions opt/vyatta/sbin opt/vyatta/etc bin diff --git a/etc/bash_completion.d/vyatta-cfg b/etc/bash_completion.d/vyatta-cfg index c16873f..587df1e 100755 --- a/etc/bash_completion.d/vyatta-cfg +++ b/etc/bash_completion.d/vyatta-cfg @@ -42,48 +42,18 @@ fi if [ -r /etc/default/vyatta ]; then source /etc/default/vyatta fi -### Top level commands and help ### -_vyatta_cfg_cmds=( "confirm" \ - "comment" \ - "commit" \ - "commit-confirm" \ - "compare" \ - "copy" \ - "delete" \ - "discard" \ - "edit" \ - "exit" \ - "load" \ - "loadkey" \ - "merge" \ - "rename" \ - "rollback" \ - "run" \ - "save" \ - "set" \ - "show" ) -_vyatta_cfg_helps=( \ - "Confirm prior commit-confirm" \ - "Add comment to this configuration element" \ - "Commit the current set of changes" \ - "Commit the current set of changes with 'confirm' required" \ - "Compare configuration revisions" \ - "Copy a configuration element" \ - "Delete a configuration element" \ - "Discard uncommitted changes" \ - "Edit a sub-element" \ - "Exit from this configuration level" \ - "Load configuration from a file and replace running configuration" \ - "Load user SSH key from a file" \ - "Load configuration from a file and merge running configuration" \ - "Rename a configuration element" \ - "Rollback to a prior config revision (requires reboot)" \ - "Run an operational-mode command" \ - "Save configuration to a file" \ - "Set the value of a parameter or create a new element" \ - "Show the configuration (default values may be suppressed)" \ - ) -### End Top level commands and help ### + +declare -a op_functions +op_functions=( /opt/vyatta/share/vyatta-op/functions/interpreter/* ) +for file in "${op_functions[@]}"; do + source $file +done + +declare -a cfg_functions +cfg_functions=( /opt/vyatta/share/vyatta-cfg/functions/interpreter/* ) +for file in "${cfg_functions[@]}"; do + source $file +done # function for shell api vyatta_cli_shell_api () @@ -128,243 +98,6 @@ for cmd in "${unalias_cmds[@]}"; do unalias $cmd >& /dev/null done -### Top level command wrappers ### - -vyatta_config_show () -{ - local -a opts=() - local -a args=() - for arg in "$@"; do - if [ "$arg" == "-all" ]; then - opts+=('--show-show-defaults') - else - args+=("$arg") - fi - done - cli-shell-api "${opts[@]}" -- showCfg "${args[@]}" \ - | eval "${VYATTA_PAGER:-cat}" -} - -vyatta_config_commit () -{ - if ! vyatta_cli_shell_api sessionChanged; then - echo "No configuration changes to commit" - return 1; - fi - local comment="commit" - local next=0 - local -a args=() - for arg in "$@"; do - if [ "$next" == "1" ]; then - comment=$arg - next=0; - elif [ "$arg" == "comment" ]; then - next=1 - elif [ "$arg" == "confirm" ]; then - echo Use commit-confirm command - return 1; - else - args[${#args[@]}]="$arg" - fi - done - - export COMMIT_COMMENT="$comment" - export COMMIT_VIA=cli - /opt/vyatta/sbin/my_commit "${args[@]}" 2>&1 - unset COMMIT_VIA - unset COMMIT_COMMENT -} - -vyatta_config_commit-confirm () -{ - if ! vyatta_cli_shell_api sessionChanged; then - echo "No configuration changes to commit" - return 1; - fi - local -a args=() - local first=1 - local minutes=10 - for arg in "$@"; do - if [ "$first" = "1" ]; then - if [[ $arg = *[[:digit:]]* ]]; then - minutes=$arg - else - args[${#args[@]}]="$arg" - fi - first=0 - else - args[${#args[@]}]="$arg" - fi - done - cmd="${vyatta_sbindir}/vyatta-config-mgmt.pl --action=commit-confirm \ - --minutes=$minutes" - eval "sudo sg vyattacfg \"$cmd\" " - if [ $? = 0 ]; then - commit "$@" - fi -} - -vyatta_config_confirm () -{ - ${vyatta_sbindir}/vyatta-config-mgmt.pl --action=confirm -} - -vyatta_config_compare () -{ - local -a comp=( "saved" ) - local -a filtered=() - get_prefix_filtered_list $1 comp filtered - if [[ "${filtered[0]}" == "saved" ]]; then - cli-shell-api showConfig --show-cfg1 /config/config.boot --show-cfg2 @WORKING --show-context-diff - else - ${vyatta_sbindir}/vyatta-config-mgmt.pl --action=diff "$@" | eval "${VYATTA_PAGER:-cat}" - fi -} - -vyatta_config_save () -{ - if vyatta_cli_shell_api sessionChanged; then - echo -e "Warning: you have uncommitted changes that will not be saved.\n" - fi - # return to top level. - reset_edit_level - # transform individual args into quoted strings - local arg='' - local save_cmd="${vyatta_sbindir}/vyatta-save-config.pl" - for arg in "$@"; do - save_cmd+=" '$arg'" - done - eval "sudo sg vyattacfg \"umask 0002 ; $save_cmd\"" - vyatta_cli_shell_api unmarkSessionUnsaved -} - -reboot () -{ - echo "Exit from configure mode before rebooting." -} - -vyatta_config_rollback () -{ - if [ $# != 1 ]; then - echo "Error: must include a revision # to rollback to" - return 1; - fi - ${vyatta_sbindir}/vyatta-config-mgmt.pl --action=rollback --revnum "$@" -} - -shutdown () -{ - echo "Exit from configure mode before shutting down system." -} - -reset_edit_level () -{ - vyatta_cli_shell_api getEditResetEnv - return $? -} - -vyatta_config_load () -{ - # don't load if there are uncommitted changes. - if vyatta_cli_shell_api sessionChanged; then - echo "Cannot load: configuration modified." - echo "Commit or discard the changes before loading a config file." - return 1 - fi - # return to top level. - reset_edit_level - ${vyatta_sbindir}/vyatta-load-config.pl "$@" -} - -vyatta_config_merge () -{ - # don't load if there are uncommitted changes. - if vyatta_cli_shell_api sessionChanged; then - echo "Cannot load: configuration modified." - echo "Commit or discard the changes before loading a config file." - return 1 - fi - # return to top level. - reset_edit_level - ${vyatta_sbindir}/vyatta-load-config.pl "$@" --merge -} - -top () -{ - if vyatta_cli_shell_api editLevelAtRoot; then - echo "Already at the top level" - return 0 - fi - - # go to the top level. - reset_edit_level -} - -vyatta_config_edit () -{ - vyatta_cli_shell_api getEditEnv "$@" - return $? -} - -up () -{ - vyatta_cli_shell_api getEditUpEnv "$@" - return $? -} - -really_exit() -{ - - if vyatta_cli_shell_api sessionUnsaved; then - echo "Warning: configuration changes have not been saved." - fi - vyatta_cli_shell_api teardownSession - unset _OFR_CONFIGURE - builtin exit 0 -} - -vyatta_config_exit () -{ - local discard - local -a comp=( "discard" ) - local -a filtered=() - get_prefix_filtered_list $1 comp filtered - if [ $# == 0 ]; then - discard=0 - elif [ $# == 1 ] && [ "${filtered[0]}" == "discard" ]; then - discard=1 - else - echo "Invalid argument \"$*\" for 'exit'" - return 1 - fi - - if vyatta_cli_shell_api editLevelAtRoot; then - # we are at the root level. check if we can really exit. - if vyatta_cli_shell_api sessionChanged; then - if (( ! discard )); then - echo "Cannot exit: configuration modified." - echo "Use 'exit discard' to discard the changes and exit." - return 1 - fi - fi - really_exit - fi - - # "exit" to the root level. - reset_edit_level -} - -# run op mode commands -vyatta_config_run () -{ - if [ $# == 0 ]; then - echo Incomplete command - return 1 - fi - /opt/vyatta/bin/vyatta-op-cmd-wrapper $@ -} - -### End Top level command wrappers ### ### Top level command completions ### # do op mode completion @@ -574,53 +307,6 @@ vyatta_commit_complete () } ### End Top level command completions ### -get_prefix_filtered_list () -{ - # $1: prefix - # $2: \@list - # $3: \@filtered - declare -a olist - local pfx=$1 - pfx=${pfx#\"} - eval "olist=( \"\${$2[@]}\" )" - local idx=0 - for elem in "${olist[@]}"; do - local sub=${elem#$pfx} - if [ "$elem" == "$sub" ] && [ -n "$pfx" ]; then - continue - fi - eval "$3[$idx]=\"$elem\"" - (( idx++ )) - done -} - -get_prefix_filtered_list2 () -{ - # $1: prefix - # $2: \@list - # $3: \@filtered - # $4: \@list2 - # $5: \@filtered2 - declare -a olist - local pfx=$1 - pfx=${pfx#\"} - eval "olist=( \"\${$2[@]}\" )" - eval "local orig_len=\${#$2[@]}" - local orig_idx=0 - local idx=0 - for (( orig_idx = 0; orig_idx < orig_len; orig_idx++ )); do - eval "local elem=\${$2[$orig_idx]}" - eval "local elem2=\${$4[$orig_idx]}" - local sub=${elem#$pfx} - if [ "$elem" == "$sub" ] && [ -n "$pfx" ]; then - continue - fi - eval "$3[$idx]=\"$elem\"" - eval "$5[$idx]=\"$elem2\"" - (( idx++ )) - done -} - declare vyatta_cfg_help="" declare vyatta_cfg_type="" declare vyatta_cfg_tag=0 @@ -947,248 +633,6 @@ fi # disallow 'Ctrl-D' exit, since we need special actions on 'exit' builtin set -o ignoreeof 1 - -### Top level wrappers ### -vyatta_cfg_cmd_run () -{ - local cmd=$1 - local -a args=( "$@" ) - local output='' - if [[ "$cmd" == "edit" ]]; then - vyatta_config_edit "${@:2}" - elif [[ "$cmd" == "show" ]]; then - vyatta_config_show "${@:2}" - else - cmd="/opt/vyatta/sbin/my_$cmd" - output=$(eval "$cmd ${args[@]:1}") - fi - vyatta_cfg_print_output "$output" -} - -vyatta_cfg_print_output () -{ - local output=$1 - if [[ ! -z "${output}" ]];then - output=$(echo "$output" | sed -e 's/^/ /') - echo -ne "\n${output}\n\n" | eval "${VYATTA_PAGER:-cat}" - fi -} - -vyatta_cfg_validate_cmd () -{ - local cmd=$1 - local -a expanded_api_args=( "$@" ) - local path='' - local opath='' - for arg in "${expanded_api_args[@]:1}"; do - if [[ "$path" == '' ]]; then - path="$arg" - else - path="$path $arg" - fi - if ! cli-shell-api validateTmplPath ${path}; then - _cli_shell_api_comp_values=() - vyatta_cli_shell_api getCompletionEnv $cmd ${path} - if [[ "${#_cli_shell_api_comp_values[@]}" != "1" - && "${#_cli_shell_api_comp_values[@]}" != "0" ]]; then - local -a _get_help_text_items=( "${_cli_shell_api_hitems[@]}" ) - local -a _get_help_text_helps=( "${_cli_shell_api_hstrs[@]}" ) - local vyatta_help_text='' - if [[ $opath == '' ]]; then - echo -ne "\n Configuation path: [$arg] is ambiguous\n" - else - echo -ne "\n Configuation path: $opath [$arg] is ambiguous\n" - fi - get_help_text - echo -e "$vyatta_help_text\n" | sed 's/^P/ P/' - echo -e " ${cmd^} failed\n" - break - else - if [[ $opath == '' ]]; then - echo -ne "\n Configuation path: [$arg] is not valid\n ${cmd^} failed\n\n" - else - echo -ne "\n Configuation path: $opath [$arg] is not valid\n ${cmd^} failed\n\n" - fi - break - fi - else - opath=$path - fi - done -} - -vyatta_config_copy () -{ - local cmd=$1 - if [[ "${#@}" == "1" ]]; then - vyatta_cfg_cmd_run $cmd - return - fi - local -a args=( "$@" ) - local -a param1=( "$cmd" ${args[@]:1:2} ) - local -a param2=( "$cmd" ${args[@]:4:5} ) - local editlvl=$(cli-shell-api getEditLevelStr) - expanded_api_args=( ) - vyatta_config_expand_compwords "${param1[@]}" - param1=( "${expanded_api_args[@]}" ) - expanded_api_args=( ) - vyatta_config_expand_compwords "${param2[@]}" - param2=( "${expanded_api_args[@]}" ) - if [[ "${args[3]}" != "to" ]]; then - echo -ne "\n Invalid command: $cmd ${param1[@]:1} ${args[3]} ${param2[@]:1}\n\n" - elif cli-shell-api validateTmplPath ${editlvl[*]} "${param1[@]:1}" && - cli-shell-api validateTmplPath ${editlvl[*]} "${param2[@]:1}" ; then - cmd="/opt/vyatta/sbin/my_$cmd" - output=$(eval "$cmd ${param1[@]:1} to ${param2[@]:1} | sed -e 's/^/ /'") - if [[ ! -z "${output}" ]];then - echo -ne "\n${output}\n\n" - fi - else - if ! cli-shell-api validateTmplPath ${editlvl[*]} "${param1[@]:1}"; then - _cli_shell_api_comp_values=() - vyatta_cli_shell_api getCompletionEnv $cmd ${param1[1]} - if [[ "${#_cli_shell_api_comp_values[@]}" != "1" - && "${#_cli_shell_api_comp_values[@]}" != "0" ]]; then - echo -ne "\n Ambiguous command: $cmd [${param1[1]}]\n" - echo -ne "\n Possible completions: ${_cli_shell_api_comp_values[@]}\n\n" - else - echo -ne "\n Invalid command: $cmd [${param1[1]}]\n\n" - fi - elif ! cli-shell-api validateTmplPath ${editlvl[*]} "${param1[@]:2}"; then - _cli_shell_api_comp_values=() - vyatta_cli_shell_api getCompletionEnv $cmd "${param2[1]}" - if [[ "${#_cli_shell_api_comp_values[@]}" != "1" - && "${#_cli_shell_api_comp_values[@]}" != "0" ]]; then - echo -ne "\n Ambiguous command: $cmd ${param2[@]:1} to [${param2[1]}]\n" - echo -ne "\n Possible completions: ${_cli_shell_api_comp_values[@]}\n\n" - else - echo -ne "\n Invalid command: $cmd ${param1[@]:1} to [${param2[1]}]\n\n" - fi - else - echo -ne "\n Invalid command: $cmd ${param1[@]:1} to ${param2[@]:1}\n\n" - fi - fi -} - -vyatta_config_comment () -{ - local cmd=$1 - if [[ "${#@}" == "1" ]]; then - vyatta_cfg_cmd_run $cmd - return - fi - # change the ifs so we can extract the entire comment - local OIFS=$IFS - local IFS='---' - local -a args=( "$@" ) - # extract the comment - local comment="'${args[$[${#args[@]}-1]]}'" - args=( "${args[@]:0:$[${#args[@]}-1]}" ) - IFS=$OIFS - local -a expanded_api_args=() - # expand the comment command - local editlvl=$(cli-shell-api getEditLevelStr) - vyatta_config_expand_compwords "${args[@]}" - if [[ "$#" != "${#expanded_api_args[@]}" ]]; then - expanded_api_args+=( $comment ) - fi - # use the standard run function with the comment expansion - vyatta_cfg_cmd_run "${expanded_api_args[@]}" -} - -vyatta_cfg_cmd () -{ - # commands that need expanded paths get called through here - local cmd=$1 - if [[ "$#" == "1" ]]; then - vyatta_cfg_cmd_run $cmd - return - fi - # Note: the below code is to account for quoted strings as - # leaf node parameter - # change the ifs so we can extract the entire last element - local OIFS=$IFS - local IFS='---' - local -a args=( "$@" ) - local lastelem="${args[$[${#args[@]}-1]]}" - args=( "${args[@]:0:$[${#args[@]}-1]}" ) - IFS=$OIFS - local -a lastelem_arr=( $lastelem ) - #if there is only one last element don't quote it - if [[ "${#lastelem_arr[@]}" == "1" ]]; then - args+=( "$lastelem" ) - else - lastelem="'$lastelem'" - fi - local -a expanded_api_args=() - local editlvl=$(cli-shell-api getEditLevelStr) - vyatta_config_expand_compwords ${args[@]} - if cli-shell-api validateTmplPath ${editlvl[*]} "${expanded_api_args[@]:1}"; then - # if we have a valid command append the last parameter and run it - if [[ "$#" != "${#expanded_api_args[@]}" ]]; then - expanded_api_args+=( $lastelem ) - fi - vyatta_cfg_cmd_run "${expanded_api_args[@]}" - else - # find broken portion of command - vyatta_cfg_validate_cmd "${expanded_api_args[@]}" - fi -} -### Top level wrappers ### - -### Main run command ### -vyatta_cfg_run () -{ - # validate top level command and execute proper function - local cmd=$1 - local -a args=( "$@" ) - local -a filtered_cmds - get_prefix_filtered_list $cmd _vyatta_cfg_cmds filtered_cmds - local found - vyatta_cfg_is_elem_of "${cmd}" _vyatta_cfg_cmds - found=$? - if [[ "${#filtered_cmds[@]}" == "0" ]]; then - echo -ne "\n Invalid command: [$cmd]\n\n" - return 1 - elif [[ "${#filtered_cmds[@]}" != "1" && "$found" == "1" ]]; then - echo -ne "\n Ambiguous command: [$cmd]\n" - local -a fitems=() - local -a fstrs=() - local -a _get_help_text_items=( "${_vyatta_cfg_cmds[@]}" ) - local -a _get_help_text_helps=( "${_vyatta_cfg_helps[@]}" ) - get_prefix_filtered_list2 "$cmd" \ - _get_help_text_items fitems _get_help_text_helps fstrs - _get_help_text_items=( "${fitems[@]}" ) - _get_help_text_helps=( "${fstrs[@]}" ) - get_help_text - echo -e "$vyatta_help_text\n" | sed 's/^P/ P/' - return 1 - fi - local fcmd; - if vyatta_cfg_is_elem_of "${cmd}" _vyatta_cfg_cmds; then - fcmd=$cmd - else - fcmd=${filtered_cmds[0]} - fi - case $fcmd in - compare) vyatta_config_compare "${@:2}" ;; - comment) vyatta_config_comment "${args[@]}" ;; # comment is a special case - copy|rename) vyatta_config_copy $fcmd ${@:2} ;; # copy is a special case - exit) vyatta_config_exit "${@:2}" ;; - run) vyatta_config_run "${@:2}" ;; - load) vyatta_config_load "${@:2}" ;; - commit) vyatta_config_commit "${@:2}";; - confirm) vyatta_config_confirm "${@:2}";; - rollback) vyatta_config_rollback "${@:2}";; - commit-confirm) vyatta_config_commit-confirm "${@:2}";; - compare) vyatta_config_compare "${@:2}";; - save) vyatta_config_save "${@:2}" ;; - merge) vyatta_config_merge "${@:2}" ;; - loadkey) vyatta_config_loadkey "${@:2}";; - *) vyatta_cfg_cmd $fcmd "${@:2}" ;; # commands requiring path expansion must go through here - esac -} - reset_edit_level export VYATTA_COMP_LINE_EMPTY=VYATTA_COMP_LINE_EMPTY @@ -1228,95 +672,6 @@ vyatta_config_default_complete () fi } -vyatta_cfg_is_elem_of () { - local elem=$1 - local -a olist - eval "olist=( \"\${$2[@]}\" )" - for e in ${olist[*]}; do - if [[ "$e" == "$elem" ]]; then - return 0 - fi - done - return 1 -} - -vyatta_cfg_expand_top_level () { - local cmd=$1 - local -a filtered_cmds=() - get_prefix_filtered_list ${cmd} _vyatta_cfg_cmds filtered_cmds - local found - vyatta_cfg_is_elem_of "${cmd}" _vyatta_cfg_cmds - found=$? - local fcmd - if [[ "${#filtered_cmds[@]}" == "1" || "$found" == "0" ]]; then - if [[ "${#filtered_cmds[@]}" == "1" ]]; then - fcmd=${filtered_cmds[0]} - else - fcmd=$cmd - fi - else - fcmd=$cmd - fi - echo $fcmd -} - -### Initalize top level command alias and completion functions -_vyatta_cfg_init () -{ - # empty and default line compeletion - complete -E -F vyatta_config_complete - complete -D -F vyatta_config_default_complete - - # create the top level aliases for the unambiguous portions of the commands - # this is the only place we need an entire enumerated list of the subcommands - for cmd in "${_vyatta_cfg_cmds[@]}"; do - for pos in $(seq 1 ${#cmd}); do - case ${cmd:0:$pos} in - for|do|done|if|fi|case|while|tr ) - continue ;; - *) ;; - esac - local -a filtered_cmds=() - get_prefix_filtered_list ${cmd:0:$pos} _vyatta_cfg_cmds filtered_cmds - local found - vyatta_cfg_is_elem_of "${cmd:0:$pos}" _vyatta_cfg_cmds - found=$? - if [[ "${#filtered_cmds[@]}" == "1" || "${cmd:0:$pos}" == "$cmd" || "$found" == "0" ]]; then - local fcmd - if [[ "${#filtered_cmds[@]}" == "1" ]]; then - fcmd=${filtered_cmds[0]} - elif vyatta_cfg_is_elem_of "${cmd:0:$pos}" _vyatta_cfg_cmds; then - fcmd=${cmd:0:$pos} - else - fcmd=$cmd - fi - case $fcmd in - save|load|merge) - complete -F vyatta_loadsave_complete ${cmd:0:$pos} ;; - discard|confirm) - continue ;; - run) - complete -F vyatta_run_complete ${cmd:0:$pos} ;; - loadkey) - complete -F vyatta_loadkey_complete ${cmd:0:$pos} ;; - compare) - complete -F vyatta_compare_complete ${cmd:0:$pos} ;; - rollback) - complete -F vyatta_rollback_complete ${cmd:0:$pos} ;; - commit|commit-confirm) - complete -F vyatta_commit_complete ${cmd:0:$pos} ;; - *) - complete -F vyatta_config_complete ${cmd:0:$pos} ;; - esac - else - complete -F vyatta_config_complete ${cmd:0:$pos} - fi - eval alias ${cmd:0:$pos}=\'vyatta_cfg_run ${cmd:0:$pos}\' - done - done - shopt -s histverify -} - _vyatta_cfg_init # Local Variables: diff --git a/functions/interpreter/vyatta-cfg-run b/functions/interpreter/vyatta-cfg-run new file mode 100644 index 0000000..c226e74 --- /dev/null +++ b/functions/interpreter/vyatta-cfg-run @@ -0,0 +1,621 @@ +# vyatta configuration mode command interpreter functions + +# **** 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. +# +# A copy of the GNU General Public License is available as +# `/usr/share/common-licenses/GPL' in the Debian GNU/Linux distribution +# or on the World Wide Web at `http://www.gnu.org/copyleft/gpl.html'. +# You can also obtain it by writing to the Free Software Foundation, +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# Author: Vyatta +# Description: Command interpreter functions for config mode +# +# **** End License **** + +### Top level commands and help ### +_vyatta_cfg_cmds=( "confirm" \ + "comment" \ + "commit" \ + "commit-confirm" \ + "compare" \ + "copy" \ + "delete" \ + "discard" \ + "edit" \ + "exit" \ + "load" \ + "loadkey" \ + "merge" \ + "rename" \ + "rollback" \ + "run" \ + "save" \ + "set" \ + "show" ) +_vyatta_cfg_helps=( \ + "Confirm prior commit-confirm" \ + "Add comment to this configuration element" \ + "Commit the current set of changes" \ + "Commit the current set of changes with 'confirm' required" \ + "Compare configuration revisions" \ + "Copy a configuration element" \ + "Delete a configuration element" \ + "Discard uncommitted changes" \ + "Edit a sub-element" \ + "Exit from this configuration level" \ + "Load configuration from a file and replace running configuration" \ + "Load user SSH key from a file" \ + "Load configuration from a file and merge running configuration" \ + "Rename a configuration element" \ + "Rollback to a prior config revision (requires reboot)" \ + "Run an operational-mode command" \ + "Save configuration to a file" \ + "Set the value of a parameter or create a new element" \ + "Show the configuration (default values may be suppressed)" \ + ) +### End Top level commands and help ### + +vyatta_cfg_expand_top_level () { + local cmd=$1 + local -a filtered_cmds=() + get_prefix_filtered_list ${cmd} _vyatta_cfg_cmds filtered_cmds + local found + is_elem_of "${cmd}" _vyatta_cfg_cmds + found=$? + local fcmd + if [[ "${#filtered_cmds[@]}" == "1" || "$found" == "0" ]]; then + if [[ "${#filtered_cmds[@]}" == "1" ]]; then + fcmd=${filtered_cmds[0]} + else + fcmd=$cmd + fi + else + fcmd=$cmd + fi + echo $fcmd +} + +### Top level command wrappers ### +vyatta_config_show () +{ + local -a opts=() + local -a args=() + for arg in "$@"; do + if [ "$arg" == "-all" ]; then + opts+=('--show-show-defaults') + else + args+=("$arg") + fi + done + cli-shell-api "${opts[@]}" -- showCfg "${args[@]}" \ + | eval "${VYATTA_PAGER:-cat}" +} + +vyatta_config_commit () +{ + if ! vyatta_cli_shell_api sessionChanged; then + echo "No configuration changes to commit" + return 1; + fi + local comment="commit" + local next=0 + local -a args=() + for arg in "$@"; do + if [ "$next" == "1" ]; then + comment=$arg + next=0; + elif [ "$arg" == "comment" ]; then + next=1 + elif [ "$arg" == "confirm" ]; then + echo Use commit-confirm command + return 1; + else + args[${#args[@]}]="$arg" + fi + done + + export COMMIT_COMMENT="$comment" + export COMMIT_VIA=cli + /opt/vyatta/sbin/my_commit "${args[@]}" 2>&1 + unset COMMIT_VIA + unset COMMIT_COMMENT +} + +vyatta_config_commit-confirm () +{ + if ! vyatta_cli_shell_api sessionChanged; then + echo "No configuration changes to commit" + return 1; + fi + local -a args=() + local first=1 + local minutes=10 + for arg in "$@"; do + if [ "$first" = "1" ]; then + if [[ $arg = *[[:digit:]]* ]]; then + minutes=$arg + else + args[${#args[@]}]="$arg" + fi + first=0 + else + args[${#args[@]}]="$arg" + fi + done + cmd="${vyatta_sbindir}/vyatta-config-mgmt.pl --action=commit-confirm \ + --minutes=$minutes" + eval "sudo sg vyattacfg \"$cmd\" " + if [ $? = 0 ]; then + commit "$@" + fi +} + +vyatta_config_confirm () +{ + ${vyatta_sbindir}/vyatta-config-mgmt.pl --action=confirm +} + +vyatta_config_compare () +{ + local -a comp=( "saved" ) + local -a filtered=() + get_prefix_filtered_list $1 comp filtered + if [[ "${filtered[0]}" == "saved" ]]; then + cli-shell-api showConfig --show-cfg1 /config/config.boot --show-cfg2 @WORKING --show-context-diff + else + ${vyatta_sbindir}/vyatta-config-mgmt.pl --action=diff "$@" | eval "${VYATTA_PAGER:-cat}" + fi +} + +vyatta_config_save () +{ + if vyatta_cli_shell_api sessionChanged; then + echo -e "Warning: you have uncommitted changes that will not be saved.\n" + fi + # return to top level. + reset_edit_level + # transform individual args into quoted strings + local arg='' + local save_cmd="${vyatta_sbindir}/vyatta-save-config.pl" + for arg in "$@"; do + save_cmd+=" '$arg'" + done + eval "sudo sg vyattacfg \"umask 0002 ; $save_cmd\"" + vyatta_cli_shell_api unmarkSessionUnsaved +} + +reboot () +{ + echo "Exit from configure mode before rebooting." +} + +vyatta_config_rollback () +{ + if [ $# != 1 ]; then + echo "Error: must include a revision # to rollback to" + return 1; + fi + ${vyatta_sbindir}/vyatta-config-mgmt.pl --action=rollback --revnum "$@" +} + +shutdown () +{ + echo "Exit from configure mode before shutting down system." +} + +reset_edit_level () +{ + vyatta_cli_shell_api getEditResetEnv + return $? +} + +vyatta_config_load () +{ + # don't load if there are uncommitted changes. + if vyatta_cli_shell_api sessionChanged; then + echo "Cannot load: configuration modified." + echo "Commit or discard the changes before loading a config file." + return 1 + fi + # return to top level. + reset_edit_level + ${vyatta_sbindir}/vyatta-load-config.pl "$@" +} + +vyatta_config_merge () +{ + # don't load if there are uncommitted changes. + if vyatta_cli_shell_api sessionChanged; then + echo "Cannot load: configuration modified." + echo "Commit or discard the changes before loading a config file." + return 1 + fi + # return to top level. + reset_edit_level + ${vyatta_sbindir}/vyatta-load-config.pl "$@" --merge +} + +top () +{ + if vyatta_cli_shell_api editLevelAtRoot; then + echo "Already at the top level" + return 0 + fi + + # go to the top level. + reset_edit_level +} + +vyatta_config_edit () +{ + vyatta_cli_shell_api getEditEnv "$@" + return $? +} + +up () +{ + vyatta_cli_shell_api getEditUpEnv "$@" + return $? +} + +really_exit() +{ + + if vyatta_cli_shell_api sessionUnsaved; then + echo "Warning: configuration changes have not been saved." + fi + vyatta_cli_shell_api teardownSession + unset _OFR_CONFIGURE + builtin exit 0 +} + +vyatta_config_exit () +{ + local discard + local -a comp=( "discard" ) + local -a filtered=() + get_prefix_filtered_list $1 comp filtered + if [ $# == 0 ]; then + discard=0 + elif [ $# == 1 ] && [ "${filtered[0]}" == "discard" ]; then + discard=1 + else + echo "Invalid argument \"$*\" for 'exit'" + return 1 + fi + + if vyatta_cli_shell_api editLevelAtRoot; then + # we are at the root level. check if we can really exit. + if vyatta_cli_shell_api sessionChanged; then + if (( ! discard )); then + echo "Cannot exit: configuration modified." + echo "Use 'exit discard' to discard the changes and exit." + return 1 + fi + fi + really_exit + fi + + # "exit" to the root level. + reset_edit_level +} + +# run op mode commands +vyatta_config_run () +{ + if [ $# == 0 ]; then + echo Incomplete command + return 1 + fi + /opt/vyatta/bin/vyatta-op-cmd-wrapper $@ +} + +### End Top level command wrappers ### + +### Top level wrappers ### +vyatta_cfg_cmd_run () +{ + local cmd=$1 + local -a args=( "$@" ) + local output='' + if [[ "$cmd" == "edit" ]]; then + vyatta_config_edit "${@:2}" + elif [[ "$cmd" == "show" ]]; then + vyatta_config_show "${@:2}" + else + cmd="/opt/vyatta/sbin/my_$cmd" + output=$(eval "$cmd ${args[@]:1}") + fi + vyatta_cfg_print_output "$output" +} + +vyatta_cfg_print_output () +{ + local output=$1 + if [[ ! -z "${output}" ]];then + output=$(echo "$output" | sed -e 's/^/ /') + echo -ne "\n${output}\n\n" | eval "${VYATTA_PAGER:-cat}" + fi +} + +vyatta_cfg_validate_cmd () +{ + local cmd=$1 + local -a expanded_api_args=( "$@" ) + local path='' + local opath='' + for arg in "${expanded_api_args[@]:1}"; do + if [[ "$path" == '' ]]; then + path="$arg" + else + path="$path $arg" + fi + if ! cli-shell-api validateTmplPath ${path}; then + _cli_shell_api_comp_values=() + vyatta_cli_shell_api getCompletionEnv $cmd ${path} + if [[ "${#_cli_shell_api_comp_values[@]}" != "1" + && "${#_cli_shell_api_comp_values[@]}" != "0" ]]; then + local -a _get_help_text_items=( "${_cli_shell_api_hitems[@]}" ) + local -a _get_help_text_helps=( "${_cli_shell_api_hstrs[@]}" ) + local vyatta_help_text='' + if [[ $opath == '' ]]; then + echo -ne "\n Configuation path: [$arg] is ambiguous\n" + else + echo -ne "\n Configuation path: $opath [$arg] is ambiguous\n" + fi + get_help_text + echo -e "$vyatta_help_text\n" | sed 's/^P/ P/' + echo -e " ${cmd^} failed\n" + break + else + if [[ $opath == '' ]]; then + echo -ne "\n Configuation path: [$arg] is not valid\n ${cmd^} failed\n\n" + else + echo -ne "\n Configuation path: $opath [$arg] is not valid\n ${cmd^} failed\n\n" + fi + break + fi + else + opath=$path + fi + done +} + +vyatta_config_copy () +{ + local cmd=$1 + if [[ "${#@}" == "1" ]]; then + vyatta_cfg_cmd_run $cmd + return + fi + local -a args=( "$@" ) + local -a param1=( "$cmd" ${args[@]:1:2} ) + local -a param2=( "$cmd" ${args[@]:4:5} ) + local editlvl=$(cli-shell-api getEditLevelStr) + expanded_api_args=( ) + vyatta_config_expand_compwords "${param1[@]}" + param1=( "${expanded_api_args[@]}" ) + expanded_api_args=( ) + vyatta_config_expand_compwords "${param2[@]}" + param2=( "${expanded_api_args[@]}" ) + if [[ "${args[3]}" != "to" ]]; then + echo -ne "\n Invalid command: $cmd ${param1[@]:1} ${args[3]} ${param2[@]:1}\n\n" + elif cli-shell-api validateTmplPath ${editlvl[*]} "${param1[@]:1}" && + cli-shell-api validateTmplPath ${editlvl[*]} "${param2[@]:1}" ; then + cmd="/opt/vyatta/sbin/my_$cmd" + output=$(eval "$cmd ${param1[@]:1} to ${param2[@]:1} | sed -e 's/^/ /'") + if [[ ! -z "${output}" ]];then + echo -ne "\n${output}\n\n" + fi + else + if ! cli-shell-api validateTmplPath ${editlvl[*]} "${param1[@]:1}"; then + _cli_shell_api_comp_values=() + vyatta_cli_shell_api getCompletionEnv $cmd ${param1[1]} + if [[ "${#_cli_shell_api_comp_values[@]}" != "1" + && "${#_cli_shell_api_comp_values[@]}" != "0" ]]; then + echo -ne "\n Ambiguous command: $cmd [${param1[1]}]\n" + echo -ne "\n Possible completions: ${_cli_shell_api_comp_values[@]}\n\n" + else + echo -ne "\n Invalid command: $cmd [${param1[1]}]\n\n" + fi + elif ! cli-shell-api validateTmplPath ${editlvl[*]} "${param1[@]:2}"; then + _cli_shell_api_comp_values=() + vyatta_cli_shell_api getCompletionEnv $cmd "${param2[1]}" + if [[ "${#_cli_shell_api_comp_values[@]}" != "1" + && "${#_cli_shell_api_comp_values[@]}" != "0" ]]; then + echo -ne "\n Ambiguous command: $cmd ${param2[@]:1} to [${param2[1]}]\n" + echo -ne "\n Possible completions: ${_cli_shell_api_comp_values[@]}\n\n" + else + echo -ne "\n Invalid command: $cmd ${param1[@]:1} to [${param2[1]}]\n\n" + fi + else + echo -ne "\n Invalid command: $cmd ${param1[@]:1} to ${param2[@]:1}\n\n" + fi + fi +} + +vyatta_config_comment () +{ + local cmd=$1 + if [[ "${#@}" == "1" ]]; then + vyatta_cfg_cmd_run $cmd + return + fi + # change the ifs so we can extract the entire comment + local OIFS=$IFS + local IFS='---' + local -a args=( "$@" ) + # extract the comment + local comment="'${args[$[${#args[@]}-1]]}'" + args=( "${args[@]:0:$[${#args[@]}-1]}" ) + IFS=$OIFS + local -a expanded_api_args=() + # expand the comment command + local editlvl=$(cli-shell-api getEditLevelStr) + vyatta_config_expand_compwords "${args[@]}" + if [[ "$#" != "${#expanded_api_args[@]}" ]]; then + expanded_api_args+=( $comment ) + fi + # use the standard run function with the comment expansion + vyatta_cfg_cmd_run "${expanded_api_args[@]}" +} + +vyatta_cfg_cmd () +{ + # commands that need expanded paths get called through here + local cmd=$1 + if [[ "$#" == "1" ]]; then + vyatta_cfg_cmd_run $cmd + return + fi + # Note: the below code is to account for quoted strings as + # leaf node parameter + # change the ifs so we can extract the entire last element + local OIFS=$IFS + local IFS='---' + local -a args=( "$@" ) + local lastelem="${args[$[${#args[@]}-1]]}" + args=( "${args[@]:0:$[${#args[@]}-1]}" ) + IFS=$OIFS + local -a lastelem_arr=( $lastelem ) + #if there is only one last element don't quote it + if [[ "${#lastelem_arr[@]}" == "1" ]]; then + args+=( "$lastelem" ) + else + lastelem="'$lastelem'" + fi + local -a expanded_api_args=() + local editlvl=$(cli-shell-api getEditLevelStr) + vyatta_config_expand_compwords ${args[@]} + if cli-shell-api validateTmplPath ${editlvl[*]} "${expanded_api_args[@]:1}"; then + # if we have a valid command append the last parameter and run it + if [[ "$#" != "${#expanded_api_args[@]}" ]]; then + expanded_api_args+=( $lastelem ) + fi + vyatta_cfg_cmd_run "${expanded_api_args[@]}" + else + # find broken portion of command + vyatta_cfg_validate_cmd "${expanded_api_args[@]}" + fi +} +### Top level wrappers ### + +### Main run command ### +vyatta_cfg_run () +{ + # validate top level command and execute proper function + local cmd=$1 + local -a args=( "$@" ) + local -a filtered_cmds + get_prefix_filtered_list $cmd _vyatta_cfg_cmds filtered_cmds + local found + is_elem_of "${cmd}" _vyatta_cfg_cmds + found=$? + if [[ "${#filtered_cmds[@]}" == "0" ]]; then + echo -ne "\n Invalid command: [$cmd]\n\n" + return 1 + elif [[ "${#filtered_cmds[@]}" != "1" && "$found" == "1" ]]; then + echo -ne "\n Ambiguous command: [$cmd]\n" + local -a fitems=() + local -a fstrs=() + local -a _get_help_text_items=( "${_vyatta_cfg_cmds[@]}" ) + local -a _get_help_text_helps=( "${_vyatta_cfg_helps[@]}" ) + get_prefix_filtered_list2 "$cmd" \ + _get_help_text_items fitems _get_help_text_helps fstrs + _get_help_text_items=( "${fitems[@]}" ) + _get_help_text_helps=( "${fstrs[@]}" ) + get_help_text + echo -e "$vyatta_help_text\n" | sed 's/^P/ P/' + return 1 + fi + local fcmd; + if is_elem_of "${cmd}" _vyatta_cfg_cmds; then + fcmd=$cmd + else + fcmd=${filtered_cmds[0]} + fi + case $fcmd in + compare) vyatta_config_compare "${@:2}" ;; + comment) vyatta_config_comment "${args[@]}" ;; # comment is a special case + copy|rename) vyatta_config_copy $fcmd ${@:2} ;; # copy is a special case + exit) vyatta_config_exit "${@:2}" ;; + run) vyatta_config_run "${@:2}" ;; + load) vyatta_config_load "${@:2}" ;; + commit) vyatta_config_commit "${@:2}";; + confirm) vyatta_config_confirm "${@:2}";; + rollback) vyatta_config_rollback "${@:2}";; + commit-confirm) vyatta_config_commit-confirm "${@:2}";; + compare) vyatta_config_compare "${@:2}";; + save) vyatta_config_save "${@:2}" ;; + merge) vyatta_config_merge "${@:2}" ;; + loadkey) vyatta_config_loadkey "${@:2}";; + *) vyatta_cfg_cmd $fcmd "${@:2}" ;; # commands requiring path expansion must go through here + esac +} + +### Initalize top level command alias and completion functions +_vyatta_cfg_init () +{ + # empty and default line compeletion + complete -E -F vyatta_config_complete + complete -D -F vyatta_config_default_complete + + # create the top level aliases for the unambiguous portions of the commands + # this is the only place we need an entire enumerated list of the subcommands + for cmd in "${_vyatta_cfg_cmds[@]}"; do + for pos in $(seq 1 ${#cmd}); do + case ${cmd:0:$pos} in + for|do|done|if|fi|case|while|tr ) + continue ;; + *) ;; + esac + local -a filtered_cmds=() + get_prefix_filtered_list ${cmd:0:$pos} _vyatta_cfg_cmds filtered_cmds + local found + is_elem_of "${cmd:0:$pos}" _vyatta_cfg_cmds + found=$? + if [[ "${#filtered_cmds[@]}" == "1" || "${cmd:0:$pos}" == "$cmd" || "$found" == "0" ]]; then + local fcmd + if [[ "${#filtered_cmds[@]}" == "1" ]]; then + fcmd=${filtered_cmds[0]} + elif is_elem_of "${cmd:0:$pos}" _vyatta_cfg_cmds; then + fcmd=${cmd:0:$pos} + else + fcmd=$cmd + fi + case $fcmd in + save|load|merge) + complete -F vyatta_loadsave_complete ${cmd:0:$pos} ;; + discard|confirm) + ;; + run) + complete -F vyatta_run_complete ${cmd:0:$pos} ;; + loadkey) + complete -F vyatta_loadkey_complete ${cmd:0:$pos} ;; + compare) + complete -F vyatta_compare_complete ${cmd:0:$pos} ;; + rollback) + complete -F vyatta_rollback_complete ${cmd:0:$pos} ;; + commit|commit-confirm) + complete -F vyatta_commit_complete ${cmd:0:$pos} ;; + *) + complete -F vyatta_config_complete ${cmd:0:$pos} ;; + esac + else + complete -F vyatta_config_complete ${cmd:0:$pos} + fi + eval alias ${cmd:0:$pos}=\'vyatta_cfg_run ${cmd:0:$pos}\' + done + done + shopt -s histverify +} |