Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/bin/rainbow-run
blob: 3ce2590d7e3a8d2dae0322c56c4e6494e7f35f8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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 :