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,
// 编译的资源限制为固定的