From 5a4392d52560b78196572d6680cb76dadc6e2782 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Mon, 26 May 2014 21:40:53 +0300 Subject: [PATCH 01/16] Add formats GCCGO, GOLANG, HASKELL --- gruntmaster-compile | 3 +++ lib/Gruntmaster/Daemon.pm | 3 +++ lib/Gruntmaster/Daemon/Format.pm | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gruntmaster-compile b/gruntmaster-compile index 4e60096..5228bdd 100755 --- a/gruntmaster-compile +++ b/gruntmaster-compile @@ -21,6 +21,9 @@ if ($ret) { exec 'gmcs', '-d:ONLINE_JUDGE', $name when 'MONO'; exec 'javac', $name when 'JAVA'; exec 'fpc', qw/-dONLINE_JUDGE -O2/, $name when 'PASCAL'; + exec 'go', qw/build -compiler gc/, $name when 'GOLANG'; + exec 'go', qw/build -compiler gccgo/, $name, when 'GCCGO'; + exec 'ghc', qw/-DONLINE_JUDGE -Wall -O2 -o/, $basename, $name when 'HASKELL'; copy $name, $basename when ['PERL', 'PYTHON'] } } diff --git a/lib/Gruntmaster/Daemon.pm b/lib/Gruntmaster/Daemon.pm index b7b6e06..1c8cece 100644 --- a/lib/Gruntmaster/Daemon.pm +++ b/lib/Gruntmaster/Daemon.pm @@ -23,6 +23,9 @@ use constant PAGE_SIZE => 10; use constant FORMAT_EXTENSION => { C => 'c', CPP => 'cpp', + GCCGO => 'go', + GOLANG => 'go', + HASKELL => 'hs', MONO => 'cs', JAVA => 'java', PASCAL => 'pas', diff --git a/lib/Gruntmaster/Daemon/Format.pm b/lib/Gruntmaster/Daemon/Format.pm index dc75fa1..2bfbc1a 100644 --- a/lib/Gruntmaster/Daemon/Format.pm +++ b/lib/Gruntmaster/Daemon/Format.pm @@ -24,7 +24,7 @@ sub command_and_args{ my ($format, $basename) = @_; given($format) { - "./$basename" when [qw/C CPP PASCAL/]; + "./$basename" when [qw/C CPP GCCGO GOLANG HASKELL PASCAL/]; "./$basename.exe" when 'MONO'; java => $basename when 'JAVA'; perl => $basename when 'PERL'; -- 2.30.2 From 498646e00c11ecb137eac12e4eab92b7f8a3fb98 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sun, 29 Jun 2014 00:35:33 +0300 Subject: [PATCH 02/16] Update gruntmaster-compile documentation --- gruntmaster-compile | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/gruntmaster-compile b/gruntmaster-compile index 5228bdd..b4c2ab1 100755 --- a/gruntmaster-compile +++ b/gruntmaster-compile @@ -55,7 +55,7 @@ Compile commands for each format: =item CPP - g++ -DONLINE_JUDGE -std=gnu11 -fabi-version=6 -Wall -Wextra -O2 -o $output $input + g++ -DONLINE_JUDGE -std=gnu++11 -fabi-version=6 -Wall -Wextra -O2 -o $output $input =item MONO @@ -69,6 +69,18 @@ Compile commands for each format: fpc -dONLINE_JUDGE -O2 $input +=item GOLANG + + go build -compiler gc $input + +=item GCCGO + + go build -compiler gccgo $input + +=item HASKELL + + ghc -DONLINE_JUDGE -Wall -O2 -o $output $input + =item PERL cp $input $output -- 2.30.2 From 3e7fd9031ca5f299f08ee12718ea8938dbb4277a Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sun, 29 Jun 2014 00:36:27 +0300 Subject: [PATCH 03/16] Bump version and update Changes --- Changes | 4 ++++ lib/Gruntmaster/Daemon.pm | 2 +- lib/Gruntmaster/Daemon/Constants.pm | 2 +- lib/Gruntmaster/Daemon/Format.pm | 2 +- lib/Gruntmaster/Daemon/Generator/File.pm | 2 +- lib/Gruntmaster/Daemon/Generator/Run.pm | 2 +- lib/Gruntmaster/Daemon/Generator/Undef.pm | 2 +- lib/Gruntmaster/Daemon/Judge/Absolute.pm | 2 +- lib/Gruntmaster/Daemon/Judge/Points.pm | 2 +- lib/Gruntmaster/Daemon/Runner/File.pm | 2 +- lib/Gruntmaster/Daemon/Runner/Interactive.pm | 2 +- lib/Gruntmaster/Daemon/Runner/Verifier.pm | 2 +- 12 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Changes b/Changes index a1ae31f..08b59dc 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,9 @@ Revision history for Perl extension Gruntmaster::Daemon. +5999.000_004 2014-06-29T00:36+03:00 + - Prevent crashing on compile errors + - Add new languages: Go (gc), Go (gccgo), Haskell (ghc) + 5999.000_003 2014-04-23T11:51+03:00 - Use new Postgres database - Improve documentation diff --git a/lib/Gruntmaster/Daemon.pm b/lib/Gruntmaster/Daemon.pm index 1c8cece..cb41e0d 100644 --- a/lib/Gruntmaster/Daemon.pm +++ b/lib/Gruntmaster/Daemon.pm @@ -4,7 +4,7 @@ use 5.014000; use strict; use warnings; -our $VERSION = '5999.000_003'; +our $VERSION = '5999.000_004'; use Gruntmaster::Daemon::Constants qw/ERR/; use Gruntmaster::Daemon::Format qw/prepare_files/; diff --git a/lib/Gruntmaster/Daemon/Constants.pm b/lib/Gruntmaster/Daemon/Constants.pm index 1171ccb..c64f57a 100644 --- a/lib/Gruntmaster/Daemon/Constants.pm +++ b/lib/Gruntmaster/Daemon/Constants.pm @@ -5,7 +5,7 @@ use strict; use warnings; use parent qw/Exporter/; -our $VERSION = "5999.000_003"; +our $VERSION = "5999.000_004"; use constant +{ # Accepted diff --git a/lib/Gruntmaster/Daemon/Format.pm b/lib/Gruntmaster/Daemon/Format.pm index 2bfbc1a..cc5f0f8 100644 --- a/lib/Gruntmaster/Daemon/Format.pm +++ b/lib/Gruntmaster/Daemon/Format.pm @@ -15,7 +15,7 @@ use List::MoreUtils qw/natatime/; use Log::Log4perl qw/get_logger/; use IPC::Signal qw/sig_name sig_num/; -our $VERSION = "5999.000_003"; +our $VERSION = "5999.000_004"; our @EXPORT_OK = qw/prepare_files/; ################################################## diff --git a/lib/Gruntmaster/Daemon/Generator/File.pm b/lib/Gruntmaster/Daemon/Generator/File.pm index 2702dba..be10f26 100644 --- a/lib/Gruntmaster/Daemon/Generator/File.pm +++ b/lib/Gruntmaster/Daemon/Generator/File.pm @@ -8,7 +8,7 @@ use File::Copy qw/copy/; use File::Slurp qw/write_file/; use Log::Log4perl qw/get_logger/; -our $VERSION = "5999.000_003"; +our $VERSION = "5999.000_004"; ################################################## diff --git a/lib/Gruntmaster/Daemon/Generator/Run.pm b/lib/Gruntmaster/Daemon/Generator/Run.pm index 6892745..2ef5200 100644 --- a/lib/Gruntmaster/Daemon/Generator/Run.pm +++ b/lib/Gruntmaster/Daemon/Generator/Run.pm @@ -6,7 +6,7 @@ use warnings; use Log::Log4perl qw/get_logger/; -our $VERSION = '5999.000_003'; +our $VERSION = '5999.000_004'; ################################################## diff --git a/lib/Gruntmaster/Daemon/Generator/Undef.pm b/lib/Gruntmaster/Daemon/Generator/Undef.pm index 6b5a56b..649a5d8 100644 --- a/lib/Gruntmaster/Daemon/Generator/Undef.pm +++ b/lib/Gruntmaster/Daemon/Generator/Undef.pm @@ -6,7 +6,7 @@ use warnings; use Log::Log4perl qw/get_logger/; -our $VERSION = "5999.000_003"; +our $VERSION = "5999.000_004"; ################################################## diff --git a/lib/Gruntmaster/Daemon/Judge/Absolute.pm b/lib/Gruntmaster/Daemon/Judge/Absolute.pm index 45745e5..d9fef04 100644 --- a/lib/Gruntmaster/Daemon/Judge/Absolute.pm +++ b/lib/Gruntmaster/Daemon/Judge/Absolute.pm @@ -6,7 +6,7 @@ use warnings; use Gruntmaster::Daemon::Constants qw/AC/; -our $VERSION = '5999.000_003'; +our $VERSION = '5999.000_004'; ################################################## diff --git a/lib/Gruntmaster/Daemon/Judge/Points.pm b/lib/Gruntmaster/Daemon/Judge/Points.pm index dc637f0..26c19f9 100644 --- a/lib/Gruntmaster/Daemon/Judge/Points.pm +++ b/lib/Gruntmaster/Daemon/Judge/Points.pm @@ -8,7 +8,7 @@ use Gruntmaster::Daemon::Constants qw/AC REJ/; use List::Util qw/sum/; use Log::Log4perl qw/get_logger/; -our $VERSION = '5999.000_003'; +our $VERSION = '5999.000_004'; ################################################## diff --git a/lib/Gruntmaster/Daemon/Runner/File.pm b/lib/Gruntmaster/Daemon/Runner/File.pm index 6d7b8f8..a79500c 100644 --- a/lib/Gruntmaster/Daemon/Runner/File.pm +++ b/lib/Gruntmaster/Daemon/Runner/File.pm @@ -8,7 +8,7 @@ use Gruntmaster::Daemon::Constants qw/WA/; use File::Slurp qw/slurp/; use Log::Log4perl qw/get_logger/; -our $VERSION = "5999.000_003"; +our $VERSION = "5999.000_004"; ################################################## diff --git a/lib/Gruntmaster/Daemon/Runner/Interactive.pm b/lib/Gruntmaster/Daemon/Runner/Interactive.pm index aaaadd7..9118e15 100644 --- a/lib/Gruntmaster/Daemon/Runner/Interactive.pm +++ b/lib/Gruntmaster/Daemon/Runner/Interactive.pm @@ -10,7 +10,7 @@ use Log::Log4perl qw/get_logger/; use POSIX qw/mkfifo/; use Try::Tiny; -our $VERSION = '5999.000_003'; +our $VERSION = '5999.000_004'; ################################################## diff --git a/lib/Gruntmaster/Daemon/Runner/Verifier.pm b/lib/Gruntmaster/Daemon/Runner/Verifier.pm index bb8652d..fd267cd 100644 --- a/lib/Gruntmaster/Daemon/Runner/Verifier.pm +++ b/lib/Gruntmaster/Daemon/Runner/Verifier.pm @@ -9,7 +9,7 @@ use File::Slurp qw/slurp/; use Log::Log4perl qw/get_logger/; use Try::Tiny; -our $VERSION = '5999.000_003'; +our $VERSION = '5999.000_004'; ################################################## -- 2.30.2 From b335c4bbcd278396e05c11d9bf60e0807a78726d Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Fri, 19 Dec 2014 13:06:46 +0200 Subject: [PATCH 04/16] Update problem_statuses after job --- lib/Gruntmaster/Daemon.pm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/Gruntmaster/Daemon.pm b/lib/Gruntmaster/Daemon.pm index cb41e0d..15f6410 100644 --- a/lib/Gruntmaster/Daemon.pm +++ b/lib/Gruntmaster/Daemon.pm @@ -147,6 +147,14 @@ sub process{ $errors ? (errors => $errors) : () }); + my $solved = $meta->{result} ? 0 : 1; + my $status = $db->problem_statuses->find($jobr->owner, $jobr->problem); + $db->problem_statuses->update_or_create({ + problem => $jobr->problem, + owner => $jobr->owner, + job => $jobr->id, + solved => $solved}); + my $log = $jobr->contest ? 'ct/' . $jobr->contest->id . '/log' : 'log'; my $page = int (($job + PAGE_SIZE - 1) / PAGE_SIZE); -- 2.30.2 From a5d85109e94cca6c36ed5038cde7fed6b046d9da Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Fri, 19 Dec 2014 13:11:36 +0200 Subject: [PATCH 05/16] Update cache purging, drop LWP dependency --- Makefile.PL | 1 - lib/Gruntmaster/Daemon.pm | 23 +++++------------------ 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index caff665..7f7b2cd 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -39,7 +39,6 @@ WriteMakefile( JSON 0 List::MoreUtils 0 Log::Log4perl 0 - LWP::UserAgent 0 Try::Tiny 0/ }, META_MERGE => { diff --git a/lib/Gruntmaster/Daemon.pm b/lib/Gruntmaster/Daemon.pm index 15f6410..681a141 100644 --- a/lib/Gruntmaster/Daemon.pm +++ b/lib/Gruntmaster/Daemon.pm @@ -17,7 +17,6 @@ use Sys::Hostname qw/hostname/; use Time::HiRes qw/time/; use Try::Tiny; use Log::Log4perl qw/get_logger/; -use LWP::UserAgent; use constant PAGE_SIZE => 10; use constant FORMAT_EXTENSION => { @@ -36,8 +35,6 @@ use constant FORMAT_EXTENSION => { ################################################## my $db; -my $ua = LWP::UserAgent->new; -my @purge_hosts = exists $ENV{PURGE_HOSTS} ? split ' ', $ENV{PURGE_HOSTS} : (); sub safe_can_nodie { my ($type, $sub, $name) = @_; @@ -55,14 +52,6 @@ sub safe_can { safe_can_nodie @_ or get_logger->logdie("No such \l$type: '$name'"); } -sub purge { - get_logger->trace("Purging $_[0]"); - for my $host (@purge_hosts) { - my $req = HTTP::Request->new(PURGE => "http://$host$_[0]"); - $ua->request($req) - } -} - sub process{ my ($job, $jobr) = @_; @@ -155,13 +144,11 @@ sub process{ job => $jobr->id, solved => $solved}); - my $log = $jobr->contest ? 'ct/' . $jobr->contest->id . '/log' : 'log'; - my $page = int (($job + PAGE_SIZE - 1) / PAGE_SIZE); - - purge "/$log/$job"; - purge "/$log/"; - purge "/$log/st"; - purge "/$log/page/$_" for $page - 1, $page, $page + 1; + purge '/log/'; + purge "/log/$job"; + purge '/st/' . $jobr->contest if $jobr->contest; + purge '/us/'; + purge '/us/' . $jobr->owner; } sub got_job{ -- 2.30.2 From 759d3ca5c69d55ebcf9a1c79a9b9030e9119069d Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Fri, 19 Dec 2014 13:14:19 +0200 Subject: [PATCH 06/16] Fix keys/values on reference experimental warnings --- lib/Gruntmaster/Daemon/Format.pm | 2 +- t/01-jobs.t | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Gruntmaster/Daemon/Format.pm b/lib/Gruntmaster/Daemon/Format.pm index cc5f0f8..146ffb0 100644 --- a/lib/Gruntmaster/Daemon/Format.pm +++ b/lib/Gruntmaster/Daemon/Format.pm @@ -84,7 +84,7 @@ sub prepare{ sub prepare_files{ my $meta = shift; - for my $file (values $meta->{files}) { + for my $file (values %{$meta->{files}}) { my ($format, $name, $content) = @{$file}{qw/format name content/}; $file->{run} = mkrun($format); diff --git a/t/01-jobs.t b/t/01-jobs.t index 1aaea44..7001ef1 100644 --- a/t/01-jobs.t +++ b/t/01-jobs.t @@ -32,7 +32,7 @@ $ENV{PATH}.=':' . cwd; sub check_job{ my $meta = shift; if (defined $meta->{results}) { - delete $meta->{results}[$_]{time} for keys $meta->{results}; + delete $meta->{results}[$_]{time} for keys %{$meta->{results}}; } is $meta->{result}, $meta->{expected_result}, "Result is correct"; is $meta->{result_text}, $meta->{expected_result_text}, "Result text is correct"; @@ -54,7 +54,7 @@ for my $problem (@problems) { $pbmeta->{okfile}[$_ - 1] = read_file "$problem/$_.ok" if $pbmeta->{runner} eq 'File'; } if (exists $pbmeta->{files}) { - $_->{content} = read_file "$problem/$_->{name}" for values $pbmeta->{files} + $_->{content} = read_file "$problem/$_->{name}" for values %{$pbmeta->{files}} } TODO: { -- 2.30.2 From 4b5d7885e5a9ebc09f4b4b631a4eb7c3ce5f1c12 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sat, 10 Jan 2015 20:26:15 +0200 Subject: [PATCH 07/16] Keep $ENV{HOME} in gruntmaster-exec --- gruntmaster-exec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gruntmaster-exec b/gruntmaster-exec index 1bb5758..69e967e 100755 --- a/gruntmaster-exec +++ b/gruntmaster-exec @@ -12,7 +12,7 @@ my ($mlimit, $olimit, @args) = @ARGV; setrlimit RLIMIT_AS, $mlimit, $mlimit or die $! if $mlimit; setrlimit RLIMIT_FSIZE, $olimit, $olimit or die $! if $olimit; -%ENV = (ONLINE_JUDGE => 1, PATH => $ENV{PATH}, HOME => $ENV{PATH}); +%ENV = (ONLINE_JUDGE => 1, PATH => $ENV{PATH}, HOME => $ENV{HOME}); exec @args; __END__ -- 2.30.2 From d520092522e87991aa1c41b2718ab75989eb3219 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sat, 10 Jan 2015 20:37:25 +0200 Subject: [PATCH 08/16] Set test log level to TRACE when TEST_VERBOSE is true --- t/01-jobs.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/01-jobs.t b/t/01-jobs.t index 7001ef1..bb2c4ba 100644 --- a/t/01-jobs.t +++ b/t/01-jobs.t @@ -17,7 +17,7 @@ use YAML::Any qw/LoadFile/; ################################################## -my $loglevel = $ENV{TEST_LOG_LEVEL} // 'OFF'; +my $loglevel = $ENV{TEST_LOG_LEVEL} // ($ENV{TEST_VERBOSE} ? 'TRACE' : 'OFF'); my $log_conf = < Date: Sat, 10 Jan 2015 20:39:10 +0200 Subject: [PATCH 09/16] Fix test failure introduced several commits ago --- t/01-jobs.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/01-jobs.t b/t/01-jobs.t index bb2c4ba..5145a77 100644 --- a/t/01-jobs.t +++ b/t/01-jobs.t @@ -32,7 +32,7 @@ $ENV{PATH}.=':' . cwd; sub check_job{ my $meta = shift; if (defined $meta->{results}) { - delete $meta->{results}[$_]{time} for keys %{$meta->{results}}; + delete $meta->{results}[$_]{time} for keys @{$meta->{results}}; } is $meta->{result}, $meta->{expected_result}, "Result is correct"; is $meta->{result_text}, $meta->{expected_result_text}, "Result text is correct"; -- 2.30.2 From c40a2dd049e5f8da7bf4f3f48feeab89f16b4176 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Mon, 19 Jan 2015 10:39:20 +0200 Subject: [PATCH 10/16] Move some Format.pm code to gruntmaster-exec --- gruntmaster-exec | 73 +++++++++++++--- lib/Gruntmaster/Daemon/Format.pm | 70 ++++++++------- selinux/gruntmasterd.fc | 7 -- selinux/gruntmasterd.te | 145 ------------------------------- 4 files changed, 100 insertions(+), 195 deletions(-) delete mode 100644 selinux/gruntmasterd.fc delete mode 100644 selinux/gruntmasterd.te diff --git a/gruntmaster-exec b/gruntmaster-exec index 69e967e..49e915a 100755 --- a/gruntmaster-exec +++ b/gruntmaster-exec @@ -1,20 +1,73 @@ -#!/usr/bin/perl -w +#!/usr/bin/perl use v5.14; use strict; +use warnings; -use BSD::Resource qw/setrlimit RLIMIT_AS RLIMIT_FSIZE/; -use sigtrap qw/XFSZ/; - -################################################## +use constant +{ + # Accepted + AC => 0, -my ($mlimit, $olimit, @args) = @ARGV; + # Internal server error + ERR => -1, -setrlimit RLIMIT_AS, $mlimit, $mlimit or die $! if $mlimit; -setrlimit RLIMIT_FSIZE, $olimit, $olimit or die $! if $olimit; + # All other errors + WA => 1, + NZX => 2, + TLE => 3, + OLE => 4, + DIED => 5, + REJ => 10, +}; -%ENV = (ONLINE_JUDGE => 1, PATH => $ENV{PATH}, HOME => $ENV{HOME}); -exec @args; +use BSD::Resource qw/setrlimit RLIMIT_AS RLIMIT_FSIZE/; +use IPC::Signal qw/sig_name sig_num/; +use sigtrap qw/XFSZ/; +use Getopt::Long; +use POSIX qw//; +use Time::HiRes qw/alarm/; + +my (@fds, $timeout, $mlimit, $olimit); +GetOptions( + "fd=s" => \@fds, + "timeout=f" => \$timeout, + "mlimit=i" => \$mlimit, + "olimit=i" => \$olimit, +); + +my $ret = fork // die 'Cannot fork'; +if ($ret) { + my $tle; + local $SIG{ALRM} = sub { kill KILL => $ret; $tle = 1}; + alarm ($timeout || 5); + waitpid $ret, 0; + alarm 0; + my $sig = $? & 127; + my $signame = sig_name $sig; + exit !say TLE, "\nTime Limit Exceeded" if $tle; + exit !say OLE, "\nOutput Limit Exceeded" if $sig && $signame eq 'XFSZ'; + exit !say DIED, "\nCrash (SIG$signame)" if $sig && $signame ne 'PIPE'; + exit !say NZX, "\nNon-zero exit status: " . ($? >> 8) if $? >> 8; + exit !say AC, "\nAll OK"; +} else { + $^F = 50; + POSIX::close $_ for 0 .. $^F; + for my $fdstring (@fds) { + my ($fd, $file) = split ' ', $fdstring, 2; + open my $fh, $file or die $!; + my $oldfd = fileno $fh; + if ($oldfd != $fd) { + POSIX::dup2 $oldfd, $fd or die $!; + POSIX::close $oldfd or die $!; + } + } + %ENV = (ONLINE_JUDGE => 1, PATH => $ENV{PATH}, HOME => $ENV{HOME}); + setrlimit RLIMIT_AS, $mlimit, $mlimit or die $! if $mlimit; + setrlimit RLIMIT_FSIZE, $olimit, $olimit or die $! if $olimit; + exec @ARGV; +} + +1; __END__ =encoding utf-8 diff --git a/lib/Gruntmaster/Daemon/Format.pm b/lib/Gruntmaster/Daemon/Format.pm index 146ffb0..93035dd 100644 --- a/lib/Gruntmaster/Daemon/Format.pm +++ b/lib/Gruntmaster/Daemon/Format.pm @@ -8,18 +8,35 @@ no if $] > 5.017011, warnings => 'experimental::smartmatch'; use POSIX qw//; use File::Basename qw/fileparse/; -use File::Slurp qw/write_file/; +use File::Slurp qw/read_file write_file/; use Gruntmaster::Daemon::Constants qw/TLE OLE DIED NZX/; use Time::HiRes qw/alarm/; use List::MoreUtils qw/natatime/; use Log::Log4perl qw/get_logger/; use IPC::Signal qw/sig_name sig_num/; +use Try::Tiny; our $VERSION = "5999.000_004"; our @EXPORT_OK = qw/prepare_files/; ################################################## +sub execlist { + my (@args) = @_; + my $ret = fork // die 'Cannot fork'; + if ($ret) { + waitpid $ret, 0; + die "gruntmaster-exec died\n" if -z 'exec-result'; + my ($excode, $exmsg) = read_file 'exec-result'; + unlink 'exec-result'; + chomp ($excode, $exmsg); + die [$excode, $exmsg] if $excode > 0; + } else { + open STDOUT, '>exec-result'; + exec 'gruntmaster-exec', @args; + } +} + sub command_and_args{ my ($format, $basename) = @_; @@ -29,7 +46,7 @@ sub command_and_args{ java => $basename when 'JAVA'; perl => $basename when 'PERL'; python => $basename when 'PYTHON'; - default { die "Don't know how to execute format $format" } + default { die "Don't know how to execute format $format\n" } } } @@ -40,35 +57,16 @@ sub mkrun{ my ($name, %args) = @_; get_logger->trace("Running $name..."); my $basename = fileparse $name, qr/\.[^.]*/; - my $ret = fork // die 'Cannot fork'; - if ($ret) { - my $tle; - local $SIG{ALRM} = sub { kill KILL => $ret; $tle = 1}; - alarm $args{timeout} if exists $args{timeout}; - waitpid $ret, 0; - alarm 0; - my $sig = $? & 127; - my $signame = sig_name $sig; - die [TLE, "Time Limit Exceeded"] if $tle; - die [OLE, 'Output Limit Exceeded'] if $sig && $signame eq 'XFSZ'; - die [DIED, "Crash (SIG$signame)"] if $sig && $signame ne 'PIPE'; - die [NZX, "Non-zero exit status: " . ($? >> 8)] if $? >> 8; - } else { - my @fds = exists $args{fds} ? @{$args{fds}} : (); - $^F = 50; - POSIX::close $_ for 0 .. $^F; - my $it = natatime 2, @fds; - while (my ($fd, $file) = $it->()) { - open my $fh, $file or die $!; - my $oldfd = fileno $fh; - if ($oldfd != $fd) { - POSIX::dup2 $oldfd, $fd or die $!; - POSIX::close $oldfd or die $!; - } - } - exec 'gruntmaster-exec', $args{mlimit} // 0, $args{olimit} // 0, command_and_args($format, $basename), exists $args{args} ? @{$args{args}} : (); - exit 42 + my @args; + push @args, '--timeout', $args{timeout} if $args{timeout}; + push @args, '--mlimit', $args{mlimit} if $args{mlimit}; + push @args, '--olimit', $args{olimit} if $args{olimit}; + my @fds = exists $args{fds} ? @{$args{fds}} : (); + my $it = natatime 2, @fds; + while (my ($fd, $file) = $it->()) { + push @args, "--fd=$fd $file"; } + execlist @args, command_and_args($format, $basename); } } @@ -76,9 +74,15 @@ sub prepare{ my ($name, $format) = @_; get_logger->trace("Preparing file $name..."); - $Gruntmaster::Daemon::errors .= `gruntmaster-compile $format $name 2>&1`; - $Gruntmaster::Daemon::errors .= "\n"; - die 'Compile error' if $? + try { + execlist '--fd=1 >>errors', '--fd=2 >>errors', 'gruntmaster-compile', $format, $name; + } catch { + die "Compile error\n" + } finally { + $Gruntmaster::Daemon::errors .= read_file 'errors'; + $Gruntmaster::Daemon::errors .= "\n"; + unlink 'errors'; + }; } sub prepare_files{ diff --git a/selinux/gruntmasterd.fc b/selinux/gruntmasterd.fc deleted file mode 100644 index f867ea4..0000000 --- a/selinux/gruntmasterd.fc +++ /dev/null @@ -1,7 +0,0 @@ -/usr/(local/)?bin/gruntmasterd gen_context(system_u:object_r:gruntmasterd_exec_t, s0) -/usr/(local/)?bin/gruntmaster-compile gen_context(system_u:object_r:gruntmaster_compile_exec_t, s0) -/usr/(local/)?bin/gruntmaster-exec gen_context(system_u:object_r:gruntmaster_job_exec_t, s0) -/usr/(local/)?bin/gruntmaster-paged gen_context(system_u:object_r:gruntmaster_paged_exec_t, s0) -/etc/gruntmasterd(/.*)? gen_context(system_u:object_r:gruntmasterd_etc_t, s0) -/var/lib/gruntmasterd(/.*)? gen_context(system_u:object_r:gruntmasterd_var_lib_t, s0) -/var/log/gruntmasterd gen_context(system_u:object_r:gruntmasterd_log_t, s0) diff --git a/selinux/gruntmasterd.te b/selinux/gruntmasterd.te deleted file mode 100644 index 1cb8f12..0000000 --- a/selinux/gruntmasterd.te +++ /dev/null @@ -1,145 +0,0 @@ -policy_module(gruntmasterd, 1.0) - -define(`read_file_perms', `{ getattr ioctl read lock open }') -define(`read_dir_perms', `{ getattr ioctl read lock open search}') -define(`everything_file_perms', `{ getattr ioctl read lock open unlink setattr append write create rename link }') -define(`everything_dir_perms', `{ getattr ioctl read lock open search unlink setattr write create rename link rmdir remove_name reparent add_name }') -define(`domain_read_files', `allow $1 $2 : dir read_dir_perms; allow $1 $2 : file read_file_perms; allow $1 $2 : lnk_file read_file_perms;') -define(`domain_everything_files', `allow $1 $2 : dir everything_dir_perms; allow $1 $2 : file everything_file_perms; allow $1 $2 : lnk_file everything_file_perms;') -define(`gruntmaster_read', `domain_read_files(gruntmasterd_t, $1)') -define(`gruntmaster_everything', `domain_everything_files(gruntmasterd_t, $1)') - -require{ - type bin_t; - type http_port_t; - type httpd_sys_content_rw_t; - type httpd_sys_content_t; - type httpd_t; - type httpd_tmp_t; - type net_conf_t; - type port_t; - type proc_t; - type urandom_device_t; -} - -# Types -type gruntmasterd_t; -type gruntmasterd_etc_t; -type gruntmasterd_exec_t; -type gruntmasterd_log_t; -type gruntmasterd_tmp_t; -type gruntmasterd_var_lib_t; -type gruntmaster_job_t; -type gruntmaster_job_exec_t; -type gruntmaster_compile_t; -type gruntmaster_compile_exec_t; -type gruntmaster_paged_t; -type gruntmaster_paged_exec_t; - -domain_type(gruntmaster_job_t) -domain_entry_file(gruntmaster_job_t, gruntmaster_job_exec_t) -role system_r types gruntmaster_job_t; - -domain_type(gruntmaster_compile_t) -domain_entry_file(gruntmaster_compile_t, gruntmaster_compile_exec_t) -role system_r types gruntmaster_compile_t; -type_transition gruntmaster_compile_t gruntmasterd_tmp_t : file gruntmaster_job_exec_t; - -init_daemon_domain(gruntmaster_paged_t, gruntmaster_paged_exec_t) -type_transition gruntmaster_paged_t httpd_sys_content_t : { file dir } httpd_sys_content_rw_t; - -init_daemon_domain(gruntmasterd_t, gruntmasterd_exec_t) -logging_log_file(gruntmasterd_log_t) -logging_log_filetrans(gruntmasterd_t, gruntmasterd_log_t, file) -logging_search_logs(gruntmasterd_t) -type_transition gruntmasterd_t gruntmaster_compile_exec_t : process gruntmaster_compile_t; -type_transition gruntmasterd_t gruntmaster_job_exec_t : process gruntmaster_job_t; -type_transition gruntmasterd_t tmp_t : dir gruntmasterd_tmp_t; -files_type(gruntmasterd_tmp_t) -files_type(gruntmasterd_etc_t) -files_type(gruntmasterd_var_lib_t) - -# Daemon permissions -allow gruntmasterd_t { gruntmaster_compile_t gruntmaster_job_t } : process { sigkill siginh rlimitinh transition }; -allow gruntmasterd_t bin_t : file { execute execute_no_trans }; -allow gruntmasterd_t self : process fork; -allow gruntmasterd_t self:fifo_file everything_file_perms; -allow gruntmasterd_t urandom_device_t:chr_file read_file_perms; -allow gruntmasterd_t { gruntmaster_compile_exec_t gruntmaster_job_exec_t } : file execute; -allow gruntmasterd_t port_t:tcp_socket name_connect; -allow gruntmasterd_t http_port_t:tcp_socket name_connect; -allow gruntmasterd_t net_conf_t:file { read getattr open }; -allow gruntmasterd_t self:udp_socket { write read create connect getattr }; -allow gruntmasterd_t self:tcp_socket { read write create ioctl connect }; -dontaudit gruntmasterd_t { gruntmaster_compile_t gruntmaster_job_t } : process noatsecure; - -allow gruntmasterd_t tmp_t : dir { getattr write search add_name }; - -gruntmaster_read(bin_t) -gruntmaster_read(gruntmaster_compile_exec_t) -gruntmaster_read(gruntmasterd_etc_t) -gruntmaster_read(gruntmasterd_var_lib_t) -gruntmaster_read(gruntmaster_job_exec_t) -gruntmaster_read(httpd_sys_content_t) -gruntmaster_read(lib_t) -gruntmaster_read(proc_t) -gruntmaster_read(usr_t) - -gruntmaster_everything(gruntmasterd_log_t) -gruntmaster_everything(gruntmasterd_tmp_t) - -files_read_etc_files(gruntmasterd_t) -files_search_etc(gruntmasterd_t) -libs_use_ld_so(gruntmasterd_t) -libs_use_shared_libs(gruntmasterd_t) -miscfiles_read_localization(gruntmasterd_t) - -# Executor and job permissions -domain_read_files(gruntmaster_job_t, bin_t) -domain_read_files(gruntmaster_job_t, usr_t) -allow gruntmaster_job_t gruntmaster_job_exec_t : file { execute execute_no_trans }; -allow gruntmaster_job_t gruntmasterd_t:fd use; -allow gruntmaster_job_t gruntmasterd_t:process sigchld; -allow gruntmaster_job_t gruntmasterd_tmp_t : dir read_dir_perms; -allow gruntmaster_job_t gruntmasterd_tmp_t : file { getattr ioctl read write }; -allow gruntmaster_job_t init_t:fd use; -allow gruntmaster_job_t self:process setrlimit; -allow gruntmaster_job_t urandom_device_t:chr_file read_file_perms; - -libs_use_ld_so(gruntmaster_job_t) -libs_use_shared_libs(gruntmaster_job_t) -miscfiles_read_localization(gruntmaster_job_t) - -# Compile permissions -domain_everything_files(gruntmaster_compile_t, gruntmaster_job_exec_t) -domain_everything_files(gruntmaster_compile_t, tmp_t) -domain_read_files(gruntmaster_compile_t, bin_t) -domain_read_files(gruntmaster_compile_t, lib_t) -domain_read_files(gruntmaster_compile_t, proc_t) -domain_read_files(gruntmaster_compile_t, proc_t) -domain_read_files(gruntmaster_compile_t, usr_t) -domain_read_files(gruntmaster_compile_t, gruntmasterd_tmp_t) -allow gruntmaster_compile_t gruntmasterd_t : fifo_file { read write ioctl }; -allow gruntmaster_compile_t gruntmasterd_t:fd use; -allow gruntmaster_compile_t gruntmasterd_t:process sigchld; -allow gruntmaster_compile_t gruntmasterd_tmp_t:dir { write add_name }; -allow gruntmaster_compile_t self : fifo_file { read write ioctl }; -allow gruntmaster_compile_t self:process signal; -allow gruntmaster_compile_t urandom_device_t:chr_file read_file_perms; -allow gruntmaster_compile_t { bin_t lib_t } : file { execute execute_no_trans }; - -libs_use_ld_so(gruntmaster_compile_t) -libs_use_shared_libs(gruntmaster_compile_t) -miscfiles_read_localization(gruntmaster_compile_t) - -# Page generator permissions -domain_everything_files(gruntmaster_paged_t, httpd_sys_content_rw_t) -domain_read_files(gruntmaster_paged_t, usr_t) -domain_read_files(gruntmaster_paged_t, bin_t) -allow gruntmaster_paged_t urandom_device_t:chr_file read_file_perms; -allow gruntmaster_paged_t port_t:tcp_socket name_connect; -allow gruntmaster_paged_t self:tcp_socket { read write create ioctl connect }; - -libs_use_ld_so(gruntmaster_paged_t) -libs_use_shared_libs(gruntmaster_paged_t) -miscfiles_read_localization(gruntmaster_paged_t) -- 2.30.2 From 740c2415f3554be3989e05dc5f36ab6acf514114 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Thu, 22 Jan 2015 23:24:44 +0200 Subject: [PATCH 11/16] Rename t/problems/increment/int.cpp to ver.cpp --- t/problems/increment/meta.yml | 2 +- t/problems/increment/{int.cpp => ver.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename t/problems/increment/{int.cpp => ver.cpp} (100%) diff --git a/t/problems/increment/meta.yml b/t/problems/increment/meta.yml index ebf126a..0e18762 100644 --- a/t/problems/increment/meta.yml +++ b/t/problems/increment/meta.yml @@ -10,4 +10,4 @@ description: A trivial interactive problem files: ver: format: CPP - name: int.cpp + name: ver.cpp diff --git a/t/problems/increment/int.cpp b/t/problems/increment/ver.cpp similarity index 100% rename from t/problems/increment/int.cpp rename to t/problems/increment/ver.cpp -- 2.30.2 From 1b82f62be869ce3b61ab5e3b1f060546b75953c2 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Thu, 22 Jan 2015 23:26:26 +0200 Subject: [PATCH 12/16] Improve test directory naming --- t/01-jobs.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/01-jobs.t b/t/01-jobs.t index 5145a77..77c9144 100644 --- a/t/01-jobs.t +++ b/t/01-jobs.t @@ -43,7 +43,7 @@ my @problems = exists $ENV{TEST_PROBLEMS} ? map {"t/problems/$_"} split ' ', $EN plan tests => 3 * sum map { my @temp = <$_/tests/*>; scalar @temp } @problems; note "Problems to be tested: " . join ', ', @problems; -my $tempdir = tempdir CLEANUP => 1; +my $tempdir = tempdir "gruntmaster-daemon-testingXXXX", TMPDIR => 1, CLEANUP => 1; my $job = 0; -- 2.30.2 From 55e61ae897ee944a61d1a822170027cd376cec2a Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Thu, 22 Jan 2015 23:41:16 +0200 Subject: [PATCH 13/16] Do not load Gruntmaster::Data if not needed --- lib/Gruntmaster/Daemon.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Gruntmaster/Daemon.pm b/lib/Gruntmaster/Daemon.pm index 681a141..a84fc57 100644 --- a/lib/Gruntmaster/Daemon.pm +++ b/lib/Gruntmaster/Daemon.pm @@ -8,7 +8,6 @@ our $VERSION = '5999.000_004'; use Gruntmaster::Daemon::Constants qw/ERR/; use Gruntmaster::Daemon::Format qw/prepare_files/; -use Gruntmaster::Data; use File::Basename qw/fileparse/; use File::Temp qw/tempdir/; @@ -34,6 +33,8 @@ use constant FORMAT_EXTENSION => { ################################################## +sub purge; + my $db; sub safe_can_nodie { @@ -168,6 +169,7 @@ sub got_job{ } sub run{ + require Gruntmaster::Data; $db = Gruntmaster::Data->connect('dbi:Pg:'); Log::Log4perl->init('/etc/gruntmasterd/gruntmasterd-log.conf'); get_logger->info("gruntmasterd $VERSION started"); -- 2.30.2 From 7be8c37d42b6782bc5d94ea4e52dd1261ce6e3ae Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Thu, 22 Jan 2015 23:48:23 +0200 Subject: [PATCH 14/16] Drop privileges in gruntmaster-exec if possible --- gruntmaster-exec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gruntmaster-exec b/gruntmaster-exec index 49e915a..a4ae94d 100755 --- a/gruntmaster-exec +++ b/gruntmaster-exec @@ -64,6 +64,8 @@ if ($ret) { %ENV = (ONLINE_JUDGE => 1, PATH => $ENV{PATH}, HOME => $ENV{HOME}); setrlimit RLIMIT_AS, $mlimit, $mlimit or die $! if $mlimit; setrlimit RLIMIT_FSIZE, $olimit, $olimit or die $! if $olimit; + POSIX::setgid 65534; # Set group id to nogroup + POSIX::setuid 65534; # Set user id to nobody exec @ARGV; } -- 2.30.2 From fdb99417bb13ca0418a5ec8d9e240e29565225c4 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Thu, 22 Jan 2015 23:50:50 +0200 Subject: [PATCH 15/16] Add virtual machine support --- Makefile.PL | 2 + lib/Gruntmaster/Daemon.pm | 4 +- lib/Gruntmaster/Daemon/Format.pm | 64 ++++++++++++++------ lib/Gruntmaster/Daemon/Runner/Interactive.pm | 11 +++- makevm | 23 +++++++ runvm | 15 +++++ vm.conf | 13 ++++ 7 files changed, 111 insertions(+), 21 deletions(-) create mode 100755 makevm create mode 100755 runvm create mode 100644 vm.conf diff --git a/Makefile.PL b/Makefile.PL index 7f7b2cd..f7d5e99 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -33,12 +33,14 @@ WriteMakefile( sigtrap 0 BSD::Resource 0 + Expect::Simple 0 File::Slurp 0 Gruntmaster::Data 0 IPC::Signal 0 JSON 0 List::MoreUtils 0 Log::Log4perl 0 + String::ShellQuote 0 Try::Tiny 0/ }, META_MERGE => { diff --git a/lib/Gruntmaster/Daemon.pm b/lib/Gruntmaster/Daemon.pm index a84fc57..1d1ca01 100644 --- a/lib/Gruntmaster/Daemon.pm +++ b/lib/Gruntmaster/Daemon.pm @@ -7,7 +7,7 @@ use warnings; our $VERSION = '5999.000_004'; use Gruntmaster::Daemon::Constants qw/ERR/; -use Gruntmaster::Daemon::Format qw/prepare_files/; +use Gruntmaster::Daemon::Format qw/prepare_files stopvms/; use File::Basename qw/fileparse/; use File::Temp qw/tempdir/; @@ -127,6 +127,7 @@ sub process{ $meta->{result} = -1; $meta->{result_text} = $_; }; + stopvms; get_logger->info("Job result: " . $meta->{result_text}); return unless $jobr; @@ -169,6 +170,7 @@ sub got_job{ } sub run{ + warn "No GRUNTMASTER_VM environment variable. Running without a VM is a security risk.\n" unless $ENV{GRUNTMASTER_VM}; require Gruntmaster::Data; $db = Gruntmaster::Data->connect('dbi:Pg:'); Log::Log4perl->init('/etc/gruntmasterd/gruntmasterd-log.conf'); diff --git a/lib/Gruntmaster/Daemon/Format.pm b/lib/Gruntmaster/Daemon/Format.pm index 93035dd..5f503a1 100644 --- a/lib/Gruntmaster/Daemon/Format.pm +++ b/lib/Gruntmaster/Daemon/Format.pm @@ -6,35 +6,62 @@ use warnings; use parent qw/Exporter/; no if $] > 5.017011, warnings => 'experimental::smartmatch'; -use POSIX qw//; +use Expect::Simple; use File::Basename qw/fileparse/; use File::Slurp qw/read_file write_file/; -use Gruntmaster::Daemon::Constants qw/TLE OLE DIED NZX/; -use Time::HiRes qw/alarm/; use List::MoreUtils qw/natatime/; use Log::Log4perl qw/get_logger/; -use IPC::Signal qw/sig_name sig_num/; +use POSIX qw/mkfifo/; +use String::ShellQuote qw/shell_quote/; use Try::Tiny; our $VERSION = "5999.000_004"; -our @EXPORT_OK = qw/prepare_files/; +our @EXPORT_OK = qw/prepare_files stopvms/; ################################################## +our (%vm); + +sub runvm { + my ($name) = @_; + return unless $ENV{GRUNTMASTER_VM}; + mkfifo "$name.in", 0600; + mkfifo "$name.out", 0600; + get_logger->trace("Starting VM $name"); + $vm{$name} = Expect::Simple->new({ + Cmd => "$ENV{GRUNTMASTER_VM} $name", + Prompt => '# ', + DisconnectCmd => 'exit', + RawPty => 1, + Timeout => 10, + }); +} + +sub stopvms { %vm = () } + sub execlist { - my (@args) = @_; - my $ret = fork // die 'Cannot fork'; - if ($ret) { - waitpid $ret, 0; - die "gruntmaster-exec died\n" if -z 'exec-result'; - my ($excode, $exmsg) = read_file 'exec-result'; - unlink 'exec-result'; - chomp ($excode, $exmsg); - die [$excode, $exmsg] if $excode > 0; + my ($vm, @args) = @_; + my $er = "exec-result-$vm"; + if ($vm{$vm}) { + my $cmd = ">$er " . shell_quote 'gruntmaster-exec', @args; + get_logger->trace("Running in VM $vm: $cmd"); + $vm{$vm}->send($cmd); } else { - open STDOUT, '>exec-result'; - exec 'gruntmaster-exec', @args; + my $ret = fork // die 'Cannot fork'; + if ($ret) { + waitpid $ret, 0; + } else { + open STDOUT, ">$er"; + exec 'gruntmaster-exec', @args; + } } + + die "gruntmaster-exec died\n" if -z $er; + my ($excode, $exmsg) = read_file $er; + unlink $er; + chomp ($excode, $exmsg); + get_logger->trace("Exec result: $excode $exmsg"); + die [$excode, $exmsg] if $excode > 0; } sub command_and_args{ @@ -66,7 +93,7 @@ sub mkrun{ while (my ($fd, $file) = $it->()) { push @args, "--fd=$fd $file"; } - execlist @args, command_and_args($format, $basename); + execlist $basename, @args, command_and_args($format, $basename); } } @@ -75,7 +102,7 @@ sub prepare{ get_logger->trace("Preparing file $name..."); try { - execlist '--fd=1 >>errors', '--fd=2 >>errors', 'gruntmaster-compile', $format, $name; + execlist prog => '--fd=1 >>errors', '--fd=2 >>errors', 'gruntmaster-compile', $format, $name; } catch { die "Compile error\n" } finally { @@ -87,6 +114,7 @@ sub prepare{ sub prepare_files{ my $meta = shift; + runvm $_ for keys %{$meta->{files}}; for my $file (values %{$meta->{files}}) { my ($format, $name, $content) = @{$file}{qw/format name content/}; diff --git a/lib/Gruntmaster/Daemon/Runner/Interactive.pm b/lib/Gruntmaster/Daemon/Runner/Interactive.pm index 9118e15..1825fcd 100644 --- a/lib/Gruntmaster/Daemon/Runner/Interactive.pm +++ b/lib/Gruntmaster/Daemon/Runner/Interactive.pm @@ -21,10 +21,16 @@ sub run{ mkfifo 'fifo1', 0600 or die $! unless -e 'fifo1'; mkfifo 'fifo2', 0600 or die $! unless -e 'fifo2'; + if ($test == 1 && $ENV{GRUNTMASTER_VM}) { + exec 'cat ver.in' if fork; + exec 'cat prog.in' if fork; + } + my $ret = fork // get_logger->logdie("Fork failed: $!"); if ($ret) { try { - $meta->{files}{prog}{run}->($meta->{files}{prog}{name}, fds => [qw/0 fifo1 1 >fifo2/], map {defined $meta->{$_} ? ($_ => $meta->{$_}) : () } qw/timeout mlimit/); + my @fds = $ENV{GRUNTMASTER_VM} ? qw,0 /dev/ttyS1 1 >/dev/ttyS1, : qw/0 fifo1 1 >fifo2/; + $meta->{files}{prog}{run}->($meta->{files}{prog}{name}, fds => \@fds, map {defined $meta->{$_} ? ($_ => $meta->{$_}) : () } qw/timeout mlimit/); } catch { die $_ } finally { @@ -33,7 +39,8 @@ sub run{ die [WA, "Wrong Answer"] if $?; } else { try { - $meta->{files}{ver}{run}->($meta->{files}{ver}{name}, fds => [qw/1 >fifo1 0 fifo2 4 >result/], args => [$test], map {defined $meta->{$_} ? ($_ => $meta->{$_}) : () } qw/timeout mlimit/); + my @fds = $ENV{GRUNTMASTER_VM} ? qw,1 >/dev/ttyS1 0 /dev/ttyS1, : qw/1 >fifo1 0 fifo2/; + $meta->{files}{ver}{run}->($meta->{files}{ver}{name}, fds => [@fds, qw,4 >result,], args => [$test], map {defined $meta->{$_} ? ($_ => $meta->{$_}) : () } qw/timeout mlimit/); } catch { exit 1; }; diff --git a/makevm b/makevm new file mode 100755 index 0000000..433370f --- /dev/null +++ b/makevm @@ -0,0 +1,23 @@ +#!/bin/bash +[ `id -u` -eq 0 ] || echo 'This script must be run as root' && exit 1 +rm -rf vm/ vm.squashfs +multistrap -f vm.conf +ln -s vm/usr/bin/mawk vm/bin/awk +echo 'virtfs /mnt 9p trans=virtio,auto 0 0' > vm/etc/fstab +echo '/sbin/poweroff -f' > vm/.bash_logout +cat > vm/.profile < vm/etc/initramfs-tools/modules < Date: Thu, 22 Jan 2015 23:52:33 +0200 Subject: [PATCH 16/16] Fix test problem names --- t/problems/double/meta.yml | 2 +- t/problems/square/meta.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/t/problems/double/meta.yml b/t/problems/double/meta.yml index 8d4cede..9c6c4a6 100644 --- a/t/problems/double/meta.yml +++ b/t/problems/double/meta.yml @@ -1,5 +1,5 @@ --- -name: A-B +name: Double generator: File judge: Absolute runner: File diff --git a/t/problems/square/meta.yml b/t/problems/square/meta.yml index 660f161..330ea65 100644 --- a/t/problems/square/meta.yml +++ b/t/problems/square/meta.yml @@ -1,5 +1,5 @@ --- -name: A-B +name: Square generator: Run judge: Points runner: Verifier -- 2.30.2