Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
Child process: support the gid and uid options
Browse files Browse the repository at this point in the history
  • Loading branch information
piscisaureus committed Apr 27, 2012
1 parent 51e66ec commit 55e4d54
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 14 deletions.
4 changes: 3 additions & 1 deletion lib/child_process.js
Expand Up @@ -346,7 +346,9 @@ var spawn = exports.spawn = function(file, args, options) {
windowsVerbatimArguments: !!(options && options.windowsVerbatimArguments),
envPairs: envPairs,
customFds: options ? options.customFds : null,
stdinStream: options ? options.stdinStream : null
stdinStream: options ? options.stdinStream : null,
uid: options ? options.uid : null,
gid: options ? options.gid : null
});

return child;
Expand Down
63 changes: 50 additions & 13 deletions src/process_wrap.cc
Expand Up @@ -53,6 +53,8 @@ using v8::TryCatch;
using v8::Context;
using v8::Arguments;
using v8::Integer;
using v8::Exception;
using v8::ThrowException;


class ProcessWrap : public HandleWrap {
Expand Down Expand Up @@ -98,22 +100,24 @@ class ProcessWrap : public HandleWrap {

Local<Object> js_options = args[0]->ToObject();

uv_process_options_t options;
uv_process_options2_t options;
memset(&options, 0, sizeof(uv_process_options_t));

options.exit_cb = OnExit;

// TODO is this possible to do without mallocing ?

// options.file
Local<Value> file_v = js_options->Get(String::New("file"));
Local<Value> file_v = js_options->Get(String::NewSymbol("file"));
if (!file_v.IsEmpty() && file_v->IsString()) {
String::Utf8Value file(file_v->ToString());
options.file = strdup(*file);
} else {
return ThrowException(Exception::TypeError(String::New("Bad argument")));
}

// options.args
Local<Value> argv_v = js_options->Get(String::New("args"));
Local<Value> argv_v = js_options->Get(String::NewSymbol("args"));
if (!argv_v.IsEmpty() && argv_v->IsArray()) {
Local<Array> js_argv = Local<Array>::Cast(argv_v);
int argc = js_argv->Length();
Expand All @@ -127,7 +131,7 @@ class ProcessWrap : public HandleWrap {
}

// options.cwd
Local<Value> cwd_v = js_options->Get(String::New("cwd"));
Local<Value> cwd_v = js_options->Get(String::NewSymbol("cwd"));
if (!cwd_v.IsEmpty() && cwd_v->IsString()) {
String::Utf8Value cwd(cwd_v->ToString());
if (cwd.length() > 0) {
Expand All @@ -136,7 +140,7 @@ class ProcessWrap : public HandleWrap {
}

// options.env
Local<Value> env_v = js_options->Get(String::New("envPairs"));
Local<Value> env_v = js_options->Get(String::NewSymbol("envPairs"));
if (!env_v.IsEmpty() && env_v->IsArray()) {
Local<Array> env = Local<Array>::Cast(env_v);
int envc = env->Length();
Expand All @@ -149,33 +153,66 @@ class ProcessWrap : public HandleWrap {
}

// options.stdin_stream
Local<Value> stdin_stream_v = js_options->Get(String::New("stdinStream"));
Local<Value> stdin_stream_v = js_options->Get(
String::NewSymbol("stdinStream"));
if (!stdin_stream_v.IsEmpty() && stdin_stream_v->IsObject()) {
PipeWrap* stdin_wrap = PipeWrap::Unwrap(stdin_stream_v->ToObject());
options.stdin_stream = stdin_wrap->UVHandle();
}

// options.stdout_stream
Local<Value> stdout_stream_v = js_options->Get(String::New("stdoutStream"));
Local<Value> stdout_stream_v = js_options->Get(
String::NewSymbol("stdoutStream"));
if (!stdout_stream_v.IsEmpty() && stdout_stream_v->IsObject()) {
PipeWrap* stdout_wrap = PipeWrap::Unwrap(stdout_stream_v->ToObject());
options.stdout_stream = stdout_wrap->UVHandle();
}

// options.stderr_stream
Local<Value> stderr_stream_v = js_options->Get(String::New("stderrStream"));
Local<Value> stderr_stream_v = js_options->Get(
String::NewSymbol("stderrStream"));
if (!stderr_stream_v.IsEmpty() && stderr_stream_v->IsObject()) {
PipeWrap* stderr_wrap = PipeWrap::Unwrap(stderr_stream_v->ToObject());
options.stderr_stream = stderr_wrap->UVHandle();
}

// options.windows_verbatim_arguments
#if defined(_WIN32)
options.windows_verbatim_arguments = js_options->
Get(String::NewSymbol("windowsVerbatimArguments"))->IsTrue();
#endif
if (js_options->Get(String::NewSymbol("windowsVerbatimArguments"))->
IsTrue()) {
options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
}

// options.uid
Local<Value> uid_v = js_options->Get(String::NewSymbol("uid"));
if (uid_v->IsInt32()) {
int32_t uid = uid_v->Int32Value();
if (uid & ~((uv_uid_t) ~0)) {

This comment has been minimized.

Copy link
@bnoordhuis

bnoordhuis Apr 27, 2012

Member

Too clever by half.

return ThrowException(Exception::RangeError(
String::New("options.uid is out of range")));
}
options.flags |= UV_PROCESS_SETUID;
options.uid = (uv_uid_t) uid;
} else if (!uid_v->IsUndefined() && !uid_v->IsNull()) {
return ThrowException(Exception::TypeError(
String::New("options.uid should be a number")));
}

// options.gid
Local<Value> gid_v = js_options->Get(String::NewSymbol("gid"));
if (gid_v->IsInt32()) {
int32_t gid = gid_v->Int32Value();
if (gid & ~((uv_gid_t) ~0)) {
return ThrowException(Exception::RangeError(
String::New("options.gid is out of range")));
}
options.flags |= UV_PROCESS_SETGID;
options.gid = (uv_gid_t) gid;
} else if (!gid_v->IsUndefined() && !gid_v->IsNull()) {
return ThrowException(Exception::TypeError(
String::New("options.gid should be a number")));
}

int r = uv_spawn(uv_default_loop(), &wrap->process_, options);
int r = uv_spawn2(uv_default_loop(), &wrap->process_, options);

if (r) {
SetErrno(uv_last_error(uv_default_loop()));
Expand Down

0 comments on commit 55e4d54

Please sign in to comment.