mirror of
https://github.com/QingdaoU/Judger.git
synced 2024-12-27 15:31:41 +00:00
use popen to run libjudger.so ✨
This commit is contained in:
parent
1dce5f71e3
commit
d54b84ab58
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,3 +8,4 @@ __pycache__
|
||||
*.pyc
|
||||
cmake-build-debug/
|
||||
.ycm_extra_conf.py
|
||||
node_modules/
|
||||
|
@ -1,18 +0,0 @@
|
||||
/*-----------------
|
||||
* author: Rainboy
|
||||
* email: rainboylvx@qq.com
|
||||
* time: 2019年 04月 24日 星期三 18:22:46 CST
|
||||
* problem: online judge-_id
|
||||
*----------------*/
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
int main(){
|
||||
string a("je");
|
||||
return 0;
|
||||
}
|
@ -1,36 +1,8 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "judgerlib",
|
||||
"type": "static_library",
|
||||
"sources": [
|
||||
"../../src/child.c",
|
||||
"../../src/killer.c",
|
||||
"../../src/logger.c",
|
||||
"../../src/runner.c",
|
||||
"../../src/rules/c_cpp.c",
|
||||
"../../src/rules/c_cpp_file_io.c",
|
||||
"../../src/rules/general.c"
|
||||
],
|
||||
'include_dirs':[
|
||||
"../../src",
|
||||
"../../src/rules"
|
||||
]
|
||||
},
|
||||
{
|
||||
"target_name": "judger",
|
||||
"sources": [ "judger.cc"],
|
||||
'include_dirs':[
|
||||
"../../src",
|
||||
"../../src/rules"
|
||||
],
|
||||
"libraries":[
|
||||
"-L/usr/lib","-lpthread","-lseccomp"
|
||||
],
|
||||
|
||||
"dependencies": [
|
||||
"judgerlib"
|
||||
]
|
||||
"sources": [ "judger.cc"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
#include "node.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include "../../src/runner.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
namespace demo {
|
||||
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Isolate;
|
||||
using v8::JSON;
|
||||
using v8::Local;
|
||||
using v8::Int32;
|
||||
using v8::Array;
|
||||
@ -22,14 +26,18 @@ namespace demo {
|
||||
using v8::Context;
|
||||
|
||||
/* 转成数字 */
|
||||
long ToNumber(Isolate * isolate,Local<Object> &args,char * key,long default_val){
|
||||
void ToNumber(Isolate * isolate,Local<Value> &args,char * key,std::string &str){
|
||||
Local<Context> context= isolate->GetCurrentContext();
|
||||
Local<Value> val = args->Get(context,String::NewFromUtf8(isolate,key)).ToLocalChecked();
|
||||
Local<Value> val = args->ToObject()->Get(context,String::NewFromUtf8(isolate,key)).ToLocalChecked();
|
||||
if(val->IsNullOrUndefined())
|
||||
return default_val;
|
||||
return ;
|
||||
else if( val->IsNumber()){
|
||||
Local<Integer> num = val->ToInteger(context).ToLocalChecked();
|
||||
return num->Value();
|
||||
str+=" --";
|
||||
str+=std::string(key);
|
||||
str+="=";
|
||||
str+=std::to_string(num->Value());
|
||||
return ;
|
||||
}
|
||||
else {
|
||||
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"typeof argument must be Object!")));
|
||||
@ -37,21 +45,30 @@ namespace demo {
|
||||
}
|
||||
|
||||
char * _ToCharPTR(Local<Value> &val,Local<Context> &context,char * str_content){
|
||||
String::Utf8Value str_val( val->ToString(context).ToLocalChecked());
|
||||
strcpy(str_content,*str_val);
|
||||
return str_content;
|
||||
String::Utf8Value str_val( val->ToString(context).ToLocalChecked());
|
||||
strcpy(str_content,*str_val);
|
||||
return str_content;
|
||||
}
|
||||
|
||||
/* 转成字符串 */
|
||||
char * ToCStr(Isolate * isolate,Local<Object> &args,char * key,char *default_val,char *str_content){
|
||||
void ToCStr(Isolate * isolate,Local<Value> &args,char * key,std::string &str){
|
||||
|
||||
char str_content[255]={0};
|
||||
Local<Context> context= isolate->GetCurrentContext();
|
||||
Local<Value> val= args->Get(context,String::NewFromUtf8(isolate,key)).ToLocalChecked();
|
||||
Local<Value> val;
|
||||
if(args->IsObject())
|
||||
val = args->ToObject()->Get(context,String::NewFromUtf8(isolate,key)).ToLocalChecked();
|
||||
else
|
||||
val = args;
|
||||
if(val->IsNullOrUndefined())
|
||||
return default_val;
|
||||
return;
|
||||
else if(val->IsString()){
|
||||
_ToCharPTR(val,context,str_content);
|
||||
return str_content;
|
||||
str+=" --";
|
||||
str+=std::string(key);
|
||||
str+="=";
|
||||
str+=std::string(str_content);
|
||||
return ;
|
||||
}
|
||||
else {
|
||||
char ret[100];
|
||||
@ -95,68 +112,55 @@ namespace demo {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
Local<Context> context= isolate->GetCurrentContext();
|
||||
|
||||
std::string _args = "/usr/lib/judger/libjudger.so";
|
||||
|
||||
if( !args[0]->IsObject()){
|
||||
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"typeof argument must be Object!")));
|
||||
}
|
||||
|
||||
Local<Object> argument = args[0]->ToObject();
|
||||
|
||||
/* 参数 */
|
||||
struct config _config;
|
||||
Local<Value> argument = args[0];
|
||||
|
||||
|
||||
/* max_cpu_time */
|
||||
_config.max_cpu_time = ToNumber(isolate,argument,(char *)"max_cpu_time",UNLIMITED);
|
||||
ToNumber(isolate,argument,(char *)"max_cpu_time",_args);
|
||||
|
||||
/* max_real_time */
|
||||
_config.max_real_time = ToNumber(isolate,argument,(char *)"max_real_time",UNLIMITED);
|
||||
ToNumber(isolate,argument,(char *)"max_real_time",_args);
|
||||
|
||||
/* max_memory */
|
||||
_config.max_memory = ToNumber(isolate,argument,(char *)"max_memory",UNLIMITED);
|
||||
|
||||
/* memory_limit_check_only */
|
||||
_config.memory_limit_check_only =
|
||||
ToNumber(isolate,argument,(char *)"memory_limit_check_only",0);
|
||||
ToNumber(isolate,argument,(char *)"max_memory",_args);
|
||||
|
||||
/* memory_limit_check_only */
|
||||
ToNumber(isolate,argument,(char *)"memory_limit_check_only",_args);
|
||||
|
||||
if(_config.memory_limit_check_only)
|
||||
_config.memory_limit_check_only = 1;
|
||||
|
||||
|
||||
/* max_stack */
|
||||
_config.max_stack =
|
||||
ToNumber(isolate,argument,(char *)"max_stack",16*1024*1024); //默认16mb
|
||||
ToNumber(isolate,argument,(char *)"max_stack",_args); //默认16mb
|
||||
|
||||
/* max_process_number */
|
||||
_config.max_process_number =
|
||||
ToNumber(isolate,argument,(char *)"max_process_number",UNLIMITED);
|
||||
ToNumber(isolate,argument,(char *)"max_process_number",_args);
|
||||
|
||||
/* max_output_size */
|
||||
_config.max_output_size =
|
||||
ToNumber(isolate,argument,(char *)"max_output_size",UNLIMITED);
|
||||
ToNumber(isolate,argument,(char *)"max_output_size",_args);
|
||||
|
||||
/* input_path */
|
||||
char input_path[255];
|
||||
_config.input_path = ToCStr(isolate,argument,(char *)"input_path",(char *)"/dev/stdin",input_path);
|
||||
ToCStr(isolate,argument,(char *)"input_path",_args);
|
||||
|
||||
/* output_path */
|
||||
char output_path[255];
|
||||
_config.output_path= ToCStr(isolate,argument,(char *)"output_path",(char *)"/dev/stdout",output_path);
|
||||
ToCStr(isolate,argument,(char *)"output_path",_args);
|
||||
|
||||
/* error_path */
|
||||
char error_path[255];
|
||||
_config.error_path= ToCStr(isolate,argument,(char *)"error_path",(char *)"/dev/stderr",error_path);
|
||||
ToCStr(isolate,argument,(char *)"error_path",_args);
|
||||
|
||||
/* exe_path */
|
||||
char exe_path[255];
|
||||
_config.exe_path = ToCStr(isolate,argument,(char *)"exe_path",(char *)"/bin/ls",exe_path);
|
||||
ToCStr(isolate,argument,(char *)"exe_path",_args);
|
||||
|
||||
/* args */
|
||||
_config.args[0] = _config.exe_path;
|
||||
|
||||
char _args[100][255];
|
||||
Local<Value> margs= argument->Get(context,String::NewFromUtf8(isolate,"args")).ToLocalChecked();
|
||||
Local<Value> margs= argument->ToObject()->Get(context,String::NewFromUtf8(isolate,"args")).ToLocalChecked();
|
||||
if( margs->IsNullOrUndefined()){
|
||||
_config.args[1] = NULL;
|
||||
NULL;
|
||||
}
|
||||
else if( margs->IsArray()){
|
||||
Local<Array> args = margs.As<Array>();
|
||||
@ -164,23 +168,16 @@ namespace demo {
|
||||
int i;
|
||||
for(i=0;i<len;i++){
|
||||
Local<Value> in = args->Get(i);
|
||||
if(in->IsString()){
|
||||
_ToCharPTR(in,context,_args[i]);
|
||||
_config.args[i+1] = _args[i];
|
||||
}
|
||||
else
|
||||
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"the content of args must be string!")));
|
||||
ToCStr(isolate,in,(char *)"args",_args);
|
||||
}
|
||||
_config.args[len+1] = NULL;
|
||||
}
|
||||
else { //not array
|
||||
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"typeof argument.args must be Array!")));
|
||||
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"args must be a list")));
|
||||
}
|
||||
|
||||
char _env[100][255];
|
||||
Local<Value> menv= argument->Get(context,String::NewFromUtf8(isolate,"env")).ToLocalChecked();
|
||||
Local<Value> menv= argument->ToObject()->Get(context,String::NewFromUtf8(isolate,"env")).ToLocalChecked();
|
||||
if( menv->IsNullOrUndefined()){
|
||||
_config.env[0] = NULL;
|
||||
NULL;
|
||||
}
|
||||
else if( margs->IsArray()){
|
||||
Local<Array> env = menv.As<Array>();
|
||||
@ -188,103 +185,75 @@ namespace demo {
|
||||
int i;
|
||||
for(i=0;i<len;i++){
|
||||
Local<Value> in = env->Get(i);
|
||||
if(in->IsString()){
|
||||
_ToCharPTR(in,context,_env[i]);
|
||||
_config.env[i] = _env[i];
|
||||
}
|
||||
else
|
||||
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"the content of env must be string!")));
|
||||
ToCStr(isolate,in,(char *)"env",_args);
|
||||
}
|
||||
_config.env[len] = NULL;
|
||||
}
|
||||
else { //not array
|
||||
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"typeof argument.env must be Array!")));
|
||||
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"env must be a list")));
|
||||
}
|
||||
|
||||
/* log_path */
|
||||
char log_path[255];
|
||||
_config.log_path= ToCStr(isolate,argument,(char *)"log_path",(char *)"judger.log",log_path);
|
||||
ToCStr(isolate,argument,(char *)"log_path",_args);
|
||||
|
||||
/* seccomp_rule_name */
|
||||
char seccomp_rule_name[255];
|
||||
_config.seccomp_rule_name = ToCStr(isolate,argument,(char *)"seccomp_rule_name",NULL,seccomp_rule_name);
|
||||
ToCStr(isolate,argument,(char *)"seccomp_rule_name",_args);
|
||||
|
||||
/* uid */
|
||||
_config.uid =
|
||||
ToNumber(isolate,argument,(char *)"uid",65534);
|
||||
ToNumber(isolate,argument,(char *)"uid",_args);
|
||||
/* gid */
|
||||
_config.gid =
|
||||
ToNumber(isolate,argument,(char *)"gid",65534);
|
||||
ToNumber(isolate,argument,(char *)"gid",_args);
|
||||
|
||||
|
||||
char buf[255];
|
||||
FILE *_result_f;
|
||||
std::string result;
|
||||
if(( _result_f = popen(_args.c_str(),"r"))==NULL)
|
||||
isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"run /usr/lib/judger/libjudger.so failed!")));
|
||||
while(fgets(buf,sizeof(buf),_result_f)){
|
||||
result += std::string(buf);
|
||||
}
|
||||
pclose(_result_f);
|
||||
|
||||
/*
|
||||
* printf("max_cpu_time %d\n",_config.max_cpu_time);
|
||||
* printf("max_real_time %d\n",_config.max_real_time);
|
||||
* printf("max_memory %ld\n",_config.max_memory);
|
||||
* printf("max_stack %ld\n",_config.max_stack);
|
||||
* printf("max_process_number %d\n",_config.max_process_number);
|
||||
* printf("max_output_size %ld\n",_config.max_output_size);
|
||||
* printf("%s\n",_config.input_path);
|
||||
* printf("%s\n",_config.output_path);
|
||||
* printf("%s\n",_config.error_path);
|
||||
*
|
||||
* int idx = 0;
|
||||
* while( _config.args[idx]!= NULL){
|
||||
* printf("args[%d] = %s\n",idx,_config.args[idx]);
|
||||
* idx++;
|
||||
* }
|
||||
*
|
||||
* idx = 0;
|
||||
* while( _config.env[idx]!= NULL){
|
||||
* printf("env[%d] = %s\n",idx,_config.env[idx]);
|
||||
* idx++;
|
||||
* }
|
||||
*
|
||||
* printf("log_path %s\n",_config.log_path);
|
||||
* printf("seccomp_rule_name %s\n",_config.seccomp_rule_name);
|
||||
* printf("uid %d\n",_config.uid);
|
||||
* printf("gid %d\n",_config.gid);
|
||||
*/
|
||||
const char *pr = result.c_str();
|
||||
int len = strlen(pr);
|
||||
for(len--;len>=0;len--){
|
||||
if( pr[len] == '{')
|
||||
break;
|
||||
}
|
||||
|
||||
struct result _result = {0, 0, 0, 0, 0, 0, 0};
|
||||
run(&_config, &_result);
|
||||
printf("%*.*s",len,len,pr); //输出 程序的输出
|
||||
|
||||
/*
|
||||
*printf("{\n"
|
||||
* " \"cpu_time\": %d,\n"
|
||||
* " \"real_time\": %d,\n"
|
||||
* " \"memory\": %ld,\n"
|
||||
* " \"signal\": %d,\n"
|
||||
* " \"exit_code\": %d,\n"
|
||||
* " \"error\": %d,\n"
|
||||
* " \"result\": %d\n"
|
||||
* "}",
|
||||
* _result.cpu_time,
|
||||
* _result.real_time,
|
||||
* _result.memory,
|
||||
* _result.signal,
|
||||
* _result.exit_code,
|
||||
* _result.error,
|
||||
* _result.result);
|
||||
*/
|
||||
|
||||
/* 返回值 */
|
||||
Local<Object> result = Object::New(isolate);
|
||||
result->Set(String::NewFromUtf8(isolate,"cpu_time"),Integer::New(isolate,_result.cpu_time));
|
||||
result->Set(String::NewFromUtf8(isolate,"real_time"),Integer::New(isolate,_result.real_time));
|
||||
result->Set(String::NewFromUtf8(isolate,"memory"),Integer::New(isolate,_result.memory));
|
||||
result->Set(String::NewFromUtf8(isolate,"signal"),Integer::New(isolate,_result.signal));
|
||||
result->Set(String::NewFromUtf8(isolate,"exit_code"),Integer::New(isolate,_result.exit_code));
|
||||
result->Set(String::NewFromUtf8(isolate,"result"),Integer::New(isolate,_result.result));
|
||||
result->Set(String::NewFromUtf8(isolate,"error"),Integer::New(isolate,_result.error));
|
||||
|
||||
args.GetReturnValue().Set(result);
|
||||
MaybeLocal<Value> mres = JSON::Parse(isolate,String::NewFromUtf8(isolate,pr+len));
|
||||
args.GetReturnValue().Set(mres.ToLocalChecked());
|
||||
}
|
||||
|
||||
void init(Local<Object> exports)
|
||||
{
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
NODE_SET_METHOD(exports, "run", Method);
|
||||
exports->Set( String::NewFromUtf8(isolate,"UNLIMITED"),Integer::New(isolate, -1));
|
||||
exports->Set(String::NewFromUtf8(isolate,"VERSION"),Integer::New(isolate, 0x020101));
|
||||
|
||||
exports->Set(String::NewFromUtf8(isolate,"RESULT_SUCCESS"),Integer::New(isolate, 0));
|
||||
exports->Set(String::NewFromUtf8(isolate,"RESULT_WRONG_ANSWER"),Integer::New(isolate, -1));
|
||||
exports->Set(String::NewFromUtf8(isolate,"RESULT_CPU_TIME_LIMIT_EXCEEDED"),Integer::New(isolate, 1));
|
||||
exports->Set(String::NewFromUtf8(isolate,"RESULT_REAL_TIME_LIMIT_EXCEEDED"),Integer::New(isolate, 2));
|
||||
exports->Set(String::NewFromUtf8(isolate,"RESULT_MEMORY_LIMIT_EXCEEDED"),Integer::New(isolate, 3));
|
||||
exports->Set(String::NewFromUtf8(isolate,"RESULT_RUNTIME_ERROR"),Integer::New(isolate, 4));
|
||||
exports->Set(String::NewFromUtf8(isolate,"RESULT_SYSTEM_ERROR"),Integer::New(isolate, 5));
|
||||
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_INVALID_CONFIG"),Integer::New(isolate, -1));
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_FORK_FAILED"),Integer::New(isolate, -2));
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_PTHREAD_FAILED"),Integer::New(isolate, -3));
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_WAIT_FAILED"),Integer::New(isolate, -4));
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_ROOT_REQUIRED"),Integer::New(isolate, -5));
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_LOAD_SECCOMP_FAILED"),Integer::New(isolate, -6));
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_SETRLIMIT_FAILED"),Integer::New(isolate, -7));
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_DUP2_FAILED"),Integer::New(isolate, -8));
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_SETUID_FAILED"),Integer::New(isolate, -9));
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_EXECVE_FAILED"),Integer::New(isolate, -10));
|
||||
exports->Set(String::NewFromUtf8(isolate,"ERROR_SPJ_ERROR"),Integer::New(isolate, -11));
|
||||
}
|
||||
|
||||
NODE_MODULE(addon, init)
|
||||
|
@ -4,6 +4,7 @@
|
||||
"description": "judger for online system",
|
||||
"main": "./build/Release/judger.node",
|
||||
"scripts": {
|
||||
"build":"node-gyp rebuild",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "virusdefender,rainboy",
|
||||
|
Loading…
Reference in New Issue
Block a user