UNPKG

@academyjs/rover

Version:

Rover allows you to learn programming interactively.

78 lines 3.21 kB
"use strict"; /** * Copyright (c) AcademyJS and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.execute = void 0; const child_process_1 = __importDefault(require("child_process")); const buffer_1 = require("buffer"); const defaultOptions = { standardOutputLimit: 64 * 1024, standardOutputEncoding: "utf8", standardErrorLimit: 64 * 1024, standardErrorEncoding: "utf8", standardInput: "", timeout: undefined, }; const execute = (executable, argumentVector, customOptions = {}) => { const options = Object.assign(Object.assign({}, defaultOptions), customOptions); return new Promise((resolve, reject) => { const standardOutput = buffer_1.Buffer.alloc(options.standardOutputLimit); let standardOutputOffset = 0; const standardError = buffer_1.Buffer.alloc(options.standardErrorLimit); let standardErrorOffset = 0; let reason = "success"; const spawnedProcess = child_process_1.default.spawn(executable, argumentVector, { timeout: options.timeout, killSignal: "SIGKILL", }); spawnedProcess.stdout.on("data", (data) => { const written = standardOutput.write(data.toString("Utf8"), standardOutputOffset, "utf8"); if (written !== data.length) { reason = "standard_output_exceeded"; /* SECURITY NOTE: SIGTERM can be caught by the child process. A malicious code can * thus evade forced termination. */ spawnedProcess.kill("SIGKILL"); } standardOutputOffset += written; }); spawnedProcess.stderr.on("data", (data) => { const written = standardError.write(data.toString("utf8"), standardErrorOffset, "utf8"); // Ensure process is still running before killing! if (written !== data.length) { reason = "standard_error_exceeded"; spawnedProcess.kill("SIGKILL"); } standardErrorOffset += written; }); spawnedProcess.on("exit", (exitCode, signal) => { const result = { exitCode, standardOutput: standardOutput.toString("utf8", 0, standardOutputOffset), standardError: standardError.toString("utf8", 0, standardErrorOffset), reason, signal, }; resolve(result); }); spawnedProcess.on("error", (error) => { reject(error); }); if (options.standardInput) { /* The newline ensures that someone reading from the standard input does not wait * forever. */ spawnedProcess.stdin.write(options.standardInput + "\n"); spawnedProcess.stdin.end(); } }); }; exports.execute = execute; //# sourceMappingURL=executor.js.map