-
-
Save ThisIsMissEm/422415 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 { | |
void *cb; | |
int type; // 0 is with uid, 1 is with uname | |
uid_t uid; | |
char name[1]; | |
struct passwd result; | |
}; | |
static int EIO_AfterGetUser(eio_req *req) { | |
ev_unref(EV_DEFAULT_UC); | |
HandleScope scope; | |
struct custom_request *creq = (struct custom_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 (req->errorno && req->errorno != 0) { | |
argc = 1; | |
argv[0] = ErrnoException(req->errorno, NULL, "", static_cast<const char*>(req->ptr1)); | |
} 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 custom_request *creq = (struct custom_request *)(req->data); | |
struct passwd pwd, *pwdp = NULL; | |
if(creq->type == 0){ | |
req->errorno = getpwuid_r(creq->uid, &pwd, getbuf, sizeof(getbuf), &pwdp); | |
memcpy(&creq->result, pwdp, sizeof(struct passwd)); | |
} else { | |
int err; | |
if ((err = getpwnam_r(creq->name, &pwd, getbuf, sizeof(getbuf), &pwdp)) || pwdp == NULL) { | |
req->errorno = err; | |
} | |
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)); | |
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 custom_request *creq = (struct custom_request *) | |
calloc(1, sizeof(struct custom_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