1#!/usr/bin/env python
2
3r"""
4See help text for details (--help or -h option)..
5
6Example properties file content:
7quiet=n
8test_mode=y
9pos=file1 file2 file3
10
11Example call:
12
13prop_call.py --prop_file_name=prop_file my_program
14
15The result is that the following command will be run:
16my_program --test_mode=y --quiet=n file1 file2 file3
17"""
18
19import sys
20import os
21
22save_path_0 = sys.path[0]
23del sys.path[0]
24
25from gen_arg import *
26from gen_print import *
27from gen_valid import *
28from gen_misc import *
29from gen_cmd import *
30
31# Restore sys.path[0].
32sys.path.insert(0, save_path_0)
33
34
35parser = argparse.ArgumentParser(
36    usage='%(prog)s [OPTIONS]',
37    description="%(prog)s will call a program using parameters retrieved" +
38    " from the given properties file.",
39    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
40    prefix_chars='-+')
41
42parser.add_argument(
43    '--prop_dir_path',
44    default=os.environ.get("PROP_DIR_PATH", os.getcwd()),
45    help='The path to the directory that contains the properties file.' +
46    '  The default value is environment variable "PROP_DIR_PATH", if' +
47    ' set.  Otherwise, it is the current working directory.')
48
49parser.add_argument(
50    '--prop_file_name',
51    help='The path to a properties file that contains the parameters to' +
52    ' pass to the program.  If the properties file has a ".properties"' +
53    ' extension, the caller need not specify the extension.  The format' +
54    ' of each line in the properties file should be as follows:' +
55    ' <parm_name=parm_value>.  Do not quote the parm value.  To specify' +
56    ' positional parms, use a parm name of "pos".  For example: pos=this'
57    ' value')
58
59parser.add_argument(
60    'program_name',
61    help='The name of the program to be run.')
62
63# Populate stock_list with options we want.
64stock_list = [("test_mode", 0), ("quiet", 1), ("debug", 0)]
65
66
67def exit_function(signal_number=0,
68                  frame=None):
69
70    r"""
71    Execute whenever the program ends normally or with the signals that we
72    catch (i.e. TERM, INT).
73    """
74
75    dprint_executing()
76    dprint_var(signal_number)
77
78    qprint_pgm_footer()
79
80
81def signal_handler(signal_number,
82                   frame):
83
84    r"""
85    Handle signals.  Without a function to catch a SIGTERM or SIGINT, our
86    program would terminate immediately with return code 143 and without
87    calling our exit_function.
88    """
89
90    # Our convention is to set up exit_function with atexit.register() so
91    # there is no need to explicitly call exit_function from here.
92
93    dprint_executing()
94
95    # Calling exit prevents us from returning to the code that was running
96    # when we received the signal.
97    exit(0)
98
99
100def validate_parms():
101
102    r"""
103    Validate program parameters, etc.  Return True or False (i.e. pass/fail)
104    accordingly.
105    """
106
107    global prop_dir_path
108    global prop_file_path
109
110    if not valid_dir_path(prop_dir_path):
111        return False
112    prop_dir_path = add_trailing_slash(prop_dir_path)
113
114    if not valid_value(prop_file_name):
115        return False
116
117    prop_file_path = prop_dir_path + prop_file_name
118
119    # If properties file is not found, try adding ".properties" extension.
120    if not os.path.isfile(prop_file_path):
121        alt_prop_file_path = prop_file_path + ".properties"
122        if os.path.isfile(alt_prop_file_path):
123            prop_file_path = alt_prop_file_path
124
125    if not valid_file_path(prop_file_path):
126        return False
127
128    if not valid_value(program_name):
129        return False
130
131    gen_post_validation(exit_function, signal_handler)
132
133    return True
134
135
136def main():
137
138    if not gen_get_options(parser, stock_list):
139        return False
140
141    if not validate_parms():
142        return False
143
144    qprint_pgm_header()
145
146    # Get the parameters from the properties file.
147    properties = my_parm_file(prop_file_path)
148    # The parms (including program name) need to go into a list.
149    parms = [program_name]
150    for key, value in properties.items():
151        if key == "pos":
152            # Process positional parm(s).
153            parms.extend(value.split())
154        else:
155            parms.append("--" + key + "=" + escape_bash_quotes(value))
156
157    # parm_string is only created for display in non-quiet mode.
158    parm_string = " ".join(parms[1:])
159    cmd_buf = program_name + " " + parm_string
160    qprint_issuing(cmd_buf)
161    if not test_mode:
162        os.execvp(program_name, parms)
163
164    return True
165
166
167# Main
168
169if not main():
170    exit(1)
171