rbx.cp 0.5.73__py3-none-any.whl → 0.6.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rbx/annotations.py +21 -1
- rbx/box/cd.py +11 -1
- rbx/box/checkers.py +9 -1
- rbx/box/cli.py +59 -46
- rbx/box/code.py +142 -3
- rbx/box/contest/build_contest_statements.py +44 -34
- rbx/box/contest/contest_package.py +4 -7
- rbx/box/contest/main.py +7 -58
- rbx/box/contest/schema.py +52 -8
- rbx/box/contest/statements.py +53 -25
- rbx/box/creation.py +3 -36
- rbx/box/environment.py +21 -9
- rbx/box/fields.py +35 -0
- rbx/box/lang.py +27 -0
- rbx/box/linting.py +26 -0
- rbx/box/package.py +4 -35
- rbx/box/packaging/boca/packager.py +48 -5
- rbx/box/packaging/contest_main.py +13 -0
- rbx/box/packaging/main.py +13 -2
- rbx/box/packaging/packager.py +4 -4
- rbx/box/packaging/pkg/packager.py +142 -0
- rbx/box/packaging/polygon/packager.py +2 -24
- rbx/box/packaging/polygon/upload.py +35 -17
- rbx/box/presets/__init__.py +362 -281
- rbx/box/presets/lock_schema.py +1 -2
- rbx/box/presets/schema.py +13 -5
- rbx/box/remote.py +2 -2
- rbx/box/retries.py +8 -0
- rbx/box/schema.py +82 -19
- rbx/box/solutions.py +77 -15
- rbx/box/statements/build_statements.py +44 -27
- rbx/box/statements/builders.py +18 -10
- rbx/box/statements/expander.py +49 -0
- rbx/box/statements/latex_jinja.py +61 -4
- rbx/box/statements/schema.py +33 -9
- rbx/box/stats.py +92 -0
- rbx/box/tasks.py +6 -3
- rbx/box/testcase_utils.py +19 -47
- rbx/box/tooling/__init__.py +0 -0
- rbx/box/tooling/boca/__init__.py +0 -0
- rbx/box/tooling/boca/main.py +13 -0
- rbx/box/tooling/boca/scrape.py +34 -0
- rbx/box/{packaging/boca/upload.py → tooling/boca/scraper.py} +77 -8
- rbx/box/tooling/main.py +8 -0
- rbx/box/ui/utils/run_ui.py +1 -1
- rbx/box/ui/widgets/interaction_box.py +19 -1
- rbx/grading/caching.py +18 -2
- rbx/grading/judge/sandbox.py +60 -5
- rbx/grading/judge/sandboxes/isolate.py +1 -0
- rbx/grading/judge/sandboxes/stupid_sandbox.py +11 -5
- rbx/grading/judge/sandboxes/timeit.py +36 -15
- rbx/grading/processing_context.py +62 -78
- rbx/grading/steps.py +92 -40
- rbx/resources/packagers/boca/checker.sh +4 -1
- rbx/resources/packagers/boca/compile/c +2 -6
- rbx/resources/packagers/boca/compile/cc +2 -6
- rbx/resources/packagers/boca/compile/cpp +2 -6
- rbx/resources/packagers/boca/compile/java +1 -6
- rbx/resources/packagers/boca/compile/kt +24 -28
- rbx/resources/packagers/boca/compile/py2 +2 -6
- rbx/resources/packagers/boca/compile/py3 +2 -6
- rbx/resources/packagers/boca/interactive/c +15 -83
- rbx/resources/packagers/boca/interactive/cc +15 -83
- rbx/resources/packagers/boca/interactive/cpp +15 -83
- rbx/resources/packagers/boca/interactive/java +15 -88
- rbx/resources/packagers/boca/interactive/kt +15 -88
- rbx/resources/packagers/boca/interactive/py2 +15 -88
- rbx/resources/packagers/boca/interactive/py3 +15 -88
- rbx/resources/packagers/boca/interactor_compile.sh +5 -2
- rbx/resources/packagers/boca/interactor_run.sh +174 -0
- rbx/resources/packagers/boca/safeexec.c +530 -0
- rbx/resources/packagers/boca/safeexec_compile.sh +49 -0
- rbx/resources/presets/default/contest/contest.rbx.yml +9 -8
- rbx/resources/presets/default/problem/problem.rbx.yml +38 -26
- rbx/resources/presets/default/problem/random.txt +3 -1
- rbx/resources/presets/default/problem/rbx.h +92 -0
- rbx/resources/presets/default/problem/statement/statement.rbx.tex +4 -7
- rbx/resources/presets/default/problem/validator.cpp +8 -8
- rbx/resources/templates/rbx.h +2 -3
- {rbx_cp-0.5.73.dist-info → rbx_cp-0.6.1.dist-info}/METADATA +23 -6
- {rbx_cp-0.5.73.dist-info → rbx_cp-0.6.1.dist-info}/RECORD +84 -71
- {rbx_cp-0.5.73.dist-info → rbx_cp-0.6.1.dist-info}/WHEEL +1 -1
- rbx/resources/packagers/boca/compile/pas +0 -172
- rbx/resources/presets/default/problem/statement/projecao.png +0 -0
- {rbx_cp-0.5.73.dist-info → rbx_cp-0.6.1.dist-info}/LICENSE +0 -0
- {rbx_cp-0.5.73.dist-info → rbx_cp-0.6.1.dist-info}/entry_points.txt +0 -0
@@ -1,87 +1,71 @@
|
|
1
|
-
import asyncio
|
2
1
|
import contextlib
|
3
2
|
import os
|
4
3
|
import signal
|
5
|
-
import
|
6
|
-
from typing import
|
4
|
+
import subprocess
|
5
|
+
from typing import List, Optional
|
7
6
|
|
8
|
-
|
9
|
-
_terminate_all_on_error = False
|
10
|
-
_lock = threading.Lock()
|
11
|
-
|
12
|
-
# Creating a processing context is not thread-safe, but adding to it is.
|
7
|
+
from rbx.grading.judge.sandbox import SandboxBase
|
13
8
|
|
14
9
|
|
15
10
|
@contextlib.contextmanager
|
16
|
-
def
|
17
|
-
|
18
|
-
with _lock:
|
19
|
-
old_processing_context_pids = _processing_context_pids
|
20
|
-
_old_terminate_all_on_error = _terminate_all_on_error
|
21
|
-
_processing_context_pids = set()
|
22
|
-
_terminate_all_on_error = terminate_all_on_error
|
11
|
+
def new_process_group():
|
12
|
+
p = subprocess.Popen(['/bin/bash', '-c', 'exec sleep infinity'])
|
23
13
|
try:
|
24
|
-
yield
|
14
|
+
yield p.pid
|
25
15
|
finally:
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
except ChildProcessError:
|
83
|
-
return
|
84
|
-
if pid in wait_pids:
|
85
|
-
process(pid, os.waitstatus_to_exitcode(status))
|
86
|
-
|
87
|
-
await asyncio.to_thread(wait_all_processes)
|
16
|
+
p.terminate()
|
17
|
+
p.wait()
|
18
|
+
|
19
|
+
|
20
|
+
def should_use_group(sandboxes: List[SandboxBase]) -> bool:
|
21
|
+
if not sandboxes:
|
22
|
+
return False
|
23
|
+
uses_pgid = all(sandbox.use_pgid() for sandbox in sandboxes)
|
24
|
+
all_pgids = set(
|
25
|
+
sandbox.params.pgid for sandbox in sandboxes if sandbox.params.pgid is not None
|
26
|
+
)
|
27
|
+
return uses_pgid and len(all_pgids) == 1
|
28
|
+
|
29
|
+
|
30
|
+
async def _fetch_pids(sandboxes: List[SandboxBase]) -> List[int]:
|
31
|
+
return [await sandbox.get_pid() for sandbox in sandboxes]
|
32
|
+
|
33
|
+
|
34
|
+
def _find_sandbox_idx(pids: List[int], pid: int) -> Optional[int]:
|
35
|
+
try:
|
36
|
+
return pids.index(pid)
|
37
|
+
except ValueError:
|
38
|
+
return None
|
39
|
+
|
40
|
+
|
41
|
+
async def _wait_for_group(sandboxes: List[SandboxBase]) -> List[int]:
|
42
|
+
pgid = [
|
43
|
+
sandbox.params.pgid for sandbox in sandboxes if sandbox.params.pgid is not None
|
44
|
+
][0]
|
45
|
+
assert pgid is not None
|
46
|
+
|
47
|
+
sandbox_pids = await _fetch_pids(sandboxes)
|
48
|
+
|
49
|
+
finished = []
|
50
|
+
while len(finished) < len(sandboxes):
|
51
|
+
try:
|
52
|
+
pid, status = os.waitpid(-pgid, 0)
|
53
|
+
except ChildProcessError:
|
54
|
+
break
|
55
|
+
|
56
|
+
if os.waitstatus_to_exitcode(status) != 0:
|
57
|
+
os.kill(pgid, signal.SIGKILL)
|
58
|
+
|
59
|
+
sandbox_idx = _find_sandbox_idx(sandbox_pids, pid)
|
60
|
+
if sandbox_idx is not None:
|
61
|
+
finished.append(sandbox_idx)
|
62
|
+
continue
|
63
|
+
|
64
|
+
return finished
|
65
|
+
|
66
|
+
|
67
|
+
async def wait_all(sandboxes: List[SandboxBase]):
|
68
|
+
if not should_use_group(sandboxes):
|
69
|
+
raise RuntimeError('Sandboxes are not using a process group')
|
70
|
+
|
71
|
+
await _wait_for_group(sandboxes)
|
rbx/grading/steps.py
CHANGED
@@ -10,7 +10,6 @@ import shutil
|
|
10
10
|
import subprocess
|
11
11
|
import sys
|
12
12
|
import tempfile
|
13
|
-
import typing
|
14
13
|
from enum import Enum
|
15
14
|
from typing import IO, Any, Dict, Iterable, List, Optional, Tuple, Union
|
16
15
|
|
@@ -53,6 +52,27 @@ class Outcome(Enum):
|
|
53
52
|
Outcome.IDLENESS_LIMIT_EXCEEDED,
|
54
53
|
]
|
55
54
|
|
55
|
+
def short_name(self) -> str:
|
56
|
+
if self == Outcome.ACCEPTED:
|
57
|
+
return 'AC'
|
58
|
+
if self == Outcome.WRONG_ANSWER:
|
59
|
+
return 'WA'
|
60
|
+
if self == Outcome.TIME_LIMIT_EXCEEDED:
|
61
|
+
return 'TLE'
|
62
|
+
if self == Outcome.IDLENESS_LIMIT_EXCEEDED:
|
63
|
+
return 'ILE'
|
64
|
+
if self == Outcome.MEMORY_LIMIT_EXCEEDED:
|
65
|
+
return 'MLE'
|
66
|
+
if self == Outcome.RUNTIME_ERROR:
|
67
|
+
return 'RTE'
|
68
|
+
if self == Outcome.OUTPUT_LIMIT_EXCEEDED:
|
69
|
+
return 'OLE'
|
70
|
+
if self == Outcome.JUDGE_FAILED:
|
71
|
+
return 'FL'
|
72
|
+
if self == Outcome.INTERNAL_ERROR:
|
73
|
+
return 'IE'
|
74
|
+
return 'XX'
|
75
|
+
|
56
76
|
|
57
77
|
class DigestHolder(BaseModel):
|
58
78
|
value: Optional[str] = None
|
@@ -372,12 +392,12 @@ def _is_c_command(exe_command: str) -> bool:
|
|
372
392
|
return 'gcc' in exe_command or 'clang' in exe_command
|
373
393
|
|
374
394
|
|
375
|
-
def
|
395
|
+
def is_cpp_command(exe_command: str) -> bool:
|
376
396
|
return 'g++' in exe_command or 'clang++' in exe_command
|
377
397
|
|
378
398
|
|
379
399
|
def is_cxx_command(exe_command: str) -> bool:
|
380
|
-
return
|
400
|
+
return is_cpp_command(exe_command) or _is_c_command(exe_command)
|
381
401
|
|
382
402
|
|
383
403
|
def is_cxx_sanitizer_command(command: str) -> bool:
|
@@ -413,7 +433,8 @@ def _complain_about_clang() -> None:
|
|
413
433
|
)
|
414
434
|
|
415
435
|
|
416
|
-
|
436
|
+
@functools.cache
|
437
|
+
def _get_cxx_version_output(command: str, extra_flags: str = '') -> Optional[str]:
|
417
438
|
cmds = shlex.split(command)
|
418
439
|
if not cmds:
|
419
440
|
return None
|
@@ -421,8 +442,8 @@ def _get_cxx_version_output(command: str) -> Optional[str]:
|
|
421
442
|
if not is_cxx_command(exe):
|
422
443
|
return None
|
423
444
|
|
424
|
-
|
425
|
-
output = subprocess.run([exe, '-v'], capture_output=True)
|
445
|
+
extra = shlex.split(extra_flags)
|
446
|
+
output = subprocess.run([exe, '-v', *extra], capture_output=True, input='')
|
426
447
|
if output.returncode != 0:
|
427
448
|
console.print('[error]Failed to get C/C++ compiler version.[/error]')
|
428
449
|
return None
|
@@ -430,6 +451,8 @@ def _get_cxx_version_output(command: str) -> Optional[str]:
|
|
430
451
|
|
431
452
|
|
432
453
|
def _maybe_get_bits_stdcpp_for_clang(command: str) -> Optional[GradingFileInput]:
|
454
|
+
if not is_cpp_command(get_exe_from_command(command)):
|
455
|
+
return None
|
433
456
|
version_output = _get_cxx_version_output(command)
|
434
457
|
if version_output is None:
|
435
458
|
return None
|
@@ -446,11 +469,44 @@ def _maybe_get_bits_stdcpp_for_clang(command: str) -> Optional[GradingFileInput]
|
|
446
469
|
return GradingFileInput(src=bits, dest=pathlib.Path('bits/stdc++.h'))
|
447
470
|
|
448
471
|
|
449
|
-
def
|
472
|
+
def _find_system_paths_in_version_output(version_output: str) -> List[pathlib.Path]:
|
473
|
+
res = []
|
474
|
+
start = False
|
475
|
+
for line in version_output.splitlines():
|
476
|
+
if line.startswith('#include <...> search starts here:'):
|
477
|
+
start = True
|
478
|
+
continue
|
479
|
+
if not start:
|
480
|
+
continue
|
481
|
+
if not line.startswith(' '):
|
482
|
+
break
|
483
|
+
res.append(pathlib.Path(line.strip()))
|
484
|
+
return res
|
485
|
+
|
486
|
+
|
487
|
+
def _get_system_bits_stdcpp(command: str) -> Optional[GradingFileInput]:
|
488
|
+
if not is_cpp_command(get_exe_from_command(command)):
|
489
|
+
return None
|
490
|
+
version_output = _get_cxx_version_output(command, '-xc++ -E -')
|
491
|
+
if version_output is None:
|
492
|
+
return None
|
493
|
+
for path in _find_system_paths_in_version_output(version_output):
|
494
|
+
bits_candidate = path / 'bits' / 'stdc++.h'
|
495
|
+
if not bits_candidate.is_file():
|
496
|
+
continue
|
497
|
+
return GradingFileInput(
|
498
|
+
src=bits_candidate.resolve().absolute(), dest=pathlib.Path('bits/stdc++.h')
|
499
|
+
)
|
500
|
+
return None
|
501
|
+
|
502
|
+
|
503
|
+
def maybe_get_bits_stdcpp_for_commands(
|
450
504
|
commands: List[str],
|
451
505
|
) -> Optional[GradingFileInput]:
|
452
506
|
for command in commands:
|
453
|
-
res =
|
507
|
+
res = _get_system_bits_stdcpp(command) or _maybe_get_bits_stdcpp_for_clang(
|
508
|
+
command
|
509
|
+
)
|
454
510
|
if res is not None:
|
455
511
|
return res
|
456
512
|
return None
|
@@ -560,10 +616,9 @@ def compile(
|
|
560
616
|
sandbox: SandboxBase,
|
561
617
|
artifacts: GradingArtifacts,
|
562
618
|
) -> bool:
|
619
|
+
sandbox.reset()
|
620
|
+
|
563
621
|
commands = _try_following_alias_for_commands(commands)
|
564
|
-
bits_artifact = _maybe_get_bits_stdcpp_for_commands(commands)
|
565
|
-
if bits_artifact is not None:
|
566
|
-
_process_input_artifacts(GradingArtifacts(inputs=[bits_artifact]), sandbox)
|
567
622
|
_process_input_artifacts(artifacts, sandbox)
|
568
623
|
|
569
624
|
if not commands:
|
@@ -571,7 +626,9 @@ def compile(
|
|
571
626
|
return True
|
572
627
|
|
573
628
|
logs: List[PreprocessLog] = []
|
574
|
-
sandbox.set_params(
|
629
|
+
sandbox.set_params(
|
630
|
+
params.model_copy(deep=True)
|
631
|
+
) # Copy to allow further modification.
|
575
632
|
|
576
633
|
for i, command in enumerate(commands):
|
577
634
|
_maybe_complain_about_sanitization(command)
|
@@ -584,10 +641,6 @@ def compile(
|
|
584
641
|
if is_java_like_command(get_exe_from_command(command)):
|
585
642
|
sandbox.params.address_space = None
|
586
643
|
|
587
|
-
if bits_artifact is not None and _is_cpp_command(cmd[0]):
|
588
|
-
# Include from sandbox directory to import bits/stdc++.h.
|
589
|
-
cmd.append('-I.')
|
590
|
-
|
591
644
|
if not sandbox.execute_without_std(cmd):
|
592
645
|
console.print(
|
593
646
|
'[error]Sandbox crashed while processing command:[/error]',
|
@@ -642,17 +695,21 @@ async def run(
|
|
642
695
|
sandbox: SandboxBase,
|
643
696
|
artifacts: GradingArtifacts,
|
644
697
|
metadata: Optional[RunLogMetadata] = None,
|
645
|
-
kill_on_processing_context_exit: bool = False,
|
646
698
|
) -> Optional[RunLog]:
|
699
|
+
sandbox.reset()
|
700
|
+
|
647
701
|
_process_input_artifacts(artifacts, sandbox)
|
648
702
|
_process_fifos(artifacts, sandbox)
|
649
703
|
cmd = _split_and_expand(command, sandbox)
|
650
|
-
sandbox.set_params(
|
704
|
+
sandbox.set_params(
|
705
|
+
params.model_copy(deep=True)
|
706
|
+
) # Copy to allow further modification.
|
651
707
|
|
652
708
|
# Remove memory constraints for Java.
|
653
709
|
if is_java_like_command(get_exe_from_command(command)):
|
654
710
|
sandbox.params.address_space = None
|
655
711
|
|
712
|
+
sandbox.pid_event.set_loop(asyncio.get_event_loop())
|
656
713
|
if not await asyncio.to_thread(sandbox.execute_without_std, cmd):
|
657
714
|
console.print(
|
658
715
|
'[error]Sandbox crashed while processing command:[/error]',
|
@@ -662,9 +719,6 @@ async def run(
|
|
662
719
|
)
|
663
720
|
return None
|
664
721
|
|
665
|
-
if sandbox.get_exit_code() != 0 and kill_on_processing_context_exit:
|
666
|
-
processing_context.terminate_all_processes_in_context(clear=False)
|
667
|
-
|
668
722
|
if not _process_output_artifacts(artifacts, sandbox):
|
669
723
|
return None
|
670
724
|
|
@@ -706,27 +760,25 @@ async def run_coordinated(
|
|
706
760
|
interactor: CoordinatedRunParams,
|
707
761
|
solution: CoordinatedRunParams,
|
708
762
|
) -> Tuple[Optional[RunLog], Optional[RunLog]]:
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
params.artifacts,
|
718
|
-
params.metadata,
|
719
|
-
kill_on_processing_context_exit=True,
|
720
|
-
)
|
763
|
+
def run_one(params: CoordinatedRunParams) -> asyncio.Task[Optional[RunLog]]:
|
764
|
+
return asyncio.create_task(
|
765
|
+
run(
|
766
|
+
params.command,
|
767
|
+
params.params,
|
768
|
+
params.sandbox,
|
769
|
+
params.artifacts,
|
770
|
+
params.metadata,
|
721
771
|
)
|
722
|
-
for params in [interactor, solution]
|
723
|
-
)
|
724
|
-
await processing_context.wait_all_processes_in_context(wait_for=2)
|
725
|
-
logs = typing.cast(
|
726
|
-
Tuple[Optional[RunLog], Optional[RunLog]],
|
727
|
-
tuple(await asyncio.gather(*runs)),
|
728
772
|
)
|
729
|
-
|
773
|
+
|
774
|
+
# Use interactor PID as the process group id.
|
775
|
+
interactor_task = run_one(interactor)
|
776
|
+
solution.sandbox.params.pgid = await interactor.sandbox.get_pid()
|
777
|
+
solution_task = run_one(solution)
|
778
|
+
|
779
|
+
await processing_context.wait_all([interactor.sandbox, solution.sandbox])
|
780
|
+
|
781
|
+
return await asyncio.gather(interactor_task, solution_task)
|
730
782
|
|
731
783
|
|
732
784
|
def _normalize_checked_words(s: str) -> Tuple[str, ...]:
|
@@ -1,4 +1,7 @@
|
|
1
1
|
### START OF CHECKER COMPILATION
|
2
|
+
CACHE_DIR="/tmp/boca-cache"
|
3
|
+
mkdir -p $CACHE_DIR
|
4
|
+
|
2
5
|
CDIR=$(pwd)
|
3
6
|
CHECKER_PATH="checker.cpp"
|
4
7
|
CHECKER_OUT="checker.exe"
|
@@ -27,7 +30,7 @@ printf "%s" "${RbxHeaderContent}" >rbx.h
|
|
27
30
|
printf "%s" "${CheckerContent}" >$CHECKER_PATH
|
28
31
|
|
29
32
|
checker_hash=($(cat $CHECKER_PATH rbx.h testlib.h | md5sum))
|
30
|
-
checker_cache="/
|
33
|
+
checker_cache="$CACHE_DIR/checker-${checker_hash}"
|
31
34
|
|
32
35
|
echo "Polygon checker hash: $checker_hash"
|
33
36
|
echo "Copying polygon checker to $CDIR/$CHECKER_OUT"
|
@@ -92,12 +92,8 @@ if [ "$4" != "" ]; then
|
|
92
92
|
fi
|
93
93
|
|
94
94
|
# setting up the timelimit according to the problem
|
95
|
-
|
96
|
-
|
97
|
-
else
|
98
|
-
time=$3
|
99
|
-
fi
|
100
|
-
let "ttime = $time + 30"
|
95
|
+
time=15
|
96
|
+
let "ttime = $time * 2"
|
101
97
|
|
102
98
|
if [ "$2" == "" ]; then
|
103
99
|
exe=run.exe
|
@@ -93,12 +93,8 @@ if [ "$4" != "" ]; then
|
|
93
93
|
fi
|
94
94
|
|
95
95
|
# setting up the timelimit according to the problem
|
96
|
-
|
97
|
-
|
98
|
-
else
|
99
|
-
time=$3
|
100
|
-
fi
|
101
|
-
let "ttime = $time + 30"
|
96
|
+
time=15
|
97
|
+
let "ttime = $time * 2"
|
102
98
|
|
103
99
|
if [ "$2" == "" ]; then
|
104
100
|
exe=run.exe
|
@@ -92,12 +92,8 @@ if [ "$4" != "" ]; then
|
|
92
92
|
fi
|
93
93
|
|
94
94
|
# setting up the timelimit according to the problem
|
95
|
-
|
96
|
-
|
97
|
-
else
|
98
|
-
time=$3
|
99
|
-
fi
|
100
|
-
let "ttime = $time + 30"
|
95
|
+
time=15
|
96
|
+
let "ttime = $time * 2"
|
101
97
|
|
102
98
|
if [ "$2" == "" ]; then
|
103
99
|
exe=run.exe
|
@@ -88,13 +88,8 @@ if [ ! -x $sf ]; then
|
|
88
88
|
fi
|
89
89
|
|
90
90
|
# setting up the timelimit according to the problem
|
91
|
-
if [ "$3" == "" ]; then
|
92
|
-
time=5
|
93
|
-
else
|
94
|
-
time=$3
|
95
|
-
fi
|
96
|
-
let "ttime = $time + 30"
|
97
91
|
time=30
|
92
|
+
ttime=30
|
98
93
|
|
99
94
|
maxm=512
|
100
95
|
if [ "$4" != "" -a "$4" -gt "512" ]; then
|
@@ -41,22 +41,22 @@
|
|
41
41
|
|
42
42
|
umask 0022
|
43
43
|
if [ "$1" == "" ]; then
|
44
|
-
|
45
|
-
|
44
|
+
echo "parameter problem"
|
45
|
+
exit 43
|
46
46
|
fi
|
47
47
|
name="$1"
|
48
48
|
if [ ! -r "$1" ]; then
|
49
|
-
|
50
|
-
|
49
|
+
echo "$1 not found or it's not readable"
|
50
|
+
exit 44
|
51
51
|
fi
|
52
52
|
id -u bocajail >/dev/null 2>/dev/null
|
53
53
|
if [ $? == 0 ]; then
|
54
|
-
bocau
|
55
|
-
bocag
|
54
|
+
bocau=$(id -u bocajail)
|
55
|
+
bocag=$(id -g bocajail)
|
56
56
|
chown bocajail.nogroup .
|
57
57
|
else
|
58
|
-
bocau
|
59
|
-
bocag
|
58
|
+
bocau=$(id -u nobody)
|
59
|
+
bocag=$(id -g nobody)
|
60
60
|
chown nobody.nogroup .
|
61
61
|
fi
|
62
62
|
if [ "$bocau" == "" -o "$bocag" == "" ]; then
|
@@ -67,10 +67,10 @@ fi
|
|
67
67
|
mkdir -p src
|
68
68
|
if [ "${name##*.}" == "zip" -a "${name##*.}" == "ZIP" ]; then
|
69
69
|
unzip "$name" -d src
|
70
|
-
|
71
|
-
name
|
70
|
+
if [ "${name##*.}" == "zip" ]; then
|
71
|
+
name=$(basename $name .zip)
|
72
72
|
else
|
73
|
-
name
|
73
|
+
name=$(basename $name .ZIP)
|
74
74
|
fi
|
75
75
|
else
|
76
76
|
cp "$name" src
|
@@ -80,42 +80,38 @@ chmod -R 700 src
|
|
80
80
|
|
81
81
|
# this script makes use of safeexec to execute the code with less privilegies
|
82
82
|
# make sure that directories below are correct.
|
83
|
-
sf
|
83
|
+
sf=$(which safeexec)
|
84
84
|
[ -x "$sf" ] || sf=/usr/bin/safeexec
|
85
85
|
if [ ! -x $sf ]; then
|
86
|
-
|
87
|
-
|
86
|
+
echo "$sf not found or it's not executable"
|
87
|
+
exit 46
|
88
88
|
fi
|
89
89
|
|
90
90
|
# setting up the timelimit according to the problem
|
91
|
-
|
92
|
-
|
93
|
-
else
|
94
|
-
time=$3
|
95
|
-
fi
|
96
|
-
let "ttime = $time + 30"
|
91
|
+
time=30
|
92
|
+
ttime=30
|
97
93
|
|
98
94
|
maxm=1024
|
99
95
|
if [ "$4" != "" -a "$4" -gt "1024" ]; then
|
100
|
-
maxm=$4
|
96
|
+
maxm=$4
|
101
97
|
fi
|
102
98
|
|
103
99
|
maxms=100
|
104
100
|
|
105
101
|
if [ "$2" == "" ]; then
|
106
|
-
|
102
|
+
jarfile=run.jar
|
107
103
|
else
|
108
|
-
|
104
|
+
jarfile=$2
|
109
105
|
fi
|
110
106
|
|
111
|
-
cdir
|
107
|
+
cdir=$(pwd)
|
112
108
|
echo "Current directory is $cdir" >&2
|
113
|
-
mainname
|
109
|
+
mainname=$(echo $name | cut -d'.' -f1)
|
114
110
|
if [ "$mainname" == "" ]; then
|
115
|
-
|
111
|
+
mainname=Main
|
116
112
|
fi
|
117
113
|
|
118
|
-
cat <<EOF >
|
114
|
+
cat <<EOF >compileit.sh
|
119
115
|
#!/bin/bash
|
120
116
|
kotlinc=/snap/kotlin/24/bin/kotlinc
|
121
117
|
[ -x "\$kotlinc" ] || kotlinc=/snap/bin/kotlinc
|
@@ -147,7 +143,7 @@ if [ "$ret" != "0" ]; then
|
|
147
143
|
echo "Compilation Error: $ret"
|
148
144
|
exit $ret
|
149
145
|
fi
|
150
|
-
ret
|
146
|
+
ret=$(cat compileit.retcode)
|
151
147
|
if [ "$ret" != "0" ]; then
|
152
148
|
echo "Compilation Error: $ret"
|
153
149
|
ret=1
|
@@ -92,12 +92,8 @@ if [ "$4" != "" ]; then
|
|
92
92
|
fi
|
93
93
|
|
94
94
|
# setting up the timelimit according to the problem
|
95
|
-
|
96
|
-
|
97
|
-
else
|
98
|
-
time=$3
|
99
|
-
fi
|
100
|
-
let "ttime = $time + 30"
|
95
|
+
time=15
|
96
|
+
let "ttime = $time * 2"
|
101
97
|
|
102
98
|
if [ "$2" == "" ]; then
|
103
99
|
exe=run.exe
|
@@ -92,12 +92,8 @@ if [ "$4" != "" ]; then
|
|
92
92
|
fi
|
93
93
|
|
94
94
|
# setting up the timelimit according to the problem
|
95
|
-
|
96
|
-
|
97
|
-
else
|
98
|
-
time=$3
|
99
|
-
fi
|
100
|
-
let "ttime = $time + 30"
|
95
|
+
time=15
|
96
|
+
let "ttime = $time * 2"
|
101
97
|
|
102
98
|
if [ "$2" == "" ]; then
|
103
99
|
exe=run.exe
|