~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/interpret.py

Modified the database so that exercises are now stored in the database, rather
than in flat files.

This also necessitated adding new tables and storm classes for test suites
and test cases.

Note that this commit merely changes the database and adds a script to
upload exercises. The code for actually reading exercises has yet
to be changed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
# Runs a student script in a safe execution environment.
23
23
 
24
24
from ivle import studpath
25
 
from ivle import db
26
25
from ivle.util import IVLEError, IVLEJailError
27
26
import ivle.conf
28
27
 
39
38
 
40
39
CGI_BLOCK_SIZE = 65535
41
40
 
42
 
uids = {}
43
 
 
44
 
def get_uid(login):
45
 
    """Get the unix uid corresponding to the given login name.
46
 
       If it is not in the dictionary of uids, then consult the
47
 
       database and retrieve an update of the user table."""
48
 
    global uids
49
 
    if login in uids:
50
 
        return uids[login]
51
 
 
52
 
    conn = db.DB()
53
 
    res = conn.get_all('login', ['login', 'unixid'])
54
 
    def repack(flds):
55
 
        return (flds['login'], flds['unixid'])
56
 
    uids = dict(map(repack,res))
57
 
 
58
 
    return uids[login]
59
 
 
60
41
def interpret_file(req, owner, jail_dir, filename, interpreter, gentle=True):
61
42
    """Serves a file by interpreting it using one of IVLE's builtin
62
43
    interpreters. All interpreters are intended to run in the user's jail. The
64
45
    to the individual interpreters to create the jail.
65
46
 
66
47
    req: An IVLE request object.
67
 
    owner: Username of the user who owns the file being served.
 
48
    owner: The user who owns the file being served.
68
49
    jail_dir: Absolute path to the user's jail.
69
50
    filename: Absolute filename within the user's jail.
70
51
    interpreter: A function object to call.
79
60
        filename_abs = os.path.join(os.sep, filename)
80
61
        filename_rel = filename
81
62
 
82
 
    # Get the UID of the owner of the file
83
63
    # (Note: files are executed by their owners, not the logged in user.
84
64
    # This ensures users are responsible for their own programs and also
85
65
    # allows them to be executed by the public).
86
 
    uid = get_uid(owner)
87
66
 
88
67
    # Split up req.path again, this time with respect to the jail
89
68
    (working_dir, _) = os.path.split(filename_abs)
94
73
    # (Note that paths "relative" to the jail actually begin with a '/' as
95
74
    # they are absolute in the jailspace)
96
75
 
97
 
    return interpreter(uid, jail_dir, working_dir, filename_abs, req,
 
76
    return interpreter(owner.unixid, jail_dir, working_dir, filename_abs, req,
98
77
                       gentle)
99
78
 
100
79
class CGIFlags:
431
410
    # Additional environment variables
432
411
    username = studpath.url_to_jailpaths(req.path)[0]
433
412
    env['HOME'] = os.path.join('/home', username)
 
413
 
 
414
class ExecutionError(Exception):
 
415
    pass
 
416
 
 
417
def execute_raw(user, jail_dir, working_dir, binary, args):
 
418
    '''Execute a binary in a user's jail, returning the raw output.
 
419
 
 
420
    The binary is executed in the given working directory with the given
 
421
    args. A tuple of (stdout, stderr) is returned.
 
422
    '''
 
423
 
 
424
    tramp = location_cgi_python
 
425
    tramp_dir = os.path.split(location_cgi_python)[0]
 
426
 
 
427
    # Fire up trampoline. Vroom, vroom.
 
428
    proc = subprocess.Popen(
 
429
        [tramp, str(user.unixid), jail_dir, working_dir, binary] + args,
 
430
        stdin=subprocess.PIPE, stdout=subprocess.PIPE,
 
431
        stderr=subprocess.PIPE, cwd=tramp_dir, close_fds=True)
 
432
    exitcode = proc.wait()
 
433
 
 
434
    if exitcode != 0:
 
435
        raise ExecutionError('subprocess ended with code %d, stderr %s' %
 
436
                             (exitcode, proc.stderr.read()))
 
437
    return (proc.stdout.read(), proc.stderr.read())