#!/usr/bin/env python3
# This phase of the installer attempts to build the RunGuard program that
# allows use of the RunguardSandbox to execute student jobs on this Moodle
# server. Do not run this until you have read the documentation on use
# and limitations of the Runguard sandbox.

import os
import subprocess


def printFailMessage():
    print("Runguard installation failed. ")
    print("Perhaps you weren't running the installer as root? You have to be ")
    print("root to make runguard a 'setuid root' program, so that it can ")
    print("run the student program as the coderunner user, thereby stopping it ")
    print("from reading the various private files that the webserver user can ")
    print("access.")
    print()
    print("If you intend to use the Runguard sandbox, you should 'cd' to the ")
    print("<moodlehome>/question/type/coderunner/sandbox directory and type the commands:\n")
    print("    make runguard")
    print("    sudo chown root runguard")
    print("    sudo chgrp <webserverUser> runguard")
    print("    sudo chmod 4750 runguard\n")
    print("where <webserverUser> is the user ID under which Apache runs")
    print("(usually either www-data or apache)")



def get_webserver():
    return 'www-data'
    '''Find the user name used to run the Apache web server'''
    '''ps_cmd = 'ps aux | egrep "(/usr/sbin/apache2)|(/usr/sbin/httpd)"'
    ps_lines = subprocess.check_output(ps_cmd, shell=True).decode('utf8').split('\n')
    names = set([ps_line.split(' ')[0] for ps_line in ps_lines])
    candidates = names.intersection(set(['apache', 'www-data']))
    if len(candidates) != 1:
        raise Exception("Couldn't determine web-server user id. Is the web server running?")
    return list(candidates)[0]'''


def do_command(cmd):
    '''Execute the given OS command user subprocess.call.
       Raise an exception on failure.
    '''
    if subprocess.call(cmd, shell=True) != 0:
        raise OSError("Command ({}) failed".format(cmd))


def install():
    if subprocess.check_output('whoami', shell=True) != b'root\n':
        print("****This script must be run by root*****")
        printFailMessage()
    else:
        if os.path.exists('/var/www/html/moodle/question'):
            moodlehome = '/var/www/html/moodle/question'
        elif os.path.exists('/var/www/moodle/question'):
            moodlehome = '/var/www/moodle/question'
        else:
            raise Exception('<moodlehome> not found in either of the expected places')
        try:
            webserver_user = get_webserver()
            print("Web server is", webserver_user)
            username = 'coderunner'
            try:
                do_command('id ' + username + '> /dev/null 2>&1')
                print('User ' + username + ' already exists')
            except:
                do_command('useradd -M -s "/bin/false" ' + username)

            commands = [
                "cd {0}/type/coderunner/sandbox".format(moodlehome),
                "gcc -o runguard runguard.c", # Add -lcgroups  if using cgroups
                "chown root runguard",
                "chgrp {0} runguard".format(webserver_user),
                "chmod 4750 runguard"
            ]
            cmd = ';'.join(commands)
            if subprocess.call(cmd, shell=True) != 0:
                raise OSError("Command ({}) failed".format(cmd))
            print("Runguard installation complete")
        except Exception as e:
            print("Exception when setting up runguard: " + str(e))
            printFailMessage()

def main():
    print ("Installing the RunGuard sandbox...")
    print("NOTE: The RunGuard sandbox is deprecated in favour of the JobeSandbox, which")
    print("can be installed on the Moodle server directly if you want to use just")
    print("a single machine (though that's not the preferred approach).")
    install()
'''
    prompt = "Proceed (Y/N)?"
    line = input(prompt)
    while (line[0].lower() not in ['y', 'n']):
        print("Please respond with yes or no")
        print(prompt)
    if line[0].lower() != 'y':
        print("RunGuard installation aborted")
'''

main()
