diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-08-01 03:24:29 +0400 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-08-01 03:24:29 +0400 |
commit | 19a62589b20000a64b5faf7992ad4f10801b2fe3 (patch) | |
tree | ea4b282ec0c09bccaa79925699f7bd05e7f09393 /lib | |
parent | 4ac633bf2160b49746e279a745ac68e52009857c (diff) |
child_process_uv: add exec, fix simple/test-child-process-exec-cwd
Diffstat (limited to 'lib')
-rw-r--r-- | lib/child_process_uv.js | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/lib/child_process_uv.js b/lib/child_process_uv.js index 342578c76f6..6352c93828e 100644 --- a/lib/child_process_uv.js +++ b/lib/child_process_uv.js @@ -47,6 +47,125 @@ function createSocket(pipe, readable) { } +exports.exec = function(command /*, options, callback */) { + var rest = Array.prototype.slice.call(arguments, 1); + var args = ['/bin/sh', ['-c', command]].concat(rest); + return exports.execFile.apply(this, args); +}; + + +exports.execFile = function(file /* args, options, callback */) { + var args, optionArg, callback; + var options = { + encoding: 'utf8', + timeout: 0, + maxBuffer: 200 * 1024, + killSignal: 'SIGTERM', + setsid: false, + cwd: null, + env: null + }; + + // Parse the parameters. + + if (typeof arguments[arguments.length - 1] === 'function') { + callback = arguments[arguments.length - 1]; + } + + if (Array.isArray(arguments[1])) { + args = arguments[1]; + if (typeof arguments[2] === 'object') optionArg = arguments[2]; + } else { + args = []; + if (typeof arguments[1] === 'object') optionArg = arguments[1]; + } + + // Merge optionArg into options + if (optionArg) { + var keys = Object.keys(options); + for (var i = 0, len = keys.length; i < len; i++) { + var k = keys[i]; + if (optionArg[k] !== undefined) options[k] = optionArg[k]; + } + } + + var child = spawn(file, args, { + cwd: options.cwd, + env: options.env + }); + + var stdout = ''; + var stderr = ''; + var killed = false; + var exited = false; + var timeoutId; + + var err; + + function exithandler(code, signal) { + if (exited) return; + exited = true; + + if (timeoutId) { + clearTimeout(timeoutId); + timeoutId = null; + } + + if (!callback) return; + + if (err) { + callback(err, stdout, stderr); + } else if (code === 0 && signal === null) { + callback(null, stdout, stderr); + } else { + var e = new Error('Command failed: ' + stderr); + e.killed = child.killed || killed; + e.code = code; + e.signal = signal; + callback(e, stdout, stderr); + } + } + + function kill() { + killed = true; + child.kill(options.killSignal); + process.nextTick(function() { + exithandler(null, options.killSignal); + }); + } + + if (options.timeout > 0) { + timeoutId = setTimeout(function() { + kill(); + timeoutId = null; + }, options.timeout); + } + + child.stdout.setEncoding(options.encoding); + child.stderr.setEncoding(options.encoding); + + child.stdout.addListener('data', function(chunk) { + stdout += chunk; + if (stdout.length > options.maxBuffer) { + err = new Error('maxBuffer exceeded.'); + kill(); + } + }); + + child.stderr.addListener('data', function(chunk) { + stderr += chunk; + if (stderr.length > options.maxBuffer) { + err = new Error('maxBuffer exceeded.'); + kill(); + } + }); + + child.addListener('exit', exithandler); + + return child; +}; + + var spawn = exports.spawn = function(file, args, options) { var child = new ChildProcess(); |