#!/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=None,
                      help="ID of shared-data group.")
    parser.add_option('-o', '--option', default=[], action='append',
                      help="Options: video, audio, serial, constant-uid, strace.")
    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('-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, home):
        return opts.spool or join(pwd.getpwnam('rainbow').pw_dir, 'spool-2')

    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, p.pw_dir

    def check_groups(opts):
        return [grp.getgrnam(g)[2] for g in opts.group]

    def check_strace(opts):
        return 'strace' 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_data_id(opts):
        return opts.id

    def check_assistant(opts):
        return opts.assistant

    uid, gid, home = check_owner(opts)
    spool = check_spool(opts, home)

    # 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', 'strace', 'audio', 'video', 'serial'):
        pset._permissions.setdefault(perm, locals()['check_'+perm.replace('-','_')](opts))

    data_id = check_data_id(opts)
    assistant = check_assistant(opts)

    args = (report, spool, env, argv, cwd, pset, safe_fds, uid, gid, groups, data_id, assistant)
    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 :
