-
-
Save Sannis/908926 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 <[email protected]> | |
#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