121791604SMichael Walsh#!/usr/bin/env python
221791604SMichael Walsh
321791604SMichael Walshr"""
421791604SMichael WalshSee help text for details (--help or -h option)..
521791604SMichael Walsh
621791604SMichael WalshExample properties file content:
721791604SMichael Walshquiet=n
821791604SMichael Walshtest_mode=y
921791604SMichael Walshpos=file1 file2 file3
1021791604SMichael Walsh
1121791604SMichael WalshExample call:
1221791604SMichael Walsh
1321791604SMichael Walshprop_call.py --prop_file_name=prop_file my_program
1421791604SMichael Walsh
1521791604SMichael WalshThe result is that the following command will be run:
1621791604SMichael Walshmy_program --test_mode=y --quiet=n file1 file2 file3
1721791604SMichael Walsh"""
1821791604SMichael Walsh
1921791604SMichael Walshimport sys
2021791604SMichael Walshimport os
2121791604SMichael Walsh
2221791604SMichael Walshsave_path_0 = sys.path[0]
2321791604SMichael Walshdel sys.path[0]
2421791604SMichael Walsh
2521791604SMichael Walshfrom gen_arg import *
2621791604SMichael Walshfrom gen_print import *
2721791604SMichael Walshfrom gen_valid import *
2821791604SMichael Walshfrom gen_misc import *
2921791604SMichael Walshfrom gen_cmd import *
3021791604SMichael Walsh
3121791604SMichael Walsh# Restore sys.path[0].
3221791604SMichael Walshsys.path.insert(0, save_path_0)
3321791604SMichael Walsh
3421791604SMichael Walsh
3521791604SMichael Walshparser = argparse.ArgumentParser(
3621791604SMichael Walsh    usage='%(prog)s [OPTIONS]',
37004ad3c9SJoy Onyerikwu    description="%(prog)s will call a program using parameters retrieved"
38004ad3c9SJoy Onyerikwu    + " from the given properties file.",
3921791604SMichael Walsh    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
4021791604SMichael Walsh    prefix_chars='-+')
4121791604SMichael Walsh
4221791604SMichael Walshparser.add_argument(
4321791604SMichael Walsh    '--prop_dir_path',
4421791604SMichael Walsh    default=os.environ.get("PROP_DIR_PATH", os.getcwd()),
45004ad3c9SJoy Onyerikwu    help='The path to the directory that contains the properties file.'
46004ad3c9SJoy Onyerikwu    + '  The default value is environment variable "PROP_DIR_PATH", if'
47004ad3c9SJoy Onyerikwu    + ' set.  Otherwise, it is the current working directory.')
4821791604SMichael Walsh
4921791604SMichael Walshparser.add_argument(
5021791604SMichael Walsh    '--prop_file_name',
51004ad3c9SJoy Onyerikwu    help='The path to a properties file that contains the parameters to'
52004ad3c9SJoy Onyerikwu    + ' pass to the program.  If the properties file has a ".properties"'
53004ad3c9SJoy Onyerikwu    + ' extension, the caller need not specify the extension.  The format'
54004ad3c9SJoy Onyerikwu    + ' of each line in the properties file should be as follows:'
55004ad3c9SJoy Onyerikwu    + ' <parm_name=parm_value>.  Do not quote the parm value.  To specify'
56004ad3c9SJoy Onyerikwu    + ' positional parms, use a parm name of "pos".  For example: pos=this'
5721791604SMichael Walsh    ' value')
5821791604SMichael Walsh
5921791604SMichael Walshparser.add_argument(
6021791604SMichael Walsh    'program_name',
6121791604SMichael Walsh    help='The name of the program to be run.')
6221791604SMichael Walsh
6321791604SMichael Walsh# Populate stock_list with options we want.
6421791604SMichael Walshstock_list = [("test_mode", 0), ("quiet", 1), ("debug", 0)]
6521791604SMichael Walsh
6621791604SMichael Walsh
6721791604SMichael Walshdef exit_function(signal_number=0,
6821791604SMichael Walsh                  frame=None):
6921791604SMichael Walsh    r"""
70*410b1787SMichael Walsh    Execute whenever the program ends normally or with the signals that we catch (i.e. TERM, INT).
7121791604SMichael Walsh    """
7221791604SMichael Walsh
7321791604SMichael Walsh    dprint_executing()
7421791604SMichael Walsh    dprint_var(signal_number)
7521791604SMichael Walsh
7621791604SMichael Walsh    qprint_pgm_footer()
7721791604SMichael Walsh
7821791604SMichael Walsh
7921791604SMichael Walshdef signal_handler(signal_number,
8021791604SMichael Walsh                   frame):
8121791604SMichael Walsh    r"""
82*410b1787SMichael Walsh    Handle signals.  Without a function to catch a SIGTERM or SIGINT, our program would terminate immediately
83*410b1787SMichael Walsh    with return code 143 and without calling our exit_function.
8421791604SMichael Walsh    """
8521791604SMichael Walsh
86*410b1787SMichael Walsh    # Our convention is to set up exit_function with atexit.register() so there is no need to explicitly
87*410b1787SMichael Walsh    # call exit_function from here.
8821791604SMichael Walsh
8921791604SMichael Walsh    dprint_executing()
9021791604SMichael Walsh
91*410b1787SMichael Walsh    # Calling exit prevents us from returning to the code that was running when we received the signal.
9221791604SMichael Walsh    exit(0)
9321791604SMichael Walsh
9421791604SMichael Walsh
9521791604SMichael Walshdef validate_parms():
9621791604SMichael Walsh    r"""
97*410b1787SMichael Walsh    Validate program parameters, etc.  Return True or False (i.e. pass/fail) accordingly.
9821791604SMichael Walsh    """
9921791604SMichael Walsh
10021791604SMichael Walsh    global prop_dir_path
10121791604SMichael Walsh    global prop_file_path
10221791604SMichael Walsh
10321791604SMichael Walsh    if not valid_dir_path(prop_dir_path):
10421791604SMichael Walsh        return False
10521791604SMichael Walsh    prop_dir_path = add_trailing_slash(prop_dir_path)
10621791604SMichael Walsh
10721791604SMichael Walsh    if not valid_value(prop_file_name):
10821791604SMichael Walsh        return False
10921791604SMichael Walsh
11021791604SMichael Walsh    prop_file_path = prop_dir_path + prop_file_name
11121791604SMichael Walsh
11221791604SMichael Walsh    # If properties file is not found, try adding ".properties" extension.
11321791604SMichael Walsh    if not os.path.isfile(prop_file_path):
11421791604SMichael Walsh        alt_prop_file_path = prop_file_path + ".properties"
11521791604SMichael Walsh        if os.path.isfile(alt_prop_file_path):
11621791604SMichael Walsh            prop_file_path = alt_prop_file_path
11721791604SMichael Walsh
11821791604SMichael Walsh    if not valid_file_path(prop_file_path):
11921791604SMichael Walsh        return False
12021791604SMichael Walsh
12121791604SMichael Walsh    if not valid_value(program_name):
12221791604SMichael Walsh        return False
12321791604SMichael Walsh
12421791604SMichael Walsh    gen_post_validation(exit_function, signal_handler)
12521791604SMichael Walsh
12621791604SMichael Walsh    return True
12721791604SMichael Walsh
12821791604SMichael Walsh
12921791604SMichael Walshdef main():
13021791604SMichael Walsh
13121791604SMichael Walsh    if not gen_get_options(parser, stock_list):
13221791604SMichael Walsh        return False
13321791604SMichael Walsh
13421791604SMichael Walsh    if not validate_parms():
13521791604SMichael Walsh        return False
13621791604SMichael Walsh
13721791604SMichael Walsh    qprint_pgm_header()
13821791604SMichael Walsh
13921791604SMichael Walsh    # Get the parameters from the properties file.
14021791604SMichael Walsh    properties = my_parm_file(prop_file_path)
14121791604SMichael Walsh    # The parms (including program name) need to go into a list.
14221791604SMichael Walsh    parms = [program_name]
14321791604SMichael Walsh    for key, value in properties.items():
14421791604SMichael Walsh        if key == "pos":
14521791604SMichael Walsh            # Process positional parm(s).
14621791604SMichael Walsh            parms.extend(value.split())
14721791604SMichael Walsh        else:
14821791604SMichael Walsh            parms.append("--" + key + "=" + escape_bash_quotes(value))
14921791604SMichael Walsh
15021791604SMichael Walsh    # parm_string is only created for display in non-quiet mode.
15121791604SMichael Walsh    parm_string = " ".join(parms[1:])
15221791604SMichael Walsh    cmd_buf = program_name + " " + parm_string
15321791604SMichael Walsh    qprint_issuing(cmd_buf)
15421791604SMichael Walsh    if not test_mode:
15521791604SMichael Walsh        os.execvp(program_name, parms)
15621791604SMichael Walsh
15721791604SMichael Walsh    return True
15821791604SMichael Walsh
15921791604SMichael Walsh
16021791604SMichael Walsh# Main
16121791604SMichael Walsh
16221791604SMichael Walshif not main():
16321791604SMichael Walsh    exit(1)
164