}
+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();
var error_count = 0;
var response = '';
-var child = exec('/usr/bin/env', {env: {'HELLO': 'WORLD'}},
- function(err, stdout, stderr) {
- if (err) {
- error_count++;
- console.log('error!: ' + err.code);
- console.log('stdout: ' + JSON.stringify(stdout));
- console.log('stderr: ' + JSON.stringify(stderr));
- assert.equal(false, err.killed);
- } else {
- success_count++;
- assert.equal(true, stdout != '');
- }
- });
+function after(err, stdout, stderr) {
+ if (err) {
+ error_count++;
+ console.log('error!: ' + err.code);
+ console.log('stdout: ' + JSON.stringify(stdout));
+ console.log('stderr: ' + JSON.stringify(stderr));
+ assert.equal(false, err.killed);
+ } else {
+ success_count++;
+ assert.equal(true, stdout != '');
+ }
+}
-child.stdout.setEncoding('utf8');
+var child = exec('/usr/bin/env', { env: { 'HELLO': 'WORLD' } }, after);
+child.stdout.setEncoding('utf8');
child.stdout.addListener('data', function(chunk) {
response += chunk;
});
process.addListener('exit', function() {
+ console.log("response: ", response);
assert.equal(1, success_count);
assert.equal(0, error_count);
assert.ok(response.indexOf('HELLO=WORLD') >= 0);