Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
// Copyright 2009 Ryan Dahl <ry@tinyclouds.org>
#include <v8.h>
#include <node.h>
#include <node_os.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <pwd.h> /* getpwuid() */
#include <grp.h> /* getgrgid() */
namespace node {
using namespace v8;
// User
static Persistent<String> username_symbol;
static Persistent<String> password_symbol;
static Persistent<String> uid_symbol;
static Persistent<String> gid_symbol;
static Persistent<String> class_symbol;
static Persistent<String> dir_symbol;
static Persistent<String> shell_symbol;
static Persistent<String> change_symbol;
static Persistent<String> expire_symbol;
static Persistent<String> gecos_symbol;
static Persistent<String> fields_symbol;
// Group
// static Persistent<String> name_symbol;
// static Persistent<String> members_symbol;
// Buffer for getpwnam_r(), getgrpam_r(); keep this scoped at file-level rather
// than method-level to avoid excess stack usage.
static char getbuf[1024];
/*-----------------------------------------------
Constructs a JS::Object from a *passwd
-----------------------------------------------*/
Local<Object> BuildUserObject(struct passwd *u) {
HandleScope scope;
if (username_symbol.IsEmpty()) {
username_symbol = NODE_PSYMBOL("username");
password_symbol = NODE_PSYMBOL("password");
uid_symbol = NODE_PSYMBOL("uid");
gid_symbol = NODE_PSYMBOL("gid");
class_symbol = NODE_PSYMBOL("class");
gecos_symbol = NODE_PSYMBOL("gecos");
dir_symbol = NODE_PSYMBOL("dir");
shell_symbol = NODE_PSYMBOL("shell");
change_symbol = NODE_PSYMBOL("change");
expire_symbol = NODE_PSYMBOL("expire");
}
Local<Object> user = Object::New();
user->Set(username_symbol, String::New(u->pw_name));
user->Set(password_symbol, String::New(u->pw_passwd));
user->Set(uid_symbol, Integer::New(u->pw_uid));
user->Set(gid_symbol, Integer::New(u->pw_gid));
user->Set(class_symbol, String::New(u->pw_class));
user->Set(gecos_symbol, String::New(u->pw_gecos));
user->Set(dir_symbol, String::New(u->pw_dir));
user->Set(shell_symbol, String::New(u->pw_shell));
user->Set(change_symbol, Undefined()); //atldate(u->pw_change/1000));
user->Set(expire_symbol, Undefined());
return scope.Close(user);
}
static int EIO_AfterGetUser(eio_req *req) {
ev_unref(EV_DEFAULT_UC);
HandleScope scope;
struct user_request *creq = (struct user_request *)(req->data);
Persistent<Function> *callback = cb_unwrap(creq->cb);
int argc = 0;
Local<Value> argv[6]; // 6 is the maximum number of args
if (creq->errorno != 0) {
argc = 2;
argv[0] = ErrnoException(creq->errorno);
argv[1] = BuildUserObject(&creq->result);
} else {
argc = 2;
argv[0] = Local<Value>::New(Null());
argv[1] = BuildUserObject(&creq->result);
}
TryCatch try_catch;
(*callback)->Call(Context::GetCurrent()->Global(), argc, argv);
if (try_catch.HasCaught()) {
FatalException(try_catch);
}
// Dispose of the persistent handle
cb_destroy(callback);
return 0;
}
static int EIO_GetUser(eio_req *req) {
struct user_request *creq = (struct user_request *)(req->data);
struct passwd pwd;
struct passwd *pwdp;
if(creq->type == 0){
creq->errorno = getpwuid_r(creq->uid, &pwd, getbuf, sizeof(getbuf), &pwdp);
fprintf(stderr, "\n %d", creq->errorno);
memcpy(&creq->result, pwdp, sizeof(struct passwd));
} else {
creq->errorno = getpwnam_r(creq->name, &pwd, getbuf, sizeof(getbuf), &pwdp);
memcpy(&creq->result, pwdp, sizeof(struct passwd));
}
return 0;
}
static Handle<Value> GetUser(const Arguments& args) {
HandleScope scope;
if ( args.Length() < 1) {
return THROW_BAD_ARGS;
}
if (args[1]->IsFunction()) {
if (args[0]->IsInt32()) {
struct user_request *creq = (struct user_request *)
calloc(1, sizeof(struct user_request));
if (!creq) {
V8::LowMemoryNotification();
return ThrowException(Exception::Error(
String::New("Could not allocate enough memory")));
}
creq->uid = static_cast<uid_t>(args[0]->Int32Value());
creq->type = 0;
creq->cb = cb_persist(args[1]);
//ASYNC_CUSTOM_CALL(blocking_func, callback, data);
ASYNC_CUSTOM_CALL(EIO_GetUser, EIO_AfterGetUser, creq);
} else {
String::Utf8Value pwnam(args[0]->ToString());
struct user_request *creq = (struct user_request *)
calloc(1, sizeof(struct user_request)+pwnam.length()+1);
if (!creq) {
V8::LowMemoryNotification();
return ThrowException(Exception::Error(
String::New("Could not allocate enough memory")));
}
strcpy(creq->name, *pwnam);
creq->type = 1;
creq->cb = cb_persist(args[1]);
//ASYNC_CUSTOM_CALL(blocking_func, callback, data);
ASYNC_CUSTOM_CALL(EIO_GetUser, EIO_AfterGetUser, creq);
}
return Undefined();
} else {
struct passwd pwd, *pwdp = NULL;
int err;
if (args[0]->IsInt32()) {
if ((err = getpwuid_r(args[0]->Int32Value(), &pwd, getbuf, sizeof(getbuf), &pwdp)) ||
pwdp == NULL) {
return ThrowException(ErrnoException(errno, "getpwuid_r"));
}
} else {
String::Utf8Value pwnam(args[0]->ToString());
if ((err = getpwnam_r(*pwnam, &pwd, getbuf, sizeof(getbuf), &pwdp)) ||
pwdp == NULL) {
return ThrowException(ErrnoException(errno, "getpwnam_r"));
}
}
return scope.Close(BuildUserObject(*&pwdp));
}
}
/*
Local<Object> BuildGroupObject(struct group *g) {
HandleScope scope;
if (name_symbol.IsEmpty()) {
name_symbol = NODE_PSYMBOL("name");
password_symbol = NODE_PSYMBOL("password");
gid_symbol = NODE_PSYMBOL("gid");
members_symbol = NODE_PSYMBOL("members");
}
Local<Object> group = Object::New();
group->Set(name_symbol, String::New(g->gr_name));
group->Set(password_symbol, String::New(g->gr_passwd));
group->Set(gid_symbol, Integer::New(g->gr_gid));
// group->Set(members_symbol, String::New(g->gr_mem[1]));
return scope.Close(group);
}
static Handle<Value> GetGroup(const Arguments& args) {
HandleScope scope;
if ( args.Length() < 1) {
return THROW_BAD_ARGS;
}
if (args[1]->IsFunction()) {
// Handle with EIO_CUSTOM
return Undefined();
} else {
if (args[0]->IsString()) {
String::Utf8Value grpnam(args[0]->ToString());
struct group grp, *grpp = NULL;
int err;
if ((err = getgrnam_r(*grpnam, &grp, getbuf, sizeof(getbuf), &grpp)) ||
grpp == NULL) {
return ThrowException(ErrnoException(errno, "getgrnam_r"));
}
//uid = (pwdp->pw_uid);
return scope.Close(BuildGroupObject(*&grpp));
} else {
return Undefined();
}
}
}
*/
void Os::Initialize(Handle<Object> target) {
HandleScope scope;
NODE_SET_METHOD(target, "getUser", GetUser);
// NODE_SET_METHOD(target, "getGroup", GetGroup);
}
} // end namespace node
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.