14d942998SMichael Walsh#!/usr/bin/wish 24d942998SMichael Walsh 34d942998SMichael Walsh# This file provides shell command procedures cmd_fnc and t_cmd_fnc. 44d942998SMichael Walsh 54d942998SMichael Walshmy_source [list print.tcl] 64d942998SMichael Walsh 74d942998SMichael Walsh 84d942998SMichael Walshproc cmd_fnc { cmd_buf { quiet {} } { test_mode {} } { print_output {} }\ 94d942998SMichael Walsh { show_err {} } { ignore_err {} } { acceptable_shell_rcs {} } } { 104d942998SMichael Walsh 11*410b1787SMichael Walsh # Run the given command in a shell and return the shell return code and the output as a 2 element list. 124d942998SMichael Walsh 134d942998SMichael Walsh # Example usage: 144d942998SMichael Walsh # set result [cmd_fnc "date"]. 154d942998SMichael Walsh 164d942998SMichael Walsh # Example output: 174d942998SMichael Walsh 184d942998SMichael Walsh # #(CST) 2018/01/17 16:23:28.951643 - 0.001086 - Issuing: date 194d942998SMichael Walsh # Mon Feb 19 10:12:10 CST 2018 204d942998SMichael Walsh # result: 214d942998SMichael Walsh # result[0]: 0x00000000 22*410b1787SMichael Walsh # result[1]: Mon Feb 19 10:12:10 CST 2018 234d942998SMichael Walsh 24*410b1787SMichael Walsh # Note: Because of the way this procedure processes parms, the user can specify blank values as a way of 25*410b1787SMichael Walsh # skipping parms. In the following example, the caller is indicating that they wish to have quiet and 264d942998SMichael Walsh # test_mode take their normal defaults but have print_output be 0.: 274d942998SMichael Walsh # cmd_fnc "date" "" "" 0 284d942998SMichael Walsh 294d942998SMichael Walsh # Description of argument(s): 304d942998SMichael Walsh # cmd_buf The command string to be run in a shell. 31*410b1787SMichael Walsh # quiet Indicates whether this procedure should run the print_issuing() procedure 32*410b1787SMichael Walsh # which prints "Issuing: <cmd string>" to stdout. The default value is 0. 33*410b1787SMichael Walsh # test_mode If test_mode is set, this procedure will not actually run the command. 34*410b1787SMichael Walsh # If print_output is set, it will print "(test_mode) Issuing: <cmd string>" 35*410b1787SMichael Walsh # to stdout. The default value is 0. 36*410b1787SMichael Walsh # print_output If this is set, this procedure will print the stdout/stderr generated by 37*410b1787SMichael Walsh # the shell command. The default value is 1. 38*410b1787SMichael Walsh # show_err If show_err is set, this procedure will print a standardized error report 39*410b1787SMichael Walsh # if the shell command returns non-zero. The default value is 1. 40*410b1787SMichael Walsh # ignore_err If ignore_err is set, this procedure will not fail if the shell command 41*410b1787SMichael Walsh # fails. However, if ignore_err is not set, this procedure will exit 1 if 42*410b1787SMichael Walsh # the shell command fails. The default value is 1. 43*410b1787SMichael Walsh # acceptable_shell_rcs A list of acceptable shell rcs. If the shell return code is found in 44*410b1787SMichael Walsh # this list, the shell command is considered successful. The default value 45*410b1787SMichael Walsh # is {0}. 464d942998SMichael Walsh 474d942998SMichael Walsh # Set defaults. 484d942998SMichael Walsh set_var_default quiet [get_stack_var quiet 0 2] 494d942998SMichael Walsh set_var_default test_mode 0 504d942998SMichael Walsh set_var_default print_output 1 514d942998SMichael Walsh set_var_default show_err 1 524d942998SMichael Walsh set_var_default ignore_err 1 534d942998SMichael Walsh set_var_default acceptable_shell_rcs 0 544d942998SMichael Walsh 554d942998SMichael Walsh qpissuing $cmd_buf $test_mode 564d942998SMichael Walsh 574d942998SMichael Walsh if { $test_mode } { return [list 0 ""] } 584d942998SMichael Walsh 594d942998SMichael Walsh set shell_rc 0 604d942998SMichael Walsh 614d942998SMichael Walsh if { [ catch {set out_buf [eval exec bash -c {$cmd_buf}]} result ] } { 624d942998SMichael Walsh set out_buf $result 634d942998SMichael Walsh set shell_rc [lindex $::errorCode 2] 644d942998SMichael Walsh } 654d942998SMichael Walsh 664d942998SMichael Walsh if { $print_output } { puts "${out_buf}" } 674d942998SMichael Walsh 684d942998SMichael Walsh # Check whether return code is acceptable. 694d942998SMichael Walsh if { [lsearch -exact $acceptable_shell_rcs ${shell_rc}] == -1 } { 704d942998SMichael Walsh # The command failed. 714d942998SMichael Walsh append error_message "The prior shell command failed.\n" 724d942998SMichael Walsh append error_message [sprint_var shell_rc "" "" 1] 734d942998SMichael Walsh if { $acceptable_shell_rcs != 0 } { 74*410b1787SMichael Walsh # acceptable_shell_rcs contains more than just a single element equal to 0. 754d942998SMichael Walsh append error_message "\n" 764d942998SMichael Walsh append error_message [sprint_list acceptable_shell_rcs "" "" 1] 774d942998SMichael Walsh } 784d942998SMichael Walsh if { ! $print_output } { 794d942998SMichael Walsh append error_message "out_buf:\n${out_buf}" 804d942998SMichael Walsh } 814d942998SMichael Walsh if { $show_err } { 824d942998SMichael Walsh print_error_report $error_message 834d942998SMichael Walsh } 844d942998SMichael Walsh 854d942998SMichael Walsh if { ! $ignore_err } { 864d942998SMichael Walsh exit 1 874d942998SMichael Walsh } 884d942998SMichael Walsh 894d942998SMichael Walsh } 904d942998SMichael Walsh 914d942998SMichael Walsh return [list $shell_rc $out_buf] 924d942998SMichael Walsh 934d942998SMichael Walsh} 944d942998SMichael Walsh 954d942998SMichael Walsh 964d942998SMichael Walshproc t_cmd_fnc { args } { 974d942998SMichael Walsh 98*410b1787SMichael Walsh # Call cmd_fnc with test_mode equal to the test_mode setting found by searching up the call stack. See 99*410b1787SMichael Walsh # cmd_fnc (above) for details for all other arguments. 1004d942998SMichael Walsh 101*410b1787SMichael Walsh # We wish to obtain a value for test_mode by searching up the call stack. This value will govern whether 102*410b1787SMichael Walsh # the command specified actually gets executed. 1034d942998SMichael Walsh set_var_default test_mode [get_stack_var test_mode 0 2] 10450146219SMichael Walsh 105*410b1787SMichael Walsh # Since we wish to manipulate the value of test_mode, which is the third positional parm, we must make 106*410b1787SMichael Walsh # sure we have at least 3 parms. We will now append blank values to the args list as needed to ensure that 107*410b1787SMichael Walsh # we have the minimum 3 parms. 10850146219SMichael Walsh set min_args 3 10950146219SMichael Walsh for {set ix [llength $args]} {$ix < $min_args} {incr ix} { 11050146219SMichael Walsh lappend args {} 11150146219SMichael Walsh } 11250146219SMichael Walsh 113*410b1787SMichael Walsh # Now replace the caller's test_mode value with the value obtained from the call stack search. It does 114*410b1787SMichael Walsh # not matter what value is specified by the caller for test_mode. It will be replaced. The whole point of 115*410b1787SMichael Walsh # calling t_cmd_fnc is to allow it to set the test_mode. 1164d942998SMichael Walsh set args [lreplace $args 2 2 $test_mode] 1174d942998SMichael Walsh 1184d942998SMichael Walsh return [cmd_fnc {*}$args] 1194d942998SMichael Walsh 1204d942998SMichael Walsh} 121