# SPDX-License-Identifier: AGPL-3.0-or-later # TODO: # - check if everything is filled in (computers, params, preparation) # - improve scoring # - test # - switch to a real SSH/SFTP client to properly handle filenames instructions = { 'si': '''\
Postavite dva navidezna računalnika - arbiter in student. Drugi mrežni vmesnik na arbiterju in edini vmesnik na studentu naj bosta povezana v isto lokalno omrežje.
Na računalnik student se prijavite z uporabniškim imenom student
in geslom vaje
.
Obstoječi datoteko {{P_c}}
v programskem jeziku C prevedite v program z imenom {{P_executable}}
. Izvorna koda je namenoma pokvarjena tako, da so vanjo vrinjeni nepotrebni znaki. Pred prevajanjem jo morate popraviti.
Napišite skripto {{P_script}}
, ki požene {{P_executable}}
z argumentom
"{{arg_c}}"
in
{{env_c}}
;
{{out_stderr_c}}
zapiše napake (stderr); in
{{out_stdout_c}}
zapiše tiste vrstice na standardnem izhodu (stdout), ki vsebujejo niz XYZZY
.
Poskrbite, da se bo dalo skripto pognati neposredno, torej z ukazom ./{{P_script}}
. Vse datoteke naj so v domačem imeniku uporabnika student
, ki naj bo tudi njihov lastnik.
''',
'en': '''\
Set up two virtual machines - arbiter and student. Connect arbiter’s second network interface and student’s first interface to the same local network.
Log in to student as the user student
with password vaje
.
Compile the existing C file {{P_c}}
into a program named {{P_executable}}
. The source code was intentionally corrupted by inserting extraneous characters. Before compiling you have to fix it.
Write a script called {{P_script}}
that runs {{P_executable}}
with the argument
"{{arg_c}}"
and
{{env_c}}
into {{P_executable}}
’s standard input;
stderr
into a file called {{out_stderr_c}}
; and
XYZZY
into {{out_stdout_c}}
.
Ensure that the script can be run directly, ie. ./{{P_script}}
. All files should be owned by student
and placed in that user’s home directory.
''',
}
computers = {
'arbiter': {
'disks': [{'name': 'dhcp-gw'}],
'flavor': 'm1.tiny',
'network_interfaces': [{'network': 'test-net'}, {'network': 'net1'}],
'config_drive': True,
'userdata': {'string': "#!/bin/bash\nsed -i '/cloud/d' /etc/fstab\npoweroff &\n"}
},
'student': {
'disks': [{ 'name': 'console-big'}],
'flavor': 'm1.tiny',
'network_interfaces': [{'network': 'net1'}],
'config_drive': True,
'userdata': {'string': "#!/bin/bash\nsed -i '/cloud/d' /etc/fstab\npoweroff &\n"}
}
}
networks = { 'test-net': {'public': True}, 'net1': {'public': False} }
params_meta = {
'student_IP': {
'descriptions': { 'si': 'IP naslov računalnika student', 'en': 'IP address of student',
}, 'w': True, 'public': True, 'type': 'IP', 'generated': False,
},
'P_c': {
'descriptions': { 'si': 'Datoteka s programom v C', 'en': 'Filename of the program in C',
}, 'w': False, 'public': True, 'type': 'filename', 'generated': True,
},
'P_executable': { 'descriptions': { 'si': 'Ime prevedenega programa v C', 'en': 'Filename of the compiled C program'
}, 'w': False, 'public': True, 'type': 'filename', 'generated': True,
},
'arg_c': {
'descriptions': { 'si': 'Vrednost argumenta', 'en': 'Argument value',
}, 'w': False, 'public': True, 'type': 'short_text', 'generated': True,
},
'env_c': {
'descriptions': { 'si': 'Ime okoljske spremenljivke', 'en': 'The name of the environment environment',
}, 'w': False, 'public': True, 'type': 'short_text', 'generated': True,
},
'out_stderr_c': {
'descriptions': { 'si': 'Datoteka z napakami', 'en': 'File to store errors',
}, 'w': False, 'public': True, 'type': 'filename', 'generated': True,
},
'P_script': {
'descriptions': { 'si': 'Ime skripte', 'en': 'Filename of the script',
}, 'w': False, 'public': True, 'type': 'filename', 'generated': True,
},
'out_stdout_c': {
'descriptions': { 'si': 'Datoteka z izhodom', 'en': 'File to store the output',
}, 'w': False, 'public': True, 'type': 'filename', 'generated': True,
},
'param_gen_seed': {
'descriptions': { 'si': 'Nakljucno seme', 'en': 'Random seed',
}, 'w': False, 'public': True, 'type': None, 'generated': True,
},
'c_destroy_gen_seed': {
'descriptions': { 'si': 'Nakljucno seme za kvarjenje kode v C', 'en': 'Random seed for destroying the C code',
}, 'w': False, 'public': False, 'type': None, 'generated': True,
}
}
def task(student_IP,
P_c, P_executable, arg_c, env_c, out_stderr_c, out_stdout_c, P_script,
param_gen_seed):
import random
r = random.Random(int(param_gen_seed))
env_val = "".join([r.choice('ABCDEFGHJKLMNPRSTUVZ012345') for i in range(11)])
arg_val = "".join([r.choice('ABCDEFGHJKLMNPRSTUVZ012345') for i in range(13)])
stdin_val = "".join([r.choice('ABCDEFGHJKLMNPRSTUVZ012345') for i in range(17)])
return kpov_util.ssh_test(student_IP, 'student', 'vaje', (
('script_ls', 'ls -l ./{}'.format(P_script)),
('executable_ls', 'ls -l ./{}'.format(P_executable)),
('script_run', 'export {}={}; ./{}'.format(env_c, env_val, P_script)),
('script_stderr', 'cat {}'.format(out_stderr_c)),
('script_stdout', 'cat {}'.format(out_stdout_c)),
('prog_stdout', 'echo "{}" | ./{} "{}" 2> /dev/null'.format(stdin_val, P_executable, arg_val)),
('prog_stderr', 'echo "{}" | ./{} "{}" > /dev/null'.format(stdin_val, P_executable, arg_val)),
))
def gen_params(user_id, params_meta):
import random
r = random.Random(user_id+'evil cornholio')
params = kpov_util.default_gen(user_id, params_meta)
params['env_c'] = "".join([r.choice('ABCDEFGHIJKLMNPRSTUVZ') for i in range(5)])
params['P_c'] = "".join([r.choice('abcdefghijklmnoprst') for i in range(5)]) + ".c"
params['param_gen_seed'] = str(r.randint(0, 2**24))
params['c_destroy_gen_seed'] = str(r.randint(0, 2**24))
return params
def task_check(results, params):
def test_out_gen(arg, env):
s_out = ""
s_err = ""
for i in range(30):
s = '{}{}\n'.format(
('XYZZY' if i%5 == 0 else ''),
(env if i%2 == 0 else arg))
if i%3 == 0:
s_err += s
else:
s_out += s
return (s_out.strip(), s_err.strip(), len(env))
score = 0
hints = []
if results['ssh'] is not True:
hints += ['ssh failed: ' + results['ssh']]
return score, hints
r = random.Random(int(params['param_gen_seed']))
env_val = "".join([r.choice('ABCDEFGHJKLMNPRSTUVZ012345') for i in range(11)])
arg_val = "".join([r.choice('ABCDEFGHJKLMNPRSTUVZ012345') for i in range(13)])
stdin_val = "".join([r.choice('ABCDEFGHJKLMNPRSTUVZ012345') for i in range(17)])
expected_script_stdout, expected_script_stderr, rval = test_out_gen(
params['arg_c'], env_val)
if expected_script_stderr != results['script_stderr']:
hints += ['wrong script stderr']
else:
score += 2
split_stdout = expected_script_stdout.split('\n')
expected_script_stdout = '\n'.join([ i for i in split_stdout if i.find('XYZZY') >= 0])
if expected_script_stdout != results['script_stdout']:
hints += ['wrong script stdout']
else:
score += 2
expected_prog_stdout, expected_prog_stderr, rval = test_out_gen(arg_val, stdin_val)
if expected_prog_stderr != results['prog_stderr']:
hints += ['wrong program stderr']
else:
score += 2
if expected_prog_stdout != results['prog_stdout']:
hints += ['wrong program stdout']
else:
score += 2
if results['script_ls'].find('-r') < 0:
hints += ['script not found']
else:
score += 1
if results['executable_ls'].find('xr') < 0:
hints += ['C executable not found']
else:
score += 1
return score, hints
def prepare_disks(templates, task_params, global_params):
c_source = '''#include