S2OJ/web/app/models/UOJLocalRun.php

92 lines
3.1 KiB
PHP

<?php
class UOJLocalRun {
public static string $judger_main_path, $judger_include_path, $judger_run_path;
public static function escapearg($arg) {
if (is_string($arg) || is_numeric($arg)) {
return escapeshellarg($arg);
} elseif (is_array($arg) && count($arg) == 2) {
if ($arg[0] === '<' || $arg[0] === '>') {
return $arg[0].escapeshellarg($arg[1]);
} else {
return escapeshellarg("--{$arg[0]}={$arg[1]}");
}
} else {
return false;
}
}
public static function getCmd($cmd) {
if (is_array($cmd)) {
return implode(' ', array_map('UOJLocalRun::escapearg', $cmd));
} elseif (is_string($cmd)) {
return $cmd;
} else {
return false;
}
}
public static function exec($cmd, array $runp_options=null) {
$cmd = static::getCmd($cmd);
if ($cmd === false) {
return false;
}
if ($runp_options) {
$res_path = tempnam('/tmp', 'runp');
if ($res_path === false) {
UOJLog::error("UOJLocalRun::exec: failed to create res file. cmd: {$cmd}");
return false;
}
$cmd = implode(' ', [
escapeshellarg(static::$judger_main_path.'/run/run_program'), static::getCmd([['res', $res_path]]), static::getCmd($runp_options), $cmd
]);
}
$ret = [];
if (exec($cmd, $ret['output'], $status) === false || $status != 0) {
UOJLog::error("exec failed with status {$status}. cmd: {$cmd}");
foreach ($ret['output'] as $line) {
UOJLog::error("exec failed. output: {$line}");
}
return false;
}
if ($runp_options) {
$fp = fopen($res_path, "r");
if ($fp === false) {
UOJLog::error("UOJLocalRun::exec: failed to open res file ({$res_path}). cmd: {$cmd}");
return false;
}
if (fscanf($fp, '%d %d %d %d', $ret['rstype'], $ret['used_time'], $ret['used_memory'], $ret['exit_code']) != 4) {
$ret['rstype'] = 7;
}
fclose($fp);
unlink($res_path);
}
return $ret;
}
public static function execAnd(array $cmds, array $runp_options=null) {
return static::exec(implode(' && ', array_map('UOJLocalRun::getCmd', $cmds)), $runp_options);
}
public static function formatter(string $src, string $dest, array $runp_options=null) {
return static::exec([
static::$judger_main_path.'/run/formatter', ['<', $src], ['>', $dest]
], $runp_options);
}
public static function compile(string $name, array $options, array $runp_options=null) {
return static::exec([
static::$judger_main_path.'/run/compile', ...$options, $name
], $runp_options);
}
}
UOJLocalRun::$judger_main_path = realpath('/opt/uoj/judger/uoj_judger');
UOJLocalRun::$judger_include_path = UOJLocalRun::$judger_main_path.'/include';
UOJLocalRun::$judger_run_path = UOJLocalRun::$judger_main_path.'/run';