├── .gitignore ├── Config ├── config.sh └── sample.config.h ├── GenerateSH.cpp ├── Install.sh ├── Local ├── TestCases │ ├── TEST1 │ │ ├── Input │ │ │ ├── 1.txt │ │ │ └── 2.txt │ │ └── Output │ │ │ ├── 1.txt │ │ │ └── 2.txt │ └── TEST2 │ │ ├── Input │ │ ├── 1.txt │ │ └── 2.txt │ │ └── Output │ │ ├── 1.txt │ │ └── 2.txt ├── id.php └── sourcecode.php ├── Makefile ├── README.md ├── coderunner.conf ├── docs ├── DEVELOPERS.md ├── DOCUMENTATION.md └── SETUP.md ├── policy.txt └── src ├── CROptions.cpp ├── CROptions.h ├── CodeRunner.cpp ├── CodeRunner.h ├── ContentParser.cpp ├── ContentParser.h ├── CurlWrapper.cpp ├── CurlWrapper.h ├── Execution.cpp ├── FileHandle.cpp ├── FileHandle.h ├── Logs.cpp ├── Logs.h ├── headers.h ├── main.cpp └── resources.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.[oad] 2 | *~ 3 | TestCases/* 4 | Files/* 5 | Logs/* 6 | main 7 | *config.h 8 | config/ 9 | !sample.config.h 10 | coderunner 11 | Execution 12 | GenerateSH 13 | CodeRunner.sh 14 | link.sh 15 | Local/Files/* 16 | -------------------------------------------------------------------------------- /Config/config.sh: -------------------------------------------------------------------------------- 1 | #appends `#define ABSOLUTE_PATH` in config.h 2 | echo "#define ABSOLUTE_PATH \""$PWD"/\"" >> $1/$2 3 | echo "\n#endif" >> $1/$2 4 | -------------------------------------------------------------------------------- /Config/sample.config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This is the sample config file for CodeRunner. 3 | * Before running make command, define the options suitably and 4 | * change the name of the file from sample.config.h to config.h 5 | * without which the source code will not compile. 6 | * All the options should be specified correctly for CodeRunner to work properly. 7 | * After that, simply run make command from command line. 8 | */ 9 | #ifndef CONFIG_H 10 | #define CONFIG_H 11 | /** 12 | * Specify the username and password to be used for communication over internet with the website. 13 | * The "username" and "password" fields will be supplied via POST request while querying for pending file ids, fetching source 14 | * code, and sending results. 15 | */ 16 | #define USERNAME "shashank" 17 | #define PASSWORD "shashank" 18 | 19 | /** 20 | * HTTPON and FTPON are two methods by which source code can be downloaded from internet. 21 | * If the preferred method is HTTP, then specify HTTPON as true. 22 | * otherwise specify FTPON as true. 23 | */ 24 | #define HTTPON true 25 | #define FTPON false 26 | 27 | /** 28 | * If the preferred method for source code download is FTP, then specify the FTP username 29 | * and password field to be user during authentication in here. 30 | */ 31 | #define FTPUSERNAME "" 32 | #define FTPPASSWORD "" 33 | 34 | /** 35 | * Specify the FTP url for downloading source code files here. 36 | */ 37 | #define FTPADDRESS "/Upload/" 38 | 39 | 40 | #define URL_TO_GET_FILE_IDS "http://localhost/projects/CodeRunner/Local/id.php" 41 | #define URL_TO_GET_SOURCE_CODE "http://localhost/projects/CodeRunner/Local/sourcecode.php" 42 | #define FILEPATH "./Local/Files/" 43 | #define TESTCASESPATH "./Local/TestCases/" 44 | 45 | /** 46 | * Specify the URL where results will be sent here. 47 | * Same username and password will be used as above. 48 | */ 49 | #define URL_TO_SEND_RESULTS "http://localhost:8089" 50 | 51 | #define LOGFILEPATH "./Logs/" 52 | #define LOGFILENAME "logs.txt" 53 | #define LOGSTATUSFILENAME "logs_status.txt" 54 | 55 | /** 56 | * Specify the interval for which CodeRunner sleeps between two epochs. 57 | * One epoch is downloading of pending file ids, their source files, their execution and finally sending their results. 58 | */ 59 | #define SLEEPINTERVAL 5 60 | 61 | #define FORCE_PUSH_RESULT false; 62 | // For sending results and forcing insertion of those results. 63 | 64 | #define GET_ALL_FILEIDS false; 65 | // For fetching all file-ids irrespective of evaluation status. 66 | 67 | #define CLEAN false; 68 | // For clearing Files directory after execution of source code. 69 | 70 | #define SEND_RESULTS true; 71 | // For sending results after evaluation. 72 | 73 | #define DOWNLOAD_SOURCE_FILE true; 74 | // For not downloading source codes. In such a case, the source codes should already be present in the Files directory. 75 | 76 | #define ONE_FILE_EXECUTION false; 77 | //For excecuting only one file 78 | 79 | #define PRINT_ON_SCREEN true; 80 | //For printing output on the screen 81 | 82 | #define VERBOSE false; 83 | 84 | 85 | /** 86 | *Specify which langauges are enabled on CodeRunner currently 87 | **/ 88 | 89 | #define LANG_C true 90 | #define LANG_CPP true 91 | #define LANG_JAVA true 92 | #define LANG_PYTHON true 93 | #define LANG_PERL true 94 | #define LANG_PHP true 95 | 96 | -------------------------------------------------------------------------------- /GenerateSH.cpp: -------------------------------------------------------------------------------- 1 | //To generate link.sh and codevillage.sh files 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | int main () 11 | { 12 | ofstream file1; 13 | ofstream file2; 14 | string currentDir; 15 | char cwd[2048]; 16 | if(getcwd(cwd, sizeof(cwd))!=NULL) 17 | { 18 | currentDir=cwd; 19 | //cout<&2 \n sleep 1 \n done"; 22 | file1.close(); 23 | file2.open ("link.sh"); 24 | file2 << currentDir+"/main -q"; 25 | file2.close(); 26 | } 27 | else 28 | perror("getcwd() Status"); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /Install.sh: -------------------------------------------------------------------------------- 1 | #Script to add the required directories and create link.sh and codeRunner.sh and to run the makefile 2 | 3 | rm main 4 | rm Execution 5 | mkdir TestCases 6 | mkdir Logs 7 | mkdir Files 8 | mkdir Local/Files 9 | g++ GenerateSH.cpp -o GenerateSH.o 10 | ./GenerateSH.o 11 | cp Config/sample.config.h Config/config.h 12 | sh Config/config.sh Config config.h 13 | make clean 14 | make 15 | chmod 755 link.sh 16 | chmod 755 CodeRunner.sh 17 | -------------------------------------------------------------------------------- /Local/TestCases/TEST1/Input/1.txt: -------------------------------------------------------------------------------- 1 | 7 -------------------------------------------------------------------------------- /Local/TestCases/TEST1/Input/2.txt: -------------------------------------------------------------------------------- 1 | 7 -------------------------------------------------------------------------------- /Local/TestCases/TEST1/Output/1.txt: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /Local/TestCases/TEST1/Output/2.txt: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /Local/TestCases/TEST2/Input/1.txt: -------------------------------------------------------------------------------- 1 | 7 -------------------------------------------------------------------------------- /Local/TestCases/TEST2/Input/2.txt: -------------------------------------------------------------------------------- 1 | 7 -------------------------------------------------------------------------------- /Local/TestCases/TEST2/Output/1.txt: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /Local/TestCases/TEST2/Output/2.txt: -------------------------------------------------------------------------------- 1 | 147 -------------------------------------------------------------------------------- /Local/id.php: -------------------------------------------------------------------------------- 1 | 5 | using namespace std; 6 | void troll() 7 | { 8 | int a[1000]; 9 | troll(); 10 | } 11 | main(){ 12 | int a=25; 13 | cout<<\"7\"< 17 | using namespace std; 18 | main(){ 19 | int a=25; 20 | cout<<\"7\"< $(DEPDIR)/$*.d 71 | @cp $(DEPDIR)/$*.d $(DEPDIR)/$*.d.tmp 72 | @sed -e 's/.*://' -e 's/\\\\$$//' < $(DEPDIR)/$*.d.tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(DEPDIR)/$*.d 73 | rm -f $(DEPDIR)/$*.d.tmp 74 | 75 | clean: 76 | rm -rf $(OBJDIR) $(DEPDIR) $(SRCDIR)/$(CONFIG) main Execution 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeRunner 2 | 3 | An online judge to conduct programming contests or run 24*7 programming site. It was initially born out of the need for organising IIT Roorkee programming competition INSOMNIA. Later development occurred when the need arose for powering the internal programming arena of IIT Roorkee. 4 | In this documentation you will find everything that you need for using it in your local programming competition or for its further development. 5 | 6 | ## Demo 7 | [Insomnia](http://insomnia.cognizance.org.in) 8 | Not a full featured demo but you can see how CodeRunner was used in action! 9 | Already being used in Codevillage (The coding arena of IIT Roorkee on intranet). 10 | 11 | ## Features 12 | * Download source code files via HTTP/FTP. 13 | * Compilation of source code files. 14 | * Execution of files. 15 | * Matching output produced by executing files with the standard solution. 16 | * Status given - Compilation Error, Wrong Answer, Time Limit Exceeded, Runtime Error, Memory Limit Exceeded. 17 | * Gives time of execution, memory used, type of runtime error(in case of runtime error) and compilation error(in case of compilation error). 18 | 19 | ## Languages supported 20 | * C/C++ 21 | * Python 22 | * Perl 23 | * Pascal 24 | * PHP 25 | * Java 26 | 27 | ## TODOs 28 | * Matching output with 10^-6 precision error. 29 | * Securing the uploads. 30 | * Add support for threads. 31 | * Add support to run on multiple servers concurrently. -------------------------------------------------------------------------------- /coderunner.conf: -------------------------------------------------------------------------------- 1 | description "Coderunner Service daemon" 2 | author "Shashank Kumar - shashankkumar.me@gmail.com" 3 | 4 | # used to be: start on startup 5 | # until we found some mounts weren't ready yet while booting: 6 | start on started mountall 7 | stop on shutdown 8 | 9 | # Automatically Respawn: 10 | respawn 11 | respawn limit 99 5 12 | 13 | script 14 | # Not sure why $HOME is needed, but we found that it is: 15 | #export HOME="/root" 16 | 17 | exec sudo -u /main 2>&1 18 | end script 19 | 20 | post-start script 21 | # Optionally put a script here that will notifiy you coderunner has (re)started 22 | end script 23 | -------------------------------------------------------------------------------- /docs/DEVELOPERS.md: -------------------------------------------------------------------------------- 1 | Documentation for Developers 2 | ==================================== 3 | 4 | Commands used for executing the programs in different languages 5 | === 6 | 7 | For C++ : 8 | 9 | Compilation: 10 | `g++ -w -static FullFileAddr.cpp -o FullFileAddr 2>&1` 11 | 12 | 13 | For C : 14 | 15 | Compilation: 16 | `gcc -w -static FullFileAddr.c -o FullFileAddr 2>&1` 17 | 18 | 19 | For Java : 20 | 21 | Compilation: 22 | `javac FullFileAddr.java` 23 | 24 | 25 | For Python : 26 | 27 | Syntax Check: 28 | `python -m py_compile FullFileAddr.py` 29 | 30 | 31 | For Pascal : 32 | 33 | Syntax Check : 34 | `fpc FullFileAddr.p` 35 | 36 | 37 | For Perl : 38 | 39 | Syntax Check : 40 | `perl -c FullFileAddr.pl` 41 | 42 | 43 | For PHP : 44 | 45 | Syntax Check : 46 | `php -l FullFileAddr.php` 47 | 48 | 49 | 50 | Measuring memory usage by a program 51 | === 52 | 53 | CodeRunner uses [proc](http://serverfault.com/questions/301980/in-unix-linux-what-is-the-proc-directory-for-why-does-it-exists) to determine memory usage by programs. For almost every process running in the system, there is a directory created in /proc/. The directory name is the process id and it contains several useful files including a file called `status`. 54 | 55 | **/proc/[pid]/status** : This file contains information regarding memory usage such as virtual memory size (VmSize), size of data segment (VmData), stack size (VmStk), and size of text segment (VmExe). All these sizes are in KB ie Kilobytes. 56 | 57 | Sample Output for `cat /proc/3159/status` : 58 | 59 | 60 | Name: chrome 61 | State: S (sleeping) 62 | Tgid: 3159 63 | Pid: 3159 64 | PPid: 2490 65 | TracerPid: 0 66 | Uid: 1000 1000 1000 1000 67 | Gid: 1000 1000 1000 1000 68 | FDSize: 256 69 | Groups: 4 24 27 30 46 109 124 1000 70 | VmPeak: 362948 kB 71 | VmSize: 362948 kB 72 | VmLck: 0 kB 73 | VmPin: 0 kB 74 | VmHWM: 136272 kB 75 | VmRSS: 136036 kB 76 | VmData: 190464 kB 77 | VmStk: 136 kB 78 | VmExe: 83228 kB 79 | VmLib: 49076 kB 80 | VmPTE: 612 kB 81 | VmSwap: 0 kB 82 | Threads: 28 83 | SigQ: 0/23036 84 | SigPnd: 0000000000000000 85 | ShdPnd: 0000000000000000 86 | SigBlk: 0000000000000000 87 | SigIgn: 0000000004001002 88 | SigCgt: 00000001c0010000 89 | CapInh: 0000000000000000 90 | CapPrm: 0000000000000000 91 | CapEff: 0000000000000000 92 | CapBnd: ffffffffffffffff 93 | Cpus_allowed: f 94 | Cpus_allowed_list: 0-3 95 | Mems_allowed: 1 96 | Mems_allowed_list: 0 97 | voluntary_ctxt_switches: 30213 98 | nonvoluntary_ctxt_switches: 17173 99 | 100 | 101 | The fields of interest are as follows: 102 | 103 | * Name: Command run by this process. 104 | 105 | * State: Current state of the process. One of "R (running)", "S 106 | (sleeping)", "D (disk sleep)", "T (stopped)", "T (tracing 107 | stop)", "Z (zombie)", or "X (dead)". 108 | 109 | * VmPeak: Peak virtual memory size. 110 | 111 | * VmSize: Virtual memory size. 112 | 113 | * VmLck: Locked memory size (see mlock(3)). 114 | 115 | * VmHWM: Peak resident set size ("high water mark"). 116 | 117 | * VmRSS: Resident set size. 118 | 119 | * VmData, VmStk, VmExe: Size of data, stack, and text segments. 120 | 121 | * VmLib: Shared library code size. 122 | 123 | * VmPTE: Page table entries size (since Linux 2.6.10). 124 | 125 | * Threads: Number of threads in process containing this thread. 126 | 127 | For detailed information about these terms, refer to man page of `proc` 128 | 129 | Note : I read some where that **data segment = data+bss+heap** 130 | 131 | **/proc/[pid]/statm**: This files also contains information about memory usage. The file has a single row of information where values are placed separated by space. These values are total program size, resident set size, size of shared pages, size of text segment, size of lib code, size of data segment + stack, and dirty pages. 132 | 133 | Sample Output for `cat /proc/3159/statm` : 134 | 135 | 136 | 90737 34018 5151 20807 0 47650 0 137 | 138 | 139 | We prefer /proc/[pid]/status over /proc/[pid]/statm because former uses KB for expressing memory size while latter uses number of pages. Assuming that 1 page = 4 KB (this is the usual case but not the general case), we can get memory usage in KBs. 140 | 141 | We are interested in computing memory usgae of the program which is given as : **memory usage = size of data + size of bss + size of heap + size of stack**. 142 | 143 | **VmData = size of data + size of bss + size of heap** 144 | 145 | **VmStk = size of stack**. 146 | 147 | This means **memory usage = VmData + VmStk** 148 | 149 | 150 | Implementation : 151 | 152 | `MemoryUsage` function in Execution.cpp returns the total memory used by the program in terms of KBs. The `p` variable defined in the function contains the output of /proc/[pid]/status. 153 | 154 | Shortcomings : 155 | 156 | * VmData and heap size can be inaccurate as kernel may allocate more memory than asked for making execution efficient. 157 | 158 | Currently MemoryUsed = max(64, MemoryUsage(cpid)) ie the MemoryUsed is reported as maximum of 64 or actual Memory Usage by the program. 159 | 160 | 161 | Measuring time take by a program 162 | === 163 | There are two cases : 164 | 165 | * Time Limit Not Exceeded : In this case, the total time taken by the program is stored in `TimeUsed` variable in `Execution.cpp`. 166 | * Time Limit Exceeded : In this case, the program gets killed after `t` seconds as specified in time limit of the program and `TLE` status is returned. 167 | 168 | Relevant resource limits are defined in `resources.h` 169 | 170 | 171 | 172 | Securing C/C++ Submissions 173 | === 174 | 175 | `gcc -w -I ../../gcc -static` The additional -I flag make the compiler look into 'gcc' folder instead of the default locations. The 'gcc' folder contains a copy of files like 'unistd.h', 'syslimits.h', 'bits/', 'linux/', 'sys' etc. This way if the submission makes a request to these files or files in these folders, then it returns compilation error (CE). So we need to make a copy of all such files in a seperate folder called 'gcc' on the server running CodeRunner. Also 'gcc' folder should be in the same directory as CodeRunner. 176 | 177 | 178 | 179 | Securing Java Submissions 180 | === 181 | To secure java submissions, we rely on enabling Java Security Manager and specifying policy files. 182 | 183 | `java -Djava.security.manager -Djava.security.policy==./policy.txt` This command replaces the default privileges with the privileges given in [policy.txt](https://github.com/shashankkumar/CodeRunner/blob/master/policy.txt). Current configuration blocks access to all networking and OS operations and does not need any change. 184 | 185 | Further details about it can be found [here](http://pic.dhe.ibm.com/infocenter/cicsts/v4r1/index.jsp?topic=%2Fcom.ibm.cics.ts.java.doc%2Ftopics%2Fdfhpj5u.html). 186 | 187 | Refer [this](http://stackoverflow.com/questions/11620354/running-java-security-manager-without-the-default-java-policy-file) for differentiating between use of '=' and '==' while running Java Security Manager. -------------------------------------------------------------------------------- /docs/DOCUMENTATION.md: -------------------------------------------------------------------------------- 1 | Documentation for Contest-Organizers 2 | ==================================== 3 | Problem Specifications 4 | 5 | === 6 | 7 | * The crux of a programming competition are its problems. While, the software has nothing to do with problem statements, the test cases need to be stored in proper format. 8 | * The test cases are to be stored in the TESTCAESPATH directory path specified in config.h By default it is set to `TestCases` folder in the `PATH` address by relative address mode. 9 | * Each problem should have a unique Problem Id. This string should be the means by which website and CodeRunner identifies a problem. For eg. PALIN, TEST etc. 10 | * For every problem, there should be a folder present in TESTCASESPATH directory and its name should be the Problem Id. Before starting a competition, the problem directories should be created first. In each problem folder, there should be two folders named `Input` and `Output` without quotes. The Input folder should contain the input files for the problem, and the output folder should contain the output for the problem. Number the test case input and output files starting from 1. There is no limit on the number of test cases present for a problem. Corresponding input and output files should have the same number. So, suppose problem with problem id TEST has got 3 testcase files, then in the input folder, there should be 3 files namely 1, 2 and 3. And correspondingly in the output folder, there should be 3 files 1, 2 and 3. A solution submitted by the user is executed once for all the test cases. If the solution gives correct output for all the test cases, then only its status is changed to AC. 11 | **Note: 12 | In case there is a large body of problems and more will be uploaded over time (like in a practice arena, or a 24\*7 judge) then the process of uploading Test Cases (creating directories, and input and output files) can be automated through the website. 13 | 14 | File List Specifications 15 | ==== 16 | CodeRunner fetches the information of pending files from the URL `URLToFetchFileIds` specified in the config.h file. The format of specifying file ids in the webpage is as following: 17 | 18 | 19 | You can specify multiple file ids in the same format separated by \n as following: 20 | 21 | 22 | 23 | . 24 | . 25 | . 26 | 27 | 28 | There is no upper limit on the number of File Ids that can be specified in one display. 29 | The list of file ids supplied at a time to be executed is called an `Epoch` from now on. 30 | However it is recommended not to supply more than 5-10 file ids at a time. 31 | The is the number of seconds under which all the user solution should run for all the test cases. 32 | The is the maximum memory in MB that a solution can consume while running. 33 | The is the language of the source code. Currently supported languages are C++, C, Java, Python, PHP, Perl. The corresponding string that should be supplied in options are `cpp, c, java, python, php, perl`. No other string should be specified in their place otherwise it may not function properly. 34 | 35 | Results Specifications 36 | ================== 37 | The results of execution of a file is sent to the URL `URLToSendResults` specified in the config.h file. The results are sent in the form of POST variables. 38 | The variables are: 39 | fileid, status, detailstatus, timeused, memoryused, numberofwrongtestcases 40 | * The `fileid` variable will contain the File Id of the source code. 41 | * The `status` variable will contain one of these codes: AC, CE, TLE, MLE, RE. 42 | * For few of these codes, `detailstatus` variable will further contain certain info as explained below: 43 | * The `timeused` variable will contain the sum of execution time of the source file on all test cases of the problem. 44 | * The `memoryused` variable contains the memory used by source file during execution. 45 | * The `numberofwrongtestcases` variable returns how many lines of output file were mismatched with respect to the input file. In case of multiple input/output files, numberofwrongtestcases returns the number of mismatches in the first input file where input does not match with output. This option is added on trial basis. If the test cases are such that every line in output file corresponds to one test case then numberofwrongtestcases returns the number of testcases which failed in a given input file. 46 | 47 | Status code and their meaning 48 | ==== 49 | AC ==> Accepted 50 | The `detailstatus` variable will not contain anything in this case. 51 | CE ==> Compilation Error 52 | The `detailstatus` variable will contain the compilation error string returned by compiler. 53 | RE ==> Runtime Error. 54 | The `detailstatus` variable will contain type of runtime error code. It will be one of following: 55 | SISSEGV, SIGFXZ, SIGNZEC, OTHER 56 | TLE ==> Time Limit Exceeded 57 | The `detailstatus` variable will not contain anything in this case. 58 | The `timeused` variable will simply be storing `0`. 59 | MLE ==> Memory Limit Exceeded 60 | If make did not give any compilation errors and you have set the options in config.h file correctly then, you are ready to run CodeRunner for the first time. 61 | 62 | Commandline options 63 | === 64 | -a ==> Fetch all file-ids irrespective of evaluation status. 65 | -b ==> For sending results and forcing insertion of those results. 66 | -c ==> Clear files directory after execution of source code. 67 | -d ==> Does not download source code. The source codes should already be present in the Files directory. 68 | -f ==> For pre-defining FileId. It is used when we are evaluating a particular file only. It has to be followed by additional(required) 69 | parameter (ie the file id) 70 | -i ==> Excectute only one file 71 | -h ==> Print all command line options with their description 72 | -l ==> For pre-defining Language. It is used when we are evaluating a particular file only. It has to be followed by additional(required) 73 | parameter (ie the language of the source program) 74 | -m ==> For specifying pre-defined memory limit. It is used when we are evaluating a particular file only. It has to be followed by 75 | additional(required) parameter (ie the max memory consumption (in MB) the program is allowed) 76 | -n ==> For not sending results after evaluation. 77 | -p ==> For pre-defining ProblemId. It is used when we are evaluating a particular file only. It has to be followed by additional(required) 78 | parameter (ie the problem id) 79 | -q ==> quiet mode ie do not print output on screen 80 | -r ==> Run CodeRunner for just one epoch. 81 | -s ==> Specifying Sleep Interval after each epoch. It has to be followed by additional(required) parameter (ie sleep-interval in seconds) 82 | -t ==> Specifying pre-defined time-limit. It is used when we are evaluating a particular file only. It has to be followed by additional (required) parameter (ie the time limit in seconds) 83 | -v ==> For printing version related information. -------------------------------------------------------------------------------- /docs/SETUP.md: -------------------------------------------------------------------------------- 1 | This guide will take you through the process of installing and running CodeRunner on your computer. 2 | 3 | 4 | Dependencies 5 | ============== 6 | CodeRunner uses Curl library for sending and receiving data over the network. The libcurl3, libcurl3-dev libraries should be installed before making build. On Ubuntu it can be installed by typing the command in the terminal- `sudo apt-get install libcurl3 libcurl3-dev` 7 | Or otherwise, the packages can be downloaded from [here](http://curl.haxx.se/) and installed on any linux flavour. 8 | Dependencies for different languages need to be installed as listed here. 9 | 10 | C : `sudo apt-get install gcc` 11 | C++ : `sudo apt-get install g++` 12 | Java : `sudo apt-get install javac` 13 | Python : `sudo apt-get install python` 14 | PHP : `sudo apt-get install php5` 15 | Pascal : `sudo apt-get install fp-compiler-2.4.4` 16 | 17 | Note that python 2.7 comes pre-installed in ubuntu 18 | 19 | Installation Steps 20 | ============== 21 | 1. Copy source code to the desired directory where you intend to run the CodeRunner. 22 | 2. Run the `./Install.sh` command on terminal. It should rhttp://curl.haxx.se/ any errors. 23 | *This script will add the required directories ans scripts to the CodeRunner with appropriate permissions. 24 | *This will also add config.h in `Config` directory 25 | 3. In the config.h file these options as required. 26 | * USERNAME and PASSWORD are the two fields which are sent to the website for authentication. Set them accordingly. 27 | * In case you want the CodeRunner to download source code files from website through FTP, then set FTPON option as `true` otherwise `false`. If you want the source code files to be downloaded through http request, then set HTTPON option to be `true` otherwise `false`. In case both options are true, then http option becomes the default choice. 28 | * FTPADDRESS is the ftp address from where CodeRunner will download the source files if FTPON option is true. 29 | * HTTPADDRESS is the http address from where CodeRunner will download the source files if HTTPON option is true. 30 | * FILEPATH is the address where the downloaded source files will be stored. 31 | * TESTCASESPATH is the address where test case input/output files of different problems are stored. By default it is set to `TestCases` folder in the PATH address by relative address mode. 32 | * URLToSendResults is the web address where CodeRunner will send the results of executed files. 33 | * LOGFILEPATH is the log file location where CodeRunner will log the results of files execution. 34 | * SLEEPINTERVAL is the time interval for which CodeRunner goes to sleep after one epoch. 35 | 36 | -------------------------------------------------------------------------------- /policy.txt: -------------------------------------------------------------------------------- 1 | grant { 2 | 3 | }; -------------------------------------------------------------------------------- /src/CROptions.cpp: -------------------------------------------------------------------------------- 1 | #include "CROptions.h" 2 | 3 | 4 | bool CROptions::RunOnce = false; 5 | unsigned int CROptions::SleepInterval = SLEEPINTERVAL; 6 | const char* CROptions::PATH = ABSOLUTE_PATH; 7 | const char* CROptions::TestCasesPath = TESTCASESPATH; 8 | const char* CROptions::URLToGetFileIds = URL_TO_GET_FILE_IDS; 9 | const char* CROptions::FilesPath = FILEPATH; 10 | const char* CROptions::URLToSendResults = URL_TO_SEND_RESULTS; 11 | const char* CROptions::LogFilePath = LOGFILEPATH; 12 | const char* CROptions::LogFileName = LOGFILENAME; 13 | const char* CROptions::LogStatusFileName = LOGSTATUSFILENAME; 14 | const char* CROptions::URLToGetSourceCode = URL_TO_GET_SOURCE_CODE; 15 | const char* CROptions::username = USERNAME; 16 | const char* CROptions::password = PASSWORD; 17 | bool CROptions::lang_c = LANG_C; 18 | bool CROptions::lang_cpp = LANG_CPP; 19 | bool CROptions::lang_java = LANG_JAVA; 20 | bool CROptions::lang_php = LANG_PHP; 21 | bool CROptions::lang_python = LANG_PYTHON; 22 | bool CROptions::lang_perl = LANG_PERL; 23 | bool CROptions::ForcePushResult = FORCE_PUSH_RESULT; 24 | bool CROptions::GetAllFileIds = GET_ALL_FILEIDS; 25 | bool CROptions::Clean = CLEAN; 26 | bool CROptions::SendResults = SEND_RESULTS; 27 | bool CROptions::DownloadSourceFile = DOWNLOAD_SOURCE_FILE; 28 | bool CROptions::OneFileExecution = ONE_FILE_EXECUTION; 29 | bool CROptions::PrintOnScreen = PRINT_ON_SCREEN; 30 | bool CROptions::Verbose = VERBOSE; 31 | CROptions::FileInfoFetchOptionsStruct *CROptions::FileInfoFetchOptions = new CROptions::FileInfoFetchOptionsStruct(); 32 | -------------------------------------------------------------------------------- /src/CROptions.h: -------------------------------------------------------------------------------- 1 | #ifndef CROPTIONS_H 2 | #define CROPTIONS_H 3 | #include "../Config/config.h" 4 | #include "headers.h" 5 | 6 | 7 | /*---------------------------------------------Struct Defination Starts-----------------------------------------------------------------*/ 8 | 9 | 10 | 11 | struct FileInfoStruct 12 | { 13 | int FileId; 14 | char ProblemId[50]; 15 | //Unique Id by which website and CodeRunner identifies a problem. For eg. PALIN, TEST etc. 16 | int TimeLimit; 17 | int MemoryLimit; 18 | char lang[11]; //acceptable values `cpp, c, java` 19 | }; 20 | 21 | 22 | 23 | /*---------------------------------------------Struct Defination Ends----------------------------------------------------------------------*/ 24 | 25 | 26 | 27 | class CROptions 28 | { 29 | public: 30 | 31 | 32 | /*---------------------Struct Defination Starts-------------------------*/ 33 | 34 | 35 | struct FileInfoFetchOptionsStruct 36 | { 37 | bool FileId_Predefined, ProblemId_Predefined, Lang_Predefined,TimeLimit_Predefined, MemoryLimit_Predefined; 38 | FileInfoStruct FileInfo; 39 | FileInfoFetchOptionsStruct() 40 | { 41 | FileId_Predefined = ProblemId_Predefined = Lang_Predefined = TimeLimit_Predefined = MemoryLimit_Predefined = false; 42 | FileInfo.FileId = 0; 43 | }; 44 | }; 45 | 46 | 47 | /*------------------Struct Defination Ends------------------------------*/ 48 | 49 | 50 | 51 | static CROptions::FileInfoFetchOptionsStruct* FileInfoFetchOptions; 52 | static bool RunOnce; 53 | static unsigned int SleepInterval; 54 | static const char* PATH; 55 | static const char* TestCasesPath; 56 | static const char* URLToGetFileIds; 57 | static const char* URLToSendResults; 58 | static const char* FilesPath; 59 | static const char* URLToGetSourceCode; 60 | static const char* LogFilePath; 61 | static const char* LogFileName; 62 | static const char* LogStatusFileName; 63 | static const char* httpAddress; 64 | static const char* username; 65 | static const char* password; 66 | static bool lang_c; 67 | static bool lang_cpp; 68 | static bool lang_java; 69 | static bool lang_php; 70 | static bool lang_python; 71 | static bool lang_perl; 72 | static bool ForcePushResult; 73 | static bool GetAllFileIds; 74 | static bool SendResults; 75 | static bool Clean; 76 | static bool SendOptions; 77 | static bool DownloadSourceFile; 78 | static bool OneFileExecution; 79 | static bool PrintOnScreen; 80 | static bool Verbose; 81 | }; 82 | 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/CodeRunner.cpp: -------------------------------------------------------------------------------- 1 | #include "CodeRunner.h" 2 | 3 | 4 | void CodeRunner::CheckPrerequisites() 5 | { 6 | ChDir(CROptions::PATH); 7 | ChDir(CROptions::TestCasesPath); 8 | ChDir(CROptions::PATH); 9 | ChDir(CROptions::FilesPath); 10 | ChDir(CROptions::PATH); 11 | ChDir(CROptions::LogFilePath); 12 | ChDir(CROptions::PATH); 13 | CodeRunner::UpdateStatus(); 14 | Logs::SetLogFileName(CROptions::LogFilePath, CROptions::LogFileName); 15 | Logs::OpenLogFile(); 16 | Logs::CodeRunnerStarted(); 17 | Logs::CloseLogFile(); 18 | } 19 | 20 | void CodeRunner::ChDir(const char* dir) 21 | { 22 | /*If successful, chdir() changes the working directory and returns 0. 23 | *If unsuccessful, chdir() does not change the working directory, returns -1, and sets errno 24 | */ 25 | 26 | if(chdir(dir)==-1) 27 | { 28 | printf("ERROR Cannot change directory to %s. %s (Errno : %d) \n ", dir,strerror(errno),errno); 29 | exit(EXIT_FAILURE); 30 | } 31 | } 32 | 33 | void CodeRunner::Run() 34 | { 35 | //CheckPrerequisites(); 36 | 37 | if(CROptions::OneFileExecution) 38 | { 39 | FileInfoStruct* FileInfo = &(CROptions::FileInfoFetchOptions->FileInfo); 40 | FileHandle F(FileInfo); 41 | F.Action(); 42 | return; 43 | } 44 | 45 | do{ 46 | Logs::OpenLogFile(); 47 | bool CurrentIteration = true; 48 | ContentParser *ContentVar = new ContentParser(); 49 | //if(ContentParser->OneFileExecution) OneFileInfoPrepare(); 50 | if(ContentVar->FetchFileInfoList()==-1){ 51 | CurrentIteration = false; 52 | } 53 | 54 | if(CurrentIteration && ContentVar->EndOfContent()){ 55 | //Logs::WriteLine("File Queue Empty. Nothing to evaluate."); 56 | CurrentIteration = false; 57 | } 58 | 59 | while(CurrentIteration && !ContentVar->EndOfContent()){ 60 | FileInfoStruct* FileInfo = ContentVar->GetNextFileInfo(); 61 | FileHandle F(FileInfo); 62 | F.Action(); 63 | //delete FileInfo; 64 | } 65 | 66 | if(CurrentIteration) ;//Logs::WriteLine("Current batch of files evaluated."); 67 | 68 | delete ContentVar; 69 | CodeRunner::GoToSleep(); 70 | Logs::CloseLogFile(); 71 | CodeRunner::UpdateStatus(); 72 | 73 | }while(!CROptions::RunOnce); 74 | } 75 | 76 | void CodeRunner::GoToSleep(){ 77 | char SleepText[50]; 78 | sprintf(SleepText, "Going to sleep for %d seconds.\n", CROptions::SleepInterval); 79 | //Logs::WriteLine(SleepText); 80 | //Logs::WriteLine("============================================================================\n"); 81 | sleep(CROptions::SleepInterval); 82 | //printf("%s\n",SleepText); 83 | } 84 | 85 | void CodeRunner::ErrorMessage(const char* msg){ 86 | Logs::WriteLine(msg); 87 | exit(EXIT_FAILURE); 88 | } 89 | 90 | void CodeRunner::UpdateStatus(){ 91 | Logs::SetLogFileName(CROptions::LogFilePath, CROptions::LogStatusFileName); 92 | Logs::OpenLogFile(); 93 | Logs::CodeRunnerStarted(); 94 | Logs::CloseLogFile(); 95 | Logs::SetLogFileName(CROptions::LogFilePath, CROptions::LogFileName); 96 | 97 | } -------------------------------------------------------------------------------- /src/CodeRunner.h: -------------------------------------------------------------------------------- 1 | #ifndef CODERUNNER_H 2 | #define CODERUNNER_H 3 | #include "CROptions.h" 4 | #include "ContentParser.h" 5 | #include "FileHandle.h" 6 | 7 | 8 | class CodeRunner 9 | { 10 | private: 11 | public: 12 | static void CheckPrerequisites(); 13 | static void ChDir(const char* dir); 14 | static void Run(); 15 | static void GoToSleep(); 16 | static void ErrorMessage(const char* msg); 17 | static void UpdateStatus(); 18 | 19 | }; 20 | 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/ContentParser.cpp: -------------------------------------------------------------------------------- 1 | #include "ContentParser.h" 2 | 3 | int ContentParser::FetchFileInfoList(){ 4 | CurlWrapper *CurlVar = new CurlWrapper(); 5 | string strContent; 6 | 7 | if(CurlVar->FetchContentFromWebPage(&strContent) == -1) { 8 | delete CurlVar; //Clean up 9 | return -1; 10 | } 11 | delete CurlVar; 12 | 13 | FileInfoListStr = new char[strContent.size() + 1]; 14 | FileInfo = new FileInfoStruct(); 15 | strcpy(FileInfoListStr, strContent.c_str()); 16 | Ix = 0; 17 | return 0; 18 | } 19 | 20 | char ContentParser::read_char() { 21 | return FileInfoListStr[ Ix++ ]; 22 | } 23 | 24 | int ContentParser::read_int(){ 25 | char c; int ret; 26 | 27 | while( !isdigit( c = read_char() ) ); 28 | ret = c - '0'; 29 | 30 | while( isdigit( c = read_char() ) ) 31 | ret = ( ret * 10 + c - '0' ); 32 | 33 | return ret; 34 | } 35 | 36 | void ContentParser::read_char_str(char * ret){ 37 | int i; 38 | for(i=0;i<10 && isalnum(FileInfoListStr[Ix]) ;Ix++, i++){ 39 | ret[i] = FileInfoListStr[Ix]; 40 | } 41 | ret[i]='\0'; 42 | } 43 | 44 | bool ContentParser::EndOfContent(){ 45 | while(true){ 46 | if(isdigit(FileInfoListStr[Ix])) return false; 47 | else if(FileInfoListStr[Ix] == '\0') return true; 48 | Ix++; 49 | } 50 | } 51 | 52 | FileInfoStruct* ContentParser::GetNextFileInfo(){ 53 | FileInfo->FileId = read_int(); 54 | read_char_str(FileInfo->ProblemId); 55 | FileInfo->TimeLimit = read_int(); 56 | FileInfo->MemoryLimit = read_int(); 57 | read_char_str(FileInfo->lang); 58 | if(strcmp(FileInfo->lang,"java")==0){ 59 | FileInfo->TimeLimit=2*FileInfo->TimeLimit; 60 | } 61 | if(strcmp(FileInfo->lang,"python")==0){ 62 | FileInfo->TimeLimit=5*FileInfo->TimeLimit; 63 | } 64 | //printf("%d %s %d %d %s\n", FileInfo.FileId, FileInfo.ProblemId, FileInfo.TimeLimit, FileInfo.MemoryLimit, FileInfo.lang); 65 | return FileInfo; 66 | } 67 | -------------------------------------------------------------------------------- /src/ContentParser.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTENTPARSER_H 2 | #define CONTENTPARSER_H 3 | #include "headers.h" 4 | #include "CurlWrapper.h" 5 | 6 | class ContentParser{ 7 | private: 8 | char* FileInfoListStr; 9 | int Ix; 10 | FileInfoStruct* FileInfo; 11 | public: 12 | 13 | int FetchFileInfoList(); 14 | char read_char(); 15 | int read_int(); 16 | void read_char_str(char *); 17 | bool EndOfContent(); 18 | FileInfoStruct* GetNextFileInfo(); 19 | }; 20 | #endif 21 | -------------------------------------------------------------------------------- /src/CurlWrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "CurlWrapper.h" 2 | 3 | 4 | 5 | size_t CurlWrapper::ContentInVar(void* ptr, size_t size, size_t nmemb, string *stream) 6 | { 7 | stream -> append((char *)ptr, size * nmemb); 8 | //Appends a copy of the first size*nmemb characters in the array of characters pointed by ptr. 9 | return size*nmemb; 10 | } 11 | 12 | 13 | 14 | size_t CurlWrapper::ContentInFileHTTP(void *ptr, size_t size, size_t nmemb, FILE *stream) 15 | { 16 | size_t written; 17 | written = fwrite(ptr, size, nmemb, stream); 18 | return written; 19 | } 20 | 21 | 22 | size_t CurlWrapper::ContentInFileFTP(void *buffer, size_t size, size_t nmemb, void *stream) 23 | { 24 | struct FtpFile *out=(struct FtpFile *)stream; 25 | if(out && !out->stream) 26 | { 27 | /* open file for writing */ 28 | out->stream=fopen(out->filename, "wb"); 29 | if(!out->stream) 30 | return -1; /* failure, can't open file to write */ 31 | } 32 | return fwrite(buffer, size, nmemb, out->stream); 33 | } 34 | 35 | int CurlWrapper::GetFileFromFTP(int FileId) 36 | { 37 | curl = curl_easy_init(); 38 | /*This function returns a CURL easy handle that is used as input to other easy-functions and initializes curl 39 | *It must have a corresponding call to curl_easy_cleanup() when the operation is complete. 40 | *If this function returns NULL, something went wrong and you cannot use the other curl functions. 41 | //string URL, FileName, SavedFileName; 42 | //URL = strcpy( URL_c ); 43 | //FileName = strcpy (*/ 44 | char FTPFileURL[100], SavedFileName[100]; 45 | sprintf(FTPFileURL, "%s%d.txt", FTPADDRESS, FileId); 46 | sprintf(SavedFileName, "%s%d.txt", FILEPATH, FileId); 47 | struct FtpFile ftpfile = 48 | { 49 | SavedFileName, /* name to store the file as if succesful */ 50 | NULL 51 | }; 52 | 53 | if(curl) 54 | { 55 | 56 | curl_easy_setopt(curl, CURLOPT_URL, FTPFileURL); 57 | /* Define our callback to get called when there's data to be written */ 58 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ContentInFileFTP); 59 | /* Set a pointer to our struct to pass to the callback */ 60 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); 61 | #ifdef FTPUSERNAME 62 | curl_easy_setopt(curl, CURLOPT_USERNAME, FTPUSERNAME); 63 | #endif 64 | #ifdef FTPPASSWORD 65 | curl_easy_setopt(curl, CURLOPT_PASSWORD, FTPPASSWORD); 66 | #endif 67 | 68 | /* Switch on full protocol/debug output */ 69 | curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 70 | 71 | res = curl_easy_perform(curl); 72 | curl_easy_cleanup(curl); 73 | if(CURLE_OK != res) 74 | { 75 | sprintf(logs, "Failure to fetch file using FTP request. Curl Error code: %d\n", res); 76 | Logs::WriteLine(logs); 77 | return -1; 78 | } 79 | } 80 | sprintf(logs, "File fetched successfully through FTP request."); 81 | Logs::WriteLine(logs); 82 | return 0; 83 | } 84 | 85 | int CurlWrapper::GetFileFromHTTP(int FileId) 86 | { 87 | 88 | struct curl_httppost *formpost = NULL; 89 | struct curl_httppost *lastptr = NULL; 90 | struct curl_slist *headerlist = NULL; 91 | static const char buf[] = "Expect: "; 92 | 93 | char FILEID[10]; 94 | sprintf(FILEID,"%d", FileId); 95 | 96 | /* Fill in the POST fields */ 97 | curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "username", CURLFORM_COPYCONTENTS, USERNAME, CURLFORM_END); 98 | curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "password", CURLFORM_COPYCONTENTS, PASSWORD, CURLFORM_END); 99 | curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "fileid", CURLFORM_COPYCONTENTS, FILEID, CURLFORM_END); 100 | 101 | FILE *fp; 102 | char SavedFileName[FILENAME_MAX]; 103 | sprintf(SavedFileName, "%s%d.txt", FILEPATH, FileId); 104 | curl = curl_easy_init(); 105 | headerlist = curl_slist_append(headerlist, buf); 106 | if (curl) 107 | { 108 | fp = fopen(SavedFileName,"wb"); 109 | if(fp==NULL) 110 | { 111 | Logs::WriteLine("IE ERROR Unable to open file for saving downloaded source code. Please check that CodeRunner has the requisite permissions and restart the program."); 112 | return -1; 113 | } 114 | curl_easy_setopt(curl, CURLOPT_URL, CROptions::URLToGetSourceCode); 115 | curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); 116 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ContentInFileHTTP); 117 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); 118 | res = curl_easy_perform(curl); 119 | curl_easy_cleanup(curl); 120 | curl_formfree(formpost); 121 | /* free slist */ 122 | curl_slist_free_all (headerlist); 123 | fclose(fp); 124 | 125 | if(CURLE_OK!=res) 126 | { 127 | Logs::WriteLine("Failure to fetch file through HTTP request..."); 128 | return -1; 129 | } 130 | else 131 | { 132 | Logs::WriteLine("File fetched successfully through HTTP request..."); 133 | return 0; 134 | } 135 | } 136 | return -1; 137 | } 138 | 139 | int CurlWrapper::FetchContentFromWebPage(string *content) 140 | { 141 | 142 | struct curl_httppost *formpost = NULL; 143 | struct curl_httppost *lastptr = NULL; 144 | struct curl_slist *headerlist = NULL; 145 | static const char buf[] = "Expect: "; 146 | 147 | /* Fill in the POST fields */ 148 | curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "username", CURLFORM_COPYCONTENTS, USERNAME, CURLFORM_END); 149 | curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "password", CURLFORM_COPYCONTENTS, PASSWORD, CURLFORM_END); 150 | 151 | char optstr[11]; 152 | if(CROptions::FileInfoFetchOptions->FileId_Predefined){ 153 | sprintf(optstr, "%d", CROptions::FileInfoFetchOptions->FileInfo.FileId); 154 | curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "fileid", CURLFORM_COPYCONTENTS, optstr, CURLFORM_END); 155 | } 156 | 157 | if(CROptions::FileInfoFetchOptions->ProblemId_Predefined){ 158 | sprintf(optstr, "%s", CROptions::FileInfoFetchOptions->FileInfo.ProblemId); 159 | curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "problemid", CURLFORM_COPYCONTENTS, optstr, CURLFORM_END); 160 | } 161 | 162 | if(CROptions::FileInfoFetchOptions->Lang_Predefined){ 163 | sprintf(optstr, "%s", CROptions::FileInfoFetchOptions->FileInfo.lang); 164 | curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "lang", CURLFORM_COPYCONTENTS, optstr, CURLFORM_END); 165 | } 166 | 167 | if(CROptions::GetAllFileIds){ 168 | curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "all", CURLFORM_COPYCONTENTS, "true", CURLFORM_END); 169 | CROptions::GetAllFileIds = false; 170 | } 171 | 172 | curl = curl_easy_init(); 173 | /* initalize custom header list (stating that Expect: 100-continue is not wanted */ 174 | headerlist = curl_slist_append(headerlist, buf); 175 | if(curl) { 176 | /* what URL that receives this POST */ 177 | curl_easy_setopt(curl, CURLOPT_URL, CROptions::URLToGetFileIds); 178 | 179 | curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); 180 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ContentInVar); 181 | string buffer; 182 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); 183 | res = curl_easy_perform(curl); 184 | 185 | (*content) = buffer; 186 | 187 | /* always cleanup */ 188 | curl_easy_cleanup(curl); 189 | /* then cleanup the formpost chain */ 190 | curl_formfree(formpost); 191 | /* free slist */ 192 | curl_slist_free_all (headerlist); 193 | if(CURLE_OK!=res){ 194 | //cout<<"Url to fetch ids is "< 7 | #include 8 | 9 | class CurlWrapper 10 | { 11 | 12 | CURL *curl; 13 | CURLcode res; 14 | char logs[1000]; 15 | 16 | 17 | /*-------------------------------------Struct Defination Starts--------------------------------*/ 18 | 19 | 20 | struct FtpFile 21 | { 22 | const char *filename; 23 | FILE *stream; 24 | }; 25 | 26 | 27 | /*-----------------------------------------Struct Defination Ends-----------------------------------*/ 28 | 29 | 30 | 31 | public: 32 | CurlWrapper() 33 | { 34 | curl_global_init(CURL_GLOBAL_DEFAULT); 35 | /*This function sets up the program environment that libcurl needs. 36 | *This function must be called at least once within a program before the program calls any other function in libcurl. 37 | *CURL_GLOBAL_DEFAULT : It will init both SSL and Win32 flags 38 | *If this function returns non-zero, something went wrong and you cannot use the other curl functions 39 | */ 40 | Logs::OpenLogFile(); 41 | } 42 | 43 | ~CurlWrapper() 44 | { 45 | curl_global_cleanup(); 46 | /*This function releases resources acquired by curl_global_init(). 47 | *Call curl_global_cleanup() once for each call made to curl_global_init() 48 | */ 49 | } 50 | 51 | static size_t ContentInFileFTP(void *buffer, size_t size, size_t nmemb, void *stream); 52 | static size_t ContentInVar(void* ptr, size_t size, size_t nmemb, string *stream); 53 | static size_t ContentInFileHTTP(void *ptr, size_t size, size_t nmemb, FILE *stream); 54 | int GetFileFromFTP(int FileId); 55 | int GetFileFromHTTP(int FileId); 56 | int FetchContentFromWebPage(string *content); 57 | void SendResultsToWebpage(const char* fileid, const char* status, const char* detailstatus, const char* time, const char* memory, const char* numberofwrongtestcases); 58 | 59 | 60 | }; 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/Execution.cpp: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | #include "resources.h" 3 | 4 | pid_t cpid; 5 | const int MicroSecSleepInterval = 71; 6 | void ToPipe(const char* str){ 7 | printf("%s\n", str); 8 | return; 9 | } 10 | 11 | void SignalHandler(int signum){ 12 | if(cpid!=0){ 13 | killpg(cpid,SIGKILL); 14 | } 15 | } 16 | 17 | /* high resolution (microsecond) sleep */ 18 | void MicroSecSleep (int ms){ 19 | struct timeval tv; 20 | int w; 21 | do{ 22 | tv.tv_sec = ms / 1000; 23 | tv.tv_usec = (ms % 1000) * 1000; 24 | w = select (0, NULL, NULL, NULL, &tv); 25 | /* The value of the timeout is undefined after the select returns */ 26 | } while ((w < 0) && (errno == EINTR)); 27 | if (w < 0) 28 | ToPipe("IE ERROR Failed while calling select in microsleep"); 29 | } 30 | 31 | int MemoryUsage(pid_t cpid){ 32 | char a[10000], *p, *q; 33 | int data, stack; 34 | int rss; /* ZP */ 35 | int n, v, fd; 36 | 37 | p = a; 38 | sprintf (p, "/proc/%d/status", cpid); 39 | fd = open (p, O_RDONLY); 40 | if (fd < 0) 41 | ToPipe("IE ERROR Failed to open /proc/pid/status") ; 42 | do{ 43 | n = read (fd, p, 10000); 44 | } while ((n < 0) && (errno == EINTR)); 45 | if (n < 0) 46 | ToPipe("IE ERROR Failed to read /proc/pid/status") ; 47 | do{ 48 | v = close (fd); 49 | } while ((v < 0) && (errno == EINTR)); 50 | if (v < 0) 51 | ToPipe("IE ERROR Failed to close file descriptor for /proc/pid/status") ; 52 | 53 | rss = data = stack = 0; 54 | q = strstr (p, "VmData:"); 55 | char tmp[10000]; 56 | sprintf(tmp, "%s\n", p); 57 | //ToPipe(tmp); 58 | if (q != NULL) 59 | { 60 | sscanf (q, "%*s %d", &data); 61 | q = strstr (q, "VmStk:"); 62 | if (q != NULL) 63 | sscanf (q, "%*s %d\n", &stack); 64 | 65 | q = strstr (q, "VmRSS:"); 66 | if (q != NULL) 67 | sscanf (q, "%*s %d\n", &rss); 68 | else 69 | rss = data + stack; 70 | } 71 | printf("The memory usage is about to be printed \n"); 72 | printf("Memory Usage: data - %d, stack - %d, rss - %d\n", data, stack, rss); 73 | return data + stack; 74 | /* return (data + stack); */ 75 | } 76 | 77 | int main(int args, char *argv[]){ 78 | 79 | if(args<4){ 80 | ToPipe("IE ERROR Not enough arguments."); 81 | return 1; 82 | } 83 | 84 | int TimeLimit, MemoryLimit, TestCaseFileId, FileId; 85 | char InputFile[25], lang[10]; 86 | struct timeval start,finish; 87 | struct sigaction SignalAction; 88 | pid_t w; 89 | int status; 90 | long long t_sec, t_usec; 91 | 92 | FileId = atoi(argv[1]), strcpy(InputFile, argv[2]); 93 | TestCaseFileId = atoi(argv[3]), TimeLimit = atoi(argv[4]), MemoryLimit = atoi(argv[5]); 94 | strcpy(lang, argv[6]); 95 | SignalAction.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT; 96 | SignalAction.sa_handler = SignalHandler; 97 | if(sigaction(SIGALRM, &SignalAction, NULL)==-1){ 98 | ToPipe("IE ERROR Could not register handler for SIGALRM"); 99 | return 1; 100 | } 101 | if(sigaction(SIGXCPU, &SignalAction, NULL)==-1){ 102 | ToPipe("IE ERROR Could not register handler fo SIGXCPU"); 103 | return 1; 104 | } 105 | 106 | gettimeofday(&start,NULL); 107 | cpid = fork(); 108 | if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); } 109 | 110 | if (cpid == 0) { /* Code executed by child */ 111 | 112 | pid_t ChildProcessId = getpid(); 113 | passwd* UserDetails = getpwnam("nobody"); 114 | char dir[25]; 115 | sprintf(dir, "%s%d/", FILEPATH, FileId); 116 | //ToPipe(dir); 117 | if( chdir(dir) == -1){ 118 | printf("%d", errno); 119 | ToPipe("IE ERROR Cannot change directory to that of file"); 120 | return 1; 121 | } 122 | 123 | //ToPipe(get_current_dir_name()); 124 | /*if(chroot(get_current_dir_name())!=0){ 125 | ToPipe("IE ERROR Cannot jail the program"); 126 | return 1; 127 | }*/ 128 | 129 | if(( setpgid( ChildProcessId, ChildProcessId) ) == -1 ){ 130 | ToPipe("IE ERROR process group could not be created\n"); 131 | return 1; 132 | } 133 | 134 | if(UserDetails!=NULL){ 135 | gid_t GroupId = UserDetails->pw_gid; 136 | if( GroupId > 0 ){ 137 | setgid( GroupId ); 138 | } 139 | else{ 140 | ToPipe("IE ERROR Could not set groupid as groupid is invalid\n"); 141 | return 1; 142 | } 143 | uid_t UserId = UserDetails->pw_uid; 144 | if( UserId > 0 ){ 145 | setuid(UserId); 146 | } 147 | else{ 148 | ToPipe("IE ERROR Failed to set userid as it is invalid\n"); 149 | return 1; 150 | } 151 | } 152 | else{ 153 | ToPipe("IE ERROR No user id associated with user nobody\n"); 154 | return 1; 155 | } 156 | 157 | char TestCaseFile[25], OutputFile[25]; 158 | sprintf(TestCaseFile, "%d.txt", TestCaseFileId); 159 | sprintf(OutputFile, "%do.txt", TestCaseFileId); 160 | 161 | if(alarm(TimeLimit)!=0){ 162 | ToPipe("IE ERROR Could not set alarm."); 163 | } 164 | //printf("Execution aginst timelimit: %d", TimeLimit); 165 | if(strcmp(lang,"java")==0){ 166 | SetResourceLimitValuesJava(TimeLimit); 167 | FILE *fpipe; 168 | char command[100]; 169 | sprintf(command, "java -Djava.security.manager -Djava.security.policy==./policy.txt -Xms1024M Main < %s > %s", TestCaseFile, OutputFile); 170 | //printf("%s\n", command); 171 | char line[256]; 172 | 173 | if ( !(fpipe = (FILE*)popen(command,"r")) ){ 174 | perror("Problems with pipe"); 175 | //Logs::WriteLine("Problems with pipe"); 176 | } 177 | else{ 178 | if ( fgets( line, sizeof line, fpipe)){ 179 | printf("%s\n", line); 180 | } 181 | } 182 | pclose(fpipe); 183 | exit(0); 184 | 185 | } 186 | 187 | 188 | if(freopen(TestCaseFile, "r", stdin)==NULL){ 189 | ToPipe("IE ERROR Could not open test case file\n"); 190 | } 191 | 192 | if(freopen(OutputFile, "w", stdout)==NULL){ 193 | ToPipe("IE ERROR Could not open output file\n"); 194 | } 195 | 196 | if(freopen("/dev/null", "w", stderr)==NULL){ 197 | ToPipe("IE ERROR Could not redirect error stream to null\n"); 198 | } 199 | /* 200 | if(strcmp(lang,"java")==0){ 201 | SetResourceLimitValuesJava(TimeLimit); 202 | if(execl("/usr/bin/java", "/usr/bin/java", "-Xms20M -Xmx500M", "-classpath", InputFile, (char *) NULL) == -1){ 203 | fclose(stdout); 204 | ToPipe("IE ERROR File not present or some other error."); 205 | } 206 | } 207 | */ 208 | 209 | //printf("execution about to begin"); 210 | SetResourceLimitValues(TimeLimit); 211 | if(strcmp(lang, "python")==0){ 212 | strcat(InputFile, ".pyc"); 213 | if(execl("/usr/bin/python", "/usr/bin/python", InputFile, (char *) NULL) == -1){ 214 | fclose(stdout); 215 | ToPipe("IE ERROR File not present or some other error."); 216 | } 217 | } 218 | else if(strcmp(lang, "perl")==0){ 219 | strcat(InputFile, ".pl"); 220 | if(execl("/usr/bin/perl", "/usr/bin/perl", InputFile, (char *) NULL) == -1){ 221 | fclose(stdout); 222 | ToPipe("IE ERROR File not present or some other error."); 223 | } 224 | } 225 | else if(strcmp(lang, "php")==0){ 226 | strcat(InputFile, ".php"); 227 | printf("%s", InputFile); 228 | if(execl("/usr/bin/php", "/usr/bin/php", InputFile, (char *) NULL) == -1){ 229 | fclose(stdout); 230 | ToPipe("IE ERROR File not present or some other error."); 231 | } 232 | } 233 | else if(execl(InputFile, InputFile,(char *) NULL) == -1){ 234 | fclose(stdout); 235 | ToPipe("IE ERROR File not present or some other error."); 236 | } 237 | } 238 | else { /* Code executed by parent */ 239 | struct rusage resourceUsage; 240 | 241 | int MemoryUsed = 64; 242 | 243 | do{ 244 | MicroSecSleep(MicroSecSleepInterval); 245 | MemoryUsed = max(MemoryUsed, MemoryUsage(cpid)); 246 | if(MemoryUsed > MemoryLimit && strcmp(lang, "java")!=0){ 247 | kill(cpid, SIGKILL); 248 | } 249 | w = wait4 (cpid, &status, WUNTRACED | WCONTINUED, &resourceUsage); 250 | //w = wait4 (cpid, &status, NULL, &resourceUsage); 251 | 252 | } while(w==0); 253 | 254 | gettimeofday(&finish,NULL); 255 | t_sec = finish.tv_sec-start.tv_sec; 256 | t_sec=finish.tv_sec-start.tv_sec; 257 | t_usec=finish.tv_usec-start.tv_usec; 258 | if(t_usec<0){ 259 | t_sec--; 260 | t_usec+=1000000; 261 | } 262 | 263 | float TimeUsed = (float)( t_sec * 1000000 + (int) t_usec ) / 1000000 ; 264 | 265 | bool sigkill = false, sigalrm = false; 266 | 267 | char executionstatus[4], detailstatus[100]; 268 | detailstatus[0] = '\0'; 269 | 270 | if(MemoryUsed > MemoryLimit && strcmp(lang, "java")!=0){ 271 | strcpy(executionstatus, "MLE"); 272 | } 273 | else if( WIFEXITED(status) == true ){ 274 | if( WEXITSTATUS(status) !=0 ){ 275 | strcpy(executionstatus, "RE"); 276 | strcpy(detailstatus, "NZEC"); 277 | } 278 | else{ 279 | strcpy(executionstatus, "AC"); 280 | } 281 | } 282 | else if( WIFSIGNALED(status) == true ){ 283 | if (WTERMSIG (status) == SIGKILL ){ 284 | strcpy(executionstatus, "TLE"); 285 | sigkill = true; 286 | } 287 | else if (WTERMSIG(status) == SIGALRM){ 288 | strcpy(executionstatus, "TLE"); 289 | sigalrm = true; 290 | } 291 | else{ 292 | strcpy(executionstatus, "RE"); 293 | if (WTERMSIG (status) == SIGXFSZ) 294 | strcpy(detailstatus, "SIGXFSZ"); 295 | else if (WTERMSIG (status) == SIGSEGV) 296 | strcpy(detailstatus, "SIGSEGV"); 297 | else if (WTERMSIG (status) == SIGFPE) 298 | strcpy(detailstatus, "SIGFPE"); 299 | else if (WTERMSIG (status) == SIGABRT) 300 | strcpy(detailstatus, "SIGABRT"); 301 | else if (WTERMSIG (status) == SIGHUP){ 302 | strcpy(executionstatus, "IE"); 303 | strcpy(detailstatus, "SIGHUP"); 304 | } 305 | else if (WTERMSIG (status) == SIGPIPE){ 306 | strcpy(executionstatus, "IE"); 307 | strcpy(detailstatus, "SIGPIPE"); 308 | } 309 | else{ 310 | strcpy(detailstatus, "OTHER"); 311 | printf("%d\n", WTERMSIG(status)); 312 | } 313 | } 314 | } 315 | 316 | char ExecutionStat[20]; 317 | sprintf(ExecutionStat, "status: %s", executionstatus); 318 | ToPipe(ExecutionStat); 319 | sprintf(ExecutionStat, "detailstatus: %s", detailstatus); 320 | ToPipe(ExecutionStat); 321 | sprintf(ExecutionStat, "timeused: %0.4f", TimeUsed); 322 | ToPipe(ExecutionStat); 323 | sprintf(ExecutionStat, "memoryused: %d", MemoryUsed); 324 | ToPipe(ExecutionStat); 325 | //printf("%d %d\n", (int)tv.tv_sec, (int)tv.tv_usec); 326 | if(sigkill) printf("SIGKILL"); 327 | else if(sigalrm) printf("SIGALRM"); 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /src/FileHandle.cpp: -------------------------------------------------------------------------------- 1 | #include "FileHandle.h" 2 | 3 | FileHandle::FileHandle(FileInfoStruct* FileInfo){ 4 | this->FileInfo = FileInfo; 5 | TimeUsed=0.0; 6 | MemoryUsed=0; 7 | NumberOfWrongCases = 0; 8 | result=true; 9 | detailstatus[0] = '\0'; 10 | 11 | sprintf(FileAddr, "%s%d", FILEPATH, FileInfo->FileId); 12 | sprintf(FileDirAddr, "%s%d/", FILEPATH, FileInfo->FileId); 13 | if(strcmp(FileInfo->lang, "java")==0){ 14 | strcpy(FileName, "Main"); 15 | } 16 | else strcpy(FileName, "test"); 17 | sprintf(FullFileAddr, "%s%s", FileDirAddr, FileName); 18 | Logs::OpenLogFile(); 19 | sprintf(logs, "File Id ==> %d, Problem Id ==> %s, TimeLimit ==> %d, MemoryLimit ==> %d, Lang ==> %s", FileInfo->FileId, FileInfo->ProblemId, FileInfo->TimeLimit, FileInfo->MemoryLimit, FileInfo->lang); 20 | Logs::WriteLine(logs, true); 21 | } 22 | 23 | 24 | int FileHandle::CheckLANG(){ 25 | if(strcmp(FileInfo->lang, "cpp")==0 && !CROptions::lang_cpp) 26 | { 27 | strcpy(status, "CE"); 28 | strcpy(detailstatus, "You are not allowed to make submissions in C++"); 29 | return -1; 30 | } 31 | if(strcmp(FileInfo->lang, "c")==0 && !CROptions::lang_c) 32 | { 33 | strcpy(status, "CE"); 34 | strcpy(detailstatus, "You are not allowed to make submissions in C"); 35 | return -1; 36 | } 37 | if(strcmp(FileInfo->lang, "java")==0 && !CROptions::lang_java) 38 | { 39 | strcpy(status, "CE"); 40 | strcpy(detailstatus, "You are not allowed to make submissions in JAVA"); 41 | return -1; 42 | } 43 | if(strcmp(FileInfo->lang, "php")==0 && !CROptions::lang_php) 44 | { 45 | strcpy(status, "CE"); 46 | strcpy(detailstatus, "You are not allowed to make submissions in PHP"); 47 | return -1; 48 | } 49 | if(strcmp(FileInfo->lang, "python")==0 && !CROptions::lang_python) 50 | { 51 | strcpy(status, "CE"); 52 | strcpy(detailstatus, "You are not allowed to make submissions in PYTHON"); 53 | return -1; 54 | } 55 | if(strcmp(FileInfo->lang, "perl")==0 && !CROptions::lang_perl) 56 | { 57 | strcpy(status, "CE"); 58 | strcpy(detailstatus, "You are not allowed to make submissions in PERL"); 59 | return -1; 60 | } 61 | return 0; 62 | } 63 | 64 | 65 | int FileHandle::FetchFile(){ 66 | if(!CROptions::DownloadSourceFile) { 67 | return 0; 68 | } 69 | if(FTPON) { 70 | int res = FileCurl.GetFileFromFTP(FileInfo->FileId); 71 | if(res==-1) { 72 | strcpy(status, "IE"); 73 | sprintf(detailstatus, "Failure to download source code."); 74 | return -1; 75 | } 76 | } 77 | else if(HTTPON){ 78 | int res = FileCurl.GetFileFromHTTP(FileInfo->FileId); 79 | if(res==-1){ 80 | strcpy(status, "IE"); 81 | sprintf(detailstatus, "Failure to download source code."); 82 | return -1; 83 | } 84 | } 85 | else { 86 | strcpy(status, "IE"); 87 | strcpy(detailstatus, "Cannot download source file. No method specified for downloading!!!"); 88 | return -1; 89 | } 90 | return 0; 91 | } 92 | 93 | int FileHandle::CheckMIME(){ 94 | FILE *fpipe; 95 | char line[256]; 96 | sprintf(command, "file -b --mime-type %s.txt", FileAddr); 97 | //printf("%s\n",command ); 98 | if ( !(fpipe = (FILE*)popen(command,"r")) ){ 99 | // If fpipe is NULL 100 | perror("Problems with pipe"); 101 | Logs::WriteLine("Problems with pipe"); 102 | return -1; 103 | } 104 | else { 105 | if ( fgets( line, sizeof line, fpipe)){ 106 | //printf("mime-type -> %s", line); 107 | 108 | if(strncmp(line+12, "x-empty", 7)==0){ 109 | result = false; 110 | strcpy(status, "CE"); 111 | strcpy(detailstatus, "You have submitted an empty file!"); 112 | } 113 | 114 | else if(strncmp(line, "text", 4) != 0){ 115 | result = false; 116 | strcpy(status, "CE"); 117 | strcpy(detailstatus, "The source file is not a text file. Failed MIME check test."); 118 | } 119 | } 120 | } 121 | pclose(fpipe); 122 | return 0; 123 | } 124 | 125 | int FileHandle::MakeDir(){ 126 | int ErrNo; 127 | 128 | Logs::WriteLine("Creating directory."); 129 | if( mkdir(FileDirAddr, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH | S_IWOTH)==-1){ 130 | ErrNo=errno; 131 | if(ErrNo==17) Logs::WriteLine("Directory already created.. Continuing"); 132 | else { 133 | strcpy(status, "IE"); 134 | sprintf(detailstatus, "Failure to create directory for file operations. Error Number: %d", errno); 135 | return -1; 136 | } 137 | } 138 | if(strcmp(FileInfo->lang, "python")==0) sprintf(systemString, "cp %s.txt %s.py", FileAddr, FullFileAddr); 139 | else if(strcmp(FileInfo->lang, "pascal")==0) sprintf(systemString, "cp %s.txt %s.p", FileAddr, FullFileAddr); 140 | else if(strcmp(FileInfo->lang, "php")==0) sprintf(systemString, "cp %s.txt %s.php", FileAddr, FullFileAddr); 141 | else if(strcmp(FileInfo->lang, "perl")==0) sprintf(systemString, "cp %s.txt %s.pl", FileAddr, FullFileAddr); 142 | else sprintf(systemString, "cp %s.txt %s.%s", FileAddr, FullFileAddr, FileInfo->lang); 143 | if(system(systemString)==-1){ 144 | strcpy(status, "IE"); 145 | strcpy(detailstatus, "Error in copying dowloaded file."); 146 | return -1; 147 | } 148 | return 0; 149 | } 150 | 151 | void FileHandle::Compile(){ 152 | pipeCompile(); 153 | /* 154 | if(CompileOutput.length()!=0){ 155 | Logs::WriteLine("Unsuccessful"); 156 | result = false; 157 | strcpy(status, "CE"); 158 | 159 | if(strlen(CompileOutput.c_str())<=10000) strcpy(detailstatus, CompileOutput.c_str()); 160 | } 161 | else Logs::WriteLine("Successful\n"); 162 | */ 163 | if(result) Logs::WriteLine("Successful\n"); 164 | } 165 | 166 | void FileHandle::pipeCompile(){ 167 | FILE *fpipe; 168 | if(strcmp(FileInfo->lang, "cpp")==0) 169 | sprintf(command, "g++ -w -I ../../gcc -static %s.cpp -o %s 2>&1", FullFileAddr, FullFileAddr); 170 | else if(strcmp(FileInfo->lang, "c") == 0) 171 | sprintf(command, "gcc -w -I ../../gcc -static %s.c -o %s 2>&1", FullFileAddr, FullFileAddr); 172 | else if(strcmp(FileInfo->lang, "java")==0) 173 | sprintf(command, "javac %s.java", FullFileAddr); 174 | else if(strcmp(FileInfo->lang, "python")==0) 175 | sprintf(command, "python -m py_compile %s.py", FullFileAddr); 176 | else if(strcmp(FileInfo->lang, "pascal")==0) 177 | sprintf(command, "fpc %s.p", FullFileAddr); 178 | else if(strcmp(FileInfo->lang, "perl")==0) 179 | sprintf(command, "perl -c %s.pl", FullFileAddr); 180 | else if(strcmp(FileInfo->lang, "php")==0) 181 | sprintf(command, "php -l %s.php", FullFileAddr); 182 | 183 | 184 | Logs::Write("\nCompiling file ==> "); 185 | char line[256]; 186 | 187 | if ( !(fpipe = (FILE*)popen(command,"r")) ){ 188 | perror("Problems with pipe"); 189 | Logs::WriteLine("Problems with pipe"); 190 | } 191 | else{ 192 | while ( fgets( line, sizeof line, fpipe)){ 193 | CompileOutput.append(line, strlen(line)); 194 | } 195 | } 196 | int compilestatus = pclose(fpipe); 197 | if(compilestatus!=0){ 198 | strcpy(status, "CE"); 199 | if(strlen(CompileOutput.c_str())<10000) strcpy(detailstatus, CompileOutput.c_str()); 200 | result = false; 201 | //printf(" Compile length %d \n", (int)strlen(detailstatus)); 202 | } 203 | //printf("compile status - %d\n", compilestatus); 204 | } 205 | 206 | int FileHandle::pipeNoOfTestCases(){ 207 | FILE *fpipe; 208 | char line[256]; 209 | int TestCaseNo; 210 | sprintf(command, "ls %s%s/Input/ -l | egrep -c '^-'", TESTCASESPATH, FileInfo->ProblemId); 211 | 212 | if ( !(fpipe = (FILE*)popen(command,"r")) ){ 213 | // If fpipe is NULL 214 | perror("Problems with pipe"); 215 | Logs::WriteLine("Problems with pipe"); 216 | return -1; 217 | } 218 | else{ 219 | if ( fgets( line, sizeof line, fpipe)){ 220 | TestCaseNo = atoi(line); 221 | } 222 | } 223 | pclose(fpipe); 224 | return TestCaseNo; 225 | } 226 | 227 | int FileHandle::PrepareToExecute(){ 228 | sprintf(systemString, "cp %s%s/Input/* %s", TESTCASESPATH, FileInfo->ProblemId, FileDirAddr); 229 | system(systemString); 230 | 231 | NoOfTestCases = pipeNoOfTestCases(); 232 | if(NoOfTestCases == 0){ 233 | strcpy(status, "IE"); 234 | strcpy(detailstatus, "No Test Case file specified."); 235 | return -1; 236 | } 237 | else if(NoOfTestCases == -1){ 238 | strcpy(status, "IE"); 239 | strcpy(detailstatus, "Problem in determining number of test case files."); 240 | return -1; 241 | } 242 | sprintf(systemString, "Number of Test Cases = %d",NoOfTestCases); 243 | Logs::WriteLine(systemString); 244 | return 0; 245 | } 246 | 247 | void FileHandle::PipeExecute(){ 248 | FILE *fpipe; 249 | int MemoryLimitInKb = FileInfo->MemoryLimit * 1024; 250 | sprintf(command, "./Execution %d %s %d %d %d %s", FileInfo->FileId, FileName, TestCaseId, FileInfo->TimeLimit, MemoryLimitInKb, FileInfo->lang); 251 | 252 | char line[1024]; 253 | 254 | if ( !(fpipe = (FILE*)popen(command,"r")) ){ 255 | // If fpipe is NULL 256 | perror("Problems with pipe"); 257 | Logs::WriteLine("Problems with pipe"); 258 | } 259 | else{ 260 | ExecutionStr.clear(); 261 | while ( fgets( line, sizeof line, fpipe)){ 262 | ExecutionStr.append(line, strlen(line)); 263 | } 264 | } 265 | pclose(fpipe); 266 | } 267 | 268 | void FileHandle::Execute(){ 269 | 270 | Logs::WriteLine("Beginning Execution... "); 271 | 272 | for( TestCaseId = 1; (result==true && TestCaseId<=NoOfTestCases); TestCaseId++ ){ 273 | 274 | PipeExecute(); 275 | sprintf(str, "\nTest Case %d\n%s", TestCaseId, ExecutionStr.c_str()); 276 | Logs::Write(str); 277 | 278 | char* ptr = strstr(str, "status"); 279 | if(ptr!=NULL){ 280 | sscanf(ptr, "%*s %s", status); 281 | if(strcmp(status, "AC")!=0) result=false; 282 | if(strcmp(status, "RE")==0){ 283 | ptr = strstr(ptr, "detailstatus"); 284 | if(ptr!=NULL) sscanf(ptr, "%*s %s", detailstatus); 285 | } 286 | else if(strcmp(status, "IE")==0){ 287 | ptr = strstr(ptr, "detailstatus"); 288 | if(ptr!=NULL){ 289 | char* ixspace = strchr(ptr, ' '); 290 | char* ixnewline = strchr(ptr, '\n'); 291 | memcpy(detailstatus, ixspace, ixnewline-ixspace); 292 | detailstatus[ixnewline-ixspace+1]='\0'; 293 | } 294 | } 295 | ptr = strstr(str, "timeused"); 296 | if(ptr!=NULL) sscanf(ptr, "%*s %f", &TestCaseExecutionTime); 297 | ptr = strstr(str, "memoryused"); 298 | if(ptr!=NULL) sscanf(ptr, "%*s %d", &TestCaseExecutionMemory); 299 | } 300 | 301 | //TimeUsed += TestCaseExecutionTime; 302 | if(TestCaseExecutionTime>TimeUsed){ 303 | TimeUsed=TestCaseExecutionTime; 304 | } 305 | MemoryUsed = max(MemoryUsed, TestCaseExecutionMemory); 306 | if( TimeUsed > (float) FileInfo->TimeLimit){ 307 | result = false; sprintf(status, "TLE"); 308 | } 309 | 310 | if(result==false) break; 311 | 312 | MatchOutput(); 313 | if(result==false){ 314 | sprintf(logs, "Output Matching: WA"); 315 | Logs::WriteLine(logs); 316 | strcpy(status,"WA"); 317 | break; 318 | } 319 | else{ 320 | sprintf(logs, "Output Matching: AC"); 321 | Logs::WriteLine(logs); 322 | } 323 | } 324 | 325 | Logs::WriteLine(""); 326 | if(result==true) Logs::WriteLine("Execution ==> Successful"); 327 | else Logs::WriteLine("Execution ==> Failed"); 328 | 329 | /* 330 | if(result==true) Logs::WriteLine("\nMatching Output... "); 331 | for(TestCaseId=1; (result==true && TestCaseId<=NoOfTestCases); TestCaseId++){ 332 | MatchOutput(); 333 | if(result==false){ 334 | sprintf(logs, "Failed on test case %d", TestCaseId); 335 | Logs::WriteLine(logs); 336 | strcpy(status,"WA"); 337 | } 338 | } 339 | if(result==true) Logs::WriteLine("All output successfully matched."); 340 | Logs::WriteLine(""); 341 | */ 342 | } 343 | 344 | void FileHandle::pipeMatch(){ 345 | FILE *fpipe; 346 | char line[256]; 347 | char count[256]; 348 | 349 | if ( !(fpipe = (FILE*)popen(command_count,"r")) ){ 350 | // If fpipe is NULL 351 | perror("Problems with pipe"); 352 | Logs::WriteLine("Problems with pipe"); 353 | } 354 | else{ 355 | while ( fgets( count, sizeof count, fpipe)){ 356 | } 357 | NumberOfWrongCases = atoi (count) ; 358 | if(NumberOfWrongCases > 0) 359 | NumberOfWrongCases--; 360 | printf("Number of wrong testcases: %lld\n", NumberOfWrongCases); 361 | } 362 | 363 | if ( !(fpipe = (FILE*)popen(command,"r")) ){ 364 | // If fpipe is NULL 365 | perror("Problems with pipe"); 366 | Logs::WriteLine("Problems with pipe"); 367 | } 368 | else{ 369 | //cout<ProblemId, TestCaseId); 383 | sprintf(ToFileStr, "%s%do.txt", FileDirAddr, TestCaseId); 384 | 385 | sprintf(command, "diff %s %s --ignore-all-space --ignore-blank-lines --ignore-tab-expansion --ignore-space-change --brief 2>&1", FromFileStr, ToFileStr); 386 | sprintf(command_count, "diff -U 0 %s %s | grep ^+ | wc -l", FromFileStr, ToFileStr); 387 | 388 | //printf("%s\n", command); 389 | pipeMatch(); 390 | } 391 | 392 | void FileHandle::SendResults(){ 393 | sprintf(timeused, "%0.3f", TimeUsed); 394 | sprintf(memoryused, "%d", MemoryUsed); 395 | sprintf(fileid, "%d", FileInfo->FileId); 396 | sprintf(numberofwrongtestcases, "%lld", NumberOfWrongCases); 397 | sprintf(logs, "FileId ==> %s Status==>%s DetailStatus==>%s TimeUsed==>%s MemoryUsed==>%s Language==>%s NumberOfWrongCases==>%s", fileid, status, detailstatus, timeused, memoryused, FileInfo->lang, numberofwrongtestcases); 398 | Logs::WriteLine(logs, true); 399 | 400 | 401 | if(CROptions::SendResults) FileCurl.SendResultsToWebpage(fileid, status, detailstatus, timeused, memoryused, numberofwrongtestcases); 402 | Logs::WriteLine("\n================================================================================\n"); 403 | 404 | } 405 | 406 | void FileHandle::CleanUp(){ 407 | //Delete directory as well source files 408 | sprintf(systemString, "rm -rf %s", FileAddr); 409 | system(systemString); 410 | sprintf(systemString, "rm -f %s.txt", FileAddr); 411 | system(systemString); 412 | } 413 | 414 | void FileHandle::FileOperations(){ 415 | 416 | if(CheckLANG() == -1 || FetchFile() == -1 || CheckMIME() == -1) return; 417 | if(result==false) return; 418 | if(MakeDir()==-1) return; 419 | 420 | Compile(); 421 | 422 | if(result==false){ 423 | CleanUp(); 424 | return; 425 | } 426 | 427 | if(PrepareToExecute()==-1){ 428 | CleanUp(); 429 | return; 430 | } 431 | 432 | Execute(); 433 | 434 | } 435 | 436 | bool FileHandle::getResult(){ 437 | return result; 438 | } 439 | 440 | void FileHandle::Action(){ 441 | FileOperations(); 442 | SendResults(); 443 | 444 | } 445 | 446 | FileHandle::~FileHandle(){ 447 | if(CROptions::Clean) 448 | CleanUp(); 449 | } 450 | -------------------------------------------------------------------------------- /src/FileHandle.h: -------------------------------------------------------------------------------- 1 | #ifndef FILEHANDLE_H 2 | #define FILEHANDLE_H 3 | #include "headers.h" 4 | #include "CurlWrapper.h" 5 | 6 | 7 | class FileHandle 8 | { 9 | private: 10 | int FileId, MemoryUsed, NoOfTestCases, TestCaseId, TimeLimit, MemoryLimit; 11 | float TimeUsed; 12 | char systemString[100]; 13 | char status[10], logs[11000], detailstatus[10000], numberofwrongtestcases[1000]; 14 | char str[10000], *token, tmp[10]; 15 | char logString[100]; 16 | float TestCaseExecutionTime; 17 | int TestCaseExecutionMemory; 18 | char FileDirAddr[100], FileAddr[100], FileName[10], FullFileAddr[100], timeused[10], memoryused[10], fileid[10]; 19 | char command[1000]; 20 | char command_count[1000]; 21 | const char* lang, *ProblemId; 22 | string CompileOutput; 23 | CurlWrapper FileCurl; 24 | string ExecutionStr; 25 | bool result; 26 | long long int NumberOfWrongCases; 27 | FileInfoStruct* FileInfo; 28 | 29 | public: 30 | FileHandle(FileInfoStruct* FileInfo); 31 | ~FileHandle(); 32 | int CheckLANG(); 33 | int FetchFile(); 34 | int CheckMIME(); 35 | int MakeDir(); 36 | void Compile(); 37 | void pipeCompile(); 38 | int pipeNoOfTestCases(); 39 | int PrepareToExecute(); 40 | void PipeExecute(); 41 | void Execute(); 42 | void MatchOutput(); 43 | void pipeMatch(); 44 | void SendResults(); 45 | void CleanUp(); 46 | bool getResult(); 47 | void FileOperations(); 48 | void Action(); 49 | 50 | }; 51 | #endif 52 | -------------------------------------------------------------------------------- /src/Logs.cpp: -------------------------------------------------------------------------------- 1 | #include "Logs.h" 2 | 3 | FILE * Logs::pLogFile; 4 | time_t Logs::rawtime; 5 | char Logs::curtime[100]; 6 | char Logs::logfile[100]; 7 | 8 | 9 | void Logs::SetLogFileName(const char* logfilepath, const char* logfilename) 10 | { 11 | /*Store logfilepath and logfilename to logfile array 12 | *A terminating null character is automatically appended after the content. 13 | */ 14 | sprintf(logfile, "%s%s", logfilepath, logfilename); 15 | } 16 | 17 | 18 | void Logs::OpenLogFile() 19 | { 20 | pLogFile = fopen(logfile, "a"); 21 | //Open the logfile in append mode ; create if not exists 22 | if(pLogFile==NULL) printf("Error : Cannot open log file for logging purposes."); 23 | } 24 | 25 | 26 | void Logs::CloseLogFile() 27 | { 28 | //close the log file 29 | fclose(pLogFile); 30 | } 31 | 32 | 33 | void Logs::SetTime() 34 | { 35 | time( &rawtime );//store time value to rawtime -- returns unix time stamp 36 | strcpy(curtime, ctime(&rawtime)); 37 | /*copies the current time to curtime in following format 38 | *Www Mmm dd hh:mm:ss yyyy 39 | *Www is the weekday, Mmm the month (in letters), dd the day of the month, hh:mm:ss the time, and yyyy the year. 40 | *The string is followed by a new-line character ('\n') and terminated with a null-character. 41 | */ 42 | } 43 | 44 | 45 | void Logs::SetAndPrintTime() 46 | { 47 | Logs::SetTime(); 48 | 49 | 50 | // fwrite(curtime, 1, sizeof(curtime), pLogFile); 51 | fputs(curtime, pLogFile); 52 | 53 | //Write an array of sizeof(curtime) number of elements each of size 1 byte from curtime array to current postion in pLogFile 54 | if(CROptions::PrintOnScreen) printf("%s", curtime); 55 | } 56 | 57 | 58 | void Logs::Write(const char* logs, bool PrintTime) 59 | { 60 | if(PrintTime) SetAndPrintTime(); 61 | fputs(logs, pLogFile); 62 | //write logs string to pLogFile 63 | //Doesnot put new line char automatically 64 | if(CROptions::PrintOnScreen) printf("%s", logs); 65 | } 66 | 67 | 68 | void Logs::Write(char* logs, bool PrintTime) 69 | { 70 | if(PrintTime) SetAndPrintTime(); 71 | fputs(logs, pLogFile); 72 | if(CROptions::PrintOnScreen) printf("%s", logs); 73 | } 74 | 75 | 76 | void Logs::WriteLine(const char* logs, bool PrintTime) 77 | { 78 | //Write and insert a line 79 | if(PrintTime) SetAndPrintTime(); 80 | fputs(logs, pLogFile); 81 | fputs("\n", pLogFile); 82 | if(CROptions::PrintOnScreen) printf("%s\n", logs); 83 | } 84 | 85 | 86 | void Logs::WriteLine(char* logs, bool PrintTime) 87 | { 88 | if(PrintTime) SetAndPrintTime(); 89 | //printf("\n%lu\n" , sizeof((*logs))); 90 | fputs(logs, pLogFile); 91 | fputs("\n", pLogFile); 92 | if(CROptions::PrintOnScreen) printf("%s\n", logs); 93 | } 94 | 95 | 96 | 97 | void Logs::LeaveLine() 98 | { 99 | Logs::WriteLine(""); 100 | } 101 | 102 | 103 | void Logs::CodeRunnerStarted() 104 | { 105 | Logs::WriteLine("===CodeRunner Started===", true); 106 | Logs::LeaveLine(); 107 | } 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /src/Logs.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGS_H 2 | #define LOGS_H 3 | 4 | #include "headers.h" 5 | #include "CROptions.h" 6 | 7 | 8 | class Logs{ 9 | 10 | private: 11 | static FILE * pLogFile; //File Object 12 | static time_t rawtime; //Time type : as returned by time function 13 | static char curtime[100]; 14 | static char logfile[100]; 15 | 16 | public: 17 | static void SetLogFileName(const char* logfilepath, const char* logfilename); 18 | static void OpenLogFile(); 19 | static void CloseLogFile(); 20 | static void Write(const char* logs, bool PrintTime = false); 21 | static void Write(char* logs, bool PrintTime = false); 22 | static void WriteLine(const char* logs, bool PrintTime = false); 23 | static void WriteLine(char* logs, bool PrintTime = false); 24 | static void LeaveLine(); 25 | static void SetTime(); 26 | static void SetAndPrintTime(); 27 | static void SetFileId(int FileId); 28 | static void CodeRunnerStarted(); 29 | 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/headers.h: -------------------------------------------------------------------------------- 1 | /*Include Headers used through out CodeRunner */ 2 | 3 | #ifndef HEADERS_H 4 | #define HEADERS_H 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "Logs.h" 32 | #endif 33 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | CodeRunner - the online judge 3 | Author: Shashank Kumar 4 | Copyright (c): 2011 All rights reserved 5 | Version: 3 6 | 7 | Copyright Shashank Kumar. All rights reserved. 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to 10 | deal in the Software without restriction, including without limitation the 11 | rights to use, copy and/or distribute copies of the Software, 12 | and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | IN THE SOFTWARE. 25 | You may contact the author of CodeRunner by e-mail at: 26 | shashankkumar.me@gmail.com 27 | 28 | ****************************************************************************/ 29 | 30 | #include "headers.h" 31 | #include "CROptions.h" 32 | #include "CodeRunner.h" 33 | 34 | int main(int argc, char* argv[]) 35 | { 36 | CodeRunner::ChDir(CROptions::PATH); 37 | 38 | int opt; 39 | bool UsageError = false; 40 | 41 | //getopt = -1 means no more command line arguments to parse 42 | 43 | while((opt = getopt(argc, argv, "abcdf:hil:m:np:qrs:t:v")) != -1){ 44 | switch(opt){ 45 | // For fetching all file-ids irrespective of evaluation status. 46 | case 'a': 47 | CROptions::GetAllFileIds = true; 48 | break; 49 | // For sending results and forcing insertion of those results. 50 | case 'b': 51 | CROptions::ForcePushResult = true; 52 | break; 53 | // For clearing Files directory after execution of source code. 54 | case 'c': 55 | CROptions::Clean = true; 56 | break; 57 | // For not downloading source codes. In such a case, the source codes 58 | // should already be present in the Files directory. 59 | case 'd': 60 | CROptions::DownloadSourceFile = false; 61 | break; 62 | // For pre-defining FileId 63 | case 'f': 64 | CROptions::FileInfoFetchOptions->FileId_Predefined = true; 65 | CROptions::FileInfoFetchOptions->FileInfo.FileId = atoi(optarg); 66 | break; 67 | case 'h': 68 | printf("-a ==> Fetch all file-ids irrespective of evaluation status.\n"); 69 | printf("-b ==> For sending results and forcing insertion of those results.\n"); 70 | printf("-c ==> Clear files directory after execution of source code. \n"); 71 | printf("-d ==> Does not download source code. The source codes should already be present in the Files directory.\n"); 72 | printf("-f ==> For pre-defining FileId. It is used when we are evaluating a particular file only. It has to be followed by additional(required) parameter (ie the file id) \n"); 73 | printf("-h ==> Print all command line options with their description\n"); 74 | printf("-i ==> Excectute only one file\n"); 75 | printf("-l ==> For pre-defining Language. It is used when we are evaluating a particular file only. It has to be followed by additional(required) parameter (ie the language of the source program)\n"); 76 | printf("-m ==> For specifying pre-defined memory limit. It is used when we are evaluating a particular file only. It has to be followed by additional(required) parameter (ie the max memory consumption (in MB) the program is allowed)\n"); 77 | printf("-n ==> For not sending results after evaluation.\n"); 78 | printf("-p ==> For pre-defining ProblemId. It is used when we are evaluating a particular file only. It has to be followed by additional(required) parameter (ie the problem id) \n"); 79 | printf("-q ==> quiet mode ie do not print output on screen\n"); 80 | printf("-r ==> Run CodeRunner for just one epoch.\n"); 81 | printf("-s ==> Specifying Sleep Interval after each epoch. It has to be followed by additional(required) parameter (ie sleep-inteval in seconds) \n"); 82 | printf("-t ==> Specifying pre-defined time-limit. It is used when we are evaluating a particular file only. It has to be followed by additional (required) parameter (ie the time limit in seconds)\n"); 83 | printf("-v ==> For printing version related information.\n"); 84 | return 0; 85 | break; 86 | case 'i': 87 | CROptions::OneFileExecution = true; 88 | break; 89 | // For pre-defining Language 90 | case 'l': 91 | CROptions::FileInfoFetchOptions->Lang_Predefined = true; 92 | strcpy(CROptions::FileInfoFetchOptions->FileInfo.lang, optarg); 93 | break; 94 | // For specifying pre-defined memory limit. 95 | case 'm': 96 | CROptions::FileInfoFetchOptions->MemoryLimit_Predefined = true; 97 | CROptions::FileInfoFetchOptions->FileInfo.MemoryLimit = atoi(optarg); 98 | break; 99 | // For not sending results after evaluation. 100 | case 'n': 101 | CROptions::SendResults = false; 102 | break; 103 | // For pre-defining ProblemId 104 | case 'p': 105 | CROptions::FileInfoFetchOptions->ProblemId_Predefined = true; 106 | strcpy(CROptions::FileInfoFetchOptions->FileInfo.ProblemId, optarg); 107 | break; 108 | case 'q': 109 | CROptions::PrintOnScreen = false; 110 | break; 111 | // For setting CodeRunner to just run for one epoch. 112 | case 'r': 113 | CROptions::RunOnce = true; 114 | break; 115 | // For specifying Sleep Interval after each epoch. 116 | case 's': 117 | CROptions::SleepInterval = atoi(optarg); 118 | break; 119 | // For specifying pre-defined time-limit. 120 | case 't': 121 | CROptions::FileInfoFetchOptions->TimeLimit_Predefined = true; 122 | CROptions::FileInfoFetchOptions->FileInfo.TimeLimit = atoi(optarg); 123 | break; 124 | // For printing version related information. 125 | case 'v': 126 | printf("Version: 3\n"); 127 | return 0; 128 | break; 129 | // For no printing on screen. Running CodeRunner in "quiet" option. 130 | default: /* '?' */ 131 | UsageError = true; 132 | } 133 | } 134 | 135 | if(CROptions::FileInfoFetchOptions->FileId_Predefined){ 136 | if(CROptions::OneFileExecution){ 137 | if(!(CROptions::FileInfoFetchOptions->MemoryLimit_Predefined && CROptions::FileInfoFetchOptions->TimeLimit_Predefined && 138 | CROptions::FileInfoFetchOptions->ProblemId_Predefined && CROptions::FileInfoFetchOptions->Lang_Predefined)) UsageError = true; 139 | } 140 | else if(CROptions::FileInfoFetchOptions->ProblemId_Predefined || CROptions::FileInfoFetchOptions->Lang_Predefined) UsageError = true; 141 | } 142 | 143 | if(UsageError){ 144 | fprintf(stderr, "Usage: %s [-f fileid [-i -p problemcode -t timelimit -m memorylimit -l lang] | [-p problemcode] [-l language] ] [-s sleepinterval] [-a] [-b] [-n] [-c] [-r] [-d] [-v]\n", argv[0]); 145 | exit(EXIT_FAILURE); 146 | } 147 | 148 | CodeRunner::CheckPrerequisites(); 149 | CodeRunner::Run(); 150 | return 0; 151 | } 152 | -------------------------------------------------------------------------------- /src/resources.h: -------------------------------------------------------------------------------- 1 | void SetResourceLimit(int resource, int softLimit, int hardLimit){ 2 | rlimit r; 3 | r.rlim_cur = softLimit, r.rlim_max = hardLimit; 4 | setrlimit(resource, &r); 5 | } 6 | 7 | 8 | void SetResourceLimitValues(int TimeLimit){ 9 | SetResourceLimit(RLIMIT_CPU,TimeLimit, TimeLimit); // Time Limit specified by the problem setter 10 | SetResourceLimit(RLIMIT_CORE, 0, 0); 11 | SetResourceLimit(RLIMIT_FSIZE, 16777216, 16777216); // Max printing allowed to the tune of 16 MB 12 | //SetResourceLimit(RLIMIT_STACK, 8192, 8192); 13 | SetResourceLimit(RLIMIT_NPROC, 0, 0); 14 | } 15 | 16 | void SetResourceLimitValuesJava(int TimeLimit){ 17 | SetResourceLimit(RLIMIT_CPU,TimeLimit, TimeLimit); // Time Limit specified by the problem setter 18 | } 19 | 20 | /** 21 | void setResourceLimitWrapper(int TimeLimit, int MemoryLimit){ 22 | setResourceLimit(RLIMIT_CPU,TimeLimit, TimeLimit); // Time Limit specified by the problem setter 23 | setResourceLimit(RLIMIT_NICE,0, 0); 24 | // Memory Limit specified by the problem setter 25 | //setResourceLimit(RLIMIT_AS, MemoryLimit * 64 * 1024 * 1024, MemoryLimit * 64 * 1024 * 1024); 26 | setResourceLimit(RLIMIT_CORE, 0, 0); 27 | setResourceLimit(RLIMIT_DATA, 67108864, 67108864); 28 | setResourceLimit(RLIMIT_FSIZE, 26214400, 26214400); // Max printing allowed to the tune of 256 MB 29 | setResourceLimit(RLIMIT_LOCKS, 1024, 1024); 30 | setResourceLimit(RLIMIT_NOFILE, 10, 10); 31 | setResourceLimit(RLIMIT_NPROC, 0, 0); 32 | setResourceLimit(RLIMIT_RSS, 4294967295, 4294967295); 33 | //setResourceLimit(RLIMIT_MEMLOCK, 32768); 34 | //setResourceLimit(RLIMIT_MSGQUEUE, 8192, 81928); 35 | //setResourceLimit(RLIMIT_RTPRIO, 0, 0); 36 | //setResourceLimit(RLIMIT_SIGPENDING, 6144, 6144); 37 | //setResourceLimit(RLIMIT_STACK, 8192, 8192); 38 | //setResourceLimit(RLIMIT_OFILE, 1, 1); // Dont know what it is?? 39 | } 40 | 41 | void Java_setResourceLimitWrapper(int TimeLimit, int MemoryLimit){ 42 | setResourceLimit(RLIMIT_CPU, TimeLimit, TimeLimit); // Time Limit specified by the problem setter 43 | setResourceLimit(RLIMIT_NICE,0, 0); 44 | // Memory Limit specified by the problem setter 45 | setResourceLimit(RLIMIT_AS, MemoryLimit * 1024 * 1024 * 100, MemoryLimit * 1024 * 1024 * 100); 46 | setResourceLimit(RLIMIT_CORE, 0, 0); 47 | setResourceLimit(RLIMIT_DATA, 67108864, 67108864); 48 | setResourceLimit(RLIMIT_FSIZE, 26214400, 26214400); // Max printing allowed to the tune of 256 MB 49 | setResourceLimit(RLIMIT_LOCKS, 1024, 1024); 50 | //setResourceLimit(RLIMIT_MEMLOCK, 32768, 32768); 51 | //setResourceLimit(RLIMIT_MSGQUEUE, 8192, 81928); 52 | setResourceLimit(RLIMIT_NOFILE, 10, 10); 53 | ////////setResourceLimit(RLIMIT_NPROC, 0, 0); 54 | setResourceLimit(RLIMIT_RSS, 4294967295, 4294967295); 55 | //setResourceLimit(RLIMIT_RTPRIO, 0, 0); 56 | //setResourceLimit(RLIMIT_SIGPENDING, 6144, 6144); 57 | setResourceLimit(RLIMIT_STACK, 8192, 8192); 58 | //setResourceLimit(RLIMIT_OFILE, 1, 1); // Dont know what it is?? 59 | } 60 | */ 61 | /* 62 | 63 | getrlimit() and setrlimit() get and set resource limits respectively. Each resource has an associated soft and hard limit, as defined by the 64 | rlimit structure (the rlim argument to both getrlimit() and setrlimit()): 65 | 66 | struct rlimit { 67 | rlim_t rlim_cur; // Soft limit 68 | rlim_t rlim_max; // Hard limit (ceiling for rlim_cur) 69 | }; 70 | 71 | The soft limit is the value that the kernel enforces for the corresponding resource. The hard limit acts as a ceiling for the soft limit: an 72 | unprivileged process may only set its soft limit to a value in the range from 0 up to the hard limit, and (irreversibly) lower its hard limit. A 73 | privileged process (under Linux: one with the CAP_SYS_RESOURCE capability) may make arbitrary changes to either limit value. 74 | 75 | The value RLIM_INFINITY denotes no limit on a resource (both in the structure returned by getrlimit() and in the structure passed to setrlimit()). 76 | 77 | resource must be one of: 78 | 79 | RLIMIT_AS 80 | The maximum size of the process's virtual memory (address space) in bytes. This limit affects calls to brk(2), mmap(2) and mremap(2), 81 | which fail with the error ENOMEM upon exceeding this limit. Also automatic stack expansion will fail (and generate a SIGSEGV that kills 82 | the process if no alternate stack has been made available via sigaltstack(2)). Since the value is a long, on machines with a 32-bit long 83 | either this limit is at most 2 GiB, or this resource is unlimited. 84 | 85 | RLIMIT_CORE 86 | Maximum size of core file. When 0 no core dump files are created. When non-zero, larger dumps are truncated to this size. 87 | 88 | RLIMIT_CPU 89 | CPU time limit in seconds. When the process reaches the soft limit, it is sent a SIGXCPU signal. The default action for this signal is to 90 | terminate the process. However, the signal can be caught, and the handler can return control to the main program. If the process contin‐ 91 | ues to consume CPU time, it will be sent SIGXCPU once per second until the hard limit is reached, at which time it is sent SIGKILL. (This 92 | latter point describes Linux 2.2 through 2.6 behavior. Implementations vary in how they treat processes which continue to consume CPU time 93 | after reaching the soft limit. Portable applications that need to catch this signal should perform an orderly termination upon first 94 | receipt of SIGXCPU.) 95 | 96 | RLIMIT_DATA 97 | The maximum size of the process's data segment (initialized data, uninitialized data, and heap). This limit affects calls to brk(2) and 98 | sbrk(2), which fail with the error ENOMEM upon encountering the soft limit of this resource. 99 | 100 | RLIMIT_FSIZE 101 | The maximum size of files that the process may create. Attempts to extend a file beyond this limit result in delivery of a SIGXFSZ signal. 102 | By default, this signal terminates a process, but a process can catch this signal instead, in which case the relevant system call (e.g., 103 | write(2), truncate(2)) fails with the error EFBIG. 104 | 105 | RLIMIT_LOCKS (Early Linux 2.4 only) 106 | A limit on the combined number of flock(2) locks and fcntl(2) leases that this process may establish. 107 | 108 | RLIMIT_MEMLOCK 109 | The maximum number of bytes of memory that may be locked into RAM. In effect this limit is rounded down to the nearest multiple of the 110 | system page size. This limit affects mlock(2) and mlockall(2) and the mmap(2) MAP_LOCKED operation. Since Linux 2.6.9 it also affects the 111 | shmctl(2) SHM_LOCK operation, where it sets a maximum on the total bytes in shared memory segments (see shmget(2)) that may be locked by 112 | the real user ID of the calling process. The shmctl(2) SHM_LOCK locks are accounted for separately from the per-process memory locks 113 | established by mlock(2), mlockall(2), and mmap(2) MAP_LOCKED; a process can lock bytes up to this limit in each of these two categories. 114 | In Linux kernels before 2.6.9, this limit controlled the amount of memory that could be locked by a privileged process. Since Linux 2.6.9, 115 | no limits are placed on the amount of memory that a privileged process may lock, and this limit instead governs the amount of memory that 116 | an unprivileged process may lock. 117 | 118 | RLIMIT_MSGQUEUE (Since Linux 2.6.8) 119 | Specifies the limit on the number of bytes that can be allocated for POSIX message queues for the real user ID of the calling process. 120 | This limit is enforced for mq_open(3). Each message queue that the user creates counts (until it is removed) against this limit according 121 | to the formula: 122 | 123 | bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) + 124 | attr.mq_maxmsg * attr.mq_msgsize 125 | 126 | where attr is the mq_attr structure specified as the fourth argument to mq_open(3). 127 | 128 | The first addend in the formula, which includes sizeof(struct msg_msg *) (4 bytes on Linux/i386), ensures that the user cannot create an 129 | unlimited number of zero-length messages (such messages nevertheless each consume some system memory for bookkeeping overhead). 130 | 131 | RLIMIT_NICE (since Linux 2.6.12, but see BUGS below) 132 | Specifies a ceiling to which the process's nice value can be raised using setpriority(2) or nice(2). The actual ceiling for the nice value 133 | is calculated as 20 - rlim_cur. (This strangeness occurs because negative numbers cannot be specified as resource limit values, since they 134 | typically have special meanings. For example, RLIM_INFINITY typically is the same as -1.) 135 | 136 | RLIMIT_NOFILE 137 | Specifies a value one greater than the maximum file descriptor number that can be opened by this process. Attempts (open(2), pipe(2), 138 | dup(2), etc.) to exceed this limit yield the error EMFILE. (Historically, this limit was named RLIMIT_OFILE on BSD.) 139 | 140 | RLIMIT_NPROC 141 | The maximum number of processes (or, more precisely on Linux, threads) that can be created for the real user ID of the calling process. 142 | Upon encountering this limit, fork(2) fails with the error EAGAIN. 143 | 144 | RLIMIT_RSS 145 | Specifies the limit (in pages) of the process's resident set (the number of virtual pages resident in RAM). This limit only has effect in 146 | Linux 2.4.x, x < 30, and there only affects calls to madvise(2) specifying MADV_WILLNEED. 147 | 148 | RLIMIT_RTPRIO (Since Linux 2.6.12, but see BUGS) 149 | Specifies a ceiling on the real-time priority that may be set for this process using sched_setscheduler(2) and sched_setparam(2). 150 | 151 | RLIMIT_RTTIME (Since Linux 2.6.25) 152 | Specifies a limit on the amount of CPU time that a process scheduled under a real-time scheduling policy may consume without making a 153 | blocking system call. For the purpose of this limit, each time a process makes a blocking system call, the count of its consumed CPU time 154 | is reset to zero. The CPU time count is not reset if the process continues trying to use the CPU but is preempted, its time slice expires, 155 | or it calls sched_yield(2). 156 | Upon reaching the soft limit, the process is sent a SIGXCPU signal. If the process catches or ignores this signal and continues consuming 157 | CPU time, then SIGXCPU will be generated once each second until the hard limit is reached, at which point the process is sent a SIGKILL 158 | signal. 159 | 160 | The intended use of this limit is to stop a runaway real-time process from locking up the system. 161 | 162 | RLIMIT_SIGPENDING (Since Linux 2.6.8) 163 | Specifies the limit on the number of signals that may be queued for the real user ID of the calling process. Both standard and real-time 164 | signals are counted for the purpose of checking this limit. However, the limit is only enforced for sigqueue(2); it is always possible to 165 | use kill(2) to queue one instance of any of the signals that are not already queued to the process. 166 | 167 | RLIMIT_STACK 168 | The maximum size of the process stack, in bytes. Upon reaching this limit, a SIGSEGV signal is generated. To handle this signal, a 169 | process must employ an alternate signal stack (sigaltstack(2)). 170 | 171 | Since Linux 2.6.23, this limit also determines the amount of space used for the process's command-line arguments and environment variables; 172 | for details, see execve(2). 173 | 174 | RETURN VALUE 175 | On success, zero is returned. On error, -1 is returned, and errno is set appropriately. 176 | 177 | ERRORS 178 | EFAULT rlim points outside the accessible address space. 179 | 180 | EINVAL resource is not valid; or, for setrlimit(): rlim->rlim_cur was greater than rlim->rlim_max. 181 | 182 | EPERM An unprivileged process tried to use setrlimit() to increase a soft or hard limit above the current hard limit; the CAP_SYS_RESOURCE capa‐ 183 | bility is required to do this. Or, the process tried to use setrlimit() to increase the soft or hard RLIMIT_NOFILE limit above the current 184 | kernel maximum (NR_OPEN). 185 | 186 | 187 | 188 | */ 189 | --------------------------------------------------------------------------------