Browse Source

Add setsid option to child_process

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
202dd8387f
  1. 7
      doc/api/child_processes.markdown
  2. 12
      lib/child_process.js
  3. 15
      src/node_child_process.cc
  4. 8
      src/node_child_process.h

7
doc/api/child_processes.markdown

@ -59,12 +59,15 @@ The third argument is used to specify additional options, which defaults to:
{ cwd: undefined,
env: process.env,
customFds: [-1, -1, -1] }
customFds: [-1, -1, -1],
setsid: false
}
`cwd` allows you to specify the working directory from which the process is spawned.
Use `env` to specify environment variables that will be visible to the new process.
With `customFds` it is possible to hook up the new process' [stdin, stout, stderr] to
existing streams; `-1` means that a new stream should be created.
existing streams; `-1` means that a new stream should be created. `setsid`,
if set true, will cause the subprocess to be run in a new session.
Example of running `ls -lh /usr`, capturing `stdout`, `stderr`, and the exit code:

12
lib/child_process.js

@ -25,6 +25,7 @@ exports.execFile = function(file /* args, options, callback */) {
timeout: 0,
maxBuffer: 200 * 1024,
killSignal: 'SIGTERM',
setsid: false,
cwd: null,
env: null };
var args, optionArg, callback;
@ -184,7 +185,7 @@ ChildProcess.prototype.kill = function(sig) {
ChildProcess.prototype.spawn = function(path, args, options, customFds) {
args = args || [];
var cwd, env;
var cwd, env, setuid;
if (!options || options.cwd === undefined &&
options.env === undefined &&
options.customFds === undefined) {
@ -192,11 +193,13 @@ ChildProcess.prototype.spawn = function(path, args, options, customFds) {
cwd = '';
env = options || process.env;
customFds = customFds || [-1, -1, -1];
setuid = false;
} else {
// Recommended API: (path, args, options)
cwd = options.cwd || '';
env = options.env || process.env;
customFds = options.customFds || [-1, -1, -1];
setuid = options.setuid ? true : false;
}
var envPairs = [];
@ -206,7 +209,12 @@ ChildProcess.prototype.spawn = function(path, args, options, customFds) {
envPairs.push(key + '=' + env[key]);
}
var fds = this._internal.spawn(path, args, cwd, envPairs, customFds);
var fds = this._internal.spawn(path,
args,
cwd,
envPairs,
customFds,
setuid);
this.fds = fds;
if (customFds[0] === -1 || customFds[0] === undefined) {

15
src/node_child_process.cc

@ -150,9 +150,15 @@ Handle<Value> ChildProcess::Spawn(const Arguments& args) {
}
}
int do_setuid = false;
if (args[5]->IsBoolean()) {
do_setuid = args[5]->BooleanValue();
}
int fds[3];
int r = child->Spawn(argv[0], argv, cwd, env, fds, custom_fds);
int r = child->Spawn(argv[0], argv, cwd, env, fds, custom_fds, do_setuid);
for (i = 0; i < argv_length; i++) free(argv[i]);
delete [] argv;
@ -226,7 +232,8 @@ int ChildProcess::Spawn(const char *file,
const char *cwd,
char **env,
int stdio_fds[3],
int custom_fds[3]) {
int custom_fds[3],
bool do_setuid) {
HandleScope scope;
assert(pid_ == -1);
assert(!ev_is_active(&child_watcher_));
@ -267,6 +274,10 @@ int ChildProcess::Spawn(const char *file,
return -4;
case 0: // Child.
if (do_setuid && setsid() < 0) {
perror("setuid");
}
if (custom_fds[0] == -1) {
close(stdin_pipe[1]); // close write end
dup2(stdin_pipe[0], STDIN_FILENO);

8
src/node_child_process.h

@ -58,7 +58,13 @@ class ChildProcess : ObjectWrap {
// are readable.
// The user of this class has responsibility to close these pipes after
// the child process exits.
int Spawn(const char *file, char *const argv[], const char *cwd, char **env, int stdio_fds[3], int custom_fds[3]);
int Spawn(const char *file,
char *const argv[],
const char *cwd,
char **env,
int stdio_fds[3],
int custom_fds[3],
bool do_setuid);
// Simple syscall wrapper. Does not disable the watcher. onexit will be
// called still.

Loading…
Cancel
Save