static int do_print_run(const serve_state_t state, int run_id, int is_privileged, int user_id) { const struct section_global_data *global = state->global; unsigned char *banner_path = 0; unsigned char *ps_path = 0; unsigned char *log_path = 0; unsigned char *sfx = ""; int arch_flags = 0, pages_num = -1, x, i; path_t run_arch; struct run_entry info; tpTask tsk = 0; unsigned char in_buf[1024]; size_t in_buf_len; FILE *f = 0; int errcode = -SRV_ERR_SYSTEM_ERROR; struct teamdb_export teaminfo; const unsigned char *printer_name = 0, *user_name = 0, *location = 0; const struct userlist_user_info *ui = 0; unsigned char program_path[PATH_MAX]; program_path[0] = 0; if (run_id < 0 || run_id >= run_get_total(state->runlog_state)) { errcode = -SRV_ERR_BAD_RUN_ID; goto cleanup; } run_get_entry(state->runlog_state, run_id, &info); if (info.status == RUN_VIRTUAL_START || info.status == RUN_VIRTUAL_STOP || info.status == RUN_EMPTY) { errcode = -SRV_ERR_BAD_RUN_ID; goto cleanup; } if (!is_privileged) { if (info.user_id != user_id) { errcode = -SRV_ERR_NO_PERMS; goto cleanup; } if (!global->enable_printing) { errcode = -SRV_ERR_NO_PERMS; goto cleanup; } if (info.pages > 0) { errcode = -SRV_ERR_ALREADY_PRINTED; goto cleanup; } } if (teamdb_export_team(state->teamdb_state, info.user_id, &teaminfo) < 0) return -1; if (teaminfo.user) ui = teaminfo.user->cnts0; if (!is_privileged) { if (ui && ui->printer_name) printer_name = ui->printer_name; } if (global->disable_banner_page <= 0) { banner_path = (unsigned char*) alloca(strlen(global->print_work_dir) + 64); sprintf(banner_path, "%s/%06d.txt", global->print_work_dir, run_id); if (print_banner_page(state, banner_path, run_id, user_id, is_privileged) < 0) { goto cleanup; } } if (global->disable_banner_page > 0) { if (state->langs[info.lang_id]) sfx = state->langs[info.lang_id]->src_sfx; if (global->printout_uses_login > 0) { user_name = teamdb_get_login(state->teamdb_state, info.user_id); } else { user_name = teamdb_get_name_2(state->teamdb_state, info.user_id); } if (!user_name) user_name = ""; location = ""; if (ui && ui->location) location = ui->location; unsigned char fixed_user_name[PATH_MAX]; unsigned char fixed_location[PATH_MAX]; fix_path_component(fixed_user_name, sizeof(fixed_user_name), user_name); fix_path_component(fixed_location, sizeof(fixed_location), location); snprintf(program_path, sizeof(program_path), "%s/%06d_%s_%s%s", global->print_work_dir, run_id, fixed_user_name, fixed_location, sfx); } else { if (state->langs[info.lang_id]) sfx = state->langs[info.lang_id]->src_sfx; snprintf(program_path, sizeof(program_path), "%s/%06d%s", global->print_work_dir, run_id, sfx); } arch_flags = serve_make_source_read_path(state, run_arch, sizeof(run_arch), &info); if (arch_flags < 0) { goto cleanup; } if (generic_copy_file(arch_flags, 0, run_arch, "", 0, 0, program_path, 0) < 0) { goto cleanup; } ps_path = (unsigned char*) alloca(strlen(global->print_work_dir) + 64); sprintf(ps_path, "%s/%06d.ps", global->print_work_dir, run_id); log_path = (unsigned char*) alloca(strlen(global->print_work_dir) + 64); sprintf(log_path, "%s/%06d.out", global->print_work_dir, run_id); if (!(tsk = task_New())) goto cleanup; task_AddArg(tsk, global->a2ps_path); if (global->a2ps_args) { for (i = 0; global->a2ps_args[i]; i++) task_AddArg(tsk, global->a2ps_args[i]); } else { task_AddArg(tsk, "-1"); task_AddArg(tsk, "-E"); /* task_AddArg(tsk, "-X"); task_AddArg(tsk, "koi8-r"); */ } task_AddArg(tsk, "-o"); task_AddArg(tsk, ps_path); if (global->disable_banner_page <= 0) { task_AddArg(tsk, banner_path); } task_AddArg(tsk, program_path); task_SetPathAsArg0(tsk); task_SetRedir(tsk, 2, TSR_FILE, log_path, O_WRONLY|O_CREAT|O_TRUNC, 0777); task_ClearEnv(tsk); if (task_Start(tsk) < 0) goto cleanup; task_Wait(tsk); task_Delete(tsk); tsk = 0; if (!(f = fopen(log_path, "r"))) goto cleanup; while (fgets(in_buf, sizeof(in_buf), f)) { in_buf_len = strlen(in_buf); if (in_buf_len > sizeof(in_buf) - 5) continue; if (!strncmp(in_buf, "[Total:", 7)) { if (sscanf(in_buf, "[Total: %d pages", &x) == 1 && x >= 1 && x < 100000) { pages_num = x; break; } } } fclose(f); f = 0; if (pages_num <= 0) goto cleanup; if (!is_privileged) { if (pages_num + run_get_total_pages(state->runlog_state, info.user_id) > global->team_page_quota) { errcode = -SRV_ERR_PAGES_QUOTA; goto cleanup; } run_set_pages(state->runlog_state, run_id, pages_num); } if (!(tsk = task_New())) goto cleanup; task_AddArg(tsk, global->lpr_path); if (global->lpr_args) { for (i = 0; global->lpr_args[i]; i++) task_AddArg(tsk, global->lpr_args[i]); } if (printer_name) { task_AddArg(tsk, "-P"); task_AddArg(tsk, printer_name); } task_AddArg(tsk, ps_path); task_SetPathAsArg0(tsk); if (task_Start(tsk) < 0) goto cleanup; task_Wait(tsk); task_Delete(tsk); tsk = 0; unlink(banner_path); unlink(program_path); unlink(ps_path); unlink(log_path); return pages_num; cleanup: if (tsk) task_Delete(tsk); if (banner_path) unlink(banner_path); if (program_path[0]) unlink(program_path); if (ps_path) unlink(ps_path); if (log_path) unlink(log_path); return errcode; }
static int check_style_only( const struct section_global_data *global, struct compile_request_packet *req, struct compile_reply_packet *rpl, const unsigned char *pkt_name, const unsigned char *run_name, const unsigned char *work_run_name, const unsigned char *report_dir, const unsigned char *status_dir) { void *reply_bin = 0; size_t reply_bin_size = 0; unsigned char msgbuf[1024] = { 0 }; path_t log_path; path_t txt_path; path_t work_src_path; path_t work_log_path; int r, i; const unsigned char *src_sfx = ""; tpTask tsk = 0; // input file: ${global->compile_src_dir}/${pkt_name}${req->src_sfx} // output log file: ${report_dir}/${run_name} // file listing: ${report_dir}/${run_name} (if OK status) // working directory: ${global->compile_work_dir} snprintf(log_path, sizeof(log_path), "%s/%s", report_dir, run_name); snprintf(txt_path, sizeof(txt_path), "%s/%s.txt", report_dir, run_name); if (req->src_sfx) src_sfx = req->src_sfx; snprintf(work_src_path, sizeof(work_src_path), "%s/%s%s", global->compile_work_dir, work_run_name, src_sfx); snprintf(work_log_path, sizeof(work_log_path), "%s/%s.log", global->compile_work_dir, work_run_name); r = generic_copy_file(REMOVE, global->compile_src_dir, pkt_name, src_sfx, 0, global->compile_work_dir, work_run_name, src_sfx); if (!r) { snprintf(msgbuf, sizeof(msgbuf), "The source file %s/%s%s is missing.\n", global->compile_src_dir, pkt_name, src_sfx); goto internal_error; } if (r < 0) { snprintf(msgbuf, sizeof(msgbuf), "Read error on the source file %s/%s%s is missing.\n", global->compile_src_dir, pkt_name, src_sfx); goto internal_error; } //info("Starting: %s %s", req->style_checker, work_src_path); tsk = task_New(); task_AddArg(tsk, req->style_checker); task_AddArg(tsk, work_src_path); task_SetPathAsArg0(tsk); task_SetWorkingDir(tsk, global->compile_work_dir); task_EnableProcessGroup(tsk); task_SetRedir(tsk, 0, TSR_FILE, "/dev/null", TSK_READ); task_SetRedir(tsk, 1, TSR_FILE, work_log_path, TSK_REWRITE, 0777); task_SetRedir(tsk, 2, TSR_DUP, 1); if (req->sc_env_num > 0) { for (i = 0; i < req->sc_env_num; i++) task_PutEnv(tsk, req->sc_env_vars[i]); } task_EnableAllSignals(tsk); task_PrintArgs(tsk); if (task_Start(tsk) < 0) { err("Failed to start style checker process"); snprintf(msgbuf, sizeof(msgbuf), "Failed to start style checker %s\n", req->style_checker); goto internal_error; } task_Wait(tsk); if (task_IsTimeout(tsk)) { err("Style checker process is timed out"); snprintf(msgbuf, sizeof(msgbuf), "Style checker %s process timeout\n", req->style_checker); goto internal_error; } r = task_Status(tsk); if (r != TSK_EXITED && r != TSK_SIGNALED) { err("Style checker invalid task status"); snprintf(msgbuf, sizeof(msgbuf), "Style checker %s invalid task status %d\n", req->style_checker, r); goto internal_error; } if (r == TSK_SIGNALED) { err("Style checker terminated by signal"); snprintf(msgbuf, sizeof(msgbuf), "Style checker %s terminated by signal %d\n", req->style_checker, task_TermSignal(tsk)); goto internal_error; } r = task_ExitCode(tsk); if (r != 0 && r != RUN_COMPILE_ERR && r != RUN_PRESENTATION_ERR && r != RUN_WRONG_ANSWER_ERR && r != RUN_STYLE_ERR) { err("Invalid style checker exit code"); snprintf(msgbuf, sizeof(msgbuf), "Style checker %s exit code %d\n", req->style_checker, r); goto internal_error; } if (r) { // style checker error rpl->status = RUN_STYLE_ERR; get_current_time(&rpl->ts3, &rpl->ts3_us); generic_copy_file(0, 0, work_log_path, "", 0, 0, log_path, ""); generic_copy_file(0, 0, work_log_path, "", 0, 0, txt_path, ""); } else { // success rpl->status = RUN_OK; get_current_time(&rpl->ts3, &rpl->ts3_us); generic_copy_file(0, 0, work_log_path, "", 0, 0, txt_path, ""); } if (compile_reply_packet_write(rpl, &reply_bin_size, &reply_bin) < 0) goto cleanup; // ignore error: we cannot do anything anyway generic_write_file(reply_bin, reply_bin_size, SAFE, status_dir, run_name, 0); cleanup: task_Delete(tsk); tsk = 0; xfree(reply_bin); reply_bin = 0; req = compile_request_packet_free(req); clear_directory(global->compile_work_dir); return 0; internal_error: rpl->status = RUN_CHECK_FAILED; get_current_time(&rpl->ts3, &rpl->ts3_us); if (compile_reply_packet_write(rpl, &reply_bin_size, &reply_bin) < 0) goto cleanup; if (generic_write_file(msgbuf, strlen(msgbuf), 0, 0, log_path, 0) < 0) goto cleanup; if (generic_write_file(reply_bin, reply_bin_size, SAFE, status_dir, run_name, 0) < 0) { unlink(log_path); } goto cleanup; }
static int run_program( const struct nwrun_in_packet *packet, const unsigned char *program_path, const unsigned char *input_path, const unsigned char *output_path, const unsigned char *error_path, struct nwrun_out_packet *result) { tpTask tsk = 0; tsk = task_New(); if (!tsk) { snprintf(result->comment, sizeof(result->comment), "cannot create a new task"); return RUN_CHECK_FAILED; } task_AddArg(tsk, program_path); task_SetPathAsArg0(tsk); task_SetWorkingDir(tsk, global->work_dir); if (packet->disable_stdin > 0) { task_SetRedir(tsk, 0, TSR_FILE, "/dev/null", TSK_READ); } else if (packet->redirect_stdin > 0 || packet->combined_stdin > 0) { task_SetRedir(tsk, 0, TSR_FILE, input_path, TSK_READ); } if (packet->ignore_stdout > 0) { task_SetRedir(tsk, 1, TSR_FILE, "/dev/null", TSK_WRITE, TSK_FULL_RW); } else if (packet->redirect_stdout > 0 || packet->combined_stdout > 0) { task_SetRedir(tsk, 1, TSR_FILE, output_path, TSK_REWRITE, TSK_FULL_RW); } if (packet->ignore_stderr > 0) { task_SetRedir(tsk, 2, TSR_FILE, "/dev/null", TSK_WRITE, TSK_FULL_RW); } else if (packet->redirect_stderr > 0) { task_SetRedir(tsk, 2, TSR_FILE, error_path, TSK_REWRITE, TSK_FULL_RW); } if (packet->time_limit_millis > 0) { task_SetMaxTimeMillis(tsk, packet->time_limit_millis); } if (packet->real_time_limit_millis > 0) { task_SetMaxRealTime(tsk, (packet->real_time_limit_millis + 999) / 1000); } if (packet->max_stack_size > 0) { task_SetStackSize(tsk, packet->max_stack_size); } if (packet->max_data_size > 0) { task_SetDataSize(tsk, packet->max_data_size); } if (packet->max_vm_size > 0) { task_SetVMSize(tsk, packet->max_vm_size); } task_SetMaxProcessCount(tsk, 1); if (packet->enable_secure_run > 0) { task_EnableSecureExec(tsk); } if (packet->enable_secure_run > 0 && packet->enable_memory_limit_error > 0) { task_EnableMemoryLimitError(tsk); } if (packet->enable_secure_run > 0 && packet->enable_security_violation_error > 0) { task_EnableSecurityViolationError(tsk); } task_EnableAllSignals(tsk); if (task_Start(tsk) < 0) { snprintf(result->comment, sizeof(result->comment), "task start is failed"); task_Delete(tsk); return RUN_CHECK_FAILED; } task_Wait(tsk); result->cpu_time_millis = task_GetRunningTime(tsk); result->real_time_available = 1; result->real_time_millis = task_GetRealTime(tsk); result->max_memory_used = task_GetMemoryUsed(tsk); result->comment[0] = 0; if (packet->enable_secure_run > 0 && packet->enable_memory_limit_error > 0 && task_IsMemoryLimit(tsk)) { task_Delete(tsk); return RUN_MEM_LIMIT_ERR; } if (packet->enable_secure_run > 0 && packet->enable_security_violation_error && task_IsSecurityViolation(tsk)) { task_Delete(tsk); return RUN_SECURITY_ERR; } if (task_IsTimeout(tsk)) { task_Delete(tsk); return RUN_TIME_LIMIT_ERR; } if (task_Status(tsk) == TSK_SIGNALED) { result->is_signaled = 1; result->signal_num = task_TermSignal(tsk); snprintf(result->exit_comment, sizeof(result->exit_comment), "%s", os_GetSignalString(result->signal_num)); task_Delete(tsk); return RUN_RUN_TIME_ERR; } result->exit_code = task_ExitCode(tsk); task_Delete(tsk); return result->exit_code == 0 ? RUN_OK : RUN_RUN_TIME_ERR; }
static int do_loop(void) { path_t src_name; path_t exe_name; path_t src_path; path_t exe_path; path_t log_path; path_t exe_out; path_t log_out; path_t txt_out; path_t report_dir, status_dir; path_t pkt_name, run_name, work_run_name; char *pkt_ptr; size_t pkt_len; int r, i; tpTask tsk = 0; unsigned char msgbuf[512]; int ce_flag; struct compile_request_packet *req = 0; struct compile_reply_packet rpl; void *rpl_pkt = 0; size_t rpl_size = 0; const unsigned char *tail_message = 0; #if HAVE_TRUNCATE - 0 struct stat stb; #endif /* HAVE_TRUNCATE */ FILE *log_f = 0; struct section_language_data *lang = 0; const struct section_global_data *global = serve_state.global; // if (cr_serialize_init(&serve_state) < 0) return -1; interrupt_init(); interrupt_disable(); while (1) { // terminate if signaled if (interrupt_get_status() || interrupt_restart_requested()) break; r = scan_dir(global->compile_queue_dir, pkt_name, sizeof(pkt_name)); if (r < 0) { switch (-r) { case ENOMEM: case ENOENT: case ENFILE: err("trying to recover, sleep for 5 seconds"); interrupt_enable(); os_Sleep(5000); interrupt_disable(); continue; default: err("unrecoverable error, exiting"); return -1; } } if (!r) { interrupt_enable(); os_Sleep(global->sleep_time); interrupt_disable(); continue; } pkt_ptr = 0; pkt_len = 0; r = generic_read_file(&pkt_ptr, 0, &pkt_len, SAFE | REMOVE, global->compile_queue_dir, pkt_name, ""); if (r == 0) continue; if (r < 0 || !pkt_ptr) { // it looks like there's no reasonable recovery strategy // so, just ignore the error continue; } r = compile_request_packet_read(pkt_len, pkt_ptr, &req); xfree(pkt_ptr); pkt_ptr = 0; if (r < 0) { /* * the incoming packet is completely broken, so just drop it */ goto cleanup_and_continue; } if (!req->contest_id) { // special packets r = req->lang_id; req = compile_request_packet_free(req); switch (r) { case 1: interrupt_flag_interrupt(); break; case 2: interrupt_flag_sighup(); break; } continue; } memset(&rpl, 0, sizeof(rpl)); rpl.judge_id = req->judge_id; rpl.contest_id = req->contest_id; rpl.run_id = req->run_id; rpl.ts1 = req->ts1; rpl.ts1_us = req->ts1_us; rpl.use_uuid = req->use_uuid; rpl.uuid[0] = req->uuid[0]; rpl.uuid[1] = req->uuid[1]; rpl.uuid[2] = req->uuid[2]; rpl.uuid[3] = req->uuid[3]; get_current_time(&rpl.ts2, &rpl.ts2_us); rpl.run_block_len = req->run_block_len; rpl.run_block = req->run_block; /* !!! shares memory with req */ msgbuf[0] = 0; /* prepare paths useful to report messages to the serve */ snprintf(report_dir, sizeof(report_dir), "%s/%06d/report", global->compile_dir, rpl.contest_id); snprintf(status_dir, sizeof(status_dir), "%s/%06d/status", global->compile_dir, rpl.contest_id); if (req->use_uuid > 0) { snprintf(run_name, sizeof(run_name), "%s", ej_uuid_unparse(req->uuid, NULL)); } else { snprintf(run_name, sizeof(run_name), "%06d", rpl.run_id); } snprintf(work_run_name, sizeof(work_run_name), "%06d", rpl.run_id); pathmake(log_out, report_dir, "/", run_name, NULL); snprintf(txt_out, sizeof(txt_out), "%s/%s.txt", report_dir, run_name); make_all_dir(status_dir, 0777); make_dir(report_dir, 0777); if (!r) { /* * there is something wrong, but we have contest_id, judge_id * and run_id in place, so we can report an error back * to serve */ snprintf(msgbuf, sizeof(msgbuf), "invalid compile packet\n"); goto report_internal_error; } if (req->style_check_only && req->style_checker && req->style_checker[0]) { check_style_only(global, req, &rpl, pkt_name, run_name, work_run_name, report_dir, status_dir); req = 0; continue; } if (req->lang_id <= 0 || req->lang_id > serve_state.max_lang || !(lang = serve_state.langs[req->lang_id])) { snprintf(msgbuf, sizeof(msgbuf), "invalid lang_id %d\n", req->lang_id); goto report_internal_error; } pathmake(src_name, work_run_name, lang->src_sfx, NULL); pathmake(exe_name, work_run_name, lang->exe_sfx, NULL); pathmake(src_path, global->compile_work_dir, "/", src_name, NULL); pathmake(exe_path, global->compile_work_dir, "/", exe_name, NULL); pathmake(log_path, global->compile_work_dir, "/", "log", NULL); /* the resulting executable file */ snprintf(exe_out, sizeof(exe_out), "%s/%s%s", report_dir, run_name, lang->exe_sfx); /* move the source file into the working dir */ r = generic_copy_file(REMOVE, global->compile_src_dir, pkt_name, lang->src_sfx, 0, global->compile_work_dir, src_name, ""); if (!r) { snprintf(msgbuf, sizeof(msgbuf), "the source file is missing\n"); err("the source file is missing"); goto report_internal_error; } if (r < 0) { snprintf(msgbuf, sizeof(msgbuf), "error reading the source file\n"); err("cannot read the source file"); goto report_internal_error; } tail_message = 0; ce_flag = 0; if (req->output_only) { // copy src_path -> exe_path generic_copy_file(0, NULL, src_path, NULL, 0, NULL, exe_path, NULL); ce_flag = 0; rpl.status = RUN_OK; } else { if (req->style_checker) { /* run style checker */ //info("Starting: %s %s", req->style_checker, src_path); tsk = task_New(); task_AddArg(tsk, req->style_checker); task_AddArg(tsk, src_path); task_SetPathAsArg0(tsk); task_SetWorkingDir(tsk, global->compile_work_dir); task_EnableProcessGroup(tsk); task_SetRedir(tsk, 0, TSR_FILE, "/dev/null", TSK_READ); task_SetRedir(tsk, 1, TSR_FILE, log_path, TSK_REWRITE, 0777); task_SetRedir(tsk, 2, TSR_DUP, 1); if (req->sc_env_num > 0) { for (i = 0; i < req->sc_env_num; i++) task_PutEnv(tsk, req->sc_env_vars[i]); } if (lang->compile_real_time_limit > 0) { task_SetMaxRealTime(tsk, lang->compile_real_time_limit); } task_EnableAllSignals(tsk); task_PrintArgs(tsk); if (task_Start(tsk) < 0) { err("Failed to start style checker process"); tail_message = "\n\nFailed to start style checker"; ce_flag = 1; rpl.status = RUN_STYLE_ERR; } else { task_Wait(tsk); if (task_IsTimeout(tsk)) { err("Style checker process timed out"); tail_message = "\n\nStyle checker process timed out"; ce_flag = 1; rpl.status = RUN_STYLE_ERR; } else if (task_IsAbnormal(tsk)) { info("Style checker failed"); ce_flag = 1; rpl.status = RUN_STYLE_ERR; } else { info("Style checker sucessful"); ce_flag = 0; rpl.status = RUN_OK; } } task_Delete(tsk); tsk = 0; } if (!ce_flag) { //info("Starting: %s %s %s", lang->cmd, src_name, exe_name); tsk = task_New(); task_AddArg(tsk, lang->cmd); task_AddArg(tsk, src_name); task_AddArg(tsk, exe_name); task_SetPathAsArg0(tsk); task_EnableProcessGroup(tsk); if (((ssize_t) req->max_vm_size) > 0) { task_SetVMSize(tsk, req->max_vm_size); } else if (((ssize_t) lang->max_vm_size) > 0) { task_SetVMSize(tsk, lang->max_vm_size); } else if (((ssize_t) global->compile_max_vm_size) > 0) { task_SetVMSize(tsk, global->compile_max_vm_size); } if (((ssize_t) req->max_stack_size) > 0) { task_SetStackSize(tsk, req->max_stack_size); } else if (((ssize_t) lang->max_stack_size) > 0) { task_SetStackSize(tsk, lang->max_stack_size); } else if (((ssize_t) global->compile_max_stack_size) > 0) { task_SetStackSize(tsk, global->compile_max_stack_size); } if (((ssize_t) req->max_file_size) > 0) { task_SetMaxFileSize(tsk, req->max_file_size); } else if (((ssize_t) lang->max_file_size) > 0) { task_SetMaxFileSize(tsk, lang->max_file_size); } else if (((ssize_t) global->compile_max_file_size) > 0) { task_SetMaxFileSize(tsk, global->compile_max_file_size); } if (req->env_num > 0) { for (i = 0; i < req->env_num; i++) task_PutEnv(tsk, req->env_vars[i]); } task_SetWorkingDir(tsk, global->compile_work_dir); task_SetRedir(tsk, 0, TSR_FILE, "/dev/null", TSK_READ); task_SetRedir(tsk, 1, TSR_FILE, log_path, TSK_APPEND, 0777); task_SetRedir(tsk, 2, TSR_DUP, 1); if (lang->compile_real_time_limit > 0) { task_SetMaxRealTime(tsk, lang->compile_real_time_limit); } task_EnableAllSignals(tsk); /* if (cr_serialize_lock(&serve_state) < 0) { // FIXME: propose reasonable recovery? return -1; } */ task_PrintArgs(tsk); task_Start(tsk); task_Wait(tsk); /* if (cr_serialize_unlock(&serve_state) < 0) { // FIXME: propose reasonable recovery? return -1; } */ if (task_IsTimeout(tsk)) { err("Compilation process timed out"); tail_message = "\n\nCompilation process timed out"; ce_flag = 1; rpl.status = RUN_COMPILE_ERR; } else if (task_IsAbnormal(tsk)) { info("Compilation failed"); ce_flag = 1; rpl.status = RUN_COMPILE_ERR; } else { info("Compilation sucessful"); ce_flag = 0; rpl.status = RUN_OK; } } } get_current_time(&rpl.ts3, &rpl.ts3_us); if (compile_reply_packet_write(&rpl, &rpl_size, &rpl_pkt) < 0) goto cleanup_and_continue; while (1) { if (ce_flag) { #if HAVE_TRUNCATE - 0 // truncate log file at size 1MB if (stat(log_path, &stb) >= 0 && stb.st_size > MAX_LOG_SIZE) { truncate(log_path, MAX_LOG_SIZE); if ((log_f = fopen(log_path, "a"))) { fprintf(log_f, "\n\nCompilation log is truncated by ejudge!\n"); fclose(log_f); log_f = 0; } } #endif // append tail_message if (tail_message && (log_f = fopen(log_path, "a"))) { fprintf(log_f, "%s\n", tail_message); fclose(log_f); log_f = 0; } r = generic_copy_file(0, 0, log_path, "", 0, 0, log_out, ""); } else { r = generic_copy_file(0, 0, exe_path, "", 0, 0, exe_out, ""); generic_copy_file(0, 0, log_path, "", 0, 0, txt_out, ""); } if (r >= 0 && generic_write_file(rpl_pkt, rpl_size, SAFE, status_dir, run_name, "") >= 0) break; info("waiting 5 seconds hoping for things to change"); interrupt_enable(); os_Sleep(5000); interrupt_disable(); } goto cleanup_and_continue; report_internal_error:; rpl.status = RUN_CHECK_FAILED; get_current_time(&rpl.ts3, &rpl.ts3_us); if (compile_reply_packet_write(&rpl, &rpl_size, &rpl_pkt) < 0) goto cleanup_and_continue; if (generic_write_file(msgbuf, strlen(msgbuf), 0, 0, log_out, 0) < 0) goto cleanup_and_continue; if (generic_write_file(rpl_pkt, rpl_size, SAFE, status_dir, run_name, 0) < 0) unlink(log_out); goto cleanup_and_continue; cleanup_and_continue:; task_Delete(tsk); tsk = 0; clear_directory(global->compile_work_dir); xfree(rpl_pkt); rpl_pkt = 0; req = compile_request_packet_free(req); } /* while (1) */ return 0; }
static int run_program(int argc, char *argv[], long *p_cpu_time, long *p_real_time) { tTask *tsk = 0; int i; int retcode = RUN_CHECK_FAILED; struct testinfo_struct tinfo; unsigned char input_path[PATH_MAX]; unsigned char output_path[PATH_MAX]; unsigned char error_path[PATH_MAX]; unsigned char buf[1024]; long used_vm_size; memset(&tinfo, 0, sizeof(tinfo)); input_path[0] = 0; output_path[0] = 0; error_path[0] = 0; if (!all_tests) { if (test_file && test_file[0] && test_pattern && test_pattern[0]) { // guess test_num from test_file and test_pat // FIXME: dumb! i = 0; do { ++i; snprintf(buf, sizeof(buf), test_pattern, i); } while (i < 1000 && strcmp(buf, test_file) != 0); if (i >= 1000) { fatal("failed to guess test_num from test_file and test_pattern"); } test_num = i; test_file = NULL; } if (test_num > 0) { if (test_pattern && test_pattern[0]) { snprintf(buf, sizeof(buf), test_pattern, test_num); test_file = strdup(buf); } if (corr_pattern && corr_pattern[0]) { snprintf(buf, sizeof(buf), corr_pattern, test_num); corr_file = strdup(buf); } if (info_pattern && info_pattern[0]) { snprintf(buf, sizeof(buf), info_pattern, test_num); info_file = strdup(buf); } if (tgzdir_pattern && tgzdir_pattern[0]) { snprintf(buf, sizeof(buf), tgzdir_pattern, test_num); tgzdir_file = strdup(buf); } } } if (info_file && (i = testinfo_parse(info_file, &tinfo, NULL)) < 0) { fatal("testinfo file parse error: %s", testinfo_strerror(-i)); } if (test_file) { if (!input_file || !input_file[0]) input_file = DEFAULT_INPUT_FILE_NAME; if (working_dir && working_dir[0]) { snprintf(input_path, sizeof(input_path), "%s/%s", working_dir, input_file); } else { snprintf(input_path, sizeof(input_path), "%s", input_file); } } if (corr_file) { if (!output_file || !output_file[0]) output_file = DEFAULT_OUTPUT_FILE_NAME; if (working_dir && working_dir[0]) { snprintf(output_path, sizeof(output_path), "%s/%s", working_dir, output_file); } else { snprintf(output_path, sizeof(output_path), "%s", output_file); } } if (info_file && tinfo.check_stderr > 0) { error_file = DEFAULT_ERROR_FILE_NAME; if (working_dir && working_dir[0]) { snprintf(error_path, sizeof(error_path), "%s/%s", working_dir, error_file); } else { snprintf(error_path, sizeof(error_path), "%s", error_file); } } if (!(tsk = task_New())) fatal("cannot create task"); task_SetQuietFlag(tsk); task_pnAddArgs(tsk, argc, argv); task_pnAddArgs(tsk, tinfo.cmd_argc, tinfo.cmd_argv); task_SetPathAsArg0(tsk); if (working_dir) task_SetWorkingDir(tsk, working_dir); if (test_file) { if (copy_file(NULL, test_file, working_dir, input_file, -1, -1) < 0) fatal("copy failed"); if (use_stdin) task_SetRedir(tsk, 0, TSR_FILE, input_path, TSK_READ); } else { if (stdin_file) task_SetRedir(tsk, 0, TSR_FILE, stdin_file, TSK_READ); } if (corr_file) { if (use_stdout) task_SetRedir(tsk, 1, TSR_FILE, output_path, TSK_REWRITE, TSK_FULL_RW); } else { if (stdout_file) task_SetRedir(tsk, 1, TSR_FILE, stdout_file, TSK_REWRITE, TSK_FULL_RW); } if (info_file && tinfo.check_stderr > 0) { task_SetRedir(tsk, 2, TSR_FILE, error_path, TSK_REWRITE, TSK_FULL_RW); } else { if (stderr_file) task_SetRedir(tsk, 2, TSR_FILE, stderr_file, TSK_REWRITE, TSK_FULL_RW); } if (clear_env_flag) task_ClearEnv(tsk); for (i = 0; i < env_vars.u; i++) task_PutEnv(tsk, env_vars.v[i]); for (i = 0; i < tinfo.env_u; ++i) { task_PutEnv(tsk, tinfo.env_v[i]); } if (time_limit_millis > 0) if (task_SetMaxTimeMillis(tsk, time_limit_millis) < 0) fatal("--time-limit-millis is not supported"); if (time_limit > 0) task_SetMaxTime(tsk, time_limit); if (real_time_limit > 0) task_SetMaxRealTime(tsk, real_time_limit); if (kill_signal) if (task_SetKillSignal(tsk, kill_signal) < 0) fatal("invalid value for --kill-signal option"); if (no_core_dump) task_DisableCoreDump(tsk); if (max_vm_size) task_SetVMSize(tsk, max_vm_size); if (max_stack_size) task_SetStackSize(tsk, max_stack_size); if (max_data_size) task_SetDataSize(tsk, max_data_size); if (memory_limit) if (task_EnableMemoryLimitError(tsk) < 0) fatal("--memory-limit is not supported"); if (secure_exec) if (task_EnableSecureExec(tsk) < 0) fatal("--secure-exec is not supported"); if (security_violation) if (task_EnableSecurityViolationError(tsk) < 0) fatal("--security-violation is not supported"); task_PrintArgs(tsk); if (task_Start(tsk) < 0) { fprintf(stderr, "Status: CF\n" "Description: cannot start task: %s\n", task_GetErrorMessage(tsk)); retcode = RUN_CHECK_FAILED; goto cleanup; } task_NewWait(tsk); if (memory_limit && task_IsMemoryLimit(tsk)) { if (all_tests <= 0) { fprintf(stderr, "Status: ML\n" "Description: memory limit exceeded\n"); } retcode = RUN_MEM_LIMIT_ERR; } else if (security_violation && task_IsSecurityViolation(tsk)) { if (all_tests <= 0) { fprintf(stderr, "Status: SV\n" "Description: security violation\n"); } retcode = RUN_SECURITY_ERR; } else if (task_IsTimeout(tsk)) { if (all_tests <= 0) { fprintf(stderr, "Status: TL\n" "Description: time limit exceeded\n"); } retcode = RUN_TIME_LIMIT_ERR; } else if (task_IsAbnormal(tsk) && (!info_file || tinfo.exit_code <= 0 || task_Status(tsk) != TSK_EXITED || task_ExitCode(tsk) != tinfo.exit_code)) { if (all_tests <= 0) { fprintf(stderr, "Status: RT\n"); if (task_Status(tsk) == TSK_SIGNALED) { fprintf(stderr, "Signal: %d\n", task_TermSignal(tsk)); } else { fprintf(stderr, "Exitcode: %d\n", task_ExitCode(tsk)); } fprintf(stderr, "Description: run-time error\n"); } retcode = RUN_RUN_TIME_ERR; } else { if (info_file && tinfo.check_stderr > 0) { if (copy_file(working_dir, error_file, NULL, corr_file, group, mode) < 0) { fprintf(stderr, "Status: PE\n"); } else { if (quiet_flag <= 0 && all_tests <= 0) fprintf(stderr, "Status: OK\n"); retcode = 0; } } else if (corr_file && update_corr > 0) { if (copy_file(working_dir, output_file, NULL, corr_file, group, mode) < 0) { fprintf(stderr, "Status: PE\n"); } else { if (quiet_flag <= 0 && all_tests <= 0) fprintf(stderr, "Status: OK\n"); retcode = 0; } } else { if (quiet_flag <= 0 && all_tests <= 0) fprintf(stderr, "Status: OK\n"); retcode = 0; } } if (quiet_flag <= 0 && all_tests <= 0) { fprintf(stderr, "CPUTime: %ld\n", task_GetRunningTime(tsk)); fprintf(stderr, "RealTime: %ld\n", task_GetRealTime(tsk)); used_vm_size = task_GetMemoryUsed(tsk); if (used_vm_size > 0) { fprintf(stderr, "VMSize: %ld\n", used_vm_size); } } if (p_cpu_time) *p_cpu_time = task_GetRunningTime(tsk); if (p_real_time) *p_real_time = task_GetRealTime(tsk); cleanup: task_Delete(tsk); tsk = NULL; if (input_path[0]) unlink(input_path); if (output_path[0]) unlink(output_path); if (error_path[0]) unlink(error_path); return retcode; }