-
-
Save ry/421874 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
} | |
struct custom_request { | |
int type; // 0 is with uid, 1 is with uname | |
int uid; | |
void *cb; | |
struct passwd result; | |
char name[1]; | |
}; | |
static int EIO_AfterGetUser(eio_req *req) { | |
} | |
static int EIO_GetUser(eio_req *req) { | |
struct custom_request *creq = (struct custom_request *)(req->data); | |
struct passwd pwd, *pwdp = NULL; | |
int err; | |
if(creq->type == 0){ | |
if ((err = getpwuid_r(creq->uid, &pwd, getbuf, sizeof(getbuf), &pwdp)) || pwdp == NULL) { | |
req->errorno = errno; | |
} | |
memcpy(&creq->result, pwdp, sizeof(struct passwd)); | |
} else { | |
if ((err = getpwnam_r(creq->uname, &pwd, getbuf, sizeof(getbuf), &pwdp)) || | |
pwdp == NULL) { | |
req->errorno = errno; | |
} | |
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 custom_request *creq = (struct custom_request *)calloc(1, sizeof(struct custom_request)); | |
creq->uid = args[0]->Int32Value(); | |
creq->type = 0; | |
} else { | |
String::Utf8Value pwnam(args[0]->ToString()); | |
struct custom_request *creq = (struct custom_request *)calloc(1, sizeof(struct custom_request)+pwnam->length()+1); | |
strcpy(creq->name, *pwnam); | |
creq->type = 1; | |
} | |
if (!creq) { | |
V8::LowMemoryNotification(); | |
return ThrowException(Exception::Error( | |
String::New("Could not allocate enough memory"))); | |
} | |
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