Interactive mode
diff --git a/judger-v2/Config.cpp b/judger-v2/Config.cpp
index 48f9e66..dfb5617 100644
--- a/judger-v2/Config.cpp
+++ b/judger-v2/Config.cpp
@@ -14,13 +14,14 @@
dispatcher_port = atoi(ini.top()["dispatcher_port"].c_str());
low_privilege_uid = atoi(ini.top()["low_privilege_uid"].c_str());
general_compile_time = atoi(ini.top()["general_compile_time"].c_str());
- generator_run_time = atoi(ini.top()["generator_run_time"].c_str());
+// generator_run_time = atoi(ini.top()["generator_run_time"].c_str());
generator_run_memory = atoi(ini.top()["generator_run_memory"].c_str());
vmlang_multiplier = atoi(ini.top()["vmlang_multiplier"].c_str());
max_output_limit = atoi(ini.top()["max_output_limit"].c_str());
extra_runtime = atoi(ini.top()["extra_runtime"].c_str());
checker_run_time = atoi(ini.top()["checker_run_time"].c_str());
checker_run_memory = atoi(ini.top()["checker_run_memory"].c_str());
+ interactive_max_run_time = atoi(ini.top()["interactive_max_run_time"].c_str());
tmpfile_path = ini.top()["tmpfile_path"];
} catch (runtime_error & e) {
cerr << e.what();
diff --git a/judger-v2/Config.h b/judger-v2/Config.h
index 37084be..230a093 100644
--- a/judger-v2/Config.h
+++ b/judger-v2/Config.h
@@ -135,6 +135,15 @@
this->vmlang_multiplier = vmlang_multiplier;
}
+ int GetInteractive_max_run_time() const {
+ return interactive_max_run_time;
+ }
+
+ void SetInteractive_max_run_time(int interactive_max_run_time) {
+ this->interactive_max_run_time = interactive_max_run_time;
+ }
+
+
protected:
@@ -151,6 +160,7 @@
int extra_runtime;
int checker_run_time;
int checker_run_memory;
+ int interactive_max_run_time;
string judge_connect_string;
string tmpfile_path;
diff --git a/judger-v2/Interactive.cpp b/judger-v2/Interactive.cpp
new file mode 100644
index 0000000..06ef692
--- /dev/null
+++ b/judger-v2/Interactive.cpp
@@ -0,0 +1,446 @@
+/*
+ * File: Interactive.cpp
+ * Author: payper
+ *
+ * Created on 2014年4月24日, 下午5:41
+ */
+
+#include "Interactive.h"
+#include "Logger.h"
+
+extern bool syscalls_other[500];
+extern bool syscalls_java[500];
+extern bool syscalls_csharp[500];
+extern int GENERAL_COMPILE_TIME,GENERATOR_RUN_TIME,GENERATOR_RUN_MEMORY,VMLANG_MULTIPLIER,MAX_OUTPUT_LIMIT,EXTRA_RUNTIME;
+extern int lowprivid;
+extern string tmpnam();
+
+Interactive::Interactive() : Program() {
+ validator_compiled = false;
+}
+
+Interactive::~Interactive() {
+ if (validator_base_filename!="") Deletefile(validator_base_filename+"*");
+ if (Checkfile(validator_src_filename)) Deletefile(validator_src_filename);
+ if (Checkfile(validator_exc_filename)) Deletefile(validator_exc_filename);
+ if (Checkfile(validator_err_filename)) Deletefile(validator_err_filename);
+}
+
+int Interactive::Excution() {
+ system(((string)"chmod +x "+exc_filename).c_str());
+ system(((string)"chmod +x "+validator_exc_filename).c_str());
+ res_filename=tmpnam();
+ struct rlimit runtime;
+ runtime.rlim_max=runtime.rlim_cur=CONFIG->GetInteractive_max_run_time()+EXTRA_RUNTIME;
+ pid_t wid;
+ if ((wid=fork())==0) {
+ pid_t pgrp = getpid();
+ pid_t vpid;
+ int vtorPipe[2];
+ int rtovPipe[2];
+ pipe(vtorPipe);
+ pipe(rtovPipe);
+ if ((vpid = fork()) == 0) {
+ setpgid(0, pgrp);
+ LOGGER->addIdentifier(getpid(), "Sandbox");
+ dup2(vtorPipe[0], STDIN_FILENO);
+ dup2(rtovPipe[1], STDOUT_FILENO);
+ close(vtorPipe[0]);
+ close(vtorPipe[1]);
+ close(rtovPipe[0]);
+ close(rtovPipe[1]);
+
+ string exc_command;
+ pid_t pid;
+ int runstat;
+ bool excuted=false;
+ struct rusage rinfo;
+ setrlimit(RLIMIT_CPU,&runtime);
+ struct user_regs_struct reg;
+ struct rlimit time_limit,output_limit;
+
+ time_limit.rlim_cur=case_time_limit<total_time_limit-time_used?case_time_limit:total_time_limit-time_used;
+ time_limit.rlim_cur=(time_limit.rlim_cur+999)/1000;
+ if (time_limit.rlim_cur<=0) time_limit.rlim_cur=1;
+ time_limit.rlim_max=time_limit.rlim_cur+1;
+ if ((pid=fork())==0) {
+ LOGGER->addIdentifier(getpid(), "Runner");
+ setpgid(0, pgrp);
+ LOG((string)"Time limit for this program is "+Inttostring(time_limit.rlim_cur));
+ setrlimit(RLIMIT_CPU,&time_limit);
+
+ setuid(lowprivid);
+ ptrace(PTRACE_TRACEME,0,NULL,NULL);
+
+ switch (language) {
+ case CPPLANG:
+ case CLANG:
+ case FORTLANG:
+ case FPASLANG:
+ case SMLLANG:
+ case ADALANG:
+ exc_command=(string)"./"+exc_filename;
+ execl(exc_command.c_str(),exc_command.c_str(),NULL);
+ break;
+ case JAVALANG:
+ execl("/usr/bin/java","java","-Djava.security.manager","-Djava.security.policy=java.policy","-client","-cp",CONFIG->GetTmpfile_path().c_str(),"Main",NULL);
+ break;
+ case CSLANG:
+ execl("/usr/bin/mono","mono",exc_filename.c_str(),NULL);
+ break;
+ case PERLLANG:
+ execl("/usr/bin/perl","perl",src_filename.c_str(),"-W",NULL);
+ case RUBYLANG:
+ execl("/usr/bin/ruby","ruby",src_filename.c_str(),"-W",NULL);
+ break;
+ case PYLANG:
+ execl("/usr/bin/python","python",exc_filename.c_str(),NULL);
+ break;
+ }
+ exit(0);
+ }
+ else {
+ if (language<MIN_LANG_NUM||language>MAX_LANG_NUM||language==VCLANG||language==VCPPLANG) {
+ result="Invalid Language";
+ LOG("Invalid Language Detected");
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ exit(0);
+ }
+ LOG("Program Child Process: "+Inttostring(pid));
+ LOG("Running program");
+ runstat=0;
+ struct timeval case_startv;
+ struct timezone case_startz;
+ gettimeofday(&case_startv,&case_startz);
+ while (1) {
+ wait4(pid,&runstat,0,&rinfo);
+ time_used=(rinfo.ru_utime.tv_sec+rinfo.ru_stime.tv_sec)*1000+(rinfo.ru_utime.tv_usec+rinfo.ru_stime.tv_usec)/1000;
+ if (total_time_limit<time_used) {
+ LOG("Dectect TLE, type:1, LOOP found. Time used: "+Inttostring(time_used)+", Limit: "+Inttostring(total_time_limit));
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ result="Time Limit Exceed";
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ break;
+ }
+ if (memory_used<getpagesize()*rinfo.ru_minflt) memory_used=getpagesize()*rinfo.ru_minflt;
+ if (WIFEXITED(runstat)) {
+ LOG((string)"Used time: "+Inttostring(time_used));
+ LOG((string)"Used Memory: "+Inttostring(memory_used));
+ LOG((string)"Run status: "+Inttostring(WEXITSTATUS(runstat)));
+ if (check_exit_status&&WEXITSTATUS(runstat)!=0) result="Runtime Error";
+ else result="Normal";
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ break;
+ }
+ if (WIFSIGNALED(runstat)&&WTERMSIG(runstat)!=SIGTRAP) {
+ int signal=WTERMSIG(runstat);
+ LOG((string)"Used time: "+Inttostring(time_used));
+ LOG((string)"Used Memory: "+Inttostring(memory_used));
+ LOG((string)"Run status: "+Inttostring(runstat));
+ switch (signal)
+ {
+ case SIGXCPU:
+ LOG("Dectect TLE, type:2, signaled");
+ result="Time Limit Exceed";
+ time_used=time_limit.rlim_cur*1000+4;
+ break;
+ case SIGXFSZ:
+ result="Output Limit Exceed";
+ break;
+ default:
+ result="Runtime Error";
+ }
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ break;
+ }
+ else if (WIFSTOPPED(runstat)&&WSTOPSIG(runstat)!=SIGTRAP) {
+ int signal=WSTOPSIG(runstat);
+ LOG((string)"Used time: "+Inttostring(time_used));
+ LOG((string)"Used Memory: "+Inttostring(memory_used));
+ LOG((string)"Run status: "+Inttostring(runstat));
+ switch (signal)
+ {
+ case SIGXCPU:
+ result="Time Limit Exceed";
+ LOG("Dectect TLE, type:2, signaled");
+ time_used=time_limit.rlim_cur*1000+4;
+ break;
+ case SIGXFSZ:
+ result="Output Limit Exceed";
+ break;
+ default:
+ result="Runtime Error";
+ }
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ break;
+ }
+ else if ((runstat>>8)!=5&&(runstat>>8)>0) {
+ LOG((string)"Used time: "+Inttostring(time_used));
+ LOG((string)"Used Memory: "+Inttostring(memory_used));
+ LOG((string)"Run status: "+Inttostring(runstat));
+ result="Runtime Error";
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ break;
+ }
+ ptrace(PTRACE_GETREGS,pid,NULL,®);
+ #ifdef __i386__
+ //printf("System call:%ld\n",reg.orig_eax);
+ if (reg.orig_eax==SYS_execve&&!excuted) excuted=true;
+ else {
+ if (language==JAVALANG) {
+ if (syscalls_java[reg.orig_eax]) {
+ LOG((string)"Invalid system call: "+ Inttostring(reg.orig_eax));
+ result="Restricted Function";
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ exit(0);
+ }
+ }
+ else if (language==CSLANG) {
+ if (syscalls_csharp[reg.orig_eax]) {
+ LOG((string)"Invalid system call: "+ Inttostring(reg.orig_eax));
+ result="Restricted Function";
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ exit(0);
+ }
+ }
+ else if (syscalls_other[reg.orig_eax]) {
+ LOG((string)"Invalid system call: "+ Inttostring(reg.orig_eax));
+ result="Restricted Function";
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ exit(0);
+ }
+ }
+ #else
+ //printf("System call:%ld\n",reg.orig_rax);
+ if (reg.orig_rax==SYS_execve&&!excuted) excuted=true;
+ else {
+ if (language==JAVALANG) {
+ if (syscalls_java[reg.orig_rax]) {
+ LOG((string)"Invalid system call: "+ Inttostring(reg.orig_rax));
+ result="Restricted Function";
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ break;
+ }
+ }
+ else if (language==CSLANG) {
+ if (syscalls_csharp[reg.orig_rax]) {
+ LOG((string)"Invalid system call: "+ Inttostring(reg.orig_rax));
+ result="Restricted Function";
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ break;
+ }
+ }
+ else if (syscalls_other[reg.orig_rax]) {
+ LOG((string)"Invalid system call: "+ Inttostring(reg.orig_rax));
+ result="Restricted Function";
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ break;
+ }
+ }
+ #endif
+ if (memory_used/1024>memory_limit) {
+ LOG((string)"Used time: "+Inttostring(time_used));
+ LOG((string)"Used Memory: "+Inttostring(memory_used));
+ LOG((string)"Run status: "+Inttostring(runstat));
+ result="Memory Limit Exceed";
+ result+="\n"+Inttostring(time_used)+"\n"+Inttostring(memory_used);
+ Savetofile(res_filename,result);
+ ptrace(PTRACE_KILL,pid,NULL,NULL);
+ break;
+ }
+ ptrace(PTRACE_SYSCALL,pid,NULL,NULL);
+ }
+ exit(0);
+ }
+ exit(0);
+ } else {
+ pid_t pvid;
+ if ((pvid = fork()) == 0) {
+ LOGGER->addIdentifier(getpid(), "Validator");
+ setpgid(0, pgrp);
+ dup2(rtovPipe[0], STDIN_FILENO);
+ dup2(vtorPipe[1], STDOUT_FILENO);
+ close(vtorPipe[0]);
+ close(vtorPipe[1]);
+ close(rtovPipe[0]);
+ close(rtovPipe[1]);
+
+ string exc_command;
+ setuid(lowprivid);
+
+ switch (language) {
+ case CPPLANG:
+ case CLANG:
+ case FORTLANG:
+ case FPASLANG:
+ case SMLLANG:
+ case ADALANG:
+ exc_command=(string)"./"+exc_filename;
+ execl(exc_command.c_str(),exc_command.c_str(),NULL);
+ break;
+ case JAVALANG:
+ execl("/usr/bin/java","java","-Djava.security.manager","-Djava.security.policy=java.policy","-client","-cp",CONFIG->GetTmpfile_path().c_str(),"Main",NULL);
+ break;
+ case CSLANG:
+ execl("/usr/bin/mono","mono",exc_filename.c_str(),NULL);
+ break;
+ case PERLLANG:
+ execl("/usr/bin/perl","perl",src_filename.c_str(),"-W",NULL);
+ case RUBYLANG:
+ execl("/usr/bin/ruby","ruby",src_filename.c_str(),"-W",NULL);
+ break;
+ case PYLANG:
+ execl("/usr/bin/python","python",exc_filename.c_str(),NULL);
+ break;
+ }
+ exit(0);
+ } else {
+ LOGGER->addIdentifier(getpid(), "ValidatorRunner");
+ int rstat, cstat, waitcnt;
+ while (1) {
+ usleep(50000);
+ waitpid(pvid, &rstat, WNOHANG);
+ if (WIFEXITED(rstat)) {
+ waitpid(pvid, &rstat, 0);
+ LOG("Validator runned.");
+ waitcnt = 10;
+ while (waitcnt--) {
+ usleep(50000);
+ waitpid(vpid, &cstat, WNOHANG);
+ if (WIFEXITED(cstat)) {
+ waitpid(vpid,&cstat,0);
+ LOG("User program runned.");
+ exit(WEXITSTATUS(rstat));
+ }
+ }
+ kill(-pgrp, SIGKILL);
+ exit(1);
+ }
+
+ waitpid(vpid, &cstat, WNOHANG);
+ if (WIFEXITED(cstat)) {
+ waitpid(vpid,&cstat,0);
+ LOG("User program runned.");
+ waitcnt = 10;
+ while (waitcnt--) {
+ usleep(50000);
+ waitpid(pvid, &rstat, 0);
+ if (WIFEXITED(rstat)) {
+ waitpid(pvid, &rstat, 0);
+ LOG("Validator runned.");
+ exit(WEXITSTATUS(rstat));
+ }
+ }
+ kill(-pgrp, SIGKILL);
+ exit(1);
+ }
+ }
+ exit(0);
+ }
+ }
+ exit(0);
+ }
+ else {
+ LOG("Watch Child Process: "+Inttostring(wid));
+ int rstat,tused;
+ struct timeval case_startv,case_nowv;
+ struct timezone case_startz,case_nowz;
+ gettimeofday(&case_startv,&case_startz);
+ int cnt=-1;
+ while (1) {
+ usleep(50000);
+ cnt++;
+ gettimeofday(&case_nowv,&case_nowz);
+ tused=case_nowv.tv_sec-case_startv.tv_sec;
+ if (cnt%20==0) LOG("Running Used: "+Inttostring(tused));
+ if (waitpid(wid,&rstat,WNOHANG)==0) {
+ if (tused>runtime.rlim_max) {
+ result="Judge Error";
+ LOG("Time too much!");
+ LOG("kill `pstree -p "+Inttostring(wid)+" | sed 's/(/\\n(/g' | grep '(' | sed 's/(\\(.*\\)).*/\\1/' | tr \"\\n\" \" \"`");
+ system(("kill `pstree -p "+Inttostring(wid)+" | sed 's/(/\\n(/g' | grep '(' | sed 's/(\\(.*\\)).*/\\1/' | tr \"\\n\" \" \"`").c_str());
+ waitpid(wid,&rstat,0);
+ return 1;
+ }
+ }
+ else if (WIFSIGNALED(rstat) && WTERMSIG(rstat)!=0) {
+ result="Judge Error";
+ LOG("Something is wrong.");
+ LOG("kill `pstree -p "+Inttostring(wid)+" | sed 's/(/\\n(/g' | grep '(' | sed 's/(\\(.*\\)).*/\\1/' | tr \"\\n\" \" \"`");
+ system(("kill `pstree -p "+Inttostring(wid)+" | sed 's/(/\\n(/g' | grep '(' | sed 's/(\\(.*\\)).*/\\1/' | tr \"\\n\" \" \"`").c_str());
+ waitpid(wid,&rstat,0);
+ return 1;
+ }
+ if (WIFEXITED(rstat)) {
+ waitpid(wid,&rstat,0);
+ LOG("Runned.");
+ break;
+ }
+ }
+ string res="";
+ fstream fin(res_filename.c_str(),fstream::in);
+ while (fin.fail()) fin.open(res_filename.c_str(),fstream::in);
+ //system(("kill -9 "+Inttostring(wid)).c_str());
+ int case_time_used,case_memory_used;
+ getline(fin,result);
+ fin>>case_time_used>>case_memory_used;
+ time_used+=case_time_used;
+ memory_used=max(memory_used,case_memory_used);
+ fin.close();
+ if (result==""||result==" ") {
+ result="Judge Error";
+ LOG("Failed to get result.");
+ } else if (result == "Normal") {
+ if (WEXITSTATUS(rstat) == 0) result = "Accepted";
+ else result = "Wrong Answer";
+ }
+ system(("rm "+res_filename).c_str());
+ }
+ return 0;
+}
+
+void Interactive::Run() {
+ if (!validator_compiled) {
+ Setresult("");
+ // reuse compile function
+ Trytocompile(validator_source, validator_language);
+ if (Getresult() != "") {
+ Setresult("Judge Error");
+ return;
+ }
+
+ // copy compile result of validator
+ validator_base_filename = Getbase_filename();
+ validator_src_filename = Getsrc_filename();
+ validator_exc_filename = Getexc_filename();
+ validator_err_filename = Geterr_filename();
+ }
+ if (!Getcompiled()) {
+ Setresult("");
+ Trytocompile(source, language);
+ if (Getresult() != "") return;
+ }
+ Excution();
+ if (total_time_limit<time_used) result="Time Limit Exceed";
+}
diff --git a/judger-v2/Interactive.h b/judger-v2/Interactive.h
new file mode 100644
index 0000000..25fe880
--- /dev/null
+++ b/judger-v2/Interactive.h
@@ -0,0 +1,86 @@
+/*
+ * File: Interactive.h
+ * Author: payper
+ *
+ * Created on 2014年4月24日, 下午5:41
+ */
+
+#ifndef INTERACTIVE_H
+#define INTERACTIVE_H
+
+#include "Program.h"
+
+class Interactive : public Program {
+public:
+ Interactive();
+ virtual ~Interactive();
+
+ string GetValidator_base_filename() const {
+ return validator_base_filename;
+ }
+
+ void SetValidator_base_filename(string validator_base_filename) {
+ this->validator_base_filename = validator_base_filename;
+ }
+
+ bool IsValidator_compiled() const {
+ return validator_compiled;
+ }
+
+ void SetValidator_compiled(bool validator_compiled) {
+ this->validator_compiled = validator_compiled;
+ }
+
+ string GetValidator_exc_filename() const {
+ return validator_exc_filename;
+ }
+
+ void SetValidator_exc_filename(string validator_exc_filename) {
+ this->validator_exc_filename = validator_exc_filename;
+ }
+
+ int GetValidator_language() const {
+ return validator_language;
+ }
+
+ void SetValidator_language(int validator_language) {
+ this->validator_language = validator_language;
+ }
+
+ string GetValidator_source() const {
+ return validator_source;
+ }
+
+ void SetValidator_source(string validator_source) {
+ this->validator_source = validator_source;
+ }
+
+ string GetValidator_src_filename() const {
+ return validator_src_filename;
+ }
+
+ void SetValidator_src_filename(string validator_src_filename) {
+ this->validator_src_filename = validator_src_filename;
+ }
+
+ void Run();
+
+private:
+ int Excution();
+
+ string validator_base_filename;
+ string validator_src_filename;
+ string validator_exc_filename;
+ string validator_in_filename;
+ string validator_out_filename;
+ string validator_err_filename;
+ string validator_res_filename;
+
+ bool validator_compiled;
+
+ string validator_source;
+ int validator_language;
+};
+
+#endif /* INTERACTIVE_H */
+
diff --git a/judger-v2/PConfig.cpp b/judger-v2/PConfig.cpp
index 92b6c83..50b82e9 100644
--- a/judger-v2/PConfig.cpp
+++ b/judger-v2/PConfig.cpp
@@ -22,6 +22,8 @@
data_checker_language = atoi(ini.top()["data_checker_language"].c_str());
solution_filename = basedir + ini.top()["solution_filename"];
solution_language = atoi(ini.top()["solution_language"].c_str());
+ validator_filename = basedir + ini.top()["validator_filename"];
+ validator_language = atoi(ini.top()["validator_language"].c_str());
error = false;
} catch (runtime_error & e) {
error = true;
diff --git a/judger-v2/PConfig.h b/judger-v2/PConfig.h
index c716aa5..2eb25dc 100644
--- a/judger-v2/PConfig.h
+++ b/judger-v2/PConfig.h
@@ -20,12 +20,31 @@
void Setsolution_language(int val) { solution_language = val; }
bool Geterror() { return error; }
void Seterror(bool val) { error = val; }
+
+ string Getvalidator_filename() const {
+ return validator_filename;
+ }
+
+ void Setvalidator_filename(string validator_filename) {
+ this->validator_filename = validator_filename;
+ }
+
+ int Getvalidator_language() const {
+ return validator_language;
+ }
+
+ void Setvalidator_language(int validator_language) {
+ this->validator_language = validator_language;
+ }
+
protected:
private:
string data_checker_filename;
string solution_filename;
+ string validator_filename;
int data_checker_language;
int solution_language;
+ int validator_language;
string basedir;
map <string,string> config;
bool error;
diff --git a/judger-v2/Program.cpp b/judger-v2/Program.cpp
index fb0e8ac..6fcf7a1 100644
--- a/judger-v2/Program.cpp
+++ b/judger-v2/Program.cpp
@@ -14,6 +14,8 @@
result="";
base_filename="";
time_used=memory_used=0;
+ compile_time_limit=GENERAL_COMPILE_TIME;
+ if (vmlang[language]) compile_time_limit=GENERAL_COMPILE_TIME*3;
check_exit_status=false;
if (!para_inited) {
init_error();
@@ -93,7 +95,7 @@
return t;
}
-int Program::Compile() {
+int Program::Compile(string source, int language) {
cinfo_filename = CONFIG->GetTmpfile_path() + tmpnam()+".txt";
if (language!=JAVALANG) base_filename = CONFIG->GetTmpfile_path() + tmpnam();
else base_filename = CONFIG->GetTmpfile_path() + "Main";
@@ -512,41 +514,51 @@
return 0;
}
-void Program::Run()
-{
- if (!compiled) {
- compile_time_limit=GENERAL_COMPILE_TIME;
- if (vmlang[language]) compile_time_limit=GENERAL_COMPILE_TIME*3;
- int res=Compile();
- compiled=true;
- if (res==-1) {
- //JUDGE ERROR
- result="Invalid Language";
- return;
- }
- else if (res==2) {
- //COMPILE ERROR
+void Program::Trytocompile(string source, int language) {
+ if (source == "") {
+ source = this->source;
+ }
+ if (language == -1) {
+ language = this->language;
+ }
+ int res=Compile(source, language);
+ compiled=true;
+ if (res==-1) {
+ //JUDGE ERROR
+ result="Invalid Language";
+ return;
+ }
+ else if (res==2) {
+ //COMPILE ERROR
+ result="Compile Error";
+ return;
+ }
+ int cnt=0;
+ while (res==1) {
+ cnt++;
+ ce_info=Loadallfromfile(cinfo_filename,200);
+ if (ce_info.length()>0||cnt>2) {
result="Compile Error";
return;
}
- int cnt=0;
- while (res==1) {
- cnt++;
- ce_info=Loadallfromfile(cinfo_filename,200);
- if (ce_info.length()>0||cnt>2) {
- result="Compile Error";
- return;
- }
- else {
- usleep(50000);
- res=Compile();
- }
+ else {
+ usleep(50000);
+ res=Compile(source, language);
}
- if (vmlang[language]) {
- total_time_limit*=VMLANG_MULTIPLIER;
- case_time_limit*=VMLANG_MULTIPLIER;
- memory_limit*=VMLANG_MULTIPLIER;
- }
+ }
+ if (vmlang[language]) {
+ total_time_limit*=VMLANG_MULTIPLIER;
+ case_time_limit*=VMLANG_MULTIPLIER;
+ memory_limit*=VMLANG_MULTIPLIER;
+ }
+}
+
+void Program::Run()
+{
+ if (!compiled) {
+ result = "";
+ Trytocompile(source, language);
+ if (result != "") return;
}
if (exc_filename!=src_filename) {
string tmps=CONFIG->GetTmpfile_path() + tmpnam();
diff --git a/judger-v2/Program.h b/judger-v2/Program.h
index cc2d37f..be87f6e 100644
--- a/judger-v2/Program.h
+++ b/judger-v2/Program.h
@@ -46,35 +46,56 @@
void Setcheck_exit_status(bool val) { check_exit_status = val; }
string Loadallfromfile(string filename,int limit=-1);
void Run();
- int Compile();
+ int Compile(string, int);
+ void Trytocompile(string, int);
void Savetofile(string filename,string content);
bool Checkfile(string);
string Inttostring(int);
+
+ string Getbase_filename() const {
+ return base_filename;
+ }
+
+ void Setbase_filename(string base_filename) {
+ this->base_filename = base_filename;
+ }
+
+ string Geterr_filename() const {
+ return err_filename;
+ }
+
+ void Seterr_filename(string err_filename) {
+ this->err_filename = err_filename;
+ }
+
+
protected:
- private:
- int Excution();
void Deletefile(string);
- string base_filename;
- string src_filename;
- string exc_filename;
- string in_filename;
- string out_filename;
- string err_filename;
- string res_filename;
- bool compiled;
- string cinfo_filename;
- string ce_info;
int total_time_limit;
int case_time_limit;
int memory_limit;
int time_used;
int memory_used;
- int language;
- string source;
+ string exc_filename;
string result;
+ string res_filename;
+ bool check_exit_status;
+ string source;
+ int language;
+ string src_filename;
+ private:
+ int Excution();
+ string base_filename;
+ string in_filename;
+ string out_filename;
+ string err_filename;
+ bool compiled;
+ string cinfo_filename;
+ string ce_info;
+
int compile_time_limit;
bool has_input;
- bool check_exit_status;
+
static bool para_inited;
};
diff --git a/judger-v2/chaclient.cpp b/judger-v2/chaclient.cpp
index e358ef6..8749b64 100644
--- a/judger-v2/chaclient.cpp
+++ b/judger-v2/chaclient.cpp
@@ -6,6 +6,7 @@
#include "PConfig.h"
#include "ini.hpp"
#include "SocketHandler.h"
+#include "Interactive.h"
map <string,string> config;
@@ -377,6 +378,35 @@
send_result(retbott.Getout_filename());
}
+void dointeractive() {
+ LOG("Runid: "+Inttostring(bott->Getrunid())+" Type: Interactive");
+
+ retbott.Settype(RESULT_REPORT);
+ retbott.Setrunid(bott->Getrunid());
+ Interactive * usrprogram=new Interactive;
+ usrprogram->Setlanguage(bott->Getlanguage());
+ usrprogram->Setsource(bott->Getsrc());
+ problem=new PConfig(bott->Getpid());
+ usrprogram->SetValidator_source(Loadallfromfile(problem->Getvalidator_filename()));
+ usrprogram->SetValidator_language(problem->Getvalidator_language());
+
+ usrprogram->Setcase_time_limit(bott->Getcase_limit());
+ usrprogram->Settotal_time_limit(bott->Gettime_limit());
+ usrprogram->Setmemory_limit(bott->Getmemory_limit());
+
+ usrprogram->Run();
+ retbott.Setce_info(usrprogram->Getce_info());
+ retbott.Settime_used(usrprogram->Gettime_used());
+ retbott.Setmemory_used(usrprogram->Getmemory_used());
+ retbott.Setresult(usrprogram->Getresult());
+
+ retbott.Setout_filename("results/"+Inttostring(retbott.Getrunid()));
+ retbott.toFile();
+ delete usrprogram;
+ delete problem;
+ send_result(retbott.Getout_filename());
+}
+
int main(int argc, char *argv[]) {
init();
//init_error();
@@ -400,6 +430,7 @@
parse_bott();
if (bott->Gettype()==DO_CHALLENGE) dochallenge();
else if (bott->Gettype()==NEED_JUDGE||bott->Gettype()==DO_TESTALL||bott->Gettype()==DO_PRETEST) dojudge(bott->Gettype());
+ else if (bott->Gettype()==DO_INTERACTIVE) dointeractive();
delete bott;
}
return 0;
diff --git a/judger-v2/chaclient.h b/judger-v2/chaclient.h
index 758ce59..63e96de 100644
--- a/judger-v2/chaclient.h
+++ b/judger-v2/chaclient.h
@@ -48,6 +48,7 @@
#define DO_CHALLENGE 4
#define DO_PRETEST 5
#define DO_TESTALL 6
+#define DO_INTERACTIVE 7
#define JUDGER_STATUS_REPORT 1
#define NEED_DATA 2
#define RESULT_REPORT 3
diff --git a/judger-v2/config.ini b/judger-v2/config.ini
index c5fb32f..c9a97ae 100644
--- a/judger-v2/config.ini
+++ b/judger-v2/config.ini
@@ -10,4 +10,5 @@
extra_runtime = 10
checker_run_time = 3
checker_run_memory = 65536
-tmpfile_path = tmpfile/
\ No newline at end of file
+tmpfile_path = tmpfile/
+interactive_max_run_time = 20