1#!/usr/bin/wish 2 3# This file provides many valuable validation procedures such as valid_value, 4# valid_integer, etc. 5 6my_source [list print.tcl call_stack.tcl] 7 8 9proc valid_value { var_name { invalid_values {}} { valid_values {}} } { 10 11 # If the value of the variable named in var_name is not valid, print an 12 # error message and exit the program with a non-zero return code. 13 14 # Description of arguments: 15 # var_name The name of the variable whose value is to 16 # be validated. 17 # invalid_values A list of invalid values. If the variable 18 # value is equal to any value in the 19 # invalid_values list, it is deemed to be 20 # invalid. Note that if you specify 21 # anything for invalid_values (below), the 22 # valid_values list is not even processed. 23 # In other words, specify either 24 # invalid_values or valid_values but not 25 # both. If no value is specified for either 26 # invalid_values or valid_values, 27 # invalid_values will default to a list with 28 # one blank entry. This is useful if you 29 # simply want to ensure that your variable 30 # is non blank. 31 # valid_values A list of invalid values. The variable 32 # value must be equal to one of the values 33 # in this list to be considered valid. 34 35 # Call get_stack_var_level to relieve the caller of the need for declaring 36 # the variable as global. 37 set stack_level [get_stack_var_level $var_name] 38 # Access the variable value. 39 upvar $stack_level $var_name var_value 40 41 set len_invalid_values [llength $invalid_values] 42 set len_valid_values [llength $valid_values] 43 44 if { $len_valid_values > 0 && $len_invalid_values > 0 } { 45 append error_message "Programmer error - You must provide either an" 46 append error_message " invalid_values list or a valid_values" 47 append error_message " list but NOT both.\n" 48 append error_message [sprint_list invalid_values "" "" 1] 49 append error_message [sprint_list valid_values "" "" 1] 50 print_error_report $error_message 51 exit 1 52 } 53 54 if { $len_valid_values > 0 } { 55 # Processing the valid_values list. 56 if { [lsearch -exact $valid_values "${var_value}"] != -1 } { return } 57 append error_message "The following variable has an invalid value:\n" 58 append error_message [sprint_varx $var_name $var_value "" "" 1] 59 append error_message "\nIt must be one of the following values:\n" 60 append error_message [sprint_list valid_values "" "" 1] 61 print_error_report $error_message 62 exit 1 63 } 64 65 if { $len_invalid_values == 0 } { 66 # Assign default value. 67 set invalid_values [list ""] 68 } 69 70 # Assertion: We have an invalid_values list. Processing it now. 71 if { [lsearch -exact $invalid_values "${var_value}"] == -1 } { return } 72 73 if { [lsearch -exact $valid_values "${var_value}"] != -1 } { return } 74 append error_message "The following variable has an invalid value:\n" 75 append error_message [sprint_varx $var_name $var_value "" "" 1] 76 append error_message "\nIt must NOT be one of the following values:\n" 77 append error_message [sprint_list invalid_values "" "" 1] 78 print_error_report $error_message 79 exit 1 80 81} 82 83 84proc valid_integer { var_name } { 85 86 # If the value of the variable named in var_name is not a valid integer, 87 # print an error message and exit the program with a non-zero return code. 88 89 # Description of arguments: 90 # var_name The name of the variable whose value is to 91 # be validated. 92 93 # Call get_stack_var_level to relieve the caller of the need for declaring 94 # the variable as global. 95 set stack_level [get_stack_var_level $var_name] 96 # Access the variable value. 97 upvar $stack_level $var_name var_value 98 99 if { [catch {format "0x%08x" "$var_value"} result] } { 100 append error_message "Invalid integer value:\n" 101 append error_message [sprint_varx $var_name $var_value] 102 print_error_report $error_message 103 exit 1 104 } 105 106} 107 108 109proc valid_dir_path { var_name { add_slash 1 } } { 110 111 # If the value of the variable named in var_name is not a valid directory 112 # path, print an error message and exit the program with a non-zero return 113 # code. 114 115 # Description of arguments: 116 # var_name The name of the variable whose value is to 117 # be validated. 118 # add_slash If set to 1, this procedure will add a 119 # trailing slash to the directory path value. 120 121 # Call get_stack_var_level to relieve the caller of the need for declaring 122 # the variable as global. 123 set stack_level [get_stack_var_level $var_name] 124 # Access the variable value. 125 upvar $stack_level $var_name var_value 126 127 expand_shell_string var_value 128 129 if { ![file isdirectory $var_value] } { 130 append error_message "The following directory does not exist:\n" 131 append error_message [sprint_varx $var_name $var_value "" "" 1] 132 print_error_report $error_message 133 exit 1 134 } 135 136 if { $add_slash } { add_trailing_string var_value / } 137 138} 139 140 141proc valid_file_path { var_name } { 142 143 # If the value of the variable named in var_name is not a valid file path, 144 # print an error message and exit the program with a non-zero return code. 145 146 # Description of arguments: 147 # var_name The name of the variable whose value is to 148 # be validated. 149 150 # Call get_stack_var_level to relieve the caller of the need for declaring 151 # the variable as global. 152 set stack_level [get_stack_var_level $var_name] 153 # Access the variable value. 154 upvar $stack_level $var_name var_value 155 156 expand_shell_string var_value 157 158 if { ![file isfile $var_value] } { 159 append error_message "The following file does not exist:\n" 160 append error_message [sprint_varx $var_name $var_value "" "" 1] 161 print_error_report $error_message 162 exit 1 163 } 164 165} 166 167 168proc get_password { {password_var_name password} } { 169 170 # Prompt user for password and return result. 171 172 # On error, print to stderr and terminate the program with non-zero return 173 # code. 174 175 set prompt\ 176 [string trimright [sprint_varx "Please enter $password_var_name" ""] "\n"] 177 puts -nonewline $prompt 178 flush stdout 179 stty -echo 180 gets stdin password1 181 stty echo 182 puts "" 183 184 set prompt [string\ 185 trimright [sprint_varx "Please re-enter $password_var_name" ""] "\n"] 186 puts -nonewline $prompt 187 flush stdout 188 stty -echo 189 gets stdin password2 190 stty echo 191 puts "" 192 193 if { $password1 != $password2 } { 194 print_error_report "Passwords do not match.\n" 195 gen_exit_proc 1 196 } 197 198 if { $password1 == "" } { 199 print_error_report "Need a non-blank value for $password_var_name.\n" 200 gen_exit_proc 1 201 } 202 203 return $password1 204 205} 206 207 208proc valid_password { var_name { prompt_user 1 } } { 209 210 # If the value of the variable named in var_name is not a valid password, 211 # print an error message and exit the program with a non-zero return code. 212 213 # Description of arguments: 214 # var_name The name of the variable whose value is to 215 # be validated. 216 # prompt_user If the variable has a blank value, prompt 217 # the user for a value. 218 219 # Call get_stack_var_level to relieve the caller of the need for declaring 220 # the variable as global. 221 set stack_level [get_stack_var_level $var_name] 222 # Access the variable value. 223 upvar $stack_level $var_name var_value 224 225 if { $var_value == "" && $prompt_user } { 226 global $var_name 227 set $var_name [get_password $var_name] 228 } 229 230 if { $var_value == "" } { 231 print_error_report "Need a non-blank value for $var_name.\n" 232 gen_exit_proc 1 233 } 234 235} 236 237 238proc process_pw_file_path {pw_file_path_var_name} { 239 240 # Process a password file path parameter by setting or validating the 241 # corresponding password variable. 242 243 # For example, let's say you have an os_pw_file_path parm defined. This 244 # procedure will set the global os_password variable. 245 246 # If there is no os_password program parm defined, then the pw_file_path 247 # must exist and will be validated by this procedure. If there is an 248 # os_password program parm defined, then either the os_pw_file_path must be 249 # valid or the os_password must be valid. Again, this procedure will verify 250 # all of this. 251 252 # When a valid pw_file_path exists, this program will read the password 253 # from it and set the global password variable with the value. 254 # Finally, this procedure will call valid_password which will prompt user 255 # if password has not been obtained by this point. 256 257 # Description of argument(s): 258 # pw_file_path_var_name The name of a global variable that 259 # contains a file path which in turn 260 # contains a password value. The variable 261 # name must end in "pw_file_path" (e.g. 262 # "os_pw_file_path"). 263 264 # Verify that $pw_file_path_var_name ends with "pw_file_path". 265 if { ! [regexp -expanded "pw_file_path$" $pw_file_path_var_name] } { 266 append message "Programming error - Proc [get_stack_proc_name] its" 267 append message " pw_file_path_var_name parameter to contain a value that" 268 append message "ends in \"pw_file_path\" instead of the current value:\n" 269 append message [sprint_var pw_file_path_var_name] 270 print_error $message 271 gen_exit_proc 1 272 } 273 274 global $pw_file_path_var_name 275 expand_shell_string $pw_file_path_var_name 276 277 # Get the prefix portion of pw_file_path_var_name which is obtained by 278 # stripping "pw_file_path" from the end. 279 regsub -expanded {pw_file_path$} $pw_file_path_var_name {} var_prefix 280 281 # Create password_var_name. 282 set password_var_name ${var_prefix}password 283 global $password_var_name 284 285 global longoptions pos_parms 286 regsub -all ":" "${longoptions} ${pos_parms}" {} parm_names 287 if { [lsearch -exact parm_names $password_var_name] == -1 } { 288 # If no corresponding password program parm has been defined, then the 289 # pw_file_path must be valid. 290 valid_file_path $pw_file_path_var_name 291 } 292 293 if { [file isfile [set $pw_file_path_var_name]] } { 294 # Read the entire password file into a list, filtering comments out. 295 set file_descriptor [open [set $pw_file_path_var_name] r] 296 set file_data [list_filter_comments [split [read $file_descriptor] "\n"]] 297 close $file_descriptor 298 299 # Assign the password value to the global password variable. 300 set $password_var_name [lindex $file_data 0] 301 # Register the password to prevent printing it. 302 register_passwords [set $password_var_name] 303 } 304 305 # Validate the password, which includes prompting the user if need be. 306 valid_password $password_var_name 307 308} 309