blob: f9865d0eae9f82c6fb4f4f6139f7338ba1942b3c [file] [log] [blame]
Michael Walsh4d942992018-02-15 17:18:54 -06001#!/usr/bin/wish
2
3# This file provides shell command procedures cmd_fnc and t_cmd_fnc.
4
5my_source [list print.tcl]
6
7
8proc cmd_fnc { cmd_buf { quiet {} } { test_mode {} } { print_output {} }\
9 { show_err {} } { ignore_err {} } { acceptable_shell_rcs {} } } {
10
Michael Walsh410b1782019-10-22 15:56:18 -050011 # Run the given command in a shell and return the shell return code and the output as a 2 element list.
Michael Walsh4d942992018-02-15 17:18:54 -060012
13 # Example usage:
14 # set result [cmd_fnc "date"].
15
16 # Example output:
17
18 # #(CST) 2018/01/17 16:23:28.951643 - 0.001086 - Issuing: date
19 # Mon Feb 19 10:12:10 CST 2018
20 # result:
21 # result[0]: 0x00000000
Michael Walsh410b1782019-10-22 15:56:18 -050022 # result[1]: Mon Feb 19 10:12:10 CST 2018
Michael Walsh4d942992018-02-15 17:18:54 -060023
Michael Walsh410b1782019-10-22 15:56:18 -050024 # Note: Because of the way this procedure processes parms, the user can specify blank values as a way of
25 # skipping parms. In the following example, the caller is indicating that they wish to have quiet and
Michael Walsh4d942992018-02-15 17:18:54 -060026 # test_mode take their normal defaults but have print_output be 0.:
27 # cmd_fnc "date" "" "" 0
28
29 # Description of argument(s):
30 # cmd_buf The command string to be run in a shell.
Michael Walsh410b1782019-10-22 15:56:18 -050031 # quiet Indicates whether this procedure should run the print_issuing() procedure
32 # which prints "Issuing: <cmd string>" to stdout. The default value is 0.
33 # test_mode If test_mode is set, this procedure will not actually run the command.
34 # If print_output is set, it will print "(test_mode) Issuing: <cmd string>"
35 # to stdout. The default value is 0.
36 # print_output If this is set, this procedure will print the stdout/stderr generated by
37 # the shell command. The default value is 1.
38 # show_err If show_err is set, this procedure will print a standardized error report
39 # if the shell command returns non-zero. The default value is 1.
40 # ignore_err If ignore_err is set, this procedure will not fail if the shell command
41 # fails. However, if ignore_err is not set, this procedure will exit 1 if
42 # the shell command fails. The default value is 1.
43 # acceptable_shell_rcs A list of acceptable shell rcs. If the shell return code is found in
44 # this list, the shell command is considered successful. The default value
45 # is {0}.
Michael Walsh4d942992018-02-15 17:18:54 -060046
47 # Set defaults.
48 set_var_default quiet [get_stack_var quiet 0 2]
49 set_var_default test_mode 0
50 set_var_default print_output 1
51 set_var_default show_err 1
52 set_var_default ignore_err 1
53 set_var_default acceptable_shell_rcs 0
54
55 qpissuing $cmd_buf $test_mode
56
57 if { $test_mode } { return [list 0 ""] }
58
59 set shell_rc 0
60
61 if { [ catch {set out_buf [eval exec bash -c {$cmd_buf}]} result ] } {
62 set out_buf $result
63 set shell_rc [lindex $::errorCode 2]
64 }
65
66 if { $print_output } { puts "${out_buf}" }
67
68 # Check whether return code is acceptable.
69 if { [lsearch -exact $acceptable_shell_rcs ${shell_rc}] == -1 } {
70 # The command failed.
71 append error_message "The prior shell command failed.\n"
72 append error_message [sprint_var shell_rc "" "" 1]
73 if { $acceptable_shell_rcs != 0 } {
Michael Walsh410b1782019-10-22 15:56:18 -050074 # acceptable_shell_rcs contains more than just a single element equal to 0.
Michael Walsh4d942992018-02-15 17:18:54 -060075 append error_message "\n"
76 append error_message [sprint_list acceptable_shell_rcs "" "" 1]
77 }
78 if { ! $print_output } {
79 append error_message "out_buf:\n${out_buf}"
80 }
81 if { $show_err } {
82 print_error_report $error_message
83 }
84
85 if { ! $ignore_err } {
86 exit 1
87 }
88
89 }
90
91 return [list $shell_rc $out_buf]
92
93}
94
95
96proc t_cmd_fnc { args } {
97
Michael Walsh410b1782019-10-22 15:56:18 -050098 # Call cmd_fnc with test_mode equal to the test_mode setting found by searching up the call stack. See
99 # cmd_fnc (above) for details for all other arguments.
Michael Walsh4d942992018-02-15 17:18:54 -0600100
Michael Walsh410b1782019-10-22 15:56:18 -0500101 # We wish to obtain a value for test_mode by searching up the call stack. This value will govern whether
102 # the command specified actually gets executed.
Michael Walsh4d942992018-02-15 17:18:54 -0600103 set_var_default test_mode [get_stack_var test_mode 0 2]
Michael Walsh50146212018-02-22 12:15:34 -0600104
Michael Walsh410b1782019-10-22 15:56:18 -0500105 # Since we wish to manipulate the value of test_mode, which is the third positional parm, we must make
106 # sure we have at least 3 parms. We will now append blank values to the args list as needed to ensure that
107 # we have the minimum 3 parms.
Michael Walsh50146212018-02-22 12:15:34 -0600108 set min_args 3
109 for {set ix [llength $args]} {$ix < $min_args} {incr ix} {
110 lappend args {}
111 }
112
Michael Walsh410b1782019-10-22 15:56:18 -0500113 # Now replace the caller's test_mode value with the value obtained from the call stack search. It does
114 # not matter what value is specified by the caller for test_mode. It will be replaced. The whole point of
115 # calling t_cmd_fnc is to allow it to set the test_mode.
Michael Walsh4d942992018-02-15 17:18:54 -0600116 set args [lreplace $args 2 2 $test_mode]
117
118 return [cmd_fnc {*}$args]
119
120}