diff options
Diffstat (limited to 'bin/rainbow-run')
-rwxr-xr-x | bin/rainbow-run | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/bin/rainbow-run b/bin/rainbow-run new file mode 100755 index 0000000..3ce2590 --- /dev/null +++ b/bin/rainbow-run @@ -0,0 +1,142 @@ +#!/usr/bin/env python + +import os +import sys +import pwd +import grp + +from stat import S_ISREG, ST_MODE +from os.path import join, isdir +from optparse import OptionParser +from pprint import pformat + +from rainbow.inject import inject +from rainbow.permissions import PermissionSet +from rainbow.util import make_reporter, trace, unshare, CLONE_NEWNS, read_envdir + +sys.excepthook = trace + +def main(): + parser = OptionParser(version='0.1') + parser.add_option('-v', '--verbose', default=0, action='count', + help='Verbosity. Repeat for more verbose output.') + parser.add_option('-q', '--quiet', default=False, action='store_true', + help='Quiet. Disable all output.') + parser.add_option('-s', '--spool', default=None, + help='Location of the rainbow spool.') + parser.add_option('-e', '--envdir', default=None, + help="Location of an envdir describing the desired environment.") + parser.add_option('-E', '--env', default=[], action='append', + help="Environment bindings to override.") + parser.add_option('-c', '--cwd', default=None, + help="Working directory.") + parser.add_option('-f', '--fd', default=[], action='append', + help="File descriptor number to leave open.") + parser.add_option('-i', '--id', default=[], action='append', + help="ID of shared-data group.") + parser.add_option('-o', '--option', default=[], action='append', + help="Options: video, audio, serial, constant-uid, xephyr, network.") + parser.add_option('-p', '--permissions', default=None, + help="Location of a permissions.info file.") + parser.add_option('-u', '--user', default=None, + help="Owning user.") + parser.add_option('-r', '--resume-user', default=None, + help="Resume <user>.") + parser.add_option('-a', '--assistant', default=None, + help="Task-specific assistant.") + parser.add_option('-G', '--group', default=[], action='append', + help="Extra groups.") + opts, args = parser.parse_args() + if len(args) == 0: + parser.print_help() + exit(1) + + report = make_reporter(opts.verbose, opts.quiet, sys.stdout) + + def check_spool(opts): + return opts.spool + + def check_env(opts): + return read_envdir(opts.envdir, opts.env) + + def check_argv(args): + return args + + def check_cwd(opts): + return opts.cwd + + def check_fds(opts): + return [int(s) for s in opts.fd] + + def check_owner(opts): + p = pwd.getpwnam(opts.user) + return p.pw_uid, p.pw_gid + + def check_groups(opts): + return [grp.getgrnam(g)[2] for g in opts.group] + + def check_xephyr(opts): + return 'xephyr' in opts.option + + def check_constant_uid(opts): + return 'constant-uid' in opts.option + + def check_audio(opts): + return 'audio' in opts.option + + def check_video(opts): + return 'video' in opts.option + + def check_serial(opts): + return 'serial' in opts.option + + def check_network(opts): + return 'network' in opts.option + + def check_resume_user(opts): + uid = None + if opts.resume_user: + uid = pwd.getpwnam(opts.resume_user).pw_uid + assert 10000 <= uid and uid < 60000 + return uid + + def check_data_ids(opts): + return opts.id + + def check_assistant(opts): + return opts.assistant + + uid, gid = check_owner(opts) + spool = check_spool(opts) + + # Use empty env? Use partial env? Fail unless perfect? + env = check_env(opts) + argv = check_argv(args) + cwd = check_cwd(opts) + + safe_fds = check_fds(opts) + + groups = check_groups(opts) + pset = PermissionSet(opts.permissions or []) + + # Dirty hack -- pass 'constant-uid' and 'strace' in as permissions. <MS> + for perm in ('constant-uid', 'audio', 'video', 'serial', 'network'): + pset._permissions.setdefault(perm, locals()['check_'+perm.replace('-','_')](opts)) + + data_ids = check_data_ids(opts) + assistant = check_assistant(opts) + xephyr = check_xephyr(opts) + + resume_uid = check_resume_user(opts) + if resume_uid: report(1, "resuming uid (%d)", resume_uid) + + args = (report, spool, env, argv, cwd, pset, safe_fds, uid, gid, resume_uid, groups, data_ids, assistant, xephyr) + report(1, 'rainbow:\n%s', pformat(args)) + + unshare(CLONE_NEWNS) + return inject(*args) + +if __name__ == '__main__': + main() + +# vim : et sw=4 ts=4 sts=4 : |