├── Container ├── SOL │ ├── errlog │ ├── tmp.out │ ├── Test │ └── Test.cpp ├── WXC │ ├── errlog │ ├── errlog2 │ ├── user.err │ ├── user.out │ ├── user │ └── user.exe ├── default_judge ├── default_judge.exe ├── makefile └── default_judge.cpp ├── Data ├── Tasks │ └── 1 │ │ ├── 1.in │ │ ├── 1.out │ │ ├── 2.in │ │ └── 2.out └── Submissions │ └── 1 │ └── user.cpp ├── VisualStudio └── ACJudge │ ├── Release │ ├── a.out │ ├── MLE.exe │ ├── TLE.exe │ ├── Test.exe │ ├── Normal.exe │ ├── Test.iobj │ ├── Test.ipdb │ ├── Normal.cpp │ ├── TLE.cpp │ └── MLE.cpp │ ├── ACJudge │ ├── Release │ │ └── ACJudge.tlog │ │ │ ├── CL.read.1.tlog │ │ │ ├── CL.write.1.tlog │ │ │ ├── CL.command.1.tlog │ │ │ └── ACJudge.lastbuildstate │ ├── ACJudge.vcxproj.filters │ └── ACJudge.vcxproj │ └── ACJudge.sln ├── Release └── offline ├── Debug ├── TestFileSys └── TestSandbox ├── Shell ├── CompileSandbox.sh └── CompileFileSys.sh ├── Judge ├── judge.cpp ├── acmjudge.h ├── oijudge.h ├── judge.h ├── oijudge.cpp └── acmjudge.cpp ├── Source ├── README.md ├── TestFileSys.cpp └── TestSandbox.cpp ├── makefile ├── Lib └── lib.h ├── .travis.yml ├── Definations ├── platform.h ├── enums.h └── types.h ├── Support ├── database.h ├── filesys.h ├── database.cpp └── filesys.cpp ├── .gitattributes ├── README.md ├── Sandbox ├── sandbox.h └── sandbox.cpp ├── .gitignore └── Main └── main.cpp /Container/SOL/errlog: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Container/WXC/errlog: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Container/WXC/errlog2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Container/WXC/user.err: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Data/Tasks/1/1.in: -------------------------------------------------------------------------------- 1 | 1 2 -------------------------------------------------------------------------------- /Data/Tasks/1/1.out: -------------------------------------------------------------------------------- 1 | 3 -------------------------------------------------------------------------------- /Data/Tasks/1/2.in: -------------------------------------------------------------------------------- 1 | 1 3 -------------------------------------------------------------------------------- /Data/Tasks/1/2.out: -------------------------------------------------------------------------------- 1 | 4 -------------------------------------------------------------------------------- /Container/WXC/user.out: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /VisualStudio/ACJudge/Release/a.out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Container/SOL/tmp.out: -------------------------------------------------------------------------------- 1 | Sandbox is finished! 2 | -------------------------------------------------------------------------------- /Release/offline: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/Release/offline -------------------------------------------------------------------------------- /Debug/TestFileSys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/Debug/TestFileSys -------------------------------------------------------------------------------- /Debug/TestSandbox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/Debug/TestSandbox -------------------------------------------------------------------------------- /Container/SOL/Test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/Container/SOL/Test -------------------------------------------------------------------------------- /Container/WXC/user: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/Container/WXC/user -------------------------------------------------------------------------------- /Container/WXC/user.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/Container/WXC/user.exe -------------------------------------------------------------------------------- /Container/default_judge: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/Container/default_judge -------------------------------------------------------------------------------- /Container/default_judge.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/Container/default_judge.exe -------------------------------------------------------------------------------- /VisualStudio/ACJudge/Release/MLE.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/VisualStudio/ACJudge/Release/MLE.exe -------------------------------------------------------------------------------- /VisualStudio/ACJudge/Release/TLE.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/VisualStudio/ACJudge/Release/TLE.exe -------------------------------------------------------------------------------- /VisualStudio/ACJudge/Release/Test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/VisualStudio/ACJudge/Release/Test.exe -------------------------------------------------------------------------------- /Shell/CompileSandbox.sh: -------------------------------------------------------------------------------- 1 | g++ ../Sandbox/sandbox.cpp ../Source/TestSandbox.cpp -lseccomp -o ../Debug/TestSandbox -std=c++11 -O2 -Wall -g -------------------------------------------------------------------------------- /VisualStudio/ACJudge/Release/Normal.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/VisualStudio/ACJudge/Release/Normal.exe -------------------------------------------------------------------------------- /VisualStudio/ACJudge/Release/Test.iobj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/VisualStudio/ACJudge/Release/Test.iobj -------------------------------------------------------------------------------- /VisualStudio/ACJudge/Release/Test.ipdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/VisualStudio/ACJudge/Release/Test.ipdb -------------------------------------------------------------------------------- /Shell/CompileFileSys.sh: -------------------------------------------------------------------------------- 1 | g++ ../Support/filesys.cpp ../Sandbox/sandbox.cpp ../Source/TestFileSys.cpp -lseccomp -o ../Debug/TestFileSys -std=c++11 -O2 -Wall -g -------------------------------------------------------------------------------- /Container/makefile: -------------------------------------------------------------------------------- 1 | objs = default_judge.o 2 | CPPFLAGS = -g -O2 -Wall -std=c++11 3 | default_judge : $(objs) 4 | g++ -o default_judge $(objs) 5 | clean: 6 | rm $(objs) -------------------------------------------------------------------------------- /VisualStudio/ACJudge/ACJudge/Release/ACJudge.tlog/CL.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/VisualStudio/ACJudge/ACJudge/Release/ACJudge.tlog/CL.read.1.tlog -------------------------------------------------------------------------------- /VisualStudio/ACJudge/ACJudge/Release/ACJudge.tlog/CL.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/VisualStudio/ACJudge/ACJudge/Release/ACJudge.tlog/CL.write.1.tlog -------------------------------------------------------------------------------- /VisualStudio/ACJudge/ACJudge/Release/ACJudge.tlog/CL.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProjectAC/ACJudge/HEAD/VisualStudio/ACJudge/ACJudge/Release/ACJudge.tlog/CL.command.1.tlog -------------------------------------------------------------------------------- /VisualStudio/ACJudge/Release/Normal.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout<<"Hello"< 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout<<"Hello"< 2 | 3 | using namespace std; 4 | 5 | int a[5000000]; 6 | 7 | int main() 8 | { 9 | cout<<"Hello"< 3 | 4 | using namespace std; 5 | using namespace ACJudge; 6 | 7 | int main() 8 | { 9 | FileSys fs(1, 1, "SOL"); 10 | cout << fs.compile(CodeType::USER, Language::CPP).ret << endl; 11 | 12 | return 0; 13 | } -------------------------------------------------------------------------------- /Judge/acmjudge.h: -------------------------------------------------------------------------------- 1 | #include "judge.h" 2 | 3 | namespace ACJudge 4 | { 5 | class ACMJudge : Judge 6 | { 7 | public: 8 | // [Interface] 9 | Grades judge(Task task, Submission submission); 10 | // [Constructor] 11 | ACMJudge(Tstring name) : Judge(name) {} 12 | }; 13 | } -------------------------------------------------------------------------------- /Judge/oijudge.h: -------------------------------------------------------------------------------- 1 | #include "judge.h" 2 | 3 | namespace ACJudge 4 | { 5 | class OIJudge : Judge 6 | { 7 | public: 8 | // [Interface] 9 | Grades judge(Task task, Submission submission); 10 | // [Constructor] 11 | OIJudge(Tstring name) : Judge(name) {} 12 | }; 13 | } -------------------------------------------------------------------------------- /Container/SOL/Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | cout<<"Sandbox is finished!"< 4 | #include 5 | #include 6 | #include "../Definations/platform.h" 7 | 8 | namespace ACJudge 9 | { 10 | template 11 | Tstring i2s(Integer i) 12 | { 13 | Tstringstream ss; 14 | Tstring s; 15 | ss << i; 16 | ss >> s; 17 | return s; 18 | } 19 | 20 | template 21 | std::string i2ss(Integer i) 22 | { 23 | std::stringstream ss; 24 | std::string s; 25 | ss << i; 26 | ss >> s; 27 | return s; 28 | } 29 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | language: cpp 4 | script: 5 | - make 6 | before_install: 7 | - ls / 8 | - sudo apt-get -qq update 9 | - sudo apt-get install -y libseccomp-dev 10 | - wget https://sourceforge.net/projects/boost/files/boost/1.61.0/boost_1_61_0.tar.bz2 /path/to/boost_1_61_0.tar.bz2 11 | - tar --bzip2 -xf /path/to/boost_1_61_0.tar.bz2 12 | - git clone https://github.com/mysql/mysql-connector-cpp.git 13 | - cd mysql-connector-cpp/ 14 | - cmake . -DBOOST_ROOT=/usr/local/boost_1_56_0 15 | - cd .. 16 | 17 | -------------------------------------------------------------------------------- /Source/TestSandbox.cpp: -------------------------------------------------------------------------------- 1 | #include "../Sandbox/sandbox.h" 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | using namespace ACJudge; 7 | 8 | int main(int argc, char *args[]) 9 | { 10 | //int i; 11 | Result res; 12 | Sandbox box("WXC"); 13 | 14 | for(int i = 0; i < argc - 1; i++) 15 | args[i] = args[i+1]; 16 | args[argc - 1] = NULL; 17 | 18 | res = box.run(args[0], args, LIMIT_INFINITE, LIMIT_INFINITE, true, "", "tmp.out", ""); 19 | cout< 4 | #include "../Definations/types.h" 5 | #include "../Definations/enums.h" 6 | #include "../Sandbox/sandbox.h" 7 | #include "../Support/filesys.h" 8 | 9 | namespace ACJudge 10 | { 11 | class Judge 12 | { 13 | protected: 14 | Tstring name; 15 | 16 | public: 17 | // [Interface] judge 18 | // Judge of 19 | // Return grades 20 | Grades judge(Task task, Submission submission); 21 | 22 | // [Constructor] Judge 23 | // Init the judge and set its name 24 | Judge(Tstring s); 25 | }; 26 | } -------------------------------------------------------------------------------- /Data/Submissions/1/user.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() 9 | { 10 | /* 11 | // 1k 12 | int small_size = 1024; 13 | // 150m 14 | int big_size = 150 * 1024 * 1024; 15 | 16 | int *s = NULL, *b = NULL; 17 | 18 | s = (int *)malloc(small_size); 19 | if(s){ 20 | printf("malloc small size succedeed\n"); 21 | } 22 | else{ 23 | printf("malloc small size failed\n"); 24 | return -1; 25 | } 26 | 27 | b = (int *)malloc(big_size); 28 | if(b){ 29 | printf("malloc big size succedeed\n"); 30 | } 31 | else{ 32 | printf("malloc big size failed\n"); 33 | return -2; 34 | } 35 | */ 36 | cout<<"3"< 4 | #include 5 | #include 6 | 7 | #ifdef _WIN32 8 | #define WINDOWS 9 | #endif 10 | #ifdef __unix__ 11 | #define _NIX 12 | #endif 13 | 14 | #if defined WINDOWS 15 | 16 | #define Tsscanf swscanf 17 | #define _T(x) L##x 18 | #define Tcout wcout 19 | #define Tstrcat wcscat 20 | typedef wchar_t Tchar; 21 | typedef std::wstring Tstring; 22 | typedef std::wifstream Tifstream; 23 | typedef std::wofstream Tofstream; 24 | typedef std::wstringstream Tstringstream; 25 | 26 | #elif defined _NIX 27 | 28 | #define Tsscanf sscanf 29 | #define _T(x) x 30 | #define Tcout cout 31 | #define Tstrcat strcat 32 | typedef char Tchar; 33 | typedef std::string Tstring; 34 | typedef std::ifstream Tifstream; 35 | typedef std::ofstream Tofstream; 36 | typedef std::stringstream Tstringstream; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /Definations/enums.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define LIMIT_INFINITE 0xffffffffu 4 | 5 | namespace ACJudge 6 | { 7 | enum Return 8 | { 9 | OK = 0, // So far so good 10 | ERR = -1, // System internal error 11 | TLE = -2, // Time limit exceeded 12 | MLE = -3, // Memory limit exceeded 13 | RTE = -4, // Other kinds of runtime error 14 | CE = -5, // Compilation error 15 | WA = -6 // Wrong Answer 16 | }; 17 | 18 | enum Language 19 | { 20 | NONE = -1, // For SPJ this means default comparer, for user code this means answer submission 21 | CPP = 0, // 22 | CPP11 = 1, // 23 | C = 2, // 24 | PYTHON = 3, // 25 | ACPL = 4 // 26 | }; 27 | 28 | enum CodeType 29 | { 30 | USER, 31 | SPJ 32 | }; 33 | 34 | enum TaskType 35 | { 36 | OI, 37 | ACM 38 | }; 39 | } -------------------------------------------------------------------------------- /Definations/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "platform.h" 5 | #include "enums.h" 6 | 7 | namespace ACJudge 8 | { 9 | typedef unsigned long long ID; 10 | typedef unsigned int Limit; 11 | typedef unsigned int Score; 12 | typedef unsigned int Number; 13 | typedef struct rlimit RLimit; 14 | typedef struct itimerval ITimerVal; 15 | typedef struct rusage RUsage; 16 | 17 | struct Result 18 | { 19 | Limit time, space; 20 | Return ret; 21 | int val; 22 | Tstring msg; 23 | }; 24 | 25 | struct Grade 26 | { 27 | Result res; 28 | Score score; 29 | }; 30 | typedef std::vector Grades; 31 | 32 | struct Data 33 | { 34 | ID did; 35 | Limit time, space; 36 | Score score; 37 | }; 38 | 39 | struct Task 40 | { 41 | ID tid; 42 | TaskType type; 43 | std::vector data; 44 | Language language; 45 | }; 46 | 47 | struct Submission 48 | { 49 | ID sid; 50 | ID tid; 51 | Language language; 52 | }; 53 | }; -------------------------------------------------------------------------------- /VisualStudio/ACJudge/ACJudge.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ACJudge", "ACJudge\ACJudge.vcxproj", "{918DC3E4-B64D-4534-B368-918211635153}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {918DC3E4-B64D-4534-B368-918211635153}.Debug|x64.ActiveCfg = Debug|x64 17 | {918DC3E4-B64D-4534-B368-918211635153}.Debug|x64.Build.0 = Debug|x64 18 | {918DC3E4-B64D-4534-B368-918211635153}.Debug|x86.ActiveCfg = Debug|Win32 19 | {918DC3E4-B64D-4534-B368-918211635153}.Debug|x86.Build.0 = Debug|Win32 20 | {918DC3E4-B64D-4534-B368-918211635153}.Release|x64.ActiveCfg = Release|x64 21 | {918DC3E4-B64D-4534-B368-918211635153}.Release|x64.Build.0 = Release|x64 22 | {918DC3E4-B64D-4534-B368-918211635153}.Release|x86.ActiveCfg = Release|Win32 23 | {918DC3E4-B64D-4534-B368-918211635153}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Support/database.h: -------------------------------------------------------------------------------- 1 | //#define CPPCONN_LIB_BUILD 2 | #define CPPCONN_PUBLIC_FUNC 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "../Definations/platform.h" 16 | #include "../Definations/types.h" 17 | 18 | #pragma comment(lib, "libmysql.lib") 19 | #pragma comment(lib, "mysqlclient.lib") 20 | #pragma comment(lib, "mysqlcppconn.lib") 21 | 22 | namespace ACJudge 23 | { 24 | class Database 25 | { 26 | private: 27 | 28 | sql::mysql::MySQL_Driver *driver; 29 | sql::Connection *conn; 30 | sql::Statement *state; 31 | 32 | public: 33 | 34 | // [Constructor] 35 | Database(std::string server, std::string username, std::string password); 36 | 37 | // [Interface] Get latest submission 38 | // This will fetch the latest submission on the currently connected server 39 | // In later versions this will be replaced by a queue 40 | Submission get_latest_submission(); 41 | 42 | // [Interface] Get task information 43 | // This will query the information and data of the task 44 | Task get_task(ID tid); 45 | 46 | // [Interface] Set grades 47 | // Write the grades to database after judging 48 | void set_grades(ID sid, Grades grades); 49 | }; 50 | } -------------------------------------------------------------------------------- /Support/filesys.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../Definations/types.h" 5 | #include "../Definations/enums.h" 6 | #include "../Sandbox/sandbox.h" 7 | 8 | namespace ACJudge 9 | { 10 | class FileSys 11 | { 12 | Tstring tpath, spath, bpath, sbn; 13 | 14 | public: 15 | // [Interface] Get std input 16 | // It will return the name of the certain file 17 | Tstring get_std_input(ID did); 18 | 19 | // [Interface] Get std output 20 | // It will return the name of the certain file 21 | Tstring get_std_output(ID did); 22 | 23 | // [Interface] Get user output 24 | // It will return the name of the certain file 25 | // This method is designed only for answer-submitting task 26 | Tstring get_user_output(ID did); 27 | 28 | // [Interface] Get user output 29 | // It will return the name of the certain file 30 | // This method is designed for normal code task 31 | Tstring get_user_output(); 32 | 33 | // [Interface] Get user error output 34 | // It will return the name of the certain file 35 | // This method is designed for normal code task 36 | Tstring get_user_err_output(); 37 | 38 | // [Interface] Compile code 39 | // It will compile code to the sandbox direction 40 | // If the code is written in a interpreted language like python 41 | // It will straightly copy the code to the sandbox direction 42 | Result compile(CodeType id, Language l); 43 | 44 | // [Interface] Run code 45 | // Run the code (of user submission or special judge) 46 | Result run(CodeType type, Language l, Data data); 47 | 48 | // [Constructor] 49 | FileSys(ID tid, ID sid, Tstring sbn); 50 | }; 51 | } -------------------------------------------------------------------------------- /Judge/oijudge.cpp: -------------------------------------------------------------------------------- 1 | #include "oijudge.h" 2 | #include "../Lib/lib.h" 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | using namespace ACJudge; 8 | 9 | Grades OIJudge::judge(Task task, Submission submission) 10 | { 11 | FileSys fs(task.tid, submission.sid, name); 12 | 13 | //Prepare 14 | Result res, res2; 15 | Grades grades; 16 | 17 | res = fs.compile(CodeType::USER, submission.language); // compile User code 18 | if(res.ret != Return::OK) 19 | { 20 | grades.push_back({{0, 0, Return::CE, 0, _T("Compilation Error. \n") + res.msg}, 0}); 21 | return grades; 22 | } 23 | 24 | if(task.language != Language::NONE) 25 | { 26 | res = fs.compile(CodeType::SPJ, task.language); // compile SPJ code 27 | if(res.ret != Return::OK) 28 | { 29 | grades.push_back({{0, 0, Return::ERR, 0, _T("System Error while compiling Special Judge code. \n") + res.msg}, 0}); 30 | return grades; 31 | } 32 | } 33 | 34 | Sandbox box(name); 35 | for(auto &data: task.data) 36 | { 37 | res = fs.run(CodeType::USER, submission.language, data); 38 | if(res.ret != Return::OK) 39 | { 40 | grades.push_back({res, 0}); 41 | continue; 42 | } 43 | 44 | res2 = fs.run(CodeType::SPJ, task.language, data); 45 | if((res2.ret != Return::RTE && res2.ret != Return::OK) || res2.val < 0) 46 | grades.push_back({{res.time, res.space, Return::ERR, 0, _T("System Error while judging. \n")+ res.msg}, 0}); 47 | else 48 | { 49 | if(res2.val != data.score) 50 | res.ret = Return::WA; 51 | grades.push_back({res, (Score)res2.val}); 52 | } 53 | } 54 | 55 | return grades; 56 | } -------------------------------------------------------------------------------- /Judge/acmjudge.cpp: -------------------------------------------------------------------------------- 1 | #include "acmjudge.h" 2 | #include "../Lib/lib.h" 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | using namespace ACJudge; 8 | 9 | Grades ACMJudge::judge(Task task, Submission submission) 10 | { 11 | FileSys fs(task.tid, submission.sid, name); 12 | 13 | //Prepare 14 | Result res, res2; 15 | Grades grades; 16 | 17 | res = fs.compile(CodeType::USER, submission.language); // compile User code 18 | if(res.ret != Return::OK) 19 | { 20 | grades.push_back({{0, 0, Return::CE, 0, _T("Compilation Error. \n") + res.msg}, 0}); 21 | return grades; 22 | } 23 | 24 | if(task.language != Language::NONE) 25 | { 26 | res = fs.compile(CodeType::SPJ, task.language); // compile SPJ code 27 | if(res.ret != Return::OK) 28 | { 29 | grades.push_back({{0, 0, Return::ERR, 0, _T("System Error while compiling Special Judge code. \n") + res.msg}, 0}); 30 | return grades; 31 | } 32 | } 33 | 34 | Sandbox box(name); 35 | for(auto &data: task.data) 36 | { 37 | res = fs.run(CodeType::USER, submission.language, data); 38 | if(res.ret != Return::OK) 39 | { 40 | grades.push_back({res, 0}); 41 | return grades; 42 | } 43 | 44 | res2 = fs.run(CodeType::SPJ, task.language, data); 45 | if((res2.ret != Return::RTE && res2.ret != Return::OK) || res2.val < 0) 46 | { 47 | grades.push_back({{res.time, res.space, Return::ERR, 0, _T("System Error while judging. \n") + res.msg}, 0}); 48 | return grades; 49 | }else 50 | { 51 | if(res2.val != data.score) 52 | { 53 | res.ret = Return::WA; 54 | grades.push_back({res, (Score)res2.val}); 55 | return grades; 56 | }else 57 | grades.push_back({res, (Score)res2.val}); 58 | } 59 | } 60 | 61 | return grades; 62 | } -------------------------------------------------------------------------------- /Support/database.cpp: -------------------------------------------------------------------------------- 1 | #include "database.h" 2 | #include "../Lib/lib.h" 3 | 4 | using namespace std; 5 | using namespace sql; 6 | using namespace sql::mysql; 7 | using namespace ACJudge; 8 | 9 | Database::Database(string server, string username, string password) 10 | { 11 | driver = get_mysql_driver_instance(); 12 | conn = driver->connect(server, username, password); 13 | state = conn->createStatement(); 14 | } 15 | 16 | Submission Database::get_latest_submission() 17 | { 18 | string SQL = "SELECT * FROM `oj_commit` WHERE ORDER BY `oj_commit`.`time` DESC LIMIT 1"; 19 | Submission s = {0, 0, Language::NONE}; 20 | 21 | ResultSet *res = state->executeQuery(SQL); 22 | if (!(res->next())) 23 | return s; 24 | 25 | s.sid = res->getUInt64("sid"); 26 | switch (res->getInt("language")) 27 | { 28 | case 0: 29 | s.language = Language::CPP; 30 | break; 31 | case 1: 32 | s.language = Language::CPP11; 33 | break; 34 | case 2: 35 | s.language = Language::C; 36 | break; 37 | case -1: 38 | s.language = Language::NONE; 39 | break; 40 | } 41 | 42 | return s; 43 | } 44 | 45 | Task Database::get_task(ID tid) 46 | { 47 | Task t; 48 | t.tid = tid; 49 | 50 | ResultSet *res = state->executeQuery("SELECT * FROM `oj_commit` WHERE ORDER BY `oj_commit`.`time` DESC LIMIT 1"); 51 | if (!(res->next())) 52 | return t; 53 | 54 | res = state->executeQuery("SELECT * FROM `test_info` WHERE test_info`.`aid` = " + i2ss(tid)); 55 | while (res->next()) 56 | t.data.push_back({res->getUInt64("did"), res->getUInt("time"), res->getUInt("memory"), res->getUInt("score")}); 57 | 58 | switch (res->getInt("type")) 59 | { 60 | case 0: 61 | t.type = TaskType::OI; 62 | break; 63 | case 1: 64 | t.type = TaskType::ACM; 65 | break; 66 | } 67 | 68 | switch (res->getInt("language")) 69 | { 70 | case 0: 71 | t.language = Language::CPP; 72 | break; 73 | case 1: 74 | t.language = Language::CPP11; 75 | break; 76 | case 2: 77 | t.language = Language::C; 78 | break; 79 | case -1: 80 | t.language = Language::NONE; 81 | break; 82 | } 83 | 84 | return t; 85 | } 86 | 87 | void Database::set_grades(ID sid, Grades grades) 88 | { 89 | ID did = 1; 90 | for (auto &grade : grades) 91 | state->execute("INSERT INTO `oj_result` (`did`, `score`, `time`, `memory`, `result`) VALUES(" + i2ss(did) + ", " + i2ss(grade.score) + ", " + i2ss(grade.res.time) + ", " + i2ss(grade.res.space) + ", " + i2ss(grade.res.ret) + ");"), 92 | did++; 93 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /VisualStudio/ACJudge/ACJudge/ACJudge.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 源文件 26 | 27 | 28 | 源文件 29 | 30 | 31 | 源文件 32 | 33 | 34 | 源文件 35 | 36 | 37 | 源文件 38 | 39 | 40 | 41 | 42 | 头文件 43 | 44 | 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ACJudge 2 | A Complex Judge, designed for ACOJ. 3 | Currently it's Linux only. But it will soon be available on Windows. 4 | Mac? Huh? What are you talking about? 5 | **ACOJ Web goes [here](https://github.com/DXkite/ACOJ)!** 6 | This project will support ANSI C no more. 7 | **Warning: My Ubuntu has crashed, so the new (online) version for Linux is NOT TESTED yet!!** 8 | 9 | ### [Judge] 10 | Scoring users' submissions. 11 | With ACPL script, problem designers can set their own, unique judging procedure. (Comming soon!) 12 | 13 | ### [Sandbox] 14 | The warden that protects the system from being damaged by user codes. 15 | The executable file should (better) be in folder "Container/XXX", while XXX is the name of the Sandbox object. 16 | 17 | ### [Supports] 18 | Including database, file and management interfaces. 19 | Database interface will get queueing submissions from database, send them to the judge, collect the results and restore to databse. 20 | File interface will prepare data, source code and things like that for the judge. 21 | Management interface is the connection between web server (script) and judge. 22 | When ACOJ Server is started, this module will be automatically started, but without it, the judge can also be used offline. 23 | 24 | 25 | ----------------------- 26 | 27 | ## Update 28 | 29 | **[ACJudge 1.4] Link Start** 30 | ACJudge Online is OK! 31 | You only need a mysql DBMS to make it run. 32 | Maybe you also want a web server (classic ones like Apache). 33 | 34 | ## License 35 | 36 | **GPL v3.** 37 | To avoid disputes, the license of this program was switched to GPL. 38 | Notice that WTFPL is not in use anymore!!!!! 39 | 40 | Thanks [QingDaoU](https://github.com/QingdaoU/Judger) for offering such a sample of sandbox on Linux! 41 | Thanks [ContestHunter](https://contesthunter.org) for default comparer! 42 | *ContestHunter is OK now! Awesome!* 43 | 44 | ----------------------- 45 | 46 | ## Build & Run 47 | 48 | ### For Linux User: 49 | 50 | Before build, please make sure you have installed libseccomp, as it is the main part of the sandbox. 51 | Then, after switching to the direction where the project is placed, follow these steps: 52 | 53 | cd Container 54 | make 55 | make clean 56 | cd .. 57 | make 58 | make clean 59 | cd Release 60 | ./acjudge 61 | 62 | If it shows the usage of the program... 63 | Voila! You've done it! 64 | 65 | ### For Windows User: 66 | 67 | You may straightly switch to /Release/ folder (for the code has already been built) and run ACJudge.exe! 68 | Solution for MS - Visual Studio 2015 is in folder Visual studio. You may need this if you wish to deal some changes. 69 | Before building, you should edit /Definations/platform.h to switch the platform, that is, from 70 | 71 | // #define WINDOWS 72 | #define _NIX 73 | 74 | to 75 | 76 | #define WINDOWS 77 | // #define _NIX 78 | 79 | Tip: The pronounciation of word "Windows" is similar with "Wen Dao Si" in Chinese, which means "Plague to Death". 80 | -------------------------------------------------------------------------------- /Support/filesys.cpp: -------------------------------------------------------------------------------- 1 | #include "filesys.h" 2 | #include "../Lib/lib.h" 3 | #include "../Definations/platform.h" 4 | 5 | using namespace std; 6 | using namespace ACJudge; 7 | 8 | Tstring FileSys::get_std_input(ID did) 9 | { 10 | return tpath + i2s(did) + _T(".in"); 11 | } 12 | 13 | Tstring FileSys::get_std_output(ID did) 14 | { 15 | return tpath + i2s(did) + _T(".out"); 16 | } 17 | 18 | Tstring FileSys::get_user_output(ID did) 19 | { 20 | return spath + i2s(did) + _T(".out"); 21 | } 22 | 23 | Tstring FileSys::get_user_err_output() 24 | { 25 | return bpath + _T("user.err"); 26 | } 27 | 28 | Tstring FileSys::get_user_output() 29 | { 30 | return bpath + _T("user.out"); 31 | } 32 | 33 | Result FileSys::compile(CodeType id, Language l) 34 | { 35 | Sandbox box(sbn); 36 | Tstring path = (id == CodeType::USER ? spath : tpath); 37 | Tstring name = (id == CodeType::USER ? _T("user") : _T("spj")); 38 | Tstring outname = name; 39 | #if defined WINDOWS 40 | outname += _T(".exe"); 41 | #endif 42 | 43 | if(l == Language::CPP) // GNU C++ 99 44 | { 45 | Tstring args[] = {_T("g++"), path + name + _T(".cpp"), _T("-o"), bpath + outname, _T("-O2"), _T("-Wall"), _T("-lm"), _T("")}; 46 | return box.run(args[0], args, 5000, LIMIT_INFINITE, 0, _T(""), _T(""), _T("errlog")); 47 | }else if(l == Language::CPP11) // GNU C++ 11 and later 48 | { 49 | Tstring args[] = {_T("g++"), path + name + _T(".cpp"), _T("-o"), bpath + outname, _T("-O2"), _T("-Wall"), _T("-lm"), _T("-DONLINE_JUDGE"), _T("-std=c++11"), _T("")}; 50 | return box.run(args[0], args, 5000, LIMIT_INFINITE, 0, _T(""), _T(""), _T("errlog")); 51 | }else if(l == Language::C) // GNU C 99 52 | { 53 | Tstring args[] = {_T("gcc"), path + name + _T(".c"), _T("-o"), bpath + outname, _T("-O2"), _T("-Wall"), _T("-lm"), _T("-DONLINE_JUDGE"), _T("-std=c99"), _T("")}; 54 | return box.run(args[0], args, 5000, LIMIT_INFINITE, 0, _T(""), _T(""), _T("errlog")); 55 | }else /*if(l == Language::PYTHON) // Python 2*/ 56 | { 57 | #if defined WINDOWS 58 | Tstring args[] = {_T("copy"), path + name + _T(".py"), bpath, _T("")}; 59 | #elif defined _NIX 60 | Tstring args[] = { _T("cp"), path + name + _T(".py"), bpath, _T("")}; 61 | #endif 62 | return box.run(args[0], args, 5000, LIMIT_INFINITE, 0, _T(""), _T(""), _T("errlog")); 63 | } 64 | } 65 | 66 | Result FileSys::run(CodeType type, Language l, Data data) 67 | { 68 | Sandbox box(sbn); 69 | 70 | if (type == CodeType::USER) 71 | { 72 | Tstring args[] = { _T("./user"), _T("") }; 73 | return box.run(args[0], args, data.time, data.space, true, _T("../") + get_std_input(data.did), _T("user.out"), _T("user.err")); 74 | } else 75 | { 76 | Tstring args[] = { _T(""), get_std_input(data.did), get_std_output(data.did), get_user_output(), i2s(data.score), _T("") }; 77 | if (l != Language::NONE) 78 | args[0] = _T("./spj"); 79 | else 80 | args[0] = _T("../default_judge"); 81 | return box.run(args[0], args, 5000, LIMIT_INFINITE, true, _T(""), _T(""), _T("errlog2")); 82 | } 83 | } 84 | 85 | FileSys::FileSys(ID tid, ID sid, Tstring sbn) 86 | { 87 | spath = _T("../Data/Submissions/")+ i2s(sid) + _T("/"); 88 | tpath = _T("../Data/Tasks/")+ i2s(tid) + _T("/"); 89 | bpath = _T("../Container/")+ sbn + _T("/"); 90 | FileSys::sbn = sbn; 91 | } -------------------------------------------------------------------------------- /Container/default_judge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class Compare 9 | { 10 | private: 11 | FILE *fstd,*fout; 12 | int LastCharStd, LastCharOut; 13 | protected: 14 | inline int Peek(FILE* f); 15 | inline void Pop(FILE* f); 16 | inline bool IsSpace(int ch); 17 | bool DoCompare(); 18 | int default_compare(const char *s1, const char *s2, int score); 19 | public: 20 | int compare(const char *s1, const char *s2, int score); 21 | }; 22 | 23 | //检查下一个字符 24 | inline int Compare::Peek(FILE* f){ 25 | if(f==fstd){ 26 | if(LastCharStd == -2) 27 | LastCharStd=fgetc(f); 28 | return LastCharStd; 29 | }else{ 30 | if(LastCharOut == -2) 31 | LastCharOut=fgetc(f); 32 | return LastCharOut; 33 | } 34 | } 35 | 36 | //取出下一个字符 37 | inline void Compare::Pop(FILE* f){ 38 | if(f==fstd){ 39 | if(LastCharStd == -2) 40 | fgetc(f); 41 | else 42 | LastCharStd = -2; 43 | }else{ 44 | if(LastCharOut == -2) 45 | fgetc(f); 46 | else 47 | LastCharOut = -2; 48 | } 49 | } 50 | 51 | //判断字符是否为空白 52 | inline bool Compare::IsSpace(int ch){ 53 | return ch>=0 && (ch<=32 || ch>=127); 54 | } 55 | 56 | //执行比较操作。 57 | bool Compare::DoCompare(){ 58 | int stdPosition=0,outPosition=0; 59 | bool stdInSpace=true,outInSpace=true; 60 | while(true){ 61 | int stdC=Peek(fstd),outC=Peek(fout); 62 | if(stdC==EOF && outC==EOF){ 63 | return true; 64 | }else if(stdC==EOF && IsSpace(outC)){ 65 | outPosition++; 66 | Pop(fout); 67 | }else if(outC==EOF && IsSpace(stdC)){ 68 | stdPosition++; 69 | Pop(fstd); 70 | }else if(IsSpace(stdC) && IsSpace(outC)){ 71 | stdPosition++; 72 | outPosition++; 73 | stdInSpace=true; 74 | outInSpace=true; 75 | Pop(fstd); 76 | Pop(fout); 77 | }else if(IsSpace(stdC) && outInSpace){ 78 | stdPosition++; 79 | Pop(fstd); 80 | }else if(IsSpace(outC) && stdInSpace){ 81 | outPosition++; 82 | Pop(fout); 83 | }else if(stdC==outC){ 84 | stdPosition++; 85 | outPosition++; 86 | stdInSpace=false; 87 | outInSpace=false; 88 | Pop(fstd); 89 | Pop(fout); 90 | }else{ 91 | return false; 92 | } 93 | } 94 | } 95 | 96 | int Compare::default_compare(const char *s1, const char *s2, int score) 97 | { 98 | //打开文件 99 | if(NULL==(fstd=fopen(s1,"r"))){ 100 | return -1; 101 | } 102 | if(NULL==(fout=fopen(s2,"r"))){ 103 | return -1; 104 | } 105 | if(DoCompare()){ 106 | return score; 107 | }else{ 108 | return 0; 109 | } 110 | } 111 | 112 | int Compare::compare(const char *s1, const char *s2, int score) 113 | { 114 | LastCharStd = -2, LastCharOut = -2; 115 | return default_compare(s1, s2, score); 116 | } 117 | 118 | int main(int argc, char *argv[]) 119 | { 120 | Compare compare; 121 | int score; 122 | sscanf(argv[4], "%d", &score); 123 | return compare.compare(argv[2], argv[3], score); 124 | } 125 | -------------------------------------------------------------------------------- /Sandbox/sandbox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../Definations/platform.h" 5 | #include "../Definations/types.h" 6 | #include "../Definations/enums.h" 7 | 8 | #if defined WINDOWS 9 | #include 10 | #endif 11 | 12 | namespace ACJudge 13 | { 14 | class Sandbox 15 | { 16 | private: 17 | // Name of the sandbox 18 | // This is also the name of the folder the certain program will run in 19 | Tstring name; 20 | 21 | #if defined WINDOWS 22 | 23 | // Set limits 24 | // Tags will be saved in 25 | JOBOBJECT_EXTENDED_LIMIT_INFORMATION set_limits(Limit time, Limit space, bool restricted); 26 | 27 | // Set UI restrictions 28 | JOBOBJECT_BASIC_UI_RESTRICTIONS set_rules_UI(bool restricted); 29 | 30 | // Redirect file input/output/error target 31 | STARTUPINFO redirection(Tstring in, Tstring out, Tstring err); 32 | 33 | #elif defined _NIX 34 | // Set time limit 35 | // Both with setitimer and setrlimit 36 | // Here time is CPU time, and stime is actual time 37 | Return set_time_limit(Limit time); 38 | 39 | // Set space limit 40 | // With setrlimit 41 | Return set_space_limit(Limit space); 42 | 43 | // Redirect I/O flow to file with name 44 | Return set_file(FILE *fp, Tstring file, Tstring mode); 45 | 46 | // Starter 47 | // This is what the starter have to do before execve 48 | void start(Tstring file, Tchar *args[], Limit time, Limit space, bool restricted, Tstring fin, Tstring fout, Tstring ferr); 49 | 50 | // Set time and space limits for current process 51 | // Always called immediately after forking 52 | Return set_limits(Limit time, Limit space); 53 | 54 | // Set rules (security) for current process 55 | // Called when is true 56 | // [Thanks] QingDaoU Judger 57 | // link: https://github.com/QingdaoU/Judger 58 | Return set_rules(Tstring s); 59 | 60 | // Set group of current process to guest for safety 61 | Return set_gid(); 62 | 63 | // Redirect file input/output/error target 64 | Return redirection(Tstring in, Tstring out, Tstring err); 65 | #endif 66 | 67 | public: 68 | 69 | // [Interface] run 70 | // Run the certain program with listed arguments 71 | // Limit time and space 72 | // And (might) restrict syscalls if set to true 73 | // Redirect I/O to file and 74 | // If these pointers are set to NULL, then stdin/out will be remained 75 | // If is started with _T("./"), the sandbox will run the program in its own path, or system path otherwise 76 | // Caution: the last member of array args[] must be NULL 77 | Result run(Tstring file, Tchar *args[], Limit time, Limit space, bool restricted, Tstring fin, Tstring fout, Tstring ferr); 78 | 79 | // [Interface] run 80 | // Same as the last function but arguments are wstrings 81 | // Caution: the last member of array args[] must be _T("")(a blank Tstring) 82 | Result run(Tstring file, Tstring args[], Limit time, Limit space, bool restricted, Tstring fin, Tstring fout, Tstring ferr); 83 | 84 | // [Interface] get path of this sandbox 85 | Tstring get_path(); 86 | 87 | // [Constructor] 88 | Sandbox(Tstring s); 89 | }; 90 | } 91 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Microsoft Azure ApplicationInsights config file 170 | ApplicationInsights.config 171 | 172 | # Windows Store app package directory 173 | AppPackages/ 174 | BundleArtifacts/ 175 | 176 | # Visual Studio cache files 177 | # files ending in .cache can be ignored 178 | *.[Cc]ache 179 | # but keep track of directories ending in .cache 180 | !*.[Cc]ache/ 181 | 182 | # Others 183 | ClientBin/ 184 | [Ss]tyle[Cc]op.* 185 | ~$* 186 | *~ 187 | *.dbmdl 188 | *.dbproj.schemaview 189 | *.pfx 190 | *.publishsettings 191 | node_modules/ 192 | orleans.codegen.cs 193 | 194 | # RIA/Silverlight projects 195 | Generated_Code/ 196 | 197 | # Backup & report files from converting an old project file 198 | # to a newer Visual Studio version. Backup files are not needed, 199 | # because we have git ;-) 200 | _UpgradeReport_Files/ 201 | Backup*/ 202 | UpgradeLog*.XML 203 | UpgradeLog*.htm 204 | 205 | # SQL Server files 206 | *.mdf 207 | *.ldf 208 | 209 | # Business Intelligence projects 210 | *.rdl.data 211 | *.bim.layout 212 | *.bim_*.settings 213 | 214 | # Microsoft Fakes 215 | FakesAssemblies/ 216 | 217 | # GhostDoc plugin setting file 218 | *.GhostDoc.xml 219 | 220 | # Node.js Tools for Visual Studio 221 | .ntvs_analysis.dat 222 | 223 | # Visual Studio 6 build log 224 | *.plg 225 | 226 | # Visual Studio 6 workspace options file 227 | *.opt 228 | 229 | # Visual Studio LightSwitch build output 230 | **/*.HTMLClient/GeneratedArtifacts 231 | **/*.DesktopClient/GeneratedArtifacts 232 | **/*.DesktopClient/ModelManifest.xml 233 | **/*.Server/GeneratedArtifacts 234 | **/*.Server/ModelManifest.xml 235 | _Pvt_Extensions 236 | 237 | # LightSwitch generated files 238 | GeneratedArtifacts/ 239 | ModelManifest.xml 240 | 241 | # Paket dependency manager 242 | .paket/paket.exe 243 | 244 | # FAKE - F# Make 245 | .fake/ -------------------------------------------------------------------------------- /Main/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../Judge/oijudge.h" 2 | #include "../Judge/acmjudge.h" 3 | #include "../Support/database.h" 4 | #include "../Definations/platform.h" 5 | #include "../Definations/types.h" 6 | #include "../Definations/enums.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | using namespace ACJudge; 14 | 15 | // The arguments are: 16 | // 1. judge name 17 | // 2. tid 18 | // 3. sid 19 | // 4. task type (see Definations/enums, currently OI and ACM only) 20 | // 5. number of data 21 | // 6. time limit (ms) 22 | // 7. memory limit (KB) 23 | // 8. user language 24 | // 9. spj language (if this argument is -1, the judge will use default comparer) 25 | #if defined WINDOWS 26 | int wmain(int argc, Tchar *args[]) 27 | #elif defined _NIX 28 | int main(int argc, Tchar *args[]) 29 | #endif 30 | { 31 | if(argc == 1) 32 | { 33 | Tcout << _T("\ 34 | The arguments for offline are:\n\ 35 | 1. judge name\n\ 36 | 2. tid\n\ 37 | 3. sid\n\ 38 | 4. task type (see Definations/enums.h, currently OI and ACM only)\n\ 39 | 5. number of data\n\ 40 | 6. time limit (ms)\n\ 41 | 7. memory limit (KB)\n\ 42 | 8. user language\n\ 43 | 9. spj language (if this argument is -1, the judge will use default comparer)\n\ 44 | The arguments for offline are:\n\ 45 | 1. judge count (the maximum number of thread(s) that can run on the server)") << endl; 46 | return 0; 47 | } 48 | else if (argc == 2) 49 | { 50 | Tstring name[2] = 51 | { 52 | _T("WXC"), 53 | _T("SOL") 54 | }; 55 | 56 | Database db("127.0.0.1", "access", "1234567"); 57 | Submission s; 58 | Task t; 59 | int cnt = 0; 60 | 61 | while (true) 62 | { 63 | if (cnt < 1 && (s = db.get_latest_submission(), s.sid)) 64 | { 65 | t = db.get_task(s.tid); 66 | cnt++; 67 | 68 | Grades grades; 69 | if (t.type == TaskType::OI) 70 | grades = (new OIJudge(name[cnt]))->judge(t, s); 71 | else if (t.type == TaskType::ACM) 72 | grades = (new ACMJudge(name[cnt]))->judge(t, s); 73 | 74 | db.set_grades(s.sid, grades); 75 | } 76 | else 77 | { 78 | #if defined WINDOWS 79 | Sleep(500); 80 | #elif define _NIX 81 | usleep(500000); 82 | #endif 83 | } 84 | } 85 | } 86 | else 87 | { 88 | Tstring result[10] = 89 | { 90 | _T("Accepted"), 91 | _T("System Error"), 92 | _T("Time Limit Exceed"), 93 | _T("Memory Limit Exceed"), 94 | _T("Runtime Error"), 95 | _T("Compilation Error"), 96 | _T("Wrong Answer") 97 | }; 98 | 99 | ID tid, sid; 100 | int type, usrlan, spjlan; 101 | Number cnt; 102 | Limit time, space; 103 | 104 | Tstring name(args[1]); 105 | #if defined WINDOWS 106 | Tsscanf(args[2], _T("%I64u"), &tid); 107 | Tsscanf(args[3], _T("%I64u"), &sid); 108 | #elif defined _NIX 109 | Tsscanf(args[2], _T("%llu"), &tid); 110 | Tsscanf(args[3], _T("%llu"), &sid); 111 | #endif 112 | Tsscanf(args[4], _T("%d"), &type); 113 | Tsscanf(args[5], _T("%u"), &cnt); 114 | Tsscanf(args[6], _T("%u"), &time); 115 | Tsscanf(args[7], _T("%u"), &space); 116 | Tsscanf(args[8], _T("%d"), &usrlan); 117 | Tsscanf(args[9], _T("%d"), &spjlan); 118 | 119 | vector data; 120 | for (Number i = 1; i <= cnt; i++) 121 | { 122 | if (type == TaskType::ACM) 123 | data.push_back({ i, time, space, 1 }); 124 | else if (type == TaskType::OI) 125 | data.push_back({ i, time, space, (Score)(100 / cnt) }); 126 | } 127 | 128 | Grades grades; 129 | if (type == TaskType::OI) 130 | grades = (new OIJudge(name))->judge({ tid, (TaskType)type, data, (Language)spjlan }, { sid, tid, (Language)usrlan }); 131 | else if (type == TaskType::ACM) 132 | grades = (new ACMJudge(name))->judge({ tid, (TaskType)type, data, (Language)spjlan }, { sid, tid, (Language)usrlan }); 133 | else 134 | { 135 | puts("Invalid task type!"); 136 | return 0; 137 | } 138 | 139 | int i = 1; 140 | Result totres = { 0, 0, Return::OK, 0, _T("") }; 141 | Score score = 0; 142 | 143 | Tcout << _T("------------------------------------------------") << endl; 144 | for (auto grade : grades) 145 | { 146 | score += grade.score; 147 | totres.ret = grade.res.ret; 148 | totres.time += grade.res.time; 149 | totres.space = max(totres.space, grade.res.space); 150 | totres.msg = grade.res.msg; 151 | 152 | Tcout << _T("[ Data #") << i << _T(" ] "); 153 | Tcout << result[-grade.res.ret]; 154 | if (type == TaskType::OI) Tcout << _T(" (") << grade.score << _T(") "); 155 | Tcout << _T(", ") << grade.res.time << _T("ms, "); 156 | Tcout << grade.res.space << _T("KB.") << endl; 157 | //Tcout << _T("Message: \n")<< grade.res.msg << endl; 158 | 159 | i++; 160 | } 161 | Tcout << _T("------------------------------------------------") << endl; 162 | 163 | i--; 164 | if (type == TaskType::OI) 165 | { 166 | Tcout << _T("Total score: ") << score << endl; 167 | } 168 | else if (type == TaskType::ACM) 169 | { 170 | if (score == cnt) 171 | Tcout << _T("Accepted") << endl; 172 | else 173 | Tcout << result[-totres.ret] << _T(" on data #") << i << endl; 174 | } 175 | Tcout << _T("Total Time: ") << totres.time << _T("ms") << endl; 176 | Tcout << _T("Total Memory: ") << totres.space << _T("KB") << endl; 177 | Tcout << _T("------------------------------------------------") << endl; 178 | Tcout << _T("Message:\n") << totres.msg << endl; 179 | Tcout << _T("------------------------------------------------") << endl; 180 | } 181 | 182 | return 0; 183 | } -------------------------------------------------------------------------------- /VisualStudio/ACJudge/ACJudge/ACJudge.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {918DC3E4-B64D-4534-B368-918211635153} 23 | Win32Proj 24 | ACJudge 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v120 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v120 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | E:\Lib\boost_1_61_0;C:\Program Files (x86)\MySQL\MySQL Server 5.7\include;C:\Program Files (x86)\MySQL\Connector.C++ 1.1\include;$(IncludePath) 81 | $(ReferencePath) 82 | C:\Program Files (x86)\MySQL\Connector.C++ 1.1\lib\opt;C:\Program Files (x86)\MySQL\MySQL Server 5.7\lib;$(LibraryPath) 83 | 84 | 85 | false 86 | E:\Lib\boost_1_61_0;C:\Program Files (x86)\MySQL\MySQL Server 5.7\include;C:\Program Files (x86)\MySQL\Connector.C++ 1.1\include;$(IncludePath) 87 | C:\Program Files (x86)\MySQL\Connector.C++ 1.1\lib\opt;C:\Program Files (x86)\MySQL\MySQL Server 5.7\lib;$(LibraryPath) 88 | 89 | 90 | 91 | 92 | 93 | Level3 94 | Disabled 95 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 96 | true 97 | 98 | 99 | Console 100 | true 101 | 102 | 103 | 104 | 105 | 106 | 107 | Level3 108 | Disabled 109 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 110 | true 111 | 112 | 113 | Console 114 | true 115 | 116 | 117 | 118 | 119 | Level3 120 | 121 | 122 | MaxSpeed 123 | true 124 | true 125 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 126 | true 127 | /D_CRT_SECURE_NO_WARNINGS %(AdditionalOptions) 128 | 129 | 130 | Console 131 | true 132 | true 133 | true 134 | $(OutDir)..\..\..\Release\$(TargetName)$(TargetExt) 135 | 136 | 137 | %(AdditionalDependencies) 138 | 139 | 140 | 141 | 142 | Level3 143 | 144 | 145 | MaxSpeed 146 | true 147 | true 148 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 149 | true 150 | /D_CRT_SECURE_NO_WARNINGS %(AdditionalOptions) 151 | 152 | 153 | Console 154 | true 155 | true 156 | true 157 | $(OutDir)..\..\..\Release\$(TargetName)$(TargetExt) 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /Sandbox/sandbox.cpp: -------------------------------------------------------------------------------- 1 | #include "../Definations/platform.h" 2 | #include 3 | #include 4 | 5 | #if defined WINDOWS 6 | 7 | #include 8 | #include 9 | #pragma comment(lib, "Psapi.lib") 10 | 11 | #include "../Lib/lib.h" 12 | #include "sandbox.h" 13 | 14 | using namespace std; 15 | using namespace ACJudge; 16 | 17 | JOBOBJECT_EXTENDED_LIMIT_INFORMATION Sandbox::set_limits(Limit time, Limit space, bool restricted) 18 | { 19 | JOBOBJECT_EXTENDED_LIMIT_INFORMATION ex_lim; 20 | 21 | // Initialize 22 | ZeroMemory(&ex_lim, sizeof(ex_lim)); 23 | 24 | // Memory limit 25 | if (space != LIMIT_INFINITE) 26 | { 27 | ex_lim.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_JOB_MEMORY; 28 | ex_lim.JobMemoryLimit = SIZE_T((space + 1000) * 1000); 29 | } 30 | 31 | // Time limit 32 | if (time != LIMIT_INFINITE) 33 | { 34 | ex_lim.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_JOB_TIME; 35 | ex_lim.BasicLimitInformation.PerJobUserTimeLimit.QuadPart = time * 10000; 36 | } 37 | 38 | if (restricted) 39 | { 40 | // Set maximum porcess number 41 | ex_lim.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS; 42 | ex_lim.BasicLimitInformation.ActiveProcessLimit = 1; 43 | 44 | // Other limits 45 | ex_lim.BasicLimitInformation.LimitFlags |= 46 | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION | 47 | JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | 48 | JOB_OBJECT_LIMIT_BREAKAWAY_OK; 49 | } 50 | 51 | return ex_lim; 52 | } 53 | 54 | JOBOBJECT_BASIC_UI_RESTRICTIONS Sandbox::set_rules_UI(bool restricted) 55 | { 56 | JOBOBJECT_BASIC_UI_RESTRICTIONS bs_ui; 57 | bs_ui.UIRestrictionsClass = 0; 58 | if (restricted) 59 | { 60 | bs_ui.UIRestrictionsClass = 61 | JOB_OBJECT_UILIMIT_EXITWINDOWS | 62 | JOB_OBJECT_UILIMIT_READCLIPBOARD | 63 | JOB_OBJECT_UILIMIT_WRITECLIPBOARD | 64 | JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | 65 | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS | 66 | JOB_OBJECT_UILIMIT_GLOBALATOMS | 67 | JOB_OBJECT_UILIMIT_DESKTOP | 68 | JOB_OBJECT_UILIMIT_HANDLES; 69 | } 70 | return bs_ui; 71 | } 72 | 73 | STARTUPINFO Sandbox::redirection(Tstring in, Tstring out, Tstring err) 74 | { 75 | SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; 76 | 77 | // Create StartUpInfo 78 | STARTUPINFO s = { sizeof(s) }; 79 | ZeroMemory(&s, sizeof(s)); 80 | s.cb = sizeof(STARTUPINFO); 81 | s.dwFlags = STARTF_USESTDHANDLES; 82 | 83 | // Create file 84 | if (in != _T("")) 85 | { 86 | HANDLE fin = CreateFile((get_path() + in).c_str(), 87 | GENERIC_READ, 88 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 89 | &sa, 90 | OPEN_EXISTING, 91 | FILE_ATTRIBUTE_NORMAL, 92 | 0); 93 | s.hStdInput = fin; 94 | } 95 | if (out != _T("")) 96 | { 97 | HANDLE fout = CreateFile((get_path() + out).c_str(), 98 | GENERIC_READ | GENERIC_WRITE, 99 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 100 | &sa, 101 | CREATE_ALWAYS, 102 | FILE_ATTRIBUTE_NORMAL, 103 | 0); 104 | s.hStdOutput = fout; 105 | } 106 | if (err != _T("")) 107 | { 108 | HANDLE ferr = CreateFile((get_path() + err).c_str(), 109 | GENERIC_READ | GENERIC_WRITE, 110 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 111 | &sa, 112 | CREATE_ALWAYS, 113 | FILE_ATTRIBUTE_NORMAL, 114 | 0); 115 | s.hStdError = ferr; 116 | } 117 | 118 | return s; 119 | } 120 | 121 | Result Sandbox::run(Tstring file, Tchar *args[], Limit time, Limit space, bool restricted, Tstring fin, Tstring fout, Tstring ferr) 122 | { 123 | // Initialize 124 | JOBOBJECT_EXTENDED_LIMIT_INFORMATION ex_lim = set_limits(time, space, restricted); 125 | JOBOBJECT_BASIC_UI_RESTRICTIONS bs_ui = set_rules_UI(restricted); 126 | STARTUPINFO s = redirection(fin, fout, ferr); 127 | _PROCESS_INFORMATION p; 128 | 129 | // Init res 130 | Result res; 131 | res.time = res.space = 0; 132 | res.ret = Return::ERR; 133 | res.val = -1; 134 | res.msg = _T("Unknown system error."); 135 | 136 | // Create JOB object 137 | HANDLE job = CreateJobObject(NULL, NULL); 138 | SetInformationJobObject(job, JobObjectExtendedLimitInformation, &ex_lim, sizeof(ex_lim)); 139 | SetInformationJobObject(job, JobObjectBasicUIRestrictions, &bs_ui, sizeof(bs_ui)); 140 | 141 | // Operate arguments 142 | Tchar *str = new Tchar[100000]; 143 | memset(str, 0, sizeof(str)); 144 | if (file[0] == _T('.')) 145 | Tstrcat(str, get_path().c_str()); 146 | Tstrcat(str, args[0]); 147 | #if defined WINDOWS 148 | Tstrcat(str, _T(".exe")); 149 | #endif 150 | for (int i = 1; args[i]; i++) 151 | Tstrcat(str, _T(" ")), Tstrcat(str, args[i]); 152 | 153 | // Create process 154 | DWORD ret = 155 | CreateProcess(NULL, str, 156 | NULL, 157 | NULL, 158 | TRUE, 159 | CREATE_SUSPENDED, 160 | NULL, 161 | NULL, 162 | &s, 163 | &p); 164 | if (!ret) 165 | { 166 | res.ret = Return::ERR; 167 | res.msg = _T("Error while creating subprocess, errcode = ") + i2s(GetLastError()); 168 | return res; 169 | } 170 | 171 | // Start process 172 | AssignProcessToJobObject(job, p.hProcess); 173 | ResumeThread(p.hThread); 174 | 175 | // Start timing 176 | HANDLE handles[2]; 177 | handles[0] = p.hProcess; 178 | handles[1] = job; 179 | ret = WaitForMultipleObjects(2, handles, FALSE, time * 3); 180 | 181 | FILETIME _, __, ___, user; 182 | SYSTEMTIME suser; 183 | PROCESS_MEMORY_COUNTERS pmc; 184 | GetProcessTimes(p.hProcess, &_, &__, &___, &user); 185 | GetProcessMemoryInfo(p.hProcess, &pmc, sizeof(pmc)); 186 | FileTimeToSystemTime(&user, &suser); 187 | 188 | res.time = suser.wMilliseconds + suser.wSecond * 1000 + suser.wMinute * 60000; 189 | if (res.time == 0) res.time = 1; 190 | res.space = (Limit)(pmc.PeakWorkingSetSize / 1000); 191 | 192 | switch (ret) 193 | { 194 | case WAIT_OBJECT_0: 195 | // Process exited normally 196 | GetExitCodeProcess(p.hProcess, (LPDWORD)&res.val); 197 | if (res.val == 1816) // CPU time TLE 198 | { 199 | res.ret = Return::TLE; 200 | res.msg = _T("CPU time TLE."); 201 | } 202 | else if (res.val == 3221225495u) // Memory limit exceed 203 | { 204 | res.ret = Return::MLE; 205 | res.msg = _T("MLE."); 206 | } 207 | else if (res.val) // Return value not zero 208 | { 209 | Tchar *file = new Tchar[1000000]; 210 | Tifstream fin(get_path() + _T("errlog")); 211 | fin.getline(file, 1000000, EOF); 212 | 213 | res.ret = Return::RTE; 214 | res.msg = _T("Return code is ") + i2s(res.val) + _T(". Errlog:\n") + _T(""); 215 | delete file; 216 | } 217 | else // It seems all right 218 | { 219 | res.ret = Return::OK; 220 | res.msg = _T("Process exited normally."); 221 | } 222 | break; 223 | 224 | case WAIT_TIMEOUT: // Real time TLE 225 | res.ret = Return::TLE; 226 | res.msg = _T("Real time TLE."); 227 | break; 228 | 229 | case WAIT_FAILED: // System error 230 | res.ret = Return::ERR; 231 | res.msg = _T("Error while waiting."); 232 | break; 233 | } 234 | 235 | return res; 236 | } 237 | 238 | #elif defined _NIX 239 | 240 | #include 241 | #include 242 | #include 243 | #include 244 | #include 245 | #include 246 | #include 247 | #include 248 | #include 249 | #include 250 | #include 251 | #include 252 | #include 253 | #include 254 | #include 255 | #include "../Lib/lib.h" 256 | #include "sandbox.h" 257 | 258 | using namespace std; 259 | using namespace ACJudge; 260 | 261 | Return Sandbox::set_time_limit(Limit time) 262 | { 263 | Limit stime = time * 3; 264 | ITimerVal time_limit; 265 | 266 | time_limit.it_interval.tv_sec = time_limit.it_interval.tv_usec = 0; 267 | 268 | // User mode CPU time 269 | time_limit.it_value.tv_sec = time / 1000; 270 | time_limit.it_value.tv_usec = time % 1000 * 1000; 271 | if(setitimer(ITIMER_VIRTUAL, &time_limit, NULL)) 272 | return Return::ERR; 273 | 274 | // All CPU time 275 | time_limit.it_value.tv_sec = stime / 1000; 276 | time_limit.it_value.tv_usec = stime % 1000 * 1000; 277 | if(setitimer(ITIMER_REAL, &time_limit, NULL)) 278 | return Return::ERR; 279 | 280 | // setrlimit 281 | RLimit limit; 282 | limit.rlim_cur = limit.rlim_max = (rlim_t)(time); 283 | if(setrlimit(RLIMIT_CPU, &limit) == -1) 284 | return Return::ERR; 285 | 286 | return Return::OK; 287 | } 288 | 289 | Return Sandbox::set_space_limit(Limit space) 290 | { 291 | // setrlimit 292 | RLimit limit; 293 | limit.rlim_cur = limit.rlim_max = (rlim_t)(space + 20000000); 294 | if(setrlimit(RLIMIT_AS, &limit) == -1) 295 | return Return::ERR; 296 | return Return::OK; 297 | } 298 | 299 | Return Sandbox::set_file(FILE *fp, Tstring file, Tstring mode) 300 | { 301 | FILE *newfp; 302 | file = get_path() + file; 303 | if((newfp = fopen(file.c_str(), mode.c_str())) == NULL) 304 | return Return::ERR; 305 | if(dup2(fileno(newfp), fileno(fp)) == -1) 306 | return Return::ERR; 307 | return Return::OK; 308 | } 309 | 310 | void Sandbox::start(Tstring file, Tchar *args[], Limit time, Limit space, bool restricted, Tstring fin, Tstring fout, Tstring ferr) 311 | { 312 | Tstring s = (file[0] == '.' ? get_path() + file : file); 313 | Tchar *arguments[1000]; 314 | int argc; 315 | //Tchar const *envp[] ={"PATH=/bin:/usr/bin"), _T("TERM=console"), NULL}; 316 | 317 | arguments[0] = (Tchar *)s.c_str(); 318 | for(argc = 1; args[argc]; argc++) 319 | arguments[argc] = args[argc]; 320 | arguments[argc] = NULL; 321 | 322 | if(set_limits(time, space) == Return::ERR) 323 | exit(Return::ERR); 324 | if(redirection(fin, fout, ferr) == Return::ERR) 325 | exit(Return::ERR); 326 | if(restricted && (set_rules(s) == Return::ERR) ) // Removed: setgid 327 | exit(Return::ERR); 328 | if(execvp(s.c_str(), arguments)) 329 | { 330 | perror("Error"); 331 | exit(Return::ERR); 332 | } 333 | } 334 | 335 | Return Sandbox::redirection(Tstring in, Tstring out, Tstring err) 336 | { 337 | if(in != _T("") && set_file(stdin , in , _T("r")) == Return::ERR) 338 | return Return::ERR; 339 | if(out != _T("") && set_file(stdout, out, _T("w")) == Return::ERR) 340 | return Return::ERR; 341 | if(err != _T("") && set_file(stderr, err, _T("w")) == Return::ERR) 342 | return Return::ERR; 343 | return Return::OK; 344 | } 345 | 346 | Return Sandbox::set_limits(Limit time, Limit space) 347 | { 348 | if(time != LIMIT_INFINITE) 349 | if(set_time_limit(time) == Return::ERR) 350 | return Return::ERR; 351 | if(space != LIMIT_INFINITE) 352 | if(set_space_limit(space * 1024) == Return::ERR) 353 | return Return::ERR; 354 | return Return::OK; 355 | } 356 | 357 | Return Sandbox::set_gid() 358 | { 359 | passwd *pwd = getpwnam("nobody"); 360 | const unsigned int groups[] = {pwd->pw_gid}; 361 | 362 | if(setgid(pwd->pw_gid) == -1) 363 | return Return::ERR; 364 | if(setgroups(1, groups) == -1) 365 | return Return::ERR; 366 | if(setuid(pwd->pw_uid) == -1) 367 | return Return::ERR; 368 | 369 | return Return::OK; 370 | } 371 | 372 | Return Sandbox::set_rules(Tstring file) 373 | { 374 | // White list 375 | int whitelist[] = {SCMP_SYS(read), SCMP_SYS(fstat), 376 | SCMP_SYS(mmap), SCMP_SYS(mprotect), 377 | SCMP_SYS(munmap), SCMP_SYS(open), 378 | SCMP_SYS(arch_prctl), SCMP_SYS(brk), 379 | SCMP_SYS(access), SCMP_SYS(exit_group), 380 | SCMP_SYS(close)}; 381 | int whitelist_length = sizeof(whitelist) / sizeof(int); 382 | int i; 383 | scmp_filter_ctx ctx; 384 | 385 | // Init 386 | if(!(ctx = seccomp_init(SCMP_ACT_KILL))) 387 | return Return::ERR; 388 | 389 | // Add whitelist 390 | for(i = 0; i < whitelist_length; i++) 391 | if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, whitelist[i], 0)) 392 | return Return::ERR; 393 | 394 | // Enable execve 395 | if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1, SCMP_A0(SCMP_CMP_EQ, (scmp_datum_t)file.c_str()))) 396 | return Return::ERR; 397 | // Allow FD but 0 1 2 only 398 | if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_LE, 2))) 399 | return Return::ERR; 400 | 401 | //Load 402 | if(seccomp_load(ctx)) 403 | return Return::ERR; 404 | 405 | seccomp_release(ctx); 406 | return Return::OK; 407 | } 408 | 409 | Result Sandbox::run(Tstring file, Tchar *args[], Limit time, Limit space, bool restricted, Tstring fin, Tstring fout, Tstring ferr) 410 | { 411 | int starter; 412 | int pid, status, signal, retval; 413 | Result res; 414 | RUsage resource_usage; 415 | 416 | // Init res 417 | res.time = res.space = 0; 418 | res.ret = Return::OK; 419 | res.val = -1; 420 | 421 | // Fork for starter 422 | if((starter = fork()) < 0) 423 | return res.ret = Return::ERR, res; 424 | else if (starter == 0) // Starter subprocess 425 | { 426 | start(file, args, time, space, restricted, fin, fout, ferr); 427 | // If this return is accessed, then something wrong must happened 428 | exit(Return::ERR); 429 | } 430 | 431 | // Else 432 | // Main process 433 | // Deal with the return value 434 | 435 | // Wait for the subprocess to quit 436 | if((pid = wait3(&status, 0, &resource_usage)) == -1) 437 | return res.ret = Return::ERR, res; 438 | 439 | // Get CPU time 440 | res.time = (int) (resource_usage.ru_utime.tv_sec * 1000 + 441 | resource_usage.ru_utime.tv_usec / 1000 + 442 | resource_usage.ru_stime.tv_sec * 1000 + 443 | resource_usage.ru_stime.tv_usec / 1000); 444 | if(res.time == 0) 445 | res.time = 1; 446 | 447 | // Get space 448 | res.space = resource_usage.ru_maxrss; 449 | 450 | // Get signal 451 | if(WIFSIGNALED(status)) 452 | { 453 | signal = WTERMSIG(status); 454 | if(signal == SIGALRM) // Real time TLE 455 | { 456 | res.ret = Return::TLE; 457 | res.msg = _T("Real time TLE."); 458 | }else if(signal == SIGVTALRM) // CPU time TLE 459 | { 460 | res.ret = Return::TLE; 461 | res.msg = _T("CPU time TLE."); 462 | }else if(signal == SIGSEGV) // Segment fault 463 | if(space != LIMIT_INFINITE && res.space > space) // MLE 464 | { 465 | res.ret = Return::MLE; 466 | res.msg = _T("MLE."); 467 | }else // Signaled RTE 468 | { 469 | res.ret = Return::RTE; 470 | res.msg = _T("Signaled RTE.\nStack overflow, NULL pointer or something like that."); 471 | } 472 | else if(signal == SIGFPE) 473 | { 474 | res.ret = Return::RTE; 475 | res.msg = _T("Signaled RTE.\nFloating point error."); 476 | } 477 | else if(signal == SIGKILL) 478 | { 479 | res.ret = Return::MLE; 480 | res.msg = _T("Process killed (Memory Limit Exceed)."); 481 | } 482 | else 483 | { 484 | res.ret = Return::RTE; 485 | res.msg = _T("Syscall failed.\nThis might happen when memory limit exceeded.\nBut it also might caused by an illegal syscall, such as fork."); 486 | } 487 | }else 488 | { 489 | if(space != LIMIT_INFINITE && res.space > space) // Return::MLE 490 | { 491 | res.ret = Return::MLE; 492 | res.msg = _T("MLE."); 493 | } 494 | 495 | retval = WEXITSTATUS(status); 496 | if(retval == Return::ERR || retval == 256 + Return::ERR) // System Return::ERRor 497 | { 498 | Tchar *file = new Tchar[1000000]; 499 | Tifstream fin((char *)(get_path() + _T("errlog")).c_str()); 500 | fin.getline(file, 1000000, EOF); 501 | 502 | res.ret = Return::ERR; 503 | res.val = retval; 504 | res.msg = _T("System Error #") + i2s(retval) + _T(".\nErrlog:\n") + file; 505 | delete file; 506 | }else if(retval) //RTE 507 | { 508 | Tchar *file = new Tchar[1000000]; 509 | Tifstream fin((char *)(get_path() + _T("errlog")).c_str()); 510 | fin.getline(file, 1000000, EOF); 511 | 512 | res.ret = Return::RTE; 513 | res.val = retval; 514 | res.msg = _T("Returned ") + i2s(retval) + _T(".\nErrlog:\n") + file; 515 | delete file; 516 | }else 517 | { 518 | res.ret = Return::OK; // All right 519 | res.val = 0; 520 | res.msg = _T("Process exited normally."); 521 | } 522 | } 523 | 524 | return res; 525 | } 526 | 527 | #endif 528 | 529 | Result Sandbox::run(Tstring file, Tstring args[], Limit time, Limit space, bool restricted, Tstring fin, Tstring fout, Tstring ferr) 530 | { 531 | Tchar *arguments[1000]; 532 | int i; 533 | 534 | for(i = 0; args[i] != _T(""); i++) 535 | arguments[i] = (Tchar *)(args[i].c_str()); 536 | arguments[i] = NULL; 537 | 538 | return run(file, arguments, time, space, restricted, fin, fout, ferr); 539 | } 540 | 541 | Tstring Sandbox::get_path() 542 | { 543 | return _T("../Container/")+ name + _T("/"); 544 | } 545 | 546 | Sandbox::Sandbox(Tstring s) 547 | { 548 | name = s; 549 | } 550 | --------------------------------------------------------------------------------