#!/usr/bin/python3
import argparse
import gettext
import os
import pwd
import sys

_ = gettext.gettext
gettext.textdomain("arkose")

currentdir = os.path.split(os.path.realpath(__file__))[0]
if os.path.exists(os.path.join(currentdir, "../arkose/__init__.py")):
    sys.path.insert(0, os.path.join(currentdir, ".."))

import arkose

default_xserver = "direct"
if not 'DISPLAY' in os.environ:
    default_xserver = "none"

# Get all the parameters
parser = argparse.ArgumentParser(description=_("Arkose application container"),
                                 add_help=False,
                                 formatter_class=argparse.RawTextHelpFormatter,
                                 epilog=_("For X to work on >= 2.6.36, "
                                          "you need one of -n (network) or "
                                          "-T (real /tmp)."
                                          """
For older versions of the kernel, only -n (network) will work."""))

# Simple on/off options
parser.add_argument("--help", action="store_true")

parser.add_argument("-h", "--home", dest="home", action="store_true",
                    help=_("Use real home directory (same as --bind $HOME)"))

parser.add_argument("-p", "--pulseaudio", dest="pulseaudio",
                    action="store_true", help=_("Allow access to pulseaudio"))

# Multiple choices options

parser.add_argument("-d", "--dbus", dest="dbus", type=str,
                    choices=("none", "system", "session", "both"),
                    default="none", help=_("DBUS access restriction "
                                           "(default: both)"))

parser.add_argument("-n", "--network", dest="network", type=str,
                    choices=("none", "direct", "filtered"), default="direct",
                    help=_("Network access restriction (default: direct)"))

parser.add_argument("-s", "--size", dest="size", type=int,
                    default=None, nargs=1,
                    help=_("""Storage size in MB
(default: 2000 on ext4, 50%% of RAM on tmpfs)"""))

parser.add_argument("-t", "--type", dest="type", type=str,
                    choices=("ext4", "tmpfs"), default="ext4",
                    help=_("Storage type. (default: ext4)"))

parser.add_argument("-x", "--xserver", dest="xserver", type=str,
                    choices=("none", "isolated", "direct"),
                    default=default_xserver,
                    help=_("Xserver access restriction (default: direct)"))

parser.add_argument("--root", dest="root", type=str, default="/",
                    help=_("Path to use as root for the container "
                           "(default: /)"))

parser.add_argument("--root-type", dest="ctype", type=str,
                    choices=("cow", "bind"), default="cow",
                    help=_("Type of root device mount (default: cow)"))

parser.add_argument("--base-path", dest="path", type=str, default=None,
                    help=_("Where to store the container "
                           "(default: ~/.arkose)"))

# Mount related options (all these can be called multiple times)

parser.add_argument("--bind", dest="bind", type=str,
                    default=[], action='append',
                    help=_("""Add a bind mount to the container.
(allowed multiple times)"""))

parser.add_argument("--cow", dest="cow", type=str,
                    default=[], action='append',
                    help=_("""Add a copy-on-write mount to the container.
(allowed multiple times)"""))

parser.add_argument("--restrict", dest="restrict", type=str,
                    default=[], action='append',
                    help=_("""Mount an empty directory on the given path.
(allowed multiple times)"""))

# Similar but for devices

parser.add_argument("--device", dest="device", type=str,
                    default=[], action='append',
                    help=_("""Allow access to an existing device in /dev
(allowed multiple times)"""))

# Final catch-all
parser.add_argument("command", metavar='CMD', type=str,
                    default=["bash"], nargs="*",
                    help=_("Run specific command in container "
                           "(command as argument)"))

args = parser.parse_args()
if args.help:
    parser.print_help()
    sys.exit(0)

if not os.geteuid() == 0:
    print(_("You must be root to use this command"))
    sys.exit(1)

# Start the container
if args.home:
    args.bind.append(os.getenv("HOME"))
    if 'XDG_RUNTIME_DIR' in os.environ:
        args.bind.append(os.environ['XDG_RUNTIME_DIR'])
if args.size:
    args.size = args.size[0]

# Get the current user
user = pwd.getpwuid(int(os.getenv(
    "PKEXEC_UID", os.getenv("SUDO_UID", os.getenv("UID", os.geteuid())))))

container = arkose.ArkoseContainer(
    pulseaudio=args.pulseaudio,
    dbus=args.dbus,
    network=args.network,
    fssize=args.size,
    fstype=args.type,
    xserver=args.xserver,
    root=args.root,
    ctype=args.ctype,
    path=args.path,
    bind=args.bind,
    cow=args.cow,
    restrict=args.restrict,
    devices=args.device
)
container.run_command(
    "su %s -c \"%s\"" % (user.pw_name, " ".join(args.command)))
container.cleanup()
