From efcdac7769bb36f57abeddab6449b7ec5399002a Mon Sep 17 00:00:00 2001 From: MeiK Date: Mon, 16 Nov 2020 18:16:40 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E9=85=8D=E7=BD=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ Cargo.toml | 3 +++ README.md | 3 --- languages.template.yaml | 44 ++++++++++++++++++++++++++++++++++++ src/config.rs | 45 +++++++++++++++++++++++++++++++++++++ src/judger.rs | 49 +++++++++-------------------------------- 6 files changed, 105 insertions(+), 41 deletions(-) create mode 100644 languages.template.yaml diff --git a/.gitignore b/.gitignore index 4c05e3b..6db6390 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ Cargo.lock .devcontainer nohup.out + +languages.yaml diff --git a/Cargo.toml b/Cargo.toml index 1bc54e3..f12c5f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,9 @@ libc = "0.2.76" log = "0.4.0" env_logger = "0.8.1" nix = "0.19.0" +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.8" +lazy_static = "1.4.0" [build-dependencies] tonic-build ={ version = "0.3" } diff --git a/README.md b/README.md index b998dc3..48138a1 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,11 @@ python3 main.py 已经完成基本功能,后续需要优化 -- 基于 ptrace 的精准内存测量 - 基于 cgroups 的资源控制 - 用户、组限制 -- 示例代码 - 安全测试 - 优化 args 生成代码,减少测量出的用户代码执行时间 - special judge - docker 部署 - 更多语言支持 -- 使用配置文件配置语言 - 使用环境变量等机制自定义评测目录 diff --git a/languages.template.yaml b/languages.template.yaml new file mode 100644 index 0000000..c9160ef --- /dev/null +++ b/languages.template.yaml @@ -0,0 +1,44 @@ +# 因为需要与 proto 保持同步,此处暂时不支持自定义增加语言 +# 如果要增加语言,需要修改 proto 并重新编译程序 +C: + compile_cmd: /usr/bin/gcc main.c -o a.out -Wall -O2 -std=c99 --static + code_file: main.c + run_cmd: ./a.out + +Cpp: + compile_cmd: /usr/bin/g++ main.cpp -O2 -Wall --static -o a.out --std=gnu++17 + code_file: main.cpp + run_cmd: ./a.out + +Python: + compile_cmd: /usr/bin/python3.8 -m compileall main.py + code_file: main.py + run_cmd: /usr/bin/python3.8 main.py + +Rust: + # compile_cmd: /root/.cargo/bin/rustc main.rs -o a.out -C opt-level=2 + compile_cmd: /home/MeiK/.cargo/bin/rustc main.rs -o a.out -C opt-level=2 + code_file: main.rs + run_cmd: ./a.out + +Node: + # compile_cmd: /usr/bin/node /plugins/js/validate.js main.js + compile_cmd: /home/MeiK/.nvm/versions/node/v13.12.0/bin/node /home/MeiK/river/plugins/js/validate.js main.js + code_file: main.js + run_cmd: /home/MeiK/.nvm/versions/node/v13.12.0/bin/node main.js + +TypeScript: + # compile_cmd: /usr/bin/tsc main.ts + compile_cmd: /home/MeiK/.nvm/versions/node/v13.12.0/bin/tsc main.ts + code_file: main.ts + run_cmd: /home/MeiK/.nvm/versions/node/v13.12.0/bin/node main.js + +Go: + compile_cmd: /usr/bin/go build -o a.out main.go + code_file: main.go + run_cmd: ./a.out + +Java: + compile_cmd: /usr/bin/javac Main.java + code_file: Main.java + run_cmd: /usr/bin/java -cp . Main diff --git a/src/config.rs b/src/config.rs index 2e96fff..235a8ab 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,48 @@ +use crate::river::Language; +use lazy_static::lazy_static; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +use std::fs; + pub static STDIN_FILENAME: &str = "stdin.txt"; pub static STDOUT_FILENAME: &str = "stdout.txt"; pub static STDERR_FILENAME: &str = "stderr.txt"; + +lazy_static! { + pub static ref LANGUAGES: HashMap = { + let config = fs::read_to_string("languages.yaml").unwrap(); + let ls: Languages = serde_yaml::from_str(&config).unwrap(); + let mut m = HashMap::new(); + // add language + m.insert(Language::C as i32, ls.C); + m.insert(Language::Cpp as i32, ls.Cpp); + m.insert(Language::Python as i32, ls.Python); + m.insert(Language::Rust as i32, ls.Rust); + m.insert(Language::Node as i32, ls.Node); + m.insert(Language::TypeScript as i32, ls.TypeScript); + m.insert(Language::Go as i32, ls.Go); + m.insert(Language::Java as i32, ls.Java); + m + }; +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct LanguageConf { + pub compile_cmd: String, + pub code_file: String, + pub run_cmd: String, +} + +#[allow(non_snake_case)] +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct Languages { + C: LanguageConf, + Cpp: LanguageConf, + Python: LanguageConf, + Rust: LanguageConf, + Node: LanguageConf, + TypeScript: LanguageConf, + Go: LanguageConf, + Java: LanguageConf, +} diff --git a/src/judger.rs b/src/judger.rs index 34de440..c8a50f6 100644 --- a/src/judger.rs +++ b/src/judger.rs @@ -1,4 +1,4 @@ -use super::config::{STDERR_FILENAME, STDOUT_FILENAME}; +use super::config::{LANGUAGES, STDERR_FILENAME, STDOUT_FILENAME}; use super::error::{Error, Result}; use super::process::Process; use super::runner::RunnerStatus; @@ -35,26 +35,18 @@ pub async fn judger( path: &Path, ) -> Result { let mut resp = JudgeResponse::new(); - // TODO: 使用配置文件 - let cmd = match Language::from_i32(request.language) { - Some(Language::C) => "./a.out", - Some(Language::Cpp) => "./a.out", - Some(Language::Python) => "/usr/bin/python3.8 main.py", - Some(Language::Rust) => "./a.out", - Some(Language::Node) => "/usr/bin/node main.js", - Some(Language::TypeScript) => "/usr/bin/node main.js", - Some(Language::Go) => "./a.out", - Some(Language::Java) => "/usr/bin/java -cp . Main", + let conf = match LANGUAGES.get(&request.language) { + Some(c) => c, None => return Err(Error::LanguageNotFound(request.language)), }; let process = Process::new( - cmd.to_string(), + conf.run_cmd.to_string(), path.to_path_buf(), &data.in_data, data.time_limit, data.memory_limit, )?; - debug!("run command: {}", cmd); + debug!("run command: {}", conf.run_cmd); // 开始执行并等待返回结果 let mut runner = process.runner.clone(); @@ -112,38 +104,19 @@ pub async fn compile( path: &Path, ) -> Result { let mut resp = JudgeResponse::new(); - // 写入代码 - let filename = match Language::from_i32(request.language) { - Some(Language::C) => "main.c", - Some(Language::Cpp) => "main.cpp", - Some(Language::Python) => "main.py", - Some(Language::Rust) => "main.rs", - Some(Language::Node) => "main.js", - Some(Language::TypeScript) => "main.ts", - Some(Language::Go) => "main.go", - Some(Language::Java) => "Main.java", + let conf = match LANGUAGES.get(&request.language) { + Some(c) => c, None => return Err(Error::LanguageNotFound(request.language)), }; - if let Err(e) = fs::write(path.join(filename), &data.code).await { + // 写入代码 + if let Err(e) = fs::write(path.join(&conf.code_file), &data.code).await { return Err(Error::FileWriteError(e)); }; - // TODO: 使用配置文件 - let cmd = match Language::from_i32(request.language) { - Some(Language::C) => "/usr/bin/gcc main.c -o a.out -Wall -O2 -std=c99 --static", - Some(Language::Cpp) => "/usr/bin/g++ main.cpp -O2 -Wall --static -o a.out --std=gnu++17", - Some(Language::Python) => "/usr/bin/python3.8 -m compileall main.py", - Some(Language::Rust) => "/root/.cargo/bin/rustc main.rs -o a.out -C opt-level=2", - Some(Language::Node) => "/usr/bin/node /plugins/js/validate.js main.js", - Some(Language::TypeScript) => "/usr/bin/tsc main.ts", - Some(Language::Go) => "/usr/bin/go build -o a.out main.go", - Some(Language::Java) => "/usr/bin/javac Main.java", - None => return Err(Error::LanguageNotFound(request.language)), - }; - debug!("build command: {}", cmd); + debug!("build command: {}", conf.compile_cmd); let v = vec![]; let process = Process::new( - cmd.to_string(), + conf.compile_cmd.to_string(), path.to_path_buf(), &v, // 编译的资源限制为固定的