// File: judge_client.cc // Author: sempr // refacted by zhblue /* * Copyright 2008 sempr * * Refacted and modified by zhblue * Bug report email newsclan@gmail.com * * * This file is part of HUSTOJ. * * HUSTOJ is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * HUSTOJ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HUSTOJ. if not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #ifdef OJ_USE_MYSQL #include #endif #include #include "okcalls.h" #define STD_MB 1048576LL #define STD_T_LIM 2 #define STD_F_LIM (STD_MB << 9) //default file size limit 512m ,2^9=512 #define STD_M_LIM (STD_MB << 8) //default memory limit 256m ,2^8=256 #define BUFFER_SIZE 4096 //default size of char buffer 5120 bytes #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) #define OJ_WT0 0 //提交排队 #define OJ_WT1 1 //重判排队 #define OJ_CI 2 //编译中(任务已派发) #define OJ_RI 3 //运行中 #define OJ_AC 4 //答案正确 #define OJ_PE 5 //格式错误 #define OJ_WA 6 //答案错误 #define OJ_TL 7 //时间超限 #define OJ_ML 8 //内存超限 #define OJ_OL 9 //输出超限 #define OJ_RE 10 //运行错误 #define OJ_CE 11 //编译错误 #define OJ_CO 12 //编译完成 #define OJ_TR 13 //测试运行结束 #define OJ_MC 14 // 等待裁判手工确认 #ifdef __arm__ // arm 的寄存器结构 struct user_regs_struct { long uregs[18]; }; #define ARM_r7 uregs[7] #define ARM_ORIG_r0 uregs[17] #define REG_SYSCALL ARM_r7 #endif #ifdef __aarch64__ //arm64的寄存器结构 #define NT_PRSTATUS 1 #define NT_ARM_SYSTEM_CALL 0x404 #define ARM_cpsr uregs[16] #define ARM_pc uregs[15] #define ARM_lr uregs[14] #define ARM_sp uregs[13] #define ARM_ip uregs[12] #define ARM_fp uregs[11] #define ARM_r10 uregs[10] #define ARM_r9 uregs[9] #define ARM_r8 regs[8] #define ARM_r7 uregs[7] #define ARM_r6 uregs[6] #define ARM_r5 uregs[5] #define ARM_r4 uregs[4] #define ARM_r3 uregs[3] #define ARM_r2 uregs[2] #define ARM_r1 uregs[1] #define ARM_r0 uregs[0] #define ARM_ORIG_r0 uregs[17] #define PTRACE_GETREGS PTRACE_GETREGSET #define PTRACE_SETREGS PTRACE_SETREGSET #define REG_SYSCALL regs[18] #endif #ifdef __mips__ //mips 龙芯的寄存器结构 typedef unsigned long long uint64_t; struct user_regs_struct{ uint64_t uregs[38]; }; #define REG_V0 2 #define REG_A0 4 #define mips_REG_V0 uregs[REG_V0] #define REG_SYSCALL mips_REG_V0 #endif #ifdef __i386 //32位x86寄存器 #define REG_SYSCALL orig_eax #define REG_RET eax #define REG_ARG0 ebx #define REG_ARG1 ecx #endif #ifdef __x86_64__ //64位x86寄存器 #define REG_SYSCALL orig_rax #define REG_RET rax #define REG_ARG0 rdi #define REG_ARG1 rsi #endif static int DEBUG = 0; static char host_name[BUFFER_SIZE/10]; //数据库服务器地址 static int port_number; //端口 static char user_name[BUFFER_SIZE/10]; //用户名 static char password[BUFFER_SIZE/10]; //密码 static char db_name[BUFFER_SIZE/10]; //库名 static char oj_home[BUFFER_SIZE/10]; //判题系统主目录 static char data_list[BUFFER_SIZE][BUFFER_SIZE]; //测试数据列表 static int data_list_len = 0; //列表长度 static char lock_file[BUFFER_SIZE]="/home/judge/run0/judge_client.pid"; //工作目录锁定文件 static int max_running; static int sleep_time; static int java_time_bonus = 5; static int java_memory_bonus = 512; static char java_xms[BUFFER_SIZE/10]; static char java_xmx[BUFFER_SIZE/10]; static int sim_enable = 0; static int oi_mode = 0; static int full_diff = 0; static int raw_text_diff = 1; static int use_max_time = 0; static int time_limit_to_total= 1; static int total_time= 0; static int http_judge = 0; static int copy_data= 0; static char http_baseurl[BUFFER_SIZE/10]; static char http_apipath[BUFFER_SIZE/10]; static char http_loginpath[BUFFER_SIZE/10]; static char http_username[BUFFER_SIZE/10]; static char http_password[BUFFER_SIZE/10]; static int http_download = 1; static double cpu_compensation = 1.0; static int shm_run = 0; static char record_call = 0; static int use_ptrace = 1; static int ignore_esol= 1; static int compile_chroot = 0; static int turbo_mode = 0; static int python_free=0; static int use_docker=0; static const char *tbname = "solution"; static char cc_opt[BUFFER_SIZE/10]; static char cc_std[BUFFER_SIZE/10]; static char cpp_std[BUFFER_SIZE/10]; static int auto_result = OJ_AC ; int num_of_test = 0; //static int sleep_tmp; size_t prelen=16; static int py2=1; // caution: py2=1 means default using py3 #define ZOJ_COM #ifdef _mysql_h MYSQL *conn; #endif static char jresult[15][4]={"PD","PR","CI","RJ","AC","PE","WA","TLE","MLE","OLE","RE","CE","CO","TR","MC"}; static char lang_ext[24][8] = {"c", "cc", "pas", "java", "rb", "sh", "py", "php", "pl", "cs", "m", "bas", "scm", "c", "cc", "lua", "js", "go","sql","f95","m","cob","R","sb3"}; //static char buf[BUFFER_SIZE]; int lockfile(int fd) { struct flock fl; fl.l_type = F_WRLCK; fl.l_start = 0; fl.l_whence = SEEK_SET; fl.l_len = 0; return (fcntl(fd, F_SETLK, &fl)); } int already_running() { int fd; char buf[16]; fd = open(lock_file, O_RDWR | O_CREAT, LOCKMODE); if (fd < 0) { if(DEBUG)printf("%s open fail.\n",lock_file); exit(1); } if (lockfile(fd) < 0) { if (errno == EACCES || errno == EAGAIN) { close(fd); return 1; } if(DEBUG)printf("%s lock fail.\n",lock_file); exit(1); } if(ftruncate(fd, 0)) printf("close file fail 0 \n"); sprintf(buf, "%d", getpid()); if(write(fd, buf, strlen(buf) + 1)>=BUFFER_SIZE) printf("buffer size overflow!...\n"); return (0); } void print_arm_regs(long long unsigned int *d){ for(int i=0;i<32;i++){ printf("[%d]:%lld ",i,d[i]%CALL_ARRAY_SIZE); } printf("\n"); } int data_list_has(char *file) { for (int i = 0; i < data_list_len; i++) { if (strcmp(data_list[i], file) == 0) return 1; } return 0; } int data_list_add(char *file) { if (data_list_len < BUFFER_SIZE - 1) { strcpy(data_list[data_list_len], file); data_list_len++; return 0; } else { return 1; } } long get_file_size(const char *filename) { struct stat f_stat; if (stat(filename, &f_stat) == -1) { return 0; } return (long)f_stat.st_size; } void write_log(const char *_fmt, ...) { va_list ap; char fmt[BUFFER_SIZE]; strncpy(fmt, _fmt,BUFFER_SIZE); char buffer[BUFFER_SIZE]; // time_t t = time(NULL); //int l; sprintf(buffer, "%s/log/client.log", oj_home); FILE *fp = fopen(buffer, "ae+"); if (fp == NULL) { fprintf(stderr, "%s/log/client.log openfile error!\n",oj_home); exit(-6); } va_start(ap, _fmt); //l = vsprintf(buffer, fmt, ap); fprintf(fp, "%s\n", buffer); if (DEBUG) printf("%s\n", buffer); va_end(ap); fclose(fp); } int execute_cmd(const char *fmt, ...) //执行命令获得返回值 { char cmd[BUFFER_SIZE]; int ret = 0; va_list ap; va_start(ap, fmt); vsprintf(cmd, fmt, ap); if (DEBUG) printf("%s\n", cmd); ret = system(cmd); va_end(ap); return ret; } const int call_array_size = CALL_ARRAY_SIZE; unsigned int call_id = 0; int call_counter[call_array_size] = {0}; static char LANG_NAME[BUFFER_SIZE]; void init_syscalls_limits(int lang) //白名单初始化 { int i; memset(call_counter, 0, sizeof(call_counter)); if (DEBUG) write_log("init_call_counter:%d", lang); if (record_call) { // recording for debuging for (i = 0; i < call_array_size; i++) { call_counter[i] = 0; } } else if (lang <= LANG_CPP || lang == LANG_CLANG || lang == LANG_CLANGPP ) { // C & C++ for (i = 0; i == 0 || LANG_CV[i]; i++) { call_counter[LANG_CV[i]] = HOJ_MAX_LIMIT; } } else if (lang == LANG_PASCAL ) { // Pascal for (i = 0; i == 0 || LANG_PV[i]; i++) call_counter[LANG_PV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_JAVA) { // Java for (i = 0; i == 0 || LANG_JV[i]; i++) call_counter[LANG_JV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_RUBY) { // Ruby for (i = 0; i == 0 || LANG_RV[i]; i++) call_counter[LANG_RV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_BASH) { // Bash for (i = 0; i == 0 || LANG_BV[i]; i++) call_counter[LANG_BV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_PYTHON) { // Python for (i = 0; i == 0 || LANG_YV[i]; i++) call_counter[LANG_YV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_PHP) { // php for (i = 0; i == 0 || LANG_PHV[i]; i++) call_counter[LANG_PHV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_PERL ) { // perl for (i = 0; i == 0 || LANG_PLV[i]; i++) call_counter[LANG_PLV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_CSHARP ) { // mono c# for (i = 0; i == 0 || LANG_CSV[i]; i++) call_counter[LANG_CSV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_OBJC ) { //objective c for (i = 0; i == 0 || LANG_OV[i]; i++) call_counter[LANG_OV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_FREEBASIC) { //free basic for (i = 0; i == 0 || LANG_BASICV[i]; i++) call_counter[LANG_BASICV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_SCHEME ) { //scheme guile for (i = 0; i == 0 || LANG_SV[i]; i++) call_counter[LANG_SV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_LUA ) { //lua for (i = 0; i == 0 || LANG_LUAV[i]; i++) call_counter[LANG_LUAV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_JS ) { //nodejs for (i = 0; i == 0 || LANG_JSV[i]; i++) call_counter[LANG_JSV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_GO ) { //go for (i = 0; i == 0 || LANG_GOV[i]; i++) call_counter[LANG_GOV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_SQL ) { //go for (i = 0; i == 0 || LANG_SQLV[i]; i++) call_counter[LANG_SQLV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_FORTRAN ) { //go for (i = 0; i == 0 || LANG_FV[i]; i++) call_counter[LANG_FV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_MATLAB ) { //matlab for (i = 0; i == 0 || LANG_MV[i]; i++) call_counter[LANG_MV[i]] = HOJ_MAX_LIMIT; } else if (lang == LANG_COBOL ) { //cobol for (i = 0; i == 0 || LANG_CBV[i]; i++) call_counter[LANG_CBV[i]] = HOJ_MAX_LIMIT; }else if(lang == LANG_R ){ for (i = 0; i == 0 || LANG_RLV[i]; i++) call_counter[LANG_RLV[i]] = HOJ_MAX_LIMIT; }else if(lang == LANG_SB3 ){ for (i = 0; i == 0 || LANG_SB3V[i]; i++) call_counter[LANG_SB3V[i]] = HOJ_MAX_LIMIT; } #ifdef __aarch64__ if (lang==3)call_counter[220]= 100; else call_counter[220]= 1; #else call_counter[SYS_execve % call_array_size ]= 1; if(lang == LANG_R ) call_counter[SYS_execve % call_array_size ]= 8; #endif printf("SYS_execve:%d [%d] \n",SYS_execve % call_array_size , call_counter[SYS_execve % call_array_size ]); } int after_equal(char *c) { int i = 0; for (; c[i] != '\0' && c[i] != '='; i++) ; return ++i; } void trim(char *c) { char buf[BUFFER_SIZE]; char *start, *end; strcpy(buf, c); start = buf; while (isspace(*start)) start++; end = start; while (!isspace(*end)) end++; *end = '\0'; strcpy(c, start); } bool read_buf(char *buf, const char *key, char *value) { if (strncmp(buf, key, strlen(key)) == 0) { strcpy(value, buf + after_equal(buf)); trim(value); if (DEBUG) printf("%s=%s\n", key, value); return 1; } return 0; } void read_double(char *buf, const char *key, double *value) { char buf2[BUFFER_SIZE]; if (read_buf(buf, key, buf2)) if(1!=sscanf(buf2, "%lf", value)) printf("double value read fail\n"); } void read_int(char *buf, const char *key, int *value) { char buf2[BUFFER_SIZE]; if (read_buf(buf, key, buf2)) if(1!=sscanf(buf2, "%d", value)) printf("int value read fail\n"); } FILE *read_cmd_output(const char *fmt, ...) { char cmd[BUFFER_SIZE]; FILE *ret = NULL; va_list ap; va_start(ap, fmt); vsprintf(cmd, fmt, ap); va_end(ap); if (DEBUG) printf("%s\n", cmd); ret = popen(cmd, "r"); return ret; } // read the configue file void init_judge_conf() //读取判题主目录etc中的配置文件judge.conf { FILE *fp = NULL; char buf[BUFFER_SIZE]; host_name[0] = 0; user_name[0] = 0; password[0] = 0; db_name[0] = 0; port_number = 3306; max_running = 3; sleep_time = 3; strcpy(java_xms, "-Xms32m"); strcpy(java_xmx, "-Xmx256m"); strcpy(cc_std,"-std=c99"); strcpy(cc_opt,"-O2"); if(__GNUC__ > 9 || ( __GNUC__ == 9 && __GNUC_MINOR__ >= 3 ) ){ // ubuntu20.04 introduce g++9.3 strcpy(cc_std,"-std=c17"); strcpy(cpp_std,"-std=c++14"); // CCF NOI change settings for NOIP to C++14 on 2021-9-1 }else{ strcpy(cc_std,"-std=c99"); strcpy(cpp_std,"-std=c++11"); } sprintf(buf, "%s/etc/judge.conf", oj_home); fp = fopen("./etc/judge.conf", "re"); if (fp != NULL) { while (fgets(buf, BUFFER_SIZE - 1, fp)) { read_buf(buf, "OJ_HOST_NAME", host_name); read_buf(buf, "OJ_USER_NAME", user_name); read_buf(buf, "OJ_PASSWORD", password); read_buf(buf, "OJ_DB_NAME", db_name); read_int(buf, "OJ_PORT_NUMBER", &port_number); read_int(buf, "OJ_JAVA_TIME_BONUS", &java_time_bonus); read_int(buf, "OJ_JAVA_MEMORY_BONUS", &java_memory_bonus); read_int(buf, "OJ_SIM_ENABLE", &sim_enable); read_buf(buf, "OJ_JAVA_XMS", java_xms); read_buf(buf, "OJ_JAVA_XMX", java_xmx); read_int(buf, "OJ_HTTP_JUDGE", &http_judge); read_buf(buf, "OJ_HTTP_BASEURL", http_baseurl); read_buf(buf, "OJ_HTTP_APIPATH", http_apipath); read_buf(buf, "OJ_HTTP_LOGINPATH", http_loginpath); read_buf(buf, "OJ_HTTP_USERNAME", http_username); read_buf(buf, "OJ_HTTP_PASSWORD", http_password); read_int(buf, "OJ_HTTP_DOWNLOAD", &http_download); read_int(buf, "OJ_OI_MODE", &oi_mode); read_int(buf, "OJ_FULL_DIFF", &full_diff); read_int(buf, "OJ_RAW_TEXT_DIFF", &raw_text_diff); read_int(buf, "OJ_SHM_RUN", &shm_run); read_int(buf, "OJ_USE_MAX_TIME", &use_max_time); read_int(buf, "OJ_TIME_LIMIT_TO_TOTAL", &time_limit_to_total); read_int(buf, "OJ_USE_PTRACE", &use_ptrace); read_int(buf, "OJ_IGNORE_ESOL", &ignore_esol); read_int(buf, "OJ_COMPILE_CHROOT", &compile_chroot); read_int(buf, "OJ_TURBO_MODE", &turbo_mode); read_double(buf, "OJ_CPU_COMPENSATION", &cpu_compensation); read_int(buf, "OJ_PYTHON_FREE", &python_free); read_int(buf, "OJ_COPY_DATA", ©_data); read_int(buf, "OJ_USE_DOCKER",&use_docker); read_buf(buf, "OJ_CC_STD", cc_std); read_buf(buf, "OJ_CPP_STD", cpp_std); read_buf(buf, "OJ_CC_OPT", cc_opt); read_int(buf, "OJ_AUTO_RESULT", &auto_result); } fclose(fp); } // fclose(fp); if(use_docker){ shm_run=0; compile_chroot=0; } if(strcmp(http_username,"IP")==0){ FILE * fjobs = fopen("/etc/hostname","r"); if(1!=fscanf(fjobs, "%s", http_username)) printf("IP/HOSTNAME read fail...\n"); fclose(fjobs); } if(turbo_mode==2) tbname="solution2"; } int isInFile(const char fname[]) { int l = strlen(fname); if (l <= 3 || strcmp(fname + l - 3, ".in") != 0) return 0; else return l - 3; } int inFile(const struct dirent * dp){ //获得测试数据目录中测试数据列表 int l = strlen(dp->d_name); if(DEBUG) printf("file name:%s\n",dp->d_name); if(DEBUG) printf("ext name:%s\n",dp->d_name + l - 3); int ret = isInFile(dp->d_name); if(DEBUG) printf("\t:%d\n",ret); return ret; } void find_next_nonspace(int &c1, int &c2, FILE *&f1, FILE *&f2, int &ret) { // Find the next non-space character or \n. while ((isspace(c1)) || (isspace(c2))) { if (c1 != c2) { if (c2 == EOF) { do { c1 = fgetc(f1); } while (isspace(c1)); continue; } else if (c1 == EOF) { do { c2 = fgetc(f2); } while (isspace(c2)); continue; }else if(ignore_esol){ if (isspace(c1) && isspace(c2)) { while (c2 == '\n' && isspace(c1) && c1 != '\n') c1 = fgetc(f1); while (c1 == '\n' && isspace(c2) && c2 != '\n') c2 = fgetc(f2); } else{ if (DEBUG) printf("%d=%c\t%d=%c", c1, c1, c2, c2); ; ret = OJ_PE; } }else if(!ignore_esol){ if ((c1 == '\r' && c2 == '\n')) { c1 = fgetc(f1); } else if ((c2 == '\r' && c1 == '\n')) { c2 = fgetc(f2); } else{ if (DEBUG) printf("%d=%c\t%d=%c", c1, c1, c2, c2); ; ret = OJ_PE; } } } if (isspace(c1)) { c1 = fgetc(f1); } if (isspace(c2)) { c2 = fgetc(f2); } } } /*** int compare_diff(const char *file1,const char *file2){ char diff[1024]; sprintf(diff,"diff -q -B -b -w --strip-trailing-cr %s %s",file1,file2); int d=system(diff); if (d) return OJ_WA; sprintf(diff,"diff -q -B --strip-trailing-cr %s %s",file1,file2); int p=system(diff); if (p) return OJ_PE; else return OJ_AC; } */ const char *getFileNameFromPath(const char *path) { for (int i = strlen(path); i >= 0; i--) { if (path[i] == '/') return &path[i + 1]; } return path; } void make_diff_out_full(FILE *f1, FILE *f2, int c1, int c2, const char *path,const char * infile,const char * userfile) { execute_cmd("echo '========[%s]========='>>diff.out", getFileNameFromPath(path)); execute_cmd("echo '\\n------test in top 100 lines------'>>diff.out"); execute_cmd("head -100 %s >>diff.out",infile); execute_cmd("echo '\\n------test out top 100 lines-----'>>diff.out"); execute_cmd("head -100 '%s'>>diff.out", path); execute_cmd("echo '\\n------user out top 100 lines-----'>>diff.out"); execute_cmd("head -100 %s >>diff.out",userfile); execute_cmd("echo '\\n------diff out 200 lines-----'>>diff.out"); execute_cmd("diff '%s' %s -y|grep \\||head -200>>diff.out", path,userfile); execute_cmd("echo '\\n=============================='>>diff.out"); } void make_diff_out(FILE *f1, FILE *f2, int c1, int c2, const char *path,const char * userfile ) { execute_cmd("echo '%s\n--\n'>>diff.out", getFileNameFromPath(path)); execute_cmd("echo 'Expected|Yours\n--|--'>>diff.out"); execute_cmd("diff '%s' %s -y|head -100|tr '>/\\' ' ||' >>diff.out", path,userfile); execute_cmd("echo '\n\n'>>diff.out"); } char * str_replace(char * old, const char * search, const char * replace){ int p,r; char *s; char buf[BUFFER_SIZE]; r=strlen(replace); p=strlen(search); while (NULL!=(s=strstr(old,search))){ strcpy(buf,s+p); if(strlen(old)-strlen(s)+strlen(buf)>BUFFER_SIZE) break; strcpy(s,replace); strcpy(s+r-p+1,buf); } return old; } void make_diff_out_simple(FILE *f1, FILE *f2,char * prefix, int c1, int c2, const char *path,const char * userfile ) { char buf[BUFFER_SIZE]; FILE *diff=fopen("diff.out","a+"); fprintf(diff,"%s\n--\n", getFileNameFromPath(path)); fprintf(diff,"|Expected|Yours\n|--|--\n"); int row=0; int need=1; while(!(feof(f1)&&feof(f2))){ row++; fprintf(diff,"|"); if(row==1){ fprintf(diff,"%s",prefix); if(feof(f2)&&strlen(prefix)>0){ fprintf(diff,"|%s\n|",prefix); need=0; } if(isprint(c1))fprintf(diff,"%c",c1); } if(!feof(f1)&&fgets(buf,BUFFER_SIZE-1,f1)){ if(buf[strlen(buf)-1]=='\n') buf[strlen(buf)-1]='\0'; fprintf(diff,"%s",buf); } fprintf(diff,"|"); if(row==1){ if(need)fprintf(diff,"%s",prefix); if(c2=='|') fprintf(diff,"丨"); else if(c2=='[') fprintf(diff,"["); else if(c2==']') fprintf(diff,"]"); else if(c2=='(') fprintf(diff,"("); else if(c2==')') fprintf(diff,")"); else if(isprint(c2))fprintf(diff,"%c",c2); else if(c2=='\n'){ fprintf(diff,"\n||"); } } if(!feof(f2)&&fgets(buf,BUFFER_SIZE-1,f2)){ str_replace(buf,"|","丨"); str_replace(buf,"[","["); str_replace(buf,"]","]"); str_replace(buf,"(","("); str_replace(buf,")",")"); if(buf[strlen(buf)-1]=='\n') buf[strlen(buf)-1]='\0'; fprintf(diff,"%s",buf); } fprintf(diff,"\n"); if(row>=5) break; } fprintf(diff,"\n\n"); fclose(diff); } /* * translated from ZOJ judger r367 * http://code.google.com/p/zoj/source/browse/trunk/judge_client/client/text_checker.cc#25 * 参考zoj的文件流式比较器,有更低的内存占用 */ int compare_zoj(const char *file1, const char *file2,const char * infile,const char * userfile) { int ret = OJ_AC; int c1, c2; char prefix[BUFFER_SIZE]; int preK=0; FILE *f1, *f2; f1 = fopen(file1, "re"); f2 = fopen(file2, "re"); if (!f1 || !f2) { ret = OJ_RE; } else for (;;) { // Find the first non-space character at the beginning of line. // Blank lines are skipped. c1 = fgetc(f1); c2 = fgetc(f2); find_next_nonspace(c1, c2, f1, f2, ret); // Compare the current line. for (;;) { // Read until 2 files return a space or 0 together. while ((!isspace(c1) && c1) || (!isspace(c2) && c2)) { if (c1 == EOF && c2 == EOF) { goto end; } if (c1 == EOF || c2 == EOF) { break; } if (c1 != c2) { // Consecutive non-space characters should be all exactly the ifconfig|grep 'inet'|awk -F: '{printf $2}'|awk '{printf $1}'same ret = OJ_WA; goto end; }else if(preK 0 && (s[L - 1] == '\n' || s[L - 1] == '\r')) s[--L] = 0; } int compare(const char *file1, const char *file2, const char * infile,const char * userfile) { #ifdef ZOJ_COM //compare ported and improved from zoj don't limit file size return compare_zoj(file1, file2,infile,userfile); #endif #ifndef ZOJ_COM //the original compare from the first version of hustoj has file size limit 原始的内存中比较,速度更快但耗用更多内存 //and waste memory FILE *f1, *f2; char *s1, *s2, *p1, *p2; int PEflg; s1 = new char[STD_F_LIM + 512]; s2 = new char[STD_F_LIM + 512]; if (!(f1 = fopen(file1, "re"))) return OJ_AC; for (p1 = s1; EOF != fscanf(f1, "%s", p1);) while (*p1) p1++; fclose(f1); if (!(f2 = fopen(file2, "re"))) return OJ_RE; for (p2 = s2; EOF != fscanf(f2, "%s", p2);) while (*p2) p2++; fclose(f2); if (strcmp(s1, s2) != 0) { // printf("A:%s\nB:%s\n",s1,s2); delete[] s1; delete[] s2; return OJ_WA; } else { f1 = fopen(file1, "re"); f2 = fopen(file2, "re"); PEflg = 0; while (PEflg == 0 && fgets(s1, STD_F_LIM, f1) && fgets(s2, STD_F_LIM, f2)) { delnextline(s1); delnextline(s2); if (strcmp(s1, s2) == 0) continue; else PEflg = 1; } delete[] s1; delete[] s2; fclose(f1); fclose(f2); if (PEflg) return OJ_PE; else return OJ_AC; } #endif } bool check_login() // http模式中检测是否已经登陆 { const char *cmd = " wget --post-data=\"checklogin=1\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\""; int ret = 0; FILE *fjobs = read_cmd_output(cmd, http_baseurl, http_apipath); if(1!=fscanf(fjobs, "%d", &ret)) printf("http login fail.."); pclose(fjobs); return ret; } void login() //http登陆 { if (!check_login()) { const char *cmd = "wget --post-data=\"user_id=%s&password=%s\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\""; FILE *fjobs = read_cmd_output(cmd, http_username, http_password, http_baseurl, http_loginpath); //fscanf(fjobs,"%d",&ret); pclose(fjobs); } } #ifdef _mysql_h /* write result back to database */ void _update_solution_mysql(int solution_id, int result, int time, int memory, int sim, int sim_s_id, double pass_rate) { char sql[BUFFER_SIZE]; char judger[BUFFER_SIZE/10]; mysql_real_escape_string(conn, judger, http_username, strlen(http_username)); if (oi_mode) { sprintf(sql, "UPDATE %s SET result=%d,time=%d,memory=%d,pass_rate=%f,judger='%s',judgetime=now() WHERE solution_id=%d ", tbname, result, time, memory, pass_rate, judger, solution_id); } else { sprintf(sql, "UPDATE %s SET result=%d,time=%d,memory=%d,judger='%s',judgetime=now() WHERE solution_id=%d ", tbname, result, time, memory,judger, solution_id); } // printf("sql= %s\n",sql); if (mysql_real_query(conn, sql, strlen(sql))) { // printf("..update failed! %s\n",mysql_error(conn)); } if (sim) { sprintf(sql, "insert into sim(s_id,sim_s_id,sim) values(%d,%d,%d) on duplicate key update sim_s_id=%d,sim=%d", solution_id, sim_s_id, sim, sim_s_id, sim); // printf("sql= %s\n",sql); if (mysql_real_query(conn, sql, strlen(sql))) { // printf("..update failed! %s\n",mysql_error(conn)); } } } #endif void _update_solution_http(int solution_id, int result, int time, int memory, int sim, int sim_s_id, double pass_rate) { const char *cmd = " wget --post-data=\"update_solution=1&sid=%d&result=%d&time=%d&memory=%d&sim=%d&simid=%d&pass_rate=%f\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\""; FILE *fjobs = read_cmd_output(cmd, solution_id, result, time, memory, sim, sim_s_id, pass_rate, http_baseurl, http_apipath); //fscanf(fjobs,"%d",&ret); pclose(fjobs); } void update_solution(int solution_id, int result, int time, int memory, int sim, int sim_s_id, double pass_rate) { if (result == OJ_TL && memory == 0) result = OJ_ML; if (result == OJ_AC ) result=auto_result; if (http_judge) { _update_solution_http(solution_id, result, time, memory, sim, sim_s_id, pass_rate); } else { #ifdef _mysql_h _update_solution_mysql(solution_id, result, time, memory, sim, sim_s_id, pass_rate); #endif } } /* write compile error message back to database */ #ifdef _mysql_h void _addceinfo_mysql(int solution_id) { char sql[(1 << 16)], *end; char ceinfo[(1 << 16)], *cend; FILE *fp = fopen("ce.txt", "re"); snprintf(sql, (1 << 16) - 1, "DELETE FROM compileinfo WHERE solution_id=%d", solution_id); mysql_real_query(conn, sql, strlen(sql)); cend = ceinfo; while (fgets(cend, 1024, fp)) { cend += strlen(cend); if (cend - ceinfo > 16384) break; } *cend = '\0'; end = sql; strcpy(end, "INSERT INTO compileinfo VALUES("); end += strlen(sql); *end++ = '\''; end += sprintf(end, "%d", solution_id); *end++ = '\''; *end++ = ','; *end++ = '\''; end += mysql_real_escape_string(conn, end, ceinfo, strlen(ceinfo)); *end++ = '\''; *end++ = ')'; *end = 0; // printf("%s\n",ceinfo); if (mysql_real_query(conn, sql, end - sql)) printf("%s\n", mysql_error(conn)); fclose(fp); } #endif // urlencoded function copied from http://www.geekhideout.com/urlcode.shtml /* Converts a hex character to its integer value */ char from_hex(char ch) { return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; } /* Converts an integer value to its hex character*/ char to_hex(char code) { static char hex[] = "0123456789abcdef"; return hex[code & 15]; } /* Returns a url-encoded version of str */ /* IMPORTANT: be sure to free() the returned string after use */ // 用url编码字符串 char *url_encode(char *str) { char *pstr = str, *buf = (char *)malloc(strlen(str) * 3 + 1), *pbuf = buf; while (*pstr) { if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') *pbuf++ = *pstr; else if (*pstr == ' ') *pbuf++ = '+'; else *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15); pstr++; } *pbuf = '\0'; return buf; } void _addceinfo_http(int solution_id) { char ceinfo[(1 << 16)], *cend; char *ceinfo_encode; FILE *fp = fopen("ce.txt", "re"); cend = ceinfo; while (fgets(cend, 1024, fp)) { cend += strlen(cend); if (cend - ceinfo > 16384) break; } *cend='\0'; fclose(fp); ceinfo_encode = url_encode(ceinfo); FILE *ce = fopen("ce.post", "we"); fprintf(ce, "addceinfo=1&sid=%d&ceinfo=%s", solution_id, ceinfo_encode); fclose(ce); free(ceinfo_encode); const char *cmd = " wget --post-file=\"ce.post\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\""; FILE *fjobs = read_cmd_output(cmd, http_baseurl, http_apipath); //fscanf(fjobs,"%d",&ret); pclose(fjobs); } void addceinfo(int solution_id) { if (http_judge) { _addceinfo_http(solution_id); } else { #ifdef _mysql_h _addceinfo_mysql(solution_id); #endif } } /* write runtime error message back to database */ #ifdef _mysql_h void _addreinfo_mysql(int solution_id, const char *filename) { char sql[(1 << 16)], *end; char reinfo[(1 << 16)], *rend; FILE *fp = fopen(filename, "re"); snprintf(sql, (1 << 16) - 1, "DELETE FROM runtimeinfo WHERE solution_id=%d", solution_id); mysql_real_query(conn, sql, strlen(sql)); rend = reinfo; while (fgets(rend, 1024, fp)) { rend += strlen(rend); if (rend - reinfo > 16384) break; } *rend = '\0'; end = sql; strcpy(end, "INSERT INTO runtimeinfo VALUES("); end += strlen(sql); *end++ = '\''; end += sprintf(end, "%d", solution_id); *end++ = '\''; *end++ = ','; *end++ = '\''; end += mysql_real_escape_string(conn, end, reinfo, strlen(reinfo)); *end++ = '\''; *end++ = ')'; *end = 0; // printf("%s\n",ceinfo); if (mysql_real_query(conn, sql, end - sql)) printf("%s\n", mysql_error(conn)); fclose(fp); } #endif void _addreinfo_http(int solution_id, const char *filename) { char reinfo[(1 << 16)], *rend; char *reinfo_encode; FILE *fp = fopen(filename, "re"); rend = reinfo; while (fgets(rend, 1024, fp)) { rend += strlen(rend); if (rend - reinfo > 16384) break; } *rend = '\0'; fclose(fp); reinfo_encode = url_encode(reinfo); FILE *re = fopen("re.post", "we"); fprintf(re, "addreinfo=1&sid=%d&reinfo=%s", solution_id, reinfo_encode); fclose(re); free(reinfo_encode); const char *cmd = " wget --post-file=\"re.post\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\""; FILE *fjobs = read_cmd_output(cmd, http_baseurl, http_apipath); //fscanf(fjobs,"%d",&ret); pclose(fjobs); } void addreinfo(int solution_id) { if (http_judge) { _addreinfo_http(solution_id, "error.out"); } else { #ifdef _mysql_h _addreinfo_mysql(solution_id, "error.out"); #endif } } void adddiffinfo(int solution_id) { if (http_judge) { _addreinfo_http(solution_id, "diff.out"); } else { #ifdef _mysql_h _addreinfo_mysql(solution_id, "diff.out"); #endif } } void addcustomout(int solution_id) { if (http_judge) { _addreinfo_http(solution_id, "user.out"); } else { #ifdef _mysql_h _addreinfo_mysql(solution_id, "user.out"); #endif } } #ifdef _mysql_h void _update_user_mysql(char *user_id) { char sql[BUFFER_SIZE]; sprintf(sql, "UPDATE `users` SET `solved`=(SELECT count(DISTINCT `problem_id`) FROM `solution` WHERE `user_id`=\'%s\' AND `result`=4) WHERE `user_id`=\'%s\'", user_id, user_id); if (mysql_real_query(conn, sql, strlen(sql))) write_log(mysql_error(conn)); sprintf(sql, "UPDATE `users` SET `submit`=(SELECT count(*) FROM `solution` WHERE `user_id`=\'%s\' and problem_id>0) WHERE `user_id`=\'%s\'", user_id, user_id); if (mysql_real_query(conn, sql, strlen(sql))) write_log(mysql_error(conn)); } #endif void _update_user_http(char *user_id) { const char *cmd = " wget --post-data=\"updateuser=1&user_id=%s\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\""; FILE *fjobs = read_cmd_output(cmd, user_id, http_baseurl, http_apipath); //fscanf(fjobs,"%d",&ret); pclose(fjobs); } void update_user(char *user_id) { if (http_judge) { _update_user_http(user_id); } else { #ifdef _mysql_h _update_user_mysql(user_id); #endif } } void _update_problem_http(int pid,int cid) { const char * cmd = " wget --post-data=\"updateproblem=1&pid=%d\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\""; FILE * fjobs = read_cmd_output(cmd, pid, http_baseurl, http_apipath); //fscanf(fjobs,"%d",&ret); pclose(fjobs); } #ifdef _mysql_h void _update_problem_mysql(int p_id,int cid) { char sql[BUFFER_SIZE]; if(cid>0){ sprintf(sql, "UPDATE `contest_problem` SET `c_accepted`=(SELECT count(*) FROM `solution` WHERE `problem_id`=%d AND `result`=4 and contest_id=%d) WHERE `problem_id`=%d and contest_id=%d", p_id,cid, p_id,cid); printf("sql:[%s]\n",sql); if (mysql_real_query(conn, sql, strlen(sql))) write_log(mysql_error(conn)); } sprintf(sql, "UPDATE `problem` SET `accepted`=(SELECT count(*) FROM `solution` WHERE `problem_id`=%d AND `result`=4) WHERE `problem_id`=%d", p_id, p_id); printf("sql:[%s]\n",sql); if (mysql_real_query(conn, sql, strlen(sql))) write_log(mysql_error(conn)); if(cid>0){ sprintf(sql, "UPDATE `contest_problem` SET `c_submit`=(SELECT count(*) FROM `solution` WHERE `problem_id`=%d AND contest_id=%d) WHERE `problem_id`=%d and contest_id=%d", p_id,cid, p_id,cid); if (mysql_real_query(conn, sql, strlen(sql))) write_log(mysql_error(conn)); } /* sprintf(sql, "UPDATE `problem` SET `submit`=(SELECT count(*) FROM `solution` WHERE `problem_id`=%d) WHERE `problem_id`=%d", p_id, p_id); if (mysql_real_query(conn, sql, strlen(sql))) write_log(mysql_error(conn)); */ } #endif void update_problem(int pid,int cid) { if (http_judge) { _update_problem_http(pid,cid); } else { #ifdef _mysql_h _update_problem_mysql(pid,cid); #endif } } void umount(char *work_dir) //清理可能存在的热加载目录 { if(chdir(work_dir)) exit(-1); execute_cmd("/bin/umount -l %s/usr 2>/dev/null", work_dir); if(strlen(work_dir)>0){ execute_cmd("/bin/umount -l %s/proc 2>/dev/null", work_dir); } execute_cmd("/bin/umount -l %s/dev 2>/dev/null", work_dir); execute_cmd("/bin/umount -l %s/usr 2>/dev/null", work_dir); execute_cmd("/bin/umount -l usr dev"); execute_cmd("/bin/umount -l lib lib64"); execute_cmd("/bin/rmdir %s/* ", work_dir); execute_cmd("/bin/rmdir %s/log/* ", work_dir); } int compile(int lang, char *work_dir) { if( lang == LANG_PYTHON || lang == LANG_JS ) return 0; // python / js don't compile int pid; char fmax_errors[BUFFER_SIZE]; if(__GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 8 ) ){ sprintf(fmax_errors,"-fmax-errors=10"); }else{ sprintf(fmax_errors,"-Wformat"); } const char *CP_C[] = {"gcc", "-fno-asm", cc_opt , fmax_errors , cc_std , "-Wall", "--static", "-DONLINE_JUDGE", "-o", "Main", "Main.c", "-lm", NULL}; // 看起来别扭,但是gcc非要-lm选项在Main.c后面才认 const char *CP_X[] = {"g++", "-fno-asm", cc_opt , fmax_errors , cpp_std , "-Wall", "-lm", "--static", "-DONLINE_JUDGE", "-o", "Main", "Main.cc", NULL}; const char *CP_P[] = {"fpc", "Main.pas", "-Cs32000000", "-Sh", "-O2", "-Co", "-Ct", "-Ci", NULL}; // const char * CP_J[] = { "javac", "-J-Xms32m", "-J-Xmx256m","-encoding","UTF-8", "Main.java",NULL }; const char *CP_R[] = {"ruby", "-c", "Main.rb", NULL}; const char *CP_B[] = {"chmod", "+rx", "Main.sh", NULL}; const char * CP_Y[] = { "python3", "-c", "import py_compile; py_compile.compile(r'Main.py')", NULL }; const char *CP_PH[] = {"php", "-l", "Main.php", NULL}; const char *CP_PL[] = {"perl", "-c", "Main.pl", NULL}; const char *CP_CS[] = {"mcs","-codepage:utf8", "-warn:0", "Main.cs", NULL}; const char *CP_OC[] = {"gcc", "-o", "Main", "Main.m", "-fconstant-string-class=NSConstantString", "-I", "/usr/include/GNUstep/", "-L", "/usr/lib/GNUstep/Libraries/", "-lobjc", "-lgnustep-base", NULL}; const char *CP_BS[] = {"fbc", "-lang", "qb", "Main.bas", NULL}; const char *CP_CLANG[] = {"clang", "Main.c", "-o", "Main", "-ferror-limit=10", "-fno-asm", "-Wall", "-lm", "--static", "-std=c99", "-DONLINE_JUDGE", NULL}; const char *CP_CLANG_CPP[] = {"clang++", "Main.cc", "-o", "Main", "-ferror-limit=10", "-fno-asm", "-Wall", "-lm", "--static", "-std=c++0x", "-DONLINE_JUDGE", NULL}; const char *CP_LUA[] = {"luac", "-o", "Main", "Main.lua", NULL}; //const char * CP_JS[] = { "js24","-c", "Main.js", NULL }; const char *CP_GO[] = {"go", "build", "-o", "Main", "Main.go", NULL}; const char *CP_FORTRAN[] = {"f95", "-static", "-o", "Main", "Main.f95", NULL}; const char *CP_COBOL[] = {"cobc","-x", "-static", "-o", "Main", "Main.cob", NULL}; const char *CP_SB3[] = {"scratch-run","--check", "Main.sb3", NULL}; char * const envp[]={(char * const )"PYTHONIOENCODING=utf-8", (char * const )"USER=judge", (char * const )"GOCACHE=/tmp", (char * const )"LANG=zh_CN.UTF-8", (char * const )"LANGUAGE=zh_CN.UTF-8", (char * const )"LC_ALL=zh_CN.utf-8",NULL}; char javac_buf[7][32]; char *CP_J[7]; for (int i = 0; i < 7; i++) CP_J[i] = javac_buf[i]; sprintf(CP_J[0], "javac"); sprintf(CP_J[1], "-J%s", java_xms); sprintf(CP_J[2], "-J%s", java_xmx); sprintf(CP_J[3], "-encoding"); sprintf(CP_J[4], "UTF-8"); sprintf(CP_J[5], "Main.java"); CP_J[6] = (char *)NULL; pid = fork(); if (pid == 0) { struct rlimit LIM; int cpu = 50; if (lang == 3) cpu = 60; LIM.rlim_max = cpu; LIM.rlim_cur = cpu; setrlimit(RLIMIT_CPU, &LIM); alarm(0); if(cpu>0)alarm(cpu);else alarm(1); LIM.rlim_max = 500 * STD_MB; LIM.rlim_cur = 500 * STD_MB; setrlimit(RLIMIT_FSIZE, &LIM); if (lang == LANG_PASCAL || lang == LANG_JAVA || lang == LANG_GO || lang == LANG_R || lang == LANG_SB3 ) { #ifdef __mips__ LIM.rlim_max = STD_MB << 12; LIM.rlim_cur = STD_MB << 12; #endif #ifdef __arm__ LIM.rlim_max = STD_MB << 11; LIM.rlim_cur = STD_MB << 11; #endif #ifdef __i386__ LIM.rlim_max = STD_MB << 11; LIM.rlim_cur = STD_MB << 11; #endif #ifdef __x86_64__ LIM.rlim_max = STD_MB << 12; LIM.rlim_cur = STD_MB << 12; #endif } else { LIM.rlim_max = STD_MB << 11 ; LIM.rlim_cur = STD_MB << 11; } if (lang != 3) setrlimit(RLIMIT_AS, &LIM); if (lang != 2 && lang != 11) { stderr=freopen("ce.txt", "w", stderr); //freopen("/dev/null", "w", stdout); } else { stdout=freopen("ce.txt", "w", stdout); } execute_cmd("/bin/chown judge %s ", work_dir); execute_cmd("/bin/chmod 750 %s ", work_dir); if (compile_chroot && lang != LANG_JAVA && lang != LANG_CSHARP && lang != LANG_PYTHON && lang != LANG_FREEBASIC && lang != LANG_BASH && lang != LANG_R ) { if (access("usr", F_OK ) == -1){ execute_cmd("mkdir -p root/.cache/go-build usr etc/alternatives proc tmp dev"); execute_cmd("chown judge -R root tmp "); execute_cmd("mount -o bind /usr usr"); execute_cmd("mount -o remount,ro usr"); execute_cmd("ln -s usr/bin bin"); execute_cmd("ln -s usr/lib lib"); execute_cmd("ln -s usr/lib32 lib32"); execute_cmd("ln -s usr/libx32 libx32"); #ifndef __i386__ execute_cmd("ln -s usr/lib64 lib64"); #endif execute_cmd("cp /etc/alternatives/* etc/alternatives"); execute_cmd("cp /etc/fpc* etc/"); execute_cmd("mount -o bind /proc proc"); if (lang > 2 && lang != 6 && lang != 10 && lang != 13 && lang != 14 ) { execute_cmd("mount -o bind /dev dev"); execute_cmd("mount -o remount,ro dev"); } //execute_cmd("mount -o remount,ro proc"); } if(chroot(work_dir)) printf("warning chroot fail!\n"); } while (setgid(1536) != 0) sleep(1); while (setuid(1536) != 0) sleep(1); while (setresuid(1536, 1536, 1536) != 0) sleep(1); switch (lang) { case LANG_C: execvp(CP_C[0], (char *const *)CP_C); break; case LANG_CPP : execvp(CP_X[0], (char *const *)CP_X); break; case LANG_PASCAL : execvp(CP_P[0], (char *const *)CP_P); break; case LANG_JAVA: execvp(CP_J[0], (char *const *)CP_J); break; case LANG_RUBY : execvp(CP_R[0], (char *const *)CP_R); break; case LANG_BASH : execvp(CP_B[0], (char *const *)CP_B); break; case LANG_PYTHON : execvp(CP_Y[0], (char * const *) CP_Y); break; case LANG_PHP : execvp(CP_PH[0], (char *const *)CP_PH); break; case LANG_PERL : execvp(CP_PL[0], (char *const *)CP_PL); break; case LANG_CSHARP : execvp(CP_CS[0], (char *const *)CP_CS); break; case LANG_OBJC : execvp(CP_OC[0], (char *const *)CP_OC); break; case LANG_FREEBASIC : execvp(CP_BS[0], (char *const *)CP_BS); break; case LANG_CLANG: execvp(CP_CLANG[0], (char *const *)CP_CLANG); break; case LANG_CLANGPP: execvp(CP_CLANG_CPP[0], (char *const *)CP_CLANG_CPP); break; case LANG_LUA : execvp(CP_LUA[0], (char *const *)CP_LUA); break; //case 16: // execvp(CP_JS[0], (char * const *) CP_JS); // break; case LANG_GO : execvpe(CP_GO[0], (char *const *)CP_GO,envp); break; case LANG_FORTRAN : execvp(CP_FORTRAN[0], (char *const *)CP_FORTRAN); break; case LANG_COBOL: execvp(CP_COBOL[0], (char *const *)CP_COBOL); break; case LANG_SB3: execvp(CP_SB3[0], (char *const *)CP_SB3); break; default: printf("nothing to do!\n"); } if (DEBUG) printf("compile end!\n"); //exit(!system("cat ce.txt")); exit(0); } else { int status = 0; waitpid(pid, &status, 0); if (lang > 3 && lang < 7) status = get_file_size("ce.txt"); if (DEBUG) printf("status=%d\n", status); execute_cmd("/bin/umount -l bin usr lib lib64 etc/alternatives dev 2>/dev/null"); //execute_cmd("/bin/umount -r %s/* 2>/dev/null", work_dir); umount(work_dir); return status; } } /* int read_proc_statm(int pid){ FILE * pf; char fn[4096]; int ret; sprintf(fn,"/proc/%d/statm",pid); pf=fopen(fn,"r"); fscanf(pf,"%d",&ret); fclose(pf); return ret; } */ int get_proc_status(int pid, const char *mark) { FILE *pf; char fn[BUFFER_SIZE], buf[BUFFER_SIZE]; int ret = 0; sprintf(fn, "/proc/%d/status", pid); pf = fopen(fn, "re"); int m = strlen(mark); while (pf && fgets(buf, BUFFER_SIZE - 1, pf)) { buf[strlen(buf) - 1] = 0; if (strncmp(buf, mark, m) == 0) { if(1!=sscanf(buf + m + 1, "%d", &ret)) printf("proc read fail\n"); } } if (pf) fclose(pf); return ret; } #ifdef _mysql_h int init_mysql_conn() //连接数据库 { conn = mysql_init(NULL); //mysql_real_connect(conn,host_name,user_name,password,db_name,port_number,0,0); const char timeout = 30; mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); if (!mysql_real_connect(conn, host_name, user_name, password, db_name, port_number, 0, 0)) { write_log("%s", mysql_error(conn)); return 0; } const char *utf8sql = "set names utf8"; if (mysql_real_query(conn, utf8sql, strlen(utf8sql))) { write_log("%s", mysql_error(conn)); return 0; } return 1; } int check_mysql_conn(){ MYSQL_RES *res; const char * sql="select 1"; while(mysql_real_query(conn,sql,strlen(sql))){ if(DEBUG){ printf("..update failed! %s\n",mysql_error(conn)); write_log("\n.......Mysql time out !---- retry............\n"); } mysql_close(conn); sleep(1); init_mysql_conn(); } res = mysql_store_result(conn); mysql_free_result(res); return 0; } #endif #ifdef _mysql_h void _get_solution_mysql(int solution_id, char *work_dir, int lang) { char sql[BUFFER_SIZE], src_pth[BUFFER_SIZE]; // get the source code MYSQL_RES *res; MYSQL_ROW row; sprintf(sql, "SELECT source FROM source_code WHERE solution_id=%d", solution_id); mysql_real_query(conn, sql, strlen(sql)); res = mysql_store_result(conn); // create the src file if (res != NULL) { row = mysql_fetch_row(res); if(row != NULL) { sprintf(src_pth, "Main.%s", lang_ext[lang]); if (DEBUG) printf("Main=%s", src_pth); FILE *fp_src = fopen(src_pth, "we"); fprintf(fp_src, "%s", row[0]); mysql_free_result(res); // free the memory res = NULL; row = NULL; fclose(fp_src); } } } #endif void _get_solution_http(int solution_id, char *work_dir, int lang) { char src_pth[BUFFER_SIZE]; // create the src file sprintf(src_pth, "Main.%s", lang_ext[lang]); if (DEBUG) printf("Main=%s", src_pth); //login(); const char *cmd2 = "wget --post-data=\"getsolution=1&sid=%d\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O %s \"%s%s\""; FILE *pout = read_cmd_output(cmd2, solution_id, src_pth, http_baseurl, http_apipath); pclose(pout); } void get_solution(int solution_id, char *work_dir, int lang,int p_id) { char src_pth[BUFFER_SIZE]; sprintf(src_pth, "Main.%s", lang_ext[lang]); if (http_judge) { _get_solution_http(solution_id, work_dir, lang); } else { #ifdef _mysql_h _get_solution_mysql(solution_id, work_dir, lang); #endif } if(lang == LANG_PYTHON ){ // 从源码中搜索python2字样,失败的结果非零默认python3,成功的结果为0是python2 py2 = execute_cmd("/bin/grep 'python2' %s/Main.py > /dev/null", work_dir); execute_cmd("sed -i 's/import.*os//g' %s/%s", work_dir, src_pth); } if(lang == LANG_SB3 ){ execute_cmd("cp %s/../data/%d/sb3/%d.sb3 %s", work_dir,p_id,solution_id, src_pth); } execute_cmd("chown judge %s/%s", work_dir, src_pth); } #ifdef _mysql_h void _get_custominput_mysql(int solution_id, char *work_dir) { char sql[BUFFER_SIZE], src_pth[BUFFER_SIZE]; // get the source code printf("geting custom input\n"); MYSQL_RES *res; MYSQL_ROW row; sprintf(sql, "SELECT input_text FROM custominput WHERE solution_id=%d", solution_id); mysql_real_query(conn, sql, strlen(sql)); res = mysql_store_result(conn); row = mysql_fetch_row(res); if (row != NULL) { // create the src file sprintf(src_pth, "data.in"); FILE *fp_src = fopen(src_pth, "w"); fprintf(fp_src, "%s", row[0]); fclose(fp_src); sprintf(sql, "DELETE FROM custominput WHERE solution_id=%d", solution_id); mysql_real_query(conn, sql, strlen(sql)); } if (res != NULL) { printf("no custom input\n"); mysql_free_result(res); // free the memory res = NULL; } } #endif void _get_custominput_http(int solution_id, char *work_dir) { char src_pth[BUFFER_SIZE]; // create the src file sprintf(src_pth, "data.in"); //login(); const char *cmd2 = "wget --post-data=\"getcustominput=1&sid=%d\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O %s \"%s%s\""; FILE *pout = read_cmd_output(cmd2, solution_id, src_pth, http_baseurl, http_apipath); pclose(pout); } void get_custominput(int solution_id, char *work_dir) { if (http_judge) { _get_custominput_http(solution_id, work_dir); } else { #ifdef _mysql_h _get_custominput_mysql(solution_id, work_dir); #endif } } #ifdef _mysql_h void _get_solution_info_mysql(int solution_id, int & p_id, char * user_id, int & lang,int &cid) { MYSQL_RES *res; MYSQL_ROW row; char sql[BUFFER_SIZE]; // get the problem id and user id from Table:solution if (turbo_mode == 2) { sprintf(sql, "insert into solution2 select * FROM solution where solution_id=%d", solution_id); //printf("%s\n",sql); mysql_real_query(conn, sql, strlen(sql)); sprintf(sql, "SELECT problem_id, user_id, language,contest_id FROM solution2 where solution_id=%d", solution_id); //printf("%s\n",sql); } else { sprintf(sql, "SELECT problem_id, user_id, language,contest_id FROM solution where solution_id=%d", solution_id); } //printf("%s\n",sql); mysql_real_query(conn, sql, strlen(sql)); res = mysql_store_result(conn); row = mysql_fetch_row(res); p_id = atoi(row[0]); strcpy(user_id, row[1]); lang = atoi(row[2]); if(row[3]==NULL) cid=0; else cid = atoi(row[3]); printf("cid:%d\n",cid); if(res!=NULL) { mysql_free_result(res); // free the memory res=NULL; } } #endif void _get_solution_info_http(int solution_id, int & p_id, char * user_id, int & lang,int & cid) { login(); const char *cmd = "wget --post-data=\"getsolutioninfo=1&sid=%d\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\""; FILE *pout = read_cmd_output(cmd, solution_id, http_baseurl, http_apipath); if(1!=fscanf(pout, "%d", &p_id)) printf("http problem_id read fail...\n"); if(1!=fscanf(pout, "%s", user_id)) printf("http user_id read fail ... \n") ; if(1!=fscanf(pout, "%d", &lang)) printf("http language read fail ... \n") ; if(1!=fscanf(pout, "%d", &cid)) printf("http contest_id read fail ... \n") ; pclose(pout); } void get_solution_info(int solution_id, int & p_id, char * user_id, int & lang,int & cid) { if (http_judge) { _get_solution_info_http(solution_id, p_id, user_id, lang,cid); } else { #ifdef _mysql_h _get_solution_info_mysql(solution_id, p_id, user_id, lang,cid); #endif } } #ifdef _mysql_h void _get_problem_info_mysql(int p_id, double &time_lmt, int &mem_lmt, int &spj) { // get the problem info from Table:problem char sql[BUFFER_SIZE]; MYSQL_RES *res; MYSQL_ROW row; sprintf(sql, "SELECT time_limit,memory_limit,spj FROM problem where problem_id=%d", p_id); mysql_real_query(conn, sql, strlen(sql)); res = mysql_store_result(conn); row = mysql_fetch_row(res); time_lmt = atof(row[0]); mem_lmt = atoi(row[1]); spj = atoi(row[2]); if (res != NULL) { mysql_free_result(res); // free the memory res = NULL; } } #endif void _get_problem_info_http(int p_id, double &time_lmt, int &mem_lmt, int &spj) { //login(); const char *cmd = "wget --post-data=\"getprobleminfo=1&pid=%d\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\""; FILE *pout = read_cmd_output(cmd, p_id, http_baseurl, http_apipath); if(1!=fscanf(pout, "%lf", &time_lmt)) printf("http read time_limit fail...\n"); if(1!=fscanf(pout, "%d", &mem_lmt) ) printf("http read memory_limit fail...\n"); if(1!=fscanf(pout, "%d", &spj) ) printf("http read special judge fail...\n"); pclose(pout); if(DEBUG) printf("time_lmt:%g\n",time_lmt); } void get_problem_info(int p_id, double &time_lmt, int &mem_lmt, int &spj) { if (http_judge) { _get_problem_info_http(p_id, time_lmt, mem_lmt, spj); } else { #ifdef _mysql_h _get_problem_info_mysql(p_id, time_lmt, mem_lmt, spj); #endif } if (time_lmt <= 0) time_lmt = 1; } char *escape(char s[], char t[]) { int i, j; for (i = j = 0; t[i] != '\0'; ++i) { if (t[i] == '\'') { s[j++] = '\''; s[j++] = '\\'; s[j++] = '\''; s[j++] = '\''; continue; } else { s[j++] = t[i]; } } s[j] = '\0'; return s; } void prepare_files(char *filename, int namelen, char *infile, int &p_id, char *work_dir, char *outfile, char *userfile, int runner_id,int lang ) { // printf("ACflg=%d %d check a file!\n",ACflg,solution_id); char fname0[BUFFER_SIZE]; char fname[BUFFER_SIZE]; strncpy(fname0, filename, namelen); fname0[namelen] = 0; escape(fname, fname0); //printf("%s\n%s\n",fname0,fname); sprintf(infile, "%s/data/%d/%s.in", oj_home, p_id, fname); char noip_file_name[BUFFER_SIZE]; sprintf(noip_file_name,"%s/data/%d/input.name",oj_home,p_id); if(DEBUG) printf("NOIP filename:%s\n",noip_file_name); if (access(noip_file_name, R_OK ) != -1){ if(DEBUG) printf("NOIP filename:%s\n",noip_file_name); FILE * fpname=fopen(noip_file_name,"r"); if(fscanf(fpname,"%s",noip_file_name)){ execute_cmd("/bin/cp '%s' %s/%s", infile, work_dir,basename(noip_file_name)); // 如果存在input.name则复制测试数据 execute_cmd("/usr/bin/chown judge %s/%s", work_dir,basename(noip_file_name)); // 修改属主 if(DEBUG) printf("NOIP filename:%s\n",noip_file_name); } fclose(fpname); }else{ if(copy_data||lang == LANG_R) execute_cmd("/bin/cp '%s' %s/data.in", infile, work_dir); // 如果开启了COPY_DATA则复制测试数据 } execute_cmd("/bin/cp %s/data/%d/*.dic %s/ 2>/dev/null", oj_home, p_id, work_dir); execute_cmd("chown judge %s/*.dic ", work_dir); sprintf(outfile, "%s/data/%d/%s.out", oj_home, p_id, fname0); sprintf(noip_file_name,"%s/data/%d/output.name",oj_home,p_id); if(DEBUG) printf("NOIP filename:%s\n",noip_file_name); if (access(noip_file_name, R_OK ) != -1){ FILE * fpname=fopen(noip_file_name,"r"); if(fscanf(fpname,"%s",noip_file_name)){ if(DEBUG) printf("NOIP filename:%s\n",noip_file_name); if(!strstr("noip_file_name","//")){ sprintf(userfile, "%s/run%d/%s", oj_home, runner_id,basename(noip_file_name)); execute_cmd("rm %s",userfile); } } fclose(fpname); }else{ sprintf(userfile, "%s/run%d/user.out", oj_home, runner_id); execute_cmd("rm %s",userfile); } } // 以下 copy_开头的函数均为准备相应语言的chroot环境,复制动态链接库等,如果使用的系统不是Ubuntu则路径有所区别,可以用ldd/find查看实际位置。 void copy_shell_runtime(char *work_dir) { execute_cmd("/bin/mkdir %s/lib", work_dir); execute_cmd("/bin/mkdir %s/lib64", work_dir); execute_cmd("/bin/mkdir %s/bin", work_dir); #ifdef __mips__ execute_cmd("/bin/cp -a /lib/mips64el-linux-gnuabi64/ %s/lib/mips64el-linux-gnuabi64",work_dir); execute_cmd("mkdir -p %s/lib/mips64el-linux-gnuabi64/",work_dir); execute_cmd("/bin/cp -a /lib64/ld.so.1 %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib/mips64el-linux-gnuabi64/libdl.so.2 %s/lib/mips64el-linux-gnuabi64", work_dir); execute_cmd("/bin/cp -a /lib/mips64el-linux-gnuabi64/libutil.so.1 %s/lib/mips64el-linux-gnuabi64", work_dir); execute_cmd("/bin/cp -a /lib/mips64el-linux-gnuabi64/libz.so.1 %s/lib/mips64el-linux-gnuabi64", work_dir); execute_cmd("/bin/cp -a /lib/mips64el-linux-gnuabi64/libm.so.6 %s/lib/mips64el-linux-gnuabi64", work_dir); execute_cmd("/bin/cp -a /lib/mips64el-linux-gnuabi64/libc.so.6 %s/lib/mips64el-linux-gnuabi64", work_dir); execute_cmd("/bin/cp -a /lib/mips64el-linux-gnuabi64/libtinfo.so.5 %s/lib/mips64el-linux-gnuabi64", work_dir); execute_cmd("/bin/cp -a /lib/mips64el-linux-gnuabi64/ld-2.24.so %s/lib/mips64el-linux-gnuabi64", work_dir); execute_cmd("/bin/cp -a /lib/mips64el-linux-gnuabi64/libc-2.24.so %s/lib/mips64el-linux-gnuabi64", work_dir); execute_cmd("/bin/cp -a /lib64/libc.so.6 %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libtinfo.so.6 %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/ld-2.27.so %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libc-2.27.so %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libdl-2.27.so %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libtinfo.so.6.1 %s/lib64/", work_dir); execute_cmd("cp /lib/mips64el-linux-gnuabi64/libpthread.so.0 %s/lib/mips64el-linux-gnuabi64/",work_dir); execute_cmd("/bin/cp -a /bin/bash %s/bin/", work_dir); #endif #ifdef __i386 execute_cmd("/bin/cp /lib/ld-linux* %s/lib/", work_dir); execute_cmd("/bin/cp -a /lib/i386-linux-gnu/ %s/lib/", work_dir); // execute_cmd("/bin/cp -a /usr/lib/i386-linux-gnu %s/lib/", work_dir); #endif #ifdef __x86_64__ execute_cmd("mount -o bind /lib %s/lib", work_dir); execute_cmd("mount -o bind /lib64 %s/lib64", work_dir); #endif // execute_cmd("/bin/cp /lib32 %s/", work_dir); execute_cmd("/bin/cp /bin/busybox %s/bin/", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/sh", work_dir); execute_cmd("/bin/cp /bin/bash %s/bin/bash", work_dir); } void copy_objc_runtime(char *work_dir) { copy_shell_runtime(work_dir); execute_cmd("/bin/mkdir -p %s/proc", work_dir); execute_cmd("/bin/mount -o bind /proc %s/proc", work_dir); execute_cmd("/bin/mkdir -p %s/lib/", work_dir); execute_cmd( "/bin/cp -aL /lib/libdbus-1.so.3 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /lib/libgcc_s.so.1 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /lib/libgcrypt.so.11 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /lib/libgpg-error.so.0 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /lib/libz.so.1 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /lib/tls/i686/cmov/libc.so.6 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /lib/tls/i686/cmov/libdl.so.2 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /lib/tls/i686/cmov/libm.so.6 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /lib/tls/i686/cmov/libnsl.so.1 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /lib/tls/i686/cmov/libpthread.so.0 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /lib/tls/i686/cmov/librt.so.1 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /usr/lib/libavahi-client.so.3 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /usr/lib/libavahi-common.so.3 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /usr/lib/libdns_sd.so.1 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /usr/lib/libffi.so.5 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /usr/lib/libgnustep-base.so.1.19 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /usr/lib/libgnutls.so.26 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /usr/lib/libobjc.so.2 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /usr/lib/libtasn1.so.3 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /usr/lib/libxml2.so.2 %s/lib/ ", work_dir); execute_cmd( "/bin/cp -aL /usr/lib/libxslt.so.1 %s/lib/ ", work_dir); } void copy_bash_runtime(char *work_dir) { //char cmd[BUFFER_SIZE]; //const char * ruby_run="/usr/bin/ruby"; copy_shell_runtime(work_dir); execute_cmd("/bin/cp `which bc` %s/bin/", work_dir); execute_cmd("busybox dos2unix Main.sh", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/grep", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/awk", work_dir); execute_cmd("/bin/cp /bin/sed %s/bin/sed", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/cut", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/sort", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/join", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/wc", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/tr", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/dc", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/dd", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/cat", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/tail", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/head", work_dir); execute_cmd("/bin/ln -s /bin/busybox %s/bin/xargs", work_dir); execute_cmd("chmod +rx %s/Main.sh", work_dir); } void copy_ruby_runtime(char *work_dir) { copy_shell_runtime(work_dir); execute_cmd("mkdir -p %s/usr/bin", work_dir); execute_cmd("mkdir -p %s/usr/lib", work_dir); execute_cmd("mkdir -p %s/usr/lib64", work_dir); execute_cmd("cp -a /usr/lib/libruby* %s/usr/lib/", work_dir); execute_cmd("cp -a /usr/lib/ruby* %s/usr/lib/", work_dir); execute_cmd("cp -a /usr/lib64/ruby* %s/usr/lib64/", work_dir); execute_cmd("cp -a /usr/lib64/libruby* %s/usr/lib64/", work_dir); execute_cmd("cp -a /usr/bin/ruby* %s/usr/bin", work_dir); #ifdef __x86_64__ execute_cmd("/bin/cp -a /usr/lib/x86_64-linux-gnu/libruby* %s/usr/lib/", work_dir); execute_cmd("/bin/cp -a /usr/lib/x86_64-linux-gnu/libgmp* %s/usr/lib/", work_dir); #endif } void copy_guile_runtime(char *work_dir) { copy_shell_runtime(work_dir); execute_cmd("/bin/mkdir -p %s/proc", work_dir); execute_cmd("/bin/mount -o bind /proc %s/proc", work_dir); execute_cmd("/bin/mkdir -p %s/usr/bin", work_dir); execute_cmd("/bin/mkdir -p %s/usr/lib", work_dir); execute_cmd("/bin/mkdir -p %s/usr/share", work_dir); execute_cmd("/bin/cp -a /usr/share/guile %s/usr/share/", work_dir); execute_cmd("/bin/cp /usr/lib/libguile* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/libgc* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/i386-linux-gnu/libffi* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/i386-linux-gnu/libunistring* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/*/libgmp* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/libgmp* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/*/libltdl* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/libltdl* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/bin/guile* %s/usr/bin", work_dir); #ifdef __x86_64__ execute_cmd("/bin/cp -a /usr/lib/x86_64-linux-gnu/libguile* %s/usr/lib/", work_dir); execute_cmd("/bin/cp -a /usr/lib/x86_64-linux-gnu/libgc* %s/usr/lib/", work_dir); execute_cmd("/bin/cp -a /usr/lib/x86_64-linux-gnu/libffi* %s/usr/lib/", work_dir); execute_cmd("/bin/cp -a /usr/lib/x86_64-linux-gnu/libunistring* %s/usr/lib/", work_dir); #endif } void copy_python_runtime(char *work_dir) { copy_shell_runtime(work_dir); execute_cmd("mkdir -p %s/usr/include", work_dir); execute_cmd("mkdir -p %s/dev", work_dir); execute_cmd("mkdir -p %s/usr/bin", work_dir); execute_cmd("mkdir -p %s/usr/lib", work_dir); execute_cmd("mkdir -p %s/usr/lib64", work_dir); execute_cmd("mkdir -p %s/usr/local/lib", work_dir); execute_cmd("mkdir -p %s/lib/x86_64-linux-gnu", work_dir); // /etc/abrt/plugins/python.conf for Centos7 execute_cmd("mkdir -p %s/etc/abrt", work_dir); execute_cmd("mkdir -p %s/etc/abrt/plugins", work_dir); execute_cmd("cp -a /etc/abrt/plugins/python.conf %s/etc/abrt/plugins/python.conf", work_dir); // /usr/share/abrt/conf.d/plugins/python.conf for Centos7 execute_cmd("mkdir -p %s/usr/share", work_dir); execute_cmd("mkdir -p %s/usr/share/abrt/", work_dir); execute_cmd("mkdir -p %s/usr/share/abrt/conf.d", work_dir); execute_cmd("mkdir -p %s/usr/share/abrt/conf.d/plugins", work_dir); execute_cmd("cp -a /usr/share/abrt/conf.d/plugins/python.conf %s/usr/share/abrt/conf.d/plugins/python.conf", work_dir); if(!py2){ execute_cmd("cp /usr/bin/python2* %s/usr/bin", work_dir); execute_cmd("cp -a /usr/lib/python2* %s/usr/lib/", work_dir); execute_cmd("cp -a /usr/lib64/python2.7 %s/usr/lib64/", work_dir); #if (defined __mips__) execute_cmd("cp -a /usr/lib64/python2* %s/usr/lib64/", work_dir); execute_cmd("mkdir -p %s/usr/local/lib/", work_dir); execute_cmd("cp -a /usr/local/lib/python2* %s/usr/local/lib/", work_dir); #endif }else{ execute_cmd("cp /usr/bin/python3* %s/usr/bin", work_dir); execute_cmd("cp -a /usr/lib/python3* %s/usr/lib/", work_dir); execute_cmd("cp -a /usr/lib64/python3.6 %s/usr/lib64/", work_dir); #if (defined __mips__) execute_cmd("cp -a /usr/lib64/python3* %s/usr/lib64/", work_dir); execute_cmd("mkdir -p %s/usr/local/lib/", work_dir); execute_cmd("cp -a /usr/local/lib/python3* %s/usr/local/lib/", work_dir); #endif } execute_cmd("cp /usr/lib/lapack/* %s/usr/lib/liblapack.so.3", work_dir); execute_cmd("cp /usr/lib/libblas/* %s/usr/lib/libblas.so.3", work_dir); execute_cmd("cp /usr/lib/x86_64-linux-gnu/libgfortran.so.3 %s/usr/lib/", work_dir); execute_cmd("cp /usr/lib/x86_64-linux-gnu/libquadmath.so.0 %s/usr/lib", work_dir); execute_cmd("cp /usr/lib/x86_64-linux-gnu/blas/* %s/usr/lib", work_dir); execute_cmd("cp /usr/lib/x86_64-linux-gnu/liblapack.so* %s/usr/lib", work_dir); execute_cmd("cp /usr/lib/x86_64-linux-gnu/libgfortran.so.4 %s/usr/lib", work_dir); #ifdef __mips__ execute_cmd("/bin/cp -a /lib64/libpthread.so.0 %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libutil.so.1 %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libm.so.6 %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libc.so.6 %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libpthread-2.27.so %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libutil-2.27.so %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libc-2.27.so %s/lib64/", work_dir); execute_cmd("/bin/cp -a /lib64/libm-2.27.so %s/lib64/", work_dir); #endif /*execute_cmd("/bin/mkdir -p %s/lib/x86_64-linux-gnu", work_dir); execute_cmd("/bin/cp -a /lib/x86_64-linux-gnu/libpthread* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp -a /lib/x86_64-linux-gnu/libdl.so.2 %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp -a /lib/x86_64-linux-gnu/libutil.so.1 %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp -a /lib/x86_64-linux-gnu/libexpat.so.1 %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp -a /lib/x86_64-linux-gnu/libz.so.1 %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp -a /lib/x86_64-linux-gnu/libm.so.6 %s/lib/x86_64-linux-gnu/", work_dir); */ //execute_cmd("/bin/cp -a /lib/x86_64-linux-gnu/ %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("cp -a /usr/lib64/libpython* %s/usr/lib64/", work_dir); execute_cmd("cp -a /usr/local/lib/python* %s/usr/local/lib/", work_dir); execute_cmd("cp -a /usr/include/python* %s/usr/include/", work_dir); execute_cmd("cp -a /usr/lib/libpython* %s/usr/lib/", work_dir); execute_cmd("/bin/mkdir -p %s/home/judge", work_dir); execute_cmd("/bin/chown judge %s", work_dir); execute_cmd("/bin/mkdir -p %s/etc", work_dir); execute_cmd("/bin/grep judge /etc/passwd>%s/etc/passwd", work_dir); execute_cmd("/bin/mount -o bind /dev %s/dev", work_dir); execute_cmd("/bin/mount -o remount,ro %s/dev", work_dir); } void copy_php_runtime(char *work_dir) { copy_shell_runtime(work_dir); execute_cmd("/bin/mkdir -p %s/usr/bin", work_dir); execute_cmd("/bin/mkdir %s/usr/lib", work_dir); execute_cmd("/bin/cp /usr/lib/libedit* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/libdb* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/libgssapi_krb5* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/libkrb5* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/libk5crypto* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/*/libedit* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/*/libdb* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/*/libgssapi_krb5* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/*/libkrb5* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/*/libk5crypto* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/libxml2* %s/usr/lib/", work_dir); #ifdef __x86_64__ execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libxml2.so* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libicuuc.so* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libicudata.so* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libstdc++.so* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libssl* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libcrypto* %s/usr/lib/", work_dir); #endif execute_cmd("/bin/cp /usr/bin/php* %s/usr/bin", work_dir); execute_cmd("chmod +rx %s/Main.php", work_dir); } void copy_perl_runtime(char *work_dir) { copy_shell_runtime(work_dir); execute_cmd("/bin/mkdir -p %s/usr/bin", work_dir); execute_cmd("/bin/mkdir %s/usr/lib", work_dir); execute_cmd("/bin/cp /usr/lib/libperl* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/bin/perl* %s/usr/bin", work_dir); } void copy_freebasic_runtime(char *work_dir) { copy_shell_runtime(work_dir); execute_cmd("/bin/mkdir -p %s/usr/local/lib", work_dir); execute_cmd("/bin/mkdir -p %s/usr/local/bin", work_dir); execute_cmd("/bin/cp /usr/local/lib/freebasic %s/usr/local/lib/", work_dir); execute_cmd("/bin/cp /usr/local/bin/fbc %s/", work_dir); execute_cmd("/bin/cp -a /lib32/* %s/lib/", work_dir); } void copy_mono_runtime(char *work_dir) { copy_shell_runtime(work_dir); execute_cmd("/bin/mkdir -p %s/usr/bin", work_dir); execute_cmd("/bin/mkdir %s/proc", work_dir); execute_cmd("/bin/mkdir -p %s/usr/lib/mono/2.0", work_dir); execute_cmd("/bin/cp -a /usr/lib/mono %s/usr/lib/", work_dir); execute_cmd("/bin/mkdir -p %s/usr/lib64/mono/2.0", work_dir); execute_cmd("/bin/cp -a /usr/lib64/mono %s/usr/lib64/", work_dir); execute_cmd("/bin/cp /usr/lib/libgthread* %s/usr/lib/", work_dir); execute_cmd("/bin/mount -o bind /proc %s/proc", work_dir); execute_cmd("/bin/cp /usr/bin/mono* %s/usr", work_dir); execute_cmd("/bin/cp /usr/lib/libgthread* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /lib/libglib* %s/lib/", work_dir); execute_cmd("/bin/cp /lib/tls/i686/cmov/lib* %s/lib/tls/i686/cmov/", work_dir); execute_cmd("/bin/cp /lib/libpcre* %s/lib/", work_dir); execute_cmd("/bin/cp /lib/ld-linux* %s/lib/", work_dir); #ifdef __x86_64__ execute_cmd("/bin/cp /lib64/ld-linux* %s/lib64/", work_dir); execute_cmd("/bin/mkdir -p %s/usr/lib/x86_64-linux-gnu", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libm.so.6 %s/usr/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/librt.so.1 %s/usr/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libpthread.so.0 %s/usr/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 %s/usr/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libc.so.6 %s/usr/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib64/ld-linux-x86-64.so.2 %s/lib64", work_dir); #endif execute_cmd("/bin/mkdir -p %s/home/judge", work_dir); execute_cmd("/bin/chown judge %s/home/judge", work_dir); execute_cmd("/bin/mkdir -p %s/etc", work_dir); execute_cmd("/bin/grep judge /etc/passwd>%s/etc/passwd", work_dir); } void copy_lua_runtime(char *work_dir) { copy_shell_runtime(work_dir); execute_cmd("mkdir -p %s/usr/bin", work_dir); execute_cmd("/bin/mkdir -p %s/usr/local/lib", work_dir); execute_cmd("/bin/mkdir -p %s/usr/local/bin", work_dir); execute_cmd("/bin/cp /usr/bin/lua %s/usr/bin", work_dir); } void copy_sql_runtime(char *work_dir) { copy_shell_runtime(work_dir); execute_cmd("mkdir -p %s/usr/bin", work_dir); execute_cmd("/bin/cp /usr/bin/sqlite3 %s/usr/bin", work_dir); #ifdef __mips__ execute_cmd("/bin/cp /lib64/libedit.so.0 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib64/libm.so.6 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib64/libdl.so.2 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib64/libz.so.1 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib64/libpthread.so.0 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib64/libc.so.6 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib64/libtinfo.so.6 %s/lib64/", work_dir); #endif #ifdef __i386__ execute_cmd("/bin/cp /usr/lib/i386-linux-gnu/libsqlite3.so.0* %s/lib/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libreadline.so.6* %s/lib/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libc.so.6* %s/lib/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libpthread.so.0 %s/lib/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libdl.so.2* %s/lib/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libtinfo.so.5* %s/lib/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libedit.so.0 %s/lib/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libm.so.6* %s/lib/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libz.so.1 %s/lib/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libtinfo.so.6* %s/lib/", work_dir); #endif #ifdef __x86_64__ execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libsqlite3.so.0 %s/lib/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libreadline.so.6 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libc.so.6 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libpthread.so.0 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libdl.so.2 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libtinfo.so.5 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libedit.so.0 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libm.so.6 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libz.so.1 %s/lib64/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libtinfo.so.6 %s/lib64/", work_dir); #endif } void copy_js_runtime(char *work_dir) { //copy_shell_runtime(work_dir); execute_cmd("mkdir -p %s/usr/bin", work_dir); execute_cmd("mkdir -p %s/dev", work_dir); execute_cmd("/bin/mount -o bind /dev %s/dev", work_dir); execute_cmd("/bin/mount -o remount,ro %s/dev", work_dir); execute_cmd("/bin/mkdir -p %s/usr/lib %s/lib/i386-linux-gnu/ %s/lib64/", work_dir, work_dir, work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libz.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/i386-linux-gnu/libuv.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/i386-linux-gnu/libicui18n.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/i386-linux-gnu/libicuuc.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/i386-linux-gnu/libicudata.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libtinfo.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/i386-linux-gnu/libcares.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/libv8.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libssl.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libcrypto.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libdl.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/librt.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/i386-linux-gnu/libstdc++.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libpthread.so.* %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libc.so.6 %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libm.so.6 %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/i386-linux-gnu/libgcc_s.so.1 %s/lib/i386-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/ld-linux.so.* %s/lib/", work_dir); #ifdef __x86_64__ execute_cmd("/bin/mkdir -p %s/usr/lib/x86_64-linux-gnu/ %s/lib/x86_64-linux-gnu/", work_dir, work_dir); //execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/ %s/usr/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/libv8.so.* %s/usr/lib/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libcares.so.* %s/usr/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libz.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libuv.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/librt.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libpthread.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libdl.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libssl.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libcrypto.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libicui18n.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libicuuc.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libstdc++.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libm.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libgcc_s.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib/x86_64-linux-gnu/libc.so.* %s/lib/x86_64-linux-gnu/", work_dir); execute_cmd("/bin/cp /lib64/ld-linux-x86-64.so.* %s/lib64/", work_dir); execute_cmd("/bin/cp /usr/lib/x86_64-linux-gnu/libicudata.so.* %s/lib/x86_64-linux-gnu/", work_dir); #endif execute_cmd("/bin/cp /usr/bin/node %s/usr/bin", work_dir); } void run_solution(int &lang, char *work_dir, double &time_lmt, int &usedtime, int &mem_lmt,char * data_file_path,int p_id) // 为每个测试数据运行一次提交的答案 { //准备环境变量处理中文,如果希望使用非中文的语言环境,可能需要修改这些环境变量 char * const envp[]={(char * const )"PYTHONIOENCODING=utf-8", (char * const )"LANG=zh_CN.UTF-8", (char * const )"LANGUAGE=zh_CN.UTF-8", (char * const )"LC_ALL=zh_CN.utf-8",NULL}; if(nice(19)!=19) printf("......................renice fail... \n"); // now the user is "judger" if(chdir(work_dir)){ write_log("Working directory :%s switch fail...",work_dir); exit(-4); } // open the files if(lang==18){ execute_cmd("/usr/bin/sqlite3 %s/data.db < %s", work_dir,data_file_path); execute_cmd("/bin/chown judge %s/data.db", work_dir); stdin=freopen("Main.sql", "r", stdin); }else{ char noip_file_name[BUFFER_SIZE]; sprintf(noip_file_name,"%s/data/%d/input.name",oj_home,p_id); if(DEBUG) printf("---------NOIP filename:%s\n",noip_file_name); if (access(noip_file_name, R_OK ) == -1){ //不存在指定文件名,使用标准输入 if(copy_data){ stdin=freopen("data.in", "r", stdin); }else{ printf("infile: [%s]\n",data_file_path); stdin=freopen(data_file_path,"r",stdin); } } } execute_cmd("touch %s/user.out", work_dir); if (copy_data){ execute_cmd("chgrp judge %s/user.out %s/data.in", work_dir,work_dir); execute_cmd("chmod 740 %s/data.in", work_dir); } execute_cmd("chmod 760 %s/user.out", work_dir); if ( (!use_docker) && lang != 3 && lang != 5 && lang != 20 && lang != 9 && !(lang ==6 && python_free ) ){ if(DEBUG)printf("chroot...............................................\n"); }else{ if(DEBUG)printf("Skiping chroot........................................\n"); } stdout=freopen("user.out", "w", stdout); stderr=freopen("error.out", "a+", stderr); // trace me ptrace(PTRACE_TRACEME, 0, NULL, NULL); // run me if ( (!use_docker) && lang != LANG_JAVA && lang != LANG_PHP && lang != LANG_BASH && lang != LANG_COBOL && lang != LANG_MATLAB && lang != LANG_CSHARP && lang != LANG_R && !(lang == LANG_PYTHON && python_free ) ){ if(chroot(work_dir)); }else{ // vm script language don't chroot within docker } while (setgid(1536) != 0) sleep(1); while (setuid(1536) != 0) sleep(1); while (setresuid(1536, 1536, 1536) != 0) sleep(1); // char java_p1[BUFFER_SIZE], java_p2[BUFFER_SIZE]; // child // set the limit struct rlimit LIM; // time limit, file limit& memory limit // time limit if (time_limit_to_total) LIM.rlim_cur = (time_lmt / cpu_compensation - usedtime / 1000.0f) + 1; else LIM.rlim_cur = time_lmt / cpu_compensation + 1 ; LIM.rlim_max = LIM.rlim_cur + 1 ; //if(DEBUG) printf("LIM_CPU=%d",(int)(LIM.rlim_cur)); setrlimit(RLIMIT_CPU, &LIM); alarm(0); // if ( num_of_test >0 ){ // if(num_of_test * time_lmt / cpu_compensation>1) // alarm( num_of_test * time_lmt / cpu_compensation); // else // alarm(1); // }else{ if(time_lmt / cpu_compensation>1) alarm( time_lmt / cpu_compensation); else alarm(1); // } // file limit LIM.rlim_max = STD_F_LIM + STD_MB; LIM.rlim_cur = STD_F_LIM; setrlimit(RLIMIT_FSIZE, &LIM); // proc limit switch (lang) { case LANG_GO: case LANG_CSHARP: //C# case LANG_JAVA: //java case LANG_R: case LANG_SB3: LIM.rlim_cur = LIM.rlim_max = 880; break; case LANG_RUBY: //ruby case LANG_PYTHON: //python case LANG_SCHEME: case LANG_JS: case LANG_MATLAB: LIM.rlim_cur = LIM.rlim_max = 200; break; case LANG_BASH: //bash LIM.rlim_cur = LIM.rlim_max = 3; break; default: LIM.rlim_cur = LIM.rlim_max = 1; } setrlimit(RLIMIT_NPROC, &LIM); // set the stack LIM.rlim_cur = STD_MB << 8; LIM.rlim_max = STD_MB << 8; setrlimit(RLIMIT_STACK, &LIM); // set the memory LIM.rlim_cur = STD_MB * mem_lmt / 2 * 3; LIM.rlim_max = STD_MB * mem_lmt * 2; if (lang < LANG_JAVA || lang == LANG_OBJC || lang == LANG_CLANG || lang == LANG_CLANGPP || lang == LANG_GO) setrlimit(RLIMIT_AS, &LIM); switch (lang) { case LANG_C: case LANG_CPP: case LANG_PASCAL: case LANG_OBJC: case LANG_FREEBASIC: case LANG_CLANG: case LANG_CLANGPP: case LANG_GO: case LANG_FORTRAN: case LANG_COBOL: execle("./Main", "./Main", (char *)NULL,envp); break; case LANG_JAVA: sprintf(java_xmx, "-Xmx%dM", mem_lmt); //sprintf(java_xmx, "-XX:MaxPermSize=%dM", mem_lmt); execle("/usr/bin/java", "/usr/bin/java",java_xmx , // the security manager has been removed in later java version "Main", (char *) NULL,envp); break; case LANG_RUBY: //system("/ruby Main.rb0&&num<=total){ if(strcasecmp(ans[num],user_answer)==0 || strcasecmp(ans[num],"*")==0 || strcasecmp(ans[num]," *")==0){ mark+=m[num]; }else{ if(raw_text_diff) fprintf(df,"%d Answer:%s[You:%s] -%.1f\n",i,ans[i],user_answer,m[i]); } m[num]=0; }else{ break; } } for(int i=1;i<=total;i++){ free(ans[i]); } free(user_answer); fclose(user); fclose(df); return mark; } int special_judge(char *oj_home, int problem_id, char *infile, char *outfile, char *userfile,double* pass_rate,int spj) { pid_t pid; char spjpath[BUFFER_SIZE/2]; char tpjpath[BUFFER_SIZE/2]; if (DEBUG) printf("pid=%d\n", problem_id); // prevent privileges settings caused spj fail in [issues686] execute_cmd("chgrp judge %s/data/%d/spj %s %s %s", oj_home, problem_id,infile, outfile, userfile); execute_cmd("chmod 751 %s/data/%d/spj %s %s %s", oj_home, problem_id,infile, outfile, userfile); pid = fork(); int ret = 0; if (pid == 0) { while (setgid(1536) != 0) sleep(1); while (setuid(1536) != 0) sleep(1); while (setresuid(1536, 1536, 1536) != 0) sleep(1); struct rlimit LIM; // time limit, file limit& memory limit LIM.rlim_cur = 15; LIM.rlim_max = LIM.rlim_cur; setrlimit(RLIMIT_CPU, &LIM); alarm(0); alarm(10); // file limit LIM.rlim_max = STD_F_LIM + STD_MB; LIM.rlim_cur = STD_F_LIM; setrlimit(RLIMIT_FSIZE, &LIM); sprintf(spjpath,"%s/data/%d/spj", oj_home, problem_id); sprintf(tpjpath,"%s/data/%d/tpj", oj_home, problem_id); if( access( tpjpath , X_OK ) == 0 ){ ret = execute_cmd("%s/data/%d/tpj %s %s %s 2>> diff.out ", oj_home, problem_id, infile, userfile, outfile); // testlib style if (DEBUG) printf("testlib spj return: %d\n", ret); }else if (access( spjpath , X_OK ) == 0 ) { ret = execute_cmd("%s/data/%d/spj %s %s %s", oj_home, problem_id, infile, outfile, userfile); // hustoj style if (DEBUG) printf("hustoj spj return: %d\n", ret); }else if(spj == 2){ }else{ printf("spj tpj not found problem: %d\n", problem_id); ret=1; } if (ret) exit(1); else exit(0); } else { int status; waitpid(pid, &status, 0); ret = WEXITSTATUS(status); if (DEBUG) printf("recorded spj: %d\n", ret); } return ret; } void judge_solution(int &ACflg, int &usedtime, double time_lmt, int spj, int p_id, char *infile, char *outfile, char *userfile, int &PEflg, int lang, char *work_dir, int &topmemory, int mem_lmt, int solution_id, int num_of_test,double * pass_rate) { //usedtime-=1000; int comp_res; if (num_of_test == 0 ) num_of_test = 1.0; if (ACflg == OJ_AC){ int real_limit=1000; if(time_limit_to_total){ // 如果限制总时间 real_limit=time_lmt*1000; if(total_time>real_limit) ACflg = OJ_TL; // 总时间超过 if(usedtime> real_limit) ACflg = OJ_TL; // 单点超过 }else if(num_of_test>0){ // 如果数据点不为0,且限制单点时间 real_limit=num_of_test*time_lmt*1000; //if(total_time>real_limit) ACflg = OJ_TL; //总时间超过测试点数*限制 if(usedtime> time_lmt*1000) ACflg = OJ_TL; // 单点超过限制 }else{ //测试数为0 ,这种情况不应该出现,但给出,作为保险。 real_limit=time_lmt*1000; // fallback if(usedtime > real_limit) ACflg = OJ_TL; if(total_time>real_limit) ACflg = OJ_TL; } } if (topmemory > mem_lmt * STD_MB) ACflg = OJ_ML; //issues79 // compare if (ACflg == OJ_AC) { if (spj) { comp_res = special_judge(oj_home, p_id, infile, outfile, userfile,pass_rate,spj); if (comp_res == 0) comp_res = OJ_AC; else { if (DEBUG) printf("fail test %s\n", infile); comp_res = OJ_WA; } } else { comp_res = compare(outfile, userfile,infile,userfile); } if (comp_res == OJ_WA) { ACflg = OJ_WA; if (DEBUG) printf("fail test %s\n", infile); } else if (comp_res == OJ_PE) PEflg = OJ_PE; ACflg = comp_res; } //jvm popup messages, if don't consider them will get miss-WrongAnswer if (lang == LANG_JAVA ) { comp_res = fix_java_mis_judge(work_dir, ACflg, topmemory, mem_lmt); } if (lang == LANG_PYTHON ) { comp_res = fix_python_mis_judge(work_dir, ACflg, topmemory, mem_lmt); } } int get_page_fault_mem(struct rusage &ruse, pid_t &pidApp) { //java use pagefault int m_vmpeak, m_vmdata, m_minflt; m_minflt = ruse.ru_minflt * getpagesize(); if (0 && DEBUG) { m_vmpeak = get_proc_status(pidApp, "VmPeak:"); m_vmdata = get_proc_status(pidApp, "VmData:"); printf("VmPeak:%d KB VmData:%d KB minflt:%d KB\n", m_vmpeak, m_vmdata, m_minflt >> 10); } return m_minflt; } void print_runtimeerror(char* infile,char *err) { FILE *ferr = fopen("error.out", "a+"); fprintf(ferr, "%s:%s\n",infile, err); fclose(ferr); } void clean_session(pid_t p) { //char cmd[BUFFER_SIZE]; const char *pre = "ps awx -o \"\%p \%P\"|grep -w "; const char *post = " | awk \'{ print $1 }\'|xargs kill -9"; execute_cmd("%s %d %s", pre, p, post); execute_cmd("ps aux |grep \\^judge|awk '{print $2}'|xargs kill"); } void watch_solution(pid_t pidApp, char *infile, int &ACflg, int spj, char *userfile, char *outfile, int solution_id, int lang, int &topmemory, int mem_lmt, int &usedtime, double time_lmt, int &p_id, int &PEflg, char *work_dir) { // 父进程中的保姆程序 int tempmemory = 0; if (DEBUG) printf("pid=%d judging %s\n", pidApp, infile); int status, sig, exitcode; char white_code[256]={0}; white_code[0]=1; // add more if new signal complain white_code[5]=1; white_code[17]=1; white_code[23]=1; white_code[133]=1; char buf[BUFFER_SIZE]; struct user_regs_struct reg; struct rusage ruse; int first = true; int tick=0; long outFileSize=get_file_size(outfile); while (1) { tick++; // check the usage wait4(pidApp, &status, __WALL, &ruse); //等待子进程切换内核态(调用系统API或者运行状态变化) if (first) { // ptrace(PTRACE_SETOPTIONS, pidApp, NULL, PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXIT // |PTRACE_O_EXITKILL // |PTRACE_O_TRACECLONE // |PTRACE_O_TRACEFORK // |PTRACE_O_TRACEVFORK // 有的发行版带的PTRACE不识别以上宏,因此注释掉 ); } //jvm gc ask VM before need,so used kernel page fault times and page size if (lang == LANG_JAVA || lang == LANG_PHP || lang == LANG_CSHARP || lang == LANG_CLANG || lang == LANG_CLANGPP || lang == LANG_JS || lang == LANG_GO || lang == LANG_MATLAB|| lang == LANG_COBOL|| lang == LANG_SB3 ) { tempmemory = get_page_fault_mem(ruse, pidApp); } else { //other use VmPeak tempmemory = get_proc_status(pidApp, "VmPeak:") << 10; } if (tempmemory > topmemory) topmemory = tempmemory; if (topmemory > mem_lmt * STD_MB) { if (DEBUG) printf("out of memory %d\n", topmemory); if (ACflg == OJ_AC) ACflg = OJ_ML; ptrace(PTRACE_KILL, pidApp, NULL, NULL); break; } //sig = status >> 8;/*status >> 8 EXITCODE*/ if (WIFEXITED(status)) { // 子进程已经退出 ,返回值不为0则判RE exitcode = WEXITSTATUS(status); char error[BUFFER_SIZE]; if(exitcode){ ACflg=OJ_RE; sprintf(error, "\t non-zero return = %d \n", exitcode); print_runtimeerror(infile+prelen,error); } break; } if ((lang < LANG_RUBY ||lang == LANG_BASH || lang == LANG_CSHARP ) && get_file_size("error.out") && !oi_mode) { ACflg = OJ_RE; //addreinfo(solution_id); ptrace(PTRACE_KILL, pidApp, NULL, NULL); break; } if (((tick & 0xff)==0x00) &&(!spj) && get_file_size(userfile) >outFileSize * 2 + 1024) { ACflg = OJ_OL; ptrace(PTRACE_KILL, pidApp, NULL, NULL); break; } exitcode = WEXITSTATUS(status) % 256 ; /*exitcode == 5 waiting for next CPU allocation * ruby using system to run,exit 17 ok * Runtime Error:Unknown signal xxx need be added here */ if (white_code[exitcode] // || ( (exitcode == 17||exitcode == 23) && (lang >= LANG_JAVA && lang!= LANG_OBJC && lang != LANG_CLANG && lang != LANG_CLANGPP) ) ){ // 进程休眠或等待IO //go on and on ; }else{ if (DEBUG) { printf("status>>8=%d\n", exitcode); } //psignal(exitcode, NULL); if (ACflg == OJ_AC) { switch (exitcode) // 根据退出的原因给出判题结果 { case SIGCHLD: case SIGALRM: alarm(0); if (DEBUG) printf("alarm:%g\n", time_lmt); case SIGKILL: case SIGXCPU: ACflg = OJ_TL; usedtime = time_lmt * 1000; if (DEBUG) printf("TLE:%d\n", usedtime); break; case SIGXFSZ: ACflg = OJ_OL; break; default: ACflg = OJ_RE; } print_runtimeerror(infile+prelen,strsignal(exitcode)); sprintf(buf,"if you can confirm the code is right and your system is somehow different from others , try adding: ' white_code[%d]=1; ' after judge_client:2888 for it, but don't panic just for a Segmentfault. ",exitcode); print_runtimeerror(buf,strsignal(exitcode)); } ptrace(PTRACE_KILL, pidApp, NULL, NULL); // 杀死出问题的进程 break; } if (WIFSIGNALED(status)) { /* WIFSIGNALED: if the process is terminated by signal * 由外部信号触发的进程终止 * psignal(int sig, char *s),like perror(char *s),print out s, with error msg from system of sig * sig = 5 means Trace/breakpoint trap * sig = 11 means Segmentation fault * sig = 25 means File size limit exceeded */ sig = WTERMSIG(status); if (DEBUG) { printf("WTERMSIG=%d\n", sig); psignal(sig, NULL); } if (ACflg == OJ_AC) { switch (sig) //根据原因给出结论 { case SIGCHLD: case SIGALRM: alarm(0); case SIGKILL: case SIGXCPU: ACflg = OJ_TL; break; case SIGXFSZ: ACflg = OJ_OL; break; default: ACflg = OJ_RE; } print_runtimeerror(infile+prelen,strsignal(sig)); } break; } /* comment from http://www.felix021.com/blog/read.php?1662 WIFSTOPPED: return true if the process is paused or stopped while ptrace is watching on it WSTOPSIG: get the signal if it was stopped by signal */ // check the system calls if (!use_ptrace){ ptrace(PTRACE_SYSCALL, pidApp, NULL, NULL); continue; } #ifdef __mips__ // if(exitcode!=5&&exitcode!=133){ //https://github.com/strace/strace/blob/master/linux/mips/syscallent-n32.h#L344 ptrace(PTRACE_GETREGS, pidApp, NULL, ®); call_id=(unsigned int)reg.REG_SYSCALL; if( (call_id > 1000 && call_id <5000 )|| (lang == LANG_PYTHON && call_id < 5500) || call_id> 6500){ // not a valid syscall ptrace(PTRACE_SYSCALL, pidApp, NULL, NULL); continue; }else{ #endif #ifdef __arm__ call_id=ptrace(PTRACE_GETREGS, pidApp, NULL, ®); call_id = ((unsigned int)reg.REG_SYSCALL) % call_array_size; #endif #ifdef __aarch64__ call_id=ptrace(PTRACE_GETREGS, pidApp, (void *)NT_ARM_SYSTEM_CALL, ®); print_arm_regs(reg.regs); printf("return call_id:%d\n",call_id); call_id = ((unsigned int)reg.REG_SYSCALL) % call_array_size; printf("regist call_id:%d\n",call_id); #endif #ifdef __i386__ call_id=ptrace(PTRACE_GETREGS, pidApp, NULL, ®); call_id = ((unsigned int)reg.REG_SYSCALL) % call_array_size; #endif #ifdef __x86_64__ call_id=ptrace(PTRACE_GETREGS, pidApp, NULL, ®); call_id = ((unsigned int)reg.REG_SYSCALL) % call_array_size; #endif // printf("call_id:%x %d\n",call_id,call_counter[call_id]); call_id = call_id % call_array_size; // printf("call_id:%d %d\n",call_id,call_counter[call_id]); if (record_call) { printf("new call id:%d\n",call_id); call_counter[call_id]++; printf("call %d: %d\n",call_id,call_counter[call_id]); }else if (call_counter[call_id]) { call_counter[call_id]--; } else { //do not limit JVM syscall for using different JVM 对于非法的系统调用,给出具体编号给管理员参考 ACflg = OJ_RE; char error[BUFFER_SIZE]; sprintf(error, "[ERROR] solution_id:%d called a Forbidden system call:%u [%u]\n" " TO FIX THIS , ask admin to add the CALLID into corresponding LANG_XXV[] located at okcalls32/64.h ,\n" "and recompile judge_client. \n" "if you are admin and you don't know what to do ,\n" "中文解释查看知乎 https://zhuanlan.zhihu.com/p/24498599\n", solution_id, call_id,(unsigned int)reg.REG_SYSCALL); write_log(error); print_runtimeerror(infile+prelen,error); //ptrace(PTRACE_SYSCALL, pidApp, NULL, NULL); //continue; ptrace(PTRACE_KILL, pidApp, NULL, NULL); } call_id=0; #ifdef __mips__ // } } #endif ptrace(PTRACE_SYSCALL, pidApp, NULL, NULL); // 继续等待下一次的系统调用或其他中断 first = false; //usleep(1); } ptrace(PTRACE_KILL, pidApp, NULL, NULL); // 杀死出问题的进程 execute_cmd("kill -9 %d",pidApp); // 抗拒的补刀 usedtime += (ruse.ru_utime.tv_sec * 1000 + ruse.ru_utime.tv_usec / 1000) * cpu_compensation; // 统计用户态耗时,在更快速的CPU上加以cpu_compensation倍数放大 usedtime += (ruse.ru_stime.tv_sec * 1000 + ruse.ru_stime.tv_usec / 1000) * cpu_compensation; // 统计内核态耗时,在更快速的CPU上加以cpu_compensation倍数放大 //clean_session(pidApp); } void clean_workdir(char *work_dir) { umount(work_dir); if (DEBUG) { execute_cmd("/bin/rmdir %s/log/* 2>/dev/null", work_dir); execute_cmd("/bin/rm -rf %s/log/* 2>/dev/null", work_dir); execute_cmd("mkdir %s/log/ 2>/dev/null", work_dir); execute_cmd("/bin/mv %s/* %s/log/ 2>/dev/null", work_dir, work_dir); } else { execute_cmd("mkdir %s/log/ 2>/dev/null", work_dir); execute_cmd("/bin/mv %s/* %s/log/ 2>/dev/null", work_dir, work_dir); execute_cmd("/bin/rmdir %s/log/* 2>/dev/null", work_dir); execute_cmd("/bin/rm -rf %s/log/* 2>/dev/null", work_dir); } } void init_parameters(int argc, char **argv, int &solution_id, int &runner_id) { if (argc < 3) { fprintf(stderr,"HUSTOJ judge_client ver 20240407\n\n"); fprintf(stderr, "Normal Usage:\n\t%s \n\n", argv[0]); fprintf(stderr, "Multi OJ with Specific home :\n\t%s [judge_base_path].\n\n", argv[0]); fprintf(stderr, "Debug with Specific home:\n\t%s [judge_base_path] [debug].\n\n", argv[0]); fprintf(stderr,"\n\n"); fprintf(stderr,"Example:\n\tsudo %s 1001 0 /home/judge/ debug \n\n",argv[0]); exit(1); } DEBUG = (argc > 4); record_call = (argc > 5); if (argc > 5) { strcpy(LANG_NAME, argv[5]); } if (argc > 3) strcpy(oj_home, argv[3]); else strcpy(oj_home, "/home/judge"); if(chdir(oj_home)) exit(-2); // change the dir// init our work solution_id = atoi(argv[1]); runner_id = atoi(argv[2]); } int get_sim(int solution_id, int lang, int pid, int &sim_s_id) { char src_pth[BUFFER_SIZE]; //char cmd[BUFFER_SIZE]; sprintf(src_pth, "Main.%s", lang_ext[lang]); int sim = execute_cmd("/usr/bin/sim.sh %s %d", src_pth, pid); FILE *pf; pf = fopen("sim", "r"); if (!sim){ execute_cmd("/bin/mkdir ../data/%d/ac/ 2>/dev/null", pid); execute_cmd("/bin/chown www-data ../data/%d/ac/ 2>/dev/null", pid); execute_cmd("/bin/cp %s ../data/%d/ac/%d.%s 2>/dev/null", src_pth, pid, solution_id,lang_ext[lang]); execute_cmd("/bin/chown www-data ../data/%d/ac/%d.%s 2>/dev/null", pid, solution_id,lang_ext[lang]); //c cpp will if (lang == 0) execute_cmd("/bin/ln ../data/%d/ac/%d.%s ../data/%d/ac/%d.%s 2>/dev/null", pid, solution_id, lang_ext[lang], pid, solution_id, lang_ext[lang + 1]); if (lang == 1) execute_cmd("/bin/ln ../data/%d/ac/%d.%s ../data/%d/ac/%d.%s 2>/dev/null", pid, solution_id, lang_ext[lang], pid, solution_id, lang_ext[lang - 1]); }else{ if (pf){ if(2==fscanf(pf, "%d%d", &sim, &sim_s_id)); } } if(pf) fclose(pf); if (solution_id <= sim_s_id) sim = 0; return sim; } void mk_shm_workdir(char *work_dir) { char shm_path[BUFFER_SIZE]; sprintf(shm_path, "/dev/shm/hustoj/%s", work_dir); execute_cmd("/bin/mkdir -p %s 2>/dev/null", shm_path); execute_cmd("/bin/ln -s %s %s/ 2>/dev/null", shm_path, oj_home); execute_cmd("/bin/chown judge %s 2>/dev/null", shm_path); execute_cmd("chmod 755 %s 2>/dev/null", shm_path); //sim need a soft link in shm_dir to work correctly sprintf(shm_path, "/dev/shm/hustoj/%s/", oj_home); execute_cmd("/bin/ln -s %s/data %s 2>/dev/null", oj_home, shm_path); } int count_in_files(char *dirpath) { const char *cmd = "ls -l %s/*.in|wc -l"; int ret = 0; FILE *fjobs = read_cmd_output(cmd, dirpath); if(1!=fscanf(fjobs, "%d", &ret)) printf("warning count files fail");; pclose(fjobs); return ret; } int get_test_file(char *work_dir, int p_id) { char filename[BUFFER_SIZE/2]; char localfile[BUFFER_SIZE]; time_t remote_date, local_date; int ret = 0; const char *cmd = " wget --post-data=\"gettestdatalist=1&time=1&pid=%d\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\""; FILE *fjobs = read_cmd_output(cmd, p_id, http_baseurl, http_apipath); while (fgets(filename, sizeof(filename) - 1, fjobs) != NULL) { if(1!=sscanf(filename, "%ld", &remote_date)) printf("http remote time stamp read fail\n"); if (fgets(filename, sizeof(filename) - 1, fjobs) == NULL) break; if(1!=sscanf(filename, "%s", filename)) printf("http filename read fail\n"); if (http_judge && (!data_list_has(filename))) data_list_add(filename); sprintf(localfile, "%s/data/%d/%s", oj_home, p_id, filename); if (DEBUG) printf("localfile[%s]\n", localfile); struct stat fst; stat(localfile, &fst); local_date = fst.st_mtime; if (access(localfile, F_OK ) == -1 || local_date < remote_date) { if (strcmp(filename, "spj") == 0) continue; execute_cmd("/bin/mkdir -p %s/data/%d", oj_home, p_id); const char *cmd2 = " wget --post-data=\"gettestdata=1&filename=%d/%s\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O \"%s\" \"%s%s\""; execute_cmd(cmd2, p_id, filename, localfile, http_baseurl, http_apipath); ret++; if (strcmp(filename, "spj.c") == 0) { // sprintf(localfile,"%s/data/%d/spj.c",oj_home,p_id); if (access(localfile, F_OK ) == 0) { const char *cmd3 = "gcc -o %s/data/%d/spj %s/data/%d/spj.c"; execute_cmd(cmd3, oj_home, p_id, oj_home, p_id); } } if (strcmp(filename, "spj.cc") == 0) { // sprintf(localfile,"%s/data/%d/spj.cc",oj_home,p_id); if (access(localfile, F_OK ) == 0) { const char *cmd4 = "g++ -o %s/data/%d/spj %s/data/%d/spj.cc"; execute_cmd(cmd4, oj_home, p_id, oj_home, p_id); } } } } pclose(fjobs); return ret; } void print_call_array() { printf("int LANG_%sV[CALL_ARRAY_SIZE]={", LANG_NAME); int i = 0; for (i = 0; i < call_array_size; i++) { if (call_counter[i]>0) { printf("%d,", i); } } printf("0};\n"); printf("int LANG_%sC[CALL_ARRAY_SIZE]={", LANG_NAME); for (i = 0; i < call_array_size; i++) { if (call_counter[i]) { printf("%d,",call_counter[i]); } } printf("0};\n"); } int has_mark_in_name=0; int mark_of_name(const char * name){ int mark; printf("reading mark from %s \n",name); if(sscanf(name,"%*[^\[][%d]",&mark)==1){ printf("reading mark %d \n",mark); has_mark_in_name=1; return mark; }else{ return 10; } } int same_subtask(char * last,char * cur){ int i=0; for(i=0;last[i]!='.' && cur[i]!='.';i++){ if (last[i]!=cur[i]){ break; } } return last[i]==cur[i]; } int main(int argc, char **argv) { char work_dir[BUFFER_SIZE]; //char cmd[BUFFER_SIZE]; char user_id[BUFFER_SIZE]; int solution_id = 1000; int runner_id = 0; int p_id, mem_lmt, lang, spj, sim, sim_s_id, max_case_time = 0,cid=0; double time_lmt; char time_space_table[BUFFER_SIZE*100]; int time_space_index=0; umask(0077); init_parameters(argc, argv, solution_id, runner_id); init_judge_conf(); #ifdef _mysql_h if (!http_judge && !init_mysql_conn()) { exit(0); //exit if mysql is down } #endif //set work directory to start running & judging sprintf(work_dir, "%s/run%s/", oj_home, argv[2]); sprintf(lock_file,"%s/client%s.pid",oj_home,argv[2]); while ( already_running()) { syslog(LOG_ERR | LOG_DAEMON, "This working directory is occupied !\n"); printf("%s already has one judge_client in it!\n",work_dir); sleep(5); } if (shm_run){ mk_shm_workdir(work_dir); }else{ execute_cmd("mkdir %s",work_dir); } clean_workdir(work_dir); if(chdir(work_dir)) exit(-3); if (http_judge) if(!system("/bin/ln -s ../cookie ./")) printf("cookie link fail \n"); get_solution_info(solution_id, p_id, user_id, lang,cid); //get the limit if (p_id == 0) { time_lmt = 5; mem_lmt = 128; spj = 0; } else { get_problem_info(p_id, time_lmt, mem_lmt, spj); } //copy source file get_solution(solution_id, work_dir, lang,p_id); //java and other VM language are lucky to have the global bonus in judge.conf if (lang >= LANG_JAVA && lang != LANG_OBJC && lang != LANG_CLANG && lang != LANG_CLANGPP && lang != LANG_GO ) { //ObjectivC Clang Clang++ Go not VM or Script // the limit for java time_lmt = time_lmt + java_time_bonus; mem_lmt = mem_lmt + java_memory_bonus; // copy java.policy if (lang == 3) { execute_cmd("/bin/cp %s/etc/java0.policy %s/java.policy", oj_home, work_dir); execute_cmd("chmod 755 %s/java.policy", work_dir); execute_cmd("chown judge %s/java.policy", work_dir); } } //never bigger than judged set value; if (time_lmt > 300 || time_lmt < 0) time_lmt = 1; if (mem_lmt > 1024 || mem_lmt < 1) mem_lmt = 1024; if (DEBUG) printf("time: %g mem: %d\n", time_lmt, mem_lmt); // compile // printf("%s\n",cmd); // set the result to compiling int Compile_OK = 0 ; if(spj!=2){ Compile_OK = compile(lang, work_dir); } if ( Compile_OK != 0 && spj!=2 ) { addceinfo(solution_id); update_solution(solution_id, OJ_CE, 0, 0, 0, 0, 0.0); if(!turbo_mode)update_user(user_id); if(!turbo_mode)update_problem(p_id,cid); #ifdef _mysql_h if (!http_judge) mysql_close(conn); #endif clean_workdir(work_dir); write_log("compile error"); exit(0); } else { if (!turbo_mode) update_solution(solution_id, OJ_RI, 0, 0, 0, 0, 0.0); umount(work_dir); } //exit(0); // run char fullpath[BUFFER_SIZE]; char infile[BUFFER_SIZE/10]; char outfile[BUFFER_SIZE/10]; char userfile[BUFFER_SIZE/10]; sprintf(fullpath, "%s/data/%d", oj_home, p_id); // the fullpath of data dir // open DIRs //DIR *dp; dirent *dirp; // using http to get remote test data files if (p_id > 0 && http_judge && http_download == 1) get_test_file(work_dir, p_id); // using rsync to get remote test data files, using id_rsa to login ,change src/install/rsync.sh if need if (p_id > 0 && http_download == 2 ) execute_cmd("%s/rsync.sh %d",oj_home,p_id); struct dirent **namelist; int namelist_len; namelist_len = scandir(fullpath,&namelist,inFile,alphasort); if(p_id > 0 && namelist_len == -1 ){ write_log("No such dir:%s!\n", fullpath); #ifdef _mysql_h if (!http_judge) mysql_close(conn); #endif exit(-1); }else{ if(DEBUG){ printf("total test case:%d \n", namelist_len); for(int i=0;id_name); } } } /* if (p_id > 0 && (dp = opendir(fullpath)) == NULL) { write_log("No such dir:%s!\n", fullpath); #ifdef _mysql_h if (!http_judge) mysql_close(conn); #endif exit(-1); } */ int ACflg, PEflg; ACflg = PEflg = OJ_AC; int namelen; int usedtime = 0, topmemory = 0; if (lang == LANG_BASH){ execute_cmd("busybox dos2unix Main.sh", work_dir); } if(!use_docker){ //create chroot for ruby bash python if (lang == LANG_RUBY) copy_ruby_runtime(work_dir); if (lang == LANG_BASH){ copy_bash_runtime(work_dir); } if (lang == LANG_PYTHON && !python_free) copy_python_runtime(work_dir); if (lang == LANG_PHP) copy_php_runtime(work_dir); if (lang == LANG_PERL) copy_perl_runtime(work_dir); // if (lang == LANG_CSHARP) // copy_mono_runtime(work_dir); if (lang == LANG_OBJC) copy_objc_runtime(work_dir); if (lang == LANG_FREEBASIC) copy_freebasic_runtime(work_dir); if (lang == LANG_SCHEME) copy_guile_runtime(work_dir); if (lang == LANG_LUA) copy_lua_runtime(work_dir); if (lang == LANG_JS) copy_js_runtime(work_dir); if (lang == LANG_SQL) copy_sql_runtime(work_dir); } // read files and run double pass_rate = 0.0; float mark=0; float total_mark=0,get_mark=0; int finalACflg = ACflg; if (p_id == 0) { //custom input running printf("running a custom input...\n"); get_custominput(solution_id, work_dir); init_syscalls_limits(lang); pid_t pidApp = fork(); if (pidApp == 0) { run_solution(lang, work_dir, time_lmt, usedtime, mem_lmt,(char *)"data.in",p_id); } else { watch_solution(pidApp, infile, ACflg, spj, userfile, outfile, solution_id, lang, topmemory, mem_lmt, usedtime, time_lmt, p_id, PEflg, work_dir); } if(DEBUG) printf("custom running result:%d PEflg:%d\n",ACflg,PEflg); if (ACflg == OJ_RE||get_file_size("error.out")>0) { if (DEBUG) printf("add RE info of %d..... \n", solution_id); addreinfo(solution_id); } else { addcustomout(solution_id); } update_solution(solution_id, OJ_TR, usedtime, topmemory >> 10, 0, 0, 0); clean_workdir(work_dir); exit(0); } /* for (;(dirp = readdir(dp)) != NULL;) { int namelen = isInFile(dirp->d_name); // check if the file is *.in or not if (namelen == 0) continue; num_of_test++; } rewinddir(dp); */ num_of_test=namelist_len; if( num_of_test == 0 ){ print_runtimeerror((char *)"no test data ",(char *)" no *.in file found"); ACflg = OJ_RE; finalACflg = OJ_RE; } char last_name[BUFFER_SIZE]; int minus_mark=0; char path_buf[BUFFER_SIZE]; sprintf(path_buf,"%s/data/%d/",oj_home,p_id); prelen=strlen(path_buf); if (prelend_name); // check if the file is *.in or not if (namelen == 0) continue; mark=mark_of_name(dirp->d_name); total_mark+=mark; if (http_judge && ( http_download==1 ) && (!data_list_has(dirp->d_name))) continue; prepare_files(dirp->d_name, namelen, infile, p_id, work_dir, outfile, userfile, runner_id, lang ); if (access(outfile, R_OK ) == -1) { //out file does not exist char error[BUFFER_SIZE]; sprintf(error, "missing out file %s, report to system administrator!\n", basename(outfile)); print_runtimeerror(infile+prelen,error); ACflg = OJ_RE; } init_syscalls_limits(lang); pid_t pidApp = fork(); //创建子进程,这里程序将自身复制一份,两份同时运行,进程根据返回值确定自己的身份 if (pidApp == 0) //返回值是0,我就是子进程 { if(spj==2){ exit(0); } run_solution(lang, work_dir, time_lmt, usedtime, mem_lmt,infile,p_id); } else { //返回值非0 ,我是父进程,返回值就是上面那个子进程的pid //num_of_test++; //看护子进程,不让他做奇怪的事 if(spj!=2)watch_solution(pidApp, infile, ACflg, spj, userfile, outfile, solution_id, lang, topmemory, mem_lmt, usedtime, time_lmt, p_id, PEflg, work_dir); kill(pidApp,9); printf("%s: mem=%d time=%d\n",infile+prelen,topmemory,usedtime); total_time+=usedtime; printf("time:%d/%d\n",usedtime,total_time); //判断用户程序输出是否正确,给出结果 judge_solution(ACflg, usedtime, time_lmt, spj, p_id, infile, outfile, userfile, PEflg, lang, work_dir, topmemory, mem_lmt, solution_id, num_of_test,&pass_rate); /* if(usedtime > time_lmt * 1000) { // 如果觉得的显示超时结果的计时过长,可以覆盖数据。 usedtime = time_lmt * 1000; } */ time_space_index+=sprintf(time_space_table+time_space_index,"%s|%ld|%s|%dk|%dms\n",infile+prelen,get_file_size(infile),jresult[ACflg],topmemory/1024,usedtime); /* // full diff code backup if( ACflg != OJ_AC ){ FILE *DF=fopen("diff.out","a"); fprintf(DF,"%s:%s mem=%dk time=%dms\n",infile+strlen(oj_home)+5,jresult[ACflg],topmemory/1024,usedtime); fprintf(DF,"=============================================================\n"); fclose(DF); } */ if (use_max_time) { max_case_time = usedtime > max_case_time ? usedtime : max_case_time; } usedtime = 0; //clean_session(pidApp); } if (oi_mode) { if (ACflg == OJ_AC) { ++pass_rate; get_mark+=mark; if(same_subtask(last_name,dirp->d_name)){ //相同子任务 if(minus_mark >=0 ){ //本子任务未曾失败 minus_mark+=mark; //累计任务内积分 }else{ get_mark-=mark; //任务已经失败,扣除本次得分 } }else{ minus_mark=mark; //跨越任务,积分重新累计 } }else{ if(same_subtask(last_name,dirp->d_name)){ //相同子任务,初次失败 if(minus_mark>=0) get_mark-=minus_mark; //扣除任务内积分 } minus_mark= -1 ; //当前任务失败,标记 } if (finalACflg < ACflg) { finalACflg = ACflg; } if ( time_limit_to_total && (ACflg==OJ_TL) ) break; // limit all TLE submit to protect the system from D.o.S flooding ACflg = OJ_AC; } #ifdef _mysql_h if (!http_judge) check_mysql_conn(); #endif strcpy(last_name,dirp->d_name); } if (ACflg == OJ_AC && PEflg == OJ_PE) ACflg = OJ_PE; if (sim_enable && ACflg == OJ_AC && (!oi_mode || finalACflg == OJ_AC)) { //bash don't supported sim = get_sim(solution_id, lang, p_id, sim_s_id); } else { sim = 0; } //if(ACflg == OJ_RE)addreinfo(solution_id); if ((oi_mode && finalACflg == OJ_RE) || ACflg == OJ_RE) { if (DEBUG) printf("add RE info of %d..... \n", solution_id); FILE *df=fopen("error.out","a"); fprintf(df,"filename|size|result|memory|time\n--|--|--|--|--\n%s\n",time_space_table); fclose(df); addreinfo(solution_id); } if (use_max_time) { if(DEBUG) printf("use max case time:%d\n",max_case_time); usedtime = max_case_time; }else{ if(DEBUG) printf("use total time:%d\n",total_time); usedtime = total_time; } if(spj!=2){ if (oi_mode) { if (num_of_test > 0){ pass_rate /= num_of_test; } if (total_mark > 0 && has_mark_in_name ){ pass_rate =get_mark; if(total_mark>100) pass_rate /= total_mark; else pass_rate /= 100.0; } update_solution(solution_id, finalACflg, usedtime, topmemory >> 10, sim, sim_s_id, pass_rate); } else { if(ACflg==OJ_AC) pass_rate=1.0; else pass_rate=0.0; update_solution(solution_id, ACflg, usedtime, topmemory >> 10, sim, sim_s_id, pass_rate); } }else{ char src_pth[BUFFER_SIZE]; printf("raw text judge %d \n",p_id); sprintf(src_pth, "Main.%s", lang_ext[lang]); mark=raw_text_judge(infile, outfile, src_pth,&total_mark); printf("raw_text_mark:%.1f\n",mark); if(mark>=0 && mark<=total_mark) pass_rate=mark; pass_rate/=100.0; if(mark==total_mark) finalACflg=ACflg=OJ_AC;else finalACflg=ACflg=OJ_WA; update_solution(solution_id, finalACflg,total_mark,mark*10,sim,sim_s_id, pass_rate); } FILE *df=fopen("diff.out","a"); fprintf(df,"filename|size|result|memory|time\n--|--|--|--|--\n%s\n",time_space_table); fclose(df); if(DEBUG) printf("ACflg:%d\n",ACflg); printf("final result:%d\n",finalACflg); if(ACflg != OJ_RE && finalACflg!= OJ_RE ) adddiffinfo(solution_id); if(!turbo_mode)update_user(user_id); if(!turbo_mode)update_problem(p_id,cid); clean_workdir(work_dir); if (DEBUG) write_log("result=%d", oi_mode ? finalACflg : ACflg); #ifdef _mysql_h if (!http_judge) mysql_close(conn); #endif if (record_call) { print_call_array(); } //closedir(dp); free(namelist); return 0; }