2015-01-15 06:51:17 +01:00
|
|
|
#!/usr/bin/env perl
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2017-03-05 22:33:31 +01:00
|
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
2011-01-26 02:59:19 +01:00
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
|
2015-01-15 06:51:17 +01:00
|
|
|
use File::Basename;
|
2017-09-10 03:21:20 +02:00
|
|
|
use POSIX;
|
2015-01-15 06:51:17 +01:00
|
|
|
|
2017-09-10 03:21:20 +02:00
|
|
|
my $USERNAME = 'compiler';
|
2011-02-01 01:41:51 +01:00
|
|
|
my $USE_LOCAL = defined $ENV{'CC_LOCAL'};
|
|
|
|
|
2015-01-15 06:51:17 +01:00
|
|
|
# uncomment the following if installed to the virtual machine
|
|
|
|
# use constant MOD_DIR => '/usr/local/share/compiler_vm/languages';
|
|
|
|
|
2017-09-10 03:21:20 +02:00
|
|
|
use constant MOD_DIR => '/usr/local/share/compiler_vm/languages';
|
2015-01-15 06:51:17 +01:00
|
|
|
|
|
|
|
use lib MOD_DIR;
|
|
|
|
|
|
|
|
my %languages;
|
|
|
|
|
|
|
|
sub load_modules {
|
|
|
|
my @files = glob MOD_DIR . "/*.pm";
|
|
|
|
foreach my $mod (@files){
|
|
|
|
print "Loading module $mod\n";
|
|
|
|
my $filename = basename($mod);
|
|
|
|
require $filename;
|
|
|
|
$filename =~ s/\.pm$//;
|
|
|
|
$languages{$filename} = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub run_server {
|
2014-02-23 01:56:51 +01:00
|
|
|
my ($input, $output, $heartbeat);
|
2011-02-01 01:41:51 +01:00
|
|
|
|
|
|
|
if(not defined $USE_LOCAL or $USE_LOCAL == 0) {
|
|
|
|
open($input, '<', "/dev/ttyS0") or die $!;
|
|
|
|
open($output, '>', "/dev/ttyS0") or die $!;
|
2014-02-23 01:56:51 +01:00
|
|
|
open($heartbeat, '>', "/dev/ttyS1") or die $!;
|
2011-02-01 01:41:51 +01:00
|
|
|
} else {
|
|
|
|
open($input, '<', "/dev/stdin") or die $!;
|
|
|
|
open($output, '>', "/dev/stdout") or die $!;
|
|
|
|
}
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2012-10-24 14:26:18 +02:00
|
|
|
my $date;
|
2011-01-26 02:59:19 +01:00
|
|
|
my $lang;
|
2015-01-15 06:51:17 +01:00
|
|
|
my $sourcefile;
|
|
|
|
my $execfile;
|
2011-01-26 02:59:19 +01:00
|
|
|
my $code;
|
2015-01-15 06:51:17 +01:00
|
|
|
my $cmdline;
|
2011-01-26 02:59:19 +01:00
|
|
|
my $user_input;
|
|
|
|
|
|
|
|
print "Waiting for input...\n";
|
|
|
|
|
2014-02-23 01:56:51 +01:00
|
|
|
my $pid = fork;
|
|
|
|
die "Fork failed: $!" if not defined $pid;
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2014-02-23 01:56:51 +01:00
|
|
|
if($pid == 0) {
|
|
|
|
while(my $line = <$input>) {
|
|
|
|
chomp $line;
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2014-02-23 01:56:51 +01:00
|
|
|
print "Got [$line]\n";
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2014-02-23 01:56:51 +01:00
|
|
|
if($line =~ m/^compile:\s*end/) {
|
|
|
|
next if not defined $lang or not defined $code;
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2014-02-23 01:56:51 +01:00
|
|
|
print "Attempting compile [$lang] ...\n";
|
2012-01-30 00:50:33 +01:00
|
|
|
|
2017-09-10 03:21:20 +02:00
|
|
|
my $pid = fork;
|
2014-02-23 01:56:51 +01:00
|
|
|
|
2017-09-10 03:21:20 +02:00
|
|
|
if (not defined $pid) {
|
|
|
|
print "fork failed: $!\n";
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($pid == 0) {
|
|
|
|
my ($uid, $gid) = (getpwnam $USERNAME)[2, 3];
|
|
|
|
if (not $uid and not $gid) {
|
|
|
|
print "Could not find user $USERNAME: $!\n";
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
POSIX::setgid($gid);
|
|
|
|
POSIX::setuid($uid);
|
|
|
|
|
|
|
|
my $result = interpret($lang, $sourcefile, $execfile, $code, $cmdline, $user_input, $date);
|
|
|
|
|
|
|
|
print "Done compiling; result: [$result]\n";
|
|
|
|
print $output "result:$result\n";
|
|
|
|
print $output "result:end\n";
|
|
|
|
exit;
|
|
|
|
} else {
|
|
|
|
waitpid $pid, 0;
|
|
|
|
}
|
2014-02-23 01:56:51 +01:00
|
|
|
|
|
|
|
if(not defined $USE_LOCAL or $USE_LOCAL == 0) {
|
|
|
|
print "input: ";
|
|
|
|
next;
|
|
|
|
} else {
|
|
|
|
exit;
|
|
|
|
}
|
2011-02-01 01:41:51 +01:00
|
|
|
}
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2014-02-23 01:56:51 +01:00
|
|
|
if($line =~ m/^compile:\s*(.*)/) {
|
|
|
|
my $options = $1;
|
2015-01-15 06:51:17 +01:00
|
|
|
$cmdline = undef;
|
2014-02-23 01:56:51 +01:00
|
|
|
$user_input = undef;
|
|
|
|
$lang = undef;
|
2015-01-15 06:51:17 +01:00
|
|
|
$sourcefile = undef;
|
|
|
|
$execfile = undef;
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2015-01-15 06:51:17 +01:00
|
|
|
($lang, $sourcefile, $execfile, $cmdline, $user_input, $date) = split /:/, $options;
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2014-02-23 01:56:51 +01:00
|
|
|
$code = "";
|
2015-01-15 06:51:17 +01:00
|
|
|
$sourcefile = "/dev/null" if not defined $sourcefile;
|
|
|
|
$execfile = "/dev/null" if not defined $execfile;
|
|
|
|
$lang = "unknown" if not defined $lang;
|
|
|
|
$cmdline = "echo No cmdline specified!" if not defined $cmdline;
|
2014-02-23 01:56:51 +01:00
|
|
|
$user_input = "" if not defined $user_input;
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2015-01-15 06:51:17 +01:00
|
|
|
print "Setting lang [$lang]; [$sourcefile]; [$cmdline]; [$user_input]; [$date]\n";
|
2015-09-04 06:32:44 +02:00
|
|
|
|
2014-02-23 01:56:51 +01:00
|
|
|
next;
|
|
|
|
}
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2014-02-23 01:56:51 +01:00
|
|
|
$code .= $line . "\n";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while(1) {
|
|
|
|
print $heartbeat "\n";
|
|
|
|
sleep 1;
|
|
|
|
}
|
2011-01-26 02:59:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
close $input;
|
|
|
|
close $output;
|
2014-02-23 01:56:51 +01:00
|
|
|
close $heartbeat;
|
2011-01-26 02:59:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub interpret {
|
2015-01-15 06:51:17 +01:00
|
|
|
my ($lang, $sourcefile, $execfile, $code, $cmdline, $input, $date) = @_;
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2015-01-15 06:51:17 +01:00
|
|
|
print "lang: [$lang], sourcefile: [$sourcefile], execfile [$execfile], code: [$code], cmdline: [$cmdline], input: [$input], date: [$date]\n";
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2015-01-15 06:51:17 +01:00
|
|
|
$lang = '_default' if not exists $languages{$lang};
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2014-02-23 01:56:51 +01:00
|
|
|
system("chmod -R 755 /home/compiler");
|
2017-09-10 03:21:20 +02:00
|
|
|
system("rm -rf /home/compiler/prog*");
|
2014-02-23 01:56:51 +01:00
|
|
|
|
2015-01-15 06:51:17 +01:00
|
|
|
my $mod = $lang->new(sourcefile => $sourcefile, execfile => $execfile, code => $code,
|
|
|
|
cmdline => $cmdline, input => $input, date => $date);
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2015-01-15 06:51:17 +01:00
|
|
|
$mod->preprocess;
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2015-05-19 05:48:15 +02:00
|
|
|
$mod->postprocess if not $mod->{error} and not $mod->{done};
|
2011-01-26 02:59:19 +01:00
|
|
|
|
2015-01-17 02:28:38 +01:00
|
|
|
if (exists $mod->{no_output} or not length $mod->{output}) {
|
|
|
|
$mod->{output} .= "\n" if length $mod->{output};
|
|
|
|
$mod->{output} .= "Success (no output).\n" if not $mod->{error};
|
|
|
|
$mod->{output} .= "Success (exit code $mod->{error}).\n" if $mod->{error};
|
2011-01-26 02:59:19 +01:00
|
|
|
}
|
|
|
|
|
2015-01-15 06:51:17 +01:00
|
|
|
return $mod->{output};
|
2011-01-26 02:59:19 +01:00
|
|
|
}
|
|
|
|
|
2015-01-15 06:51:17 +01:00
|
|
|
load_modules;
|
|
|
|
run_server;
|