use popen to run libjudger.so

This commit is contained in:
rainboy 2019-04-26 10:50:59 +08:00
parent 1dce5f71e3
commit d54b84ab58
5 changed files with 104 additions and 179 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@ __pycache__
*.pyc
cmake-build-debug/
.ycm_extra_conf.py
node_modules/

View File

@ -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;
}

View File

@ -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"]
}
]
}

View File

@ -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)

View File

@ -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",