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
00049 def main():
00050 from optparse import OptionParser
00051 parser = OptionParser(prog = "env",
00052 usage = "Usage: %prog [OPTION]... [NAME=VALUE]... [COMMAND [ARG]...]",
00053 description = "Set each NAME to VALUE in the environment and run COMMAND.",
00054 epilog = "The operations are performed in the order: unset, set, append, "
00055 "prepend. If no COMMAND, print the resulting environment." )
00056 parser.add_option("-i", "--ignore-environment",
00057 action = "store_true",
00058 help = "start with an empty environment")
00059 parser.add_option("-u", "--unset",
00060 metavar = "NAME",
00061 action = "append",
00062 help = "remove variable from the environment")
00063 parser.add_option("-s", "--set",
00064 metavar = "NAME=VALUE",
00065 action = "append",
00066 help = "set the variable NAME to VALUE")
00067 parser.add_option("-a", "--append",
00068 metavar = "NAME=VALUE",
00069 action = "append",
00070 help = "append VALUE to the variable NAME (with a '%s' as separator)" % os.pathsep)
00071 parser.add_option("-p", "--prepend",
00072 metavar = "NAME=VALUE",
00073 action = "append",
00074 help = "prepend VALUE to the variable NAME (with a '%s' as separator)" % os.pathsep)
00075 parser.add_option("-x", "--xml",
00076 action = "append",
00077 help = "XML file describing the changes to the environment")
00078 parser.disable_interspersed_args()
00079 parser.set_defaults(unset = [],
00080 set = [],
00081 append = [],
00082 prepend = [],
00083 xml = [],
00084 ignore_environment = False)
00085
00086 opts, args = parser.parse_args()
00087
00088
00089 i = 0
00090 argc = len(args)
00091 while (i < argc) and ("=" in args[i]):
00092 i += 1
00093 opts.set.extend(args[:i])
00094 cmd = args[i:]
00095
00096
00097 if opts.ignore_environment:
00098 env = {}
00099 else:
00100 env = dict(os.environ)
00101
00102 if opts.xml:
00103 from EnvConfig import Control
00104 control = Control.Environment()
00105
00106 for v in env:
00107 control.declare(v, ("PATH" in v or "DIRS" in v) and "list" or "scalar", False)
00108 for k in env:
00109 control.set(k, env[k])
00110
00111 for f in opts.xml:
00112 control.loadXML(f)
00113 env = control.vars()
00114
00115 env = set_env(env,
00116 set = opts.set, unset = opts.unset,
00117 append = opts.append, prepend = opts.prepend)
00118
00119 if not cmd:
00120 for nv in env.items():
00121 print "%s=%s" % nv
00122 return 0
00123 else:
00124 from subprocess import Popen
00125 return Popen(cmd, env = env).wait()
00126
00127 if __name__ == "__main__":
00128 import sys
00129 sys.exit(main())