-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathsandbox.js
More file actions
77 lines (71 loc) · 2.34 KB
/
sandbox.js
File metadata and controls
77 lines (71 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
'use strict';
const exec = require('child_process').exec;
const fse = require('fs-extra');
const langs = require('./langs').langs;
const settings = require('./settings').settings;
//Limits
const tl = settings.timeLimit;
const maxbuf = settings.maxBufferSize;
//Stringify each value in varObj
const stringifyVarObj = (varObj) => {
for (let key in varObj) {
varObj[key] = JSON.stringify(varObj[key]);
}
return varObj;
}
/*
* @description: This function replaces flow constants with their value,
* and add suitable statement to get output of last line.
*/
const prepareCode = (code, lang, varObj) => {
varObj = stringifyVarObj(varObj);
console.log("varObj->",varObj)
code = code.replace(/\$\w+\b/g, match => varObj[match]||match).trim();
console.log("removed $->",code)
return langs[lang].addStdout(code);
}
/*
* @description: This function produces a folder that contains the source file,
* this folder is mounted to our Docker container when we run it.
*/
const prepare = async(code, lang, varObj, id) => {
console.log("initail->",code)
code = prepareCode(code, lang, varObj);
console.log("final->",code)
const fileDir = __dirname + `/space/${id}`;
const fileName = fileDir + '/prog' + langs[lang].ext;
await fse.outputFile(fileName, code);
return fileDir;
}
/*
* @description: This function run the Docker container and execute script inside it.
* return the output generated and delete the mounted folder.
*/
exports.execute = async(code, lang, varObj, id) => {
try {
console.log("***Started***",Date(Date.now()))
const fileDir = await prepare(code, lang, varObj, id);
const cmd = langs[lang].cmd(fileDir);
const result = await new Promise((resolve, reject) => {
exec(cmd, {timeout:tl, maxBuffer:maxbuf}, (error, stdout, stderr) => {
if (stderr) {
resolve({status: 'error', output:stderr});
}
else if (error) {
const msg = (error.signal=='SIGTERM') ? 'time limit exceed':'runtime error';
resolve({status: 'error', output:msg});
}
else {
resolve({status:'success', output: stdout});
}
});
});
await fse.remove(fileDir);
console.log("***Done***",Date(Date.now()))
return result;
}
catch (error) {
console.log(error)
return {status:'error', output:'something went wrong'};
}
}