00001
00002 """
00003 Small script to execute a command in a modified environment (see man 1 env).
00004 """
00005 import os
00006
00007 def set_env(env, set = [], unset = [], append = [], prepend = []):
00008 """
00009 Manipulate the dictionary-like object 'env' according to the prescriptions in
00010 the lists 'unset', 'set', 'append' and 'prepend' (in this order).
00011 The lists must contain strings of the format 'NAME=VALUE' except for 'unset'
00012 which requires only 'NAME'.
00013 """
00014 def parse(x):
00015 """split the "NAME=VALUE" string into the tuple ("NAME", "VALUE")
00016 replacing '[:]' with os.pathsep in VALUE"""
00017 n, v = x.split('=', 1)
00018 return n, v.replace('[:]', os.pathsep)
00019 def dictlist(l):
00020 """create a dictionary from the list of pairs by appending to lists"""
00021 d = {}
00022 for n, v in l:
00023 if n in d:
00024 d[n].append(v)
00025 else:
00026 d[n] = [v]
00027 return d
00028
00029 for n in unset:
00030 if n in env:
00031 log.debug("unset %s", n)
00032 del env[n]
00033
00034 env.update(map(parse, set))
00035
00036 for n, v in dictlist(map(parse, append)).items():
00037 if n in env:
00038 v.insert(0, env[n])
00039 env[n] = os.pathsep.join(v)
00040
00041 for n, v in dictlist(map(parse, reversed(prepend))).items():
00042 if n in env:
00043 v.append(env[n])
00044 env[n] = os.pathsep.join(v)
00045
00046 return env
00047
00048 def parse_args():
00049 from optparse import OptionParser
00050 parser = OptionParser(prog = "env",
00051 usage = "Usage: %prog [OPTION]... [NAME=VALUE]... [COMMAND [ARG]...]",
00052 description = "Set each NAME to VALUE in the environment and run COMMAND.",
00053 epilog = "The operations are performed in the order: unset, set, append, "
00054 "prepend. If no COMMAND, print the resulting environment." )
00055 parser.add_option("-i", "--ignore-environment",
00056 action = "store_true",
00057 help = "start with an empty environment")
00058 parser.add_option("-u", "--unset",
00059 metavar = "NAME",
00060 action = "append",
00061 help = "remove variable from the environment")
00062 parser.add_option("-s", "--set",
00063 metavar = "NAME=VALUE",
00064 action = "append",
00065 help = "set the variable NAME to VALUE")
00066 parser.add_option("-a", "--append",
00067 metavar = "NAME=VALUE",
00068 action = "append",
00069 help = "append VALUE to the variable NAME (with a '%s' as separator)" % os.pathsep)
00070 parser.add_option("-p", "--prepend",
00071 metavar = "NAME=VALUE",
00072 action = "append",
00073 help = "prepend VALUE to the variable NAME (with a '%s' as separator)" % os.pathsep)
00074 parser.add_option("-x", "--xml",
00075 action = "append",
00076 help = "XML file describing the changes to the environment")
00077 parser.disable_interspersed_args()
00078 parser.set_defaults(unset = [],
00079 set = [],
00080 append = [],
00081 prepend = [],
00082 xml = [],
00083 ignore_environment = False)
00084
00085 return parser.parse_args()
00086
00087 def envFromXML(env, xmlfiles):
00088 '''
00089 Extend the environment declared in the dictionary env with the actions
00090 in the XML files specified in the list 'xmlfiles'.
00091 '''
00092 from EnvConfig import Control
00093 control = Control.Environment()
00094
00095 for k, v in env.items():
00096 if 'PATH' in k or 'DIRS' in k:
00097 t = 'list'
00098 else:
00099 t = 'scalar'
00100 control.declare(k, t, False)
00101 control.set(k, v)
00102
00103 for f in xmlfiles:
00104 control.loadXML(f)
00105
00106 return control.vars()
00107
00108 def main():
00109 opts, args = parse_args()
00110
00111
00112 i = 0
00113 argc = len(args)
00114 while (i < argc) and ("=" in args[i]):
00115 i += 1
00116 opts.set.extend(args[:i])
00117 cmd = args[i:]
00118
00119
00120 if opts.ignore_environment:
00121 env = {}
00122 else:
00123 env = dict(os.environ)
00124
00125 if opts.xml:
00126 env = envFromXML(env, opts.xml)
00127
00128 env = set_env(env,
00129 set = opts.set, unset = opts.unset,
00130 append = opts.append, prepend = opts.prepend)
00131 if sys.platform.startswith("win"):
00132 env["PATH"] = env["PATH"] + os.pathsep + env["LD_LIBRARY_PATH"]
00133 elif sys.platform.startswith("darwin"):
00134 if "DYLD_LIBRARY_PATH" in env:
00135 env["DYLD_LIBRARY_PATH"] = env["DYLD_LIBRARY_PATH"] + os.pathsep + env["LD_LIBRARY_PATH"]
00136 else:
00137 env["DYLD_LIBRARY_PATH"] = env["LD_LIBRARY_PATH"]
00138
00139
00140 if not cmd:
00141 for nv in env.items():
00142 print "%s=%s" % nv
00143 return 0
00144 else:
00145 from subprocess import Popen
00146 return Popen(cmd, env=env).wait()
00147
00148 if __name__ == "__main__":
00149 import sys
00150 sys.exit(main())