// Copyright (c) 2002 David Muse
// See the COPYING file for more information
#include <rudiments/passwdentry.h>
#include <rudiments/charstring.h>
#include <rudiments/rawbuffer.h>
#include <rudiments/error.h>
#ifdef MINGW32
// for LPUSER_INFO_23, functions
#include <windows.h>
#include <lm.h>
#else
// for passwd, functions
#include <pwd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#define MAXBUFFER (32*1024)
#ifdef RUDIMENTS_NAMESPACE
namespace rudiments {
#endif
class passwdentryprivate {
friend class passwdentry;
private:
#ifndef MINGW32
passwd *_pwd;
#if defined(RUDIMENTS_HAVE_GETPWNAM_R) && \
defined(RUDIMENTS_HAVE_GETPWUID_R)
passwd _pwdbuffer;
char *_buffer;
#endif
#else
LPUSER_INFO_23 _buffer;
char *_name;
char *_fullname;
#endif
};
// LAME: not in the class
#if (!defined(RUDIMENTS_HAVE_GETPWNAM_R) || !defined(RUDIMENTS_HAVE_GETPWUID_R))
static mutex *pemutex;
#endif
passwdentry::passwdentry() {
pvt=new passwdentryprivate;
#ifndef MINGW32
pvt->_pwd=NULL;
#if defined(RUDIMENTS_HAVE_GETPWNAM_R) && \
defined(RUDIMENTS_HAVE_GETPWUID_R)
rawbuffer::zero(&pvt->_pwdbuffer,sizeof(pvt->_pwdbuffer));
pvt->_buffer=NULL;
#endif
#else
pvr->_buffer=NULL;
pvr->_name=NULL;
pvr->_fullname=NULL;
#endif
}
passwdentry::passwdentry(const passwdentry &p) {
pvt=new passwdentryprivate;
initialize(p.getName());
}
passwdentry &passwdentry::operator=(const passwdentry &p) {
if (this!=&p) {
initialize(p.getName());
}
return *this;
}
passwdentry::~passwdentry() {
#ifndef MINGW32
#if defined(RUDIMENTS_HAVE_GETPWNAM_R) && \
defined(RUDIMENTS_HAVE_GETPWUID_R)
delete[] pvt->_buffer;
#endif
delete pvt;
#else
if (pvt->_buffer) {
NetApiBufferFree(pvt->_buffer);
}
delete[] pvt->_name;
delete[] pvt->_fullname;
#endif
}
const char *passwdentry::getName() const {
#ifndef MINGW32
return pvt->_pwd->pw_name;
#else
return pvt->_name;
#endif
}
const char *passwdentry::getPassword() const {
#ifndef MINGW32
return pvt->_pwd->pw_passwd;
#else
// FIXME:
return "";
#endif
}
uid_t passwdentry::getUserId() const {
#ifndef MINGW32
return pvt->_pwd->pw_uid;
#else
// FIXME:
return 0;
#endif
}
gid_t passwdentry::getPrimaryGroupId() const {
#ifndef MINGW32
return pvt->_pwd->pw_gid;
#else
// FIXME:
return 0;
#endif
}
const char *passwdentry::getRealName() const {
#ifndef MINGW32
return pvt->_pwd->pw_gecos;
#else
return pvt->_fullname;
#endif
}
const char *passwdentry::getHomeDirectory() const {
#ifndef MINGW32
return pvt->_pwd->pw_dir;
#else
// FIXME:
return "";
#endif
}
const char *passwdentry::getShell() const {
#ifndef MINGW32
return pvt->_pwd->pw_shell;
#else
// FIXME:
return "";
#endif
}
bool passwdentry::needsMutex() {
#if !defined(RUDIMENTS_HAVE_GETPWNAM_R) || \
!defined(RUDIMENTS_HAVE_GETPWUID_R)
return true;
#else
return false;
#endif
}
void passwdentry::setMutex(mutex *mtx) {
#if !defined(RUDIMENTS_HAVE_GETPWNAM_R) || \
!defined(RUDIMENTS_HAVE_GETPWUID_R)
pemutex=mtx;
#endif
}
bool passwdentry::initialize(const char *username) {
return initialize(username,0);
}
bool passwdentry::initialize(uid_t userid) {
return initialize(NULL,userid);
}
#ifndef MINGW32
bool passwdentry::initialize(const char *username, uid_t userid) {
#if defined(RUDIMENTS_HAVE_GETPWNAM_R) && \
defined(RUDIMENTS_HAVE_GETPWUID_R)
if (pvt->_pwd) {
pvt->_pwd=NULL;
delete[] pvt->_buffer;
pvt->_buffer=NULL;
}
// getpwnam_r and getpwuid_r are goofy.
// They will retrieve an arbitrarily large amount of data, but
// require that you pass them a pre-allocated buffer. If the
// buffer is too small, they returns an ENOMEM and you have to
// just make the buffer bigger and try again.
for (int size=1024; size<MAXBUFFER; size=size+1024) {
pvt->_buffer=new char[size];
#if defined(RUDIMENTS_HAVE_GETPWNAM_R_5) && \
defined(RUDIMENTS_HAVE_GETPWUID_R_5)
if (!((username)
?(getpwnam_r(username,
&pvt->_pwdbuffer,
pvt->_buffer,size,
&pvt->_pwd))
:(getpwuid_r(userid,
&pvt->_pwdbuffer,
pvt->_buffer,size,
&pvt->_pwd)))) {
return (pvt->_pwd!=NULL);
}
#elif defined(RUDIMENTS_HAVE_GETPWNAM_R_4) && \
defined(RUDIMENTS_HAVE_GETPWUID_R_4)
if ((username)
?(pvt->_pwd=getpwnam_r(username,
&pvt->_pwdbuffer,
pvt->_buffer,size))
:(pvt->_pwd=getpwuid_r(userid,
&pvt->_pwdbuffer,
pvt->_buffer,size))) {
return true;
}
#endif
delete[] pvt->_buffer;
pvt->_buffer=NULL;
pvt->_pwd=NULL;
if (error::getErrorNumber()!=ENOMEM) {
return false;
}
}
return false;
#else
pvt->_pwd=NULL;
return (!(pemutex && !pemutex->lock()) &&
((pvt->_pwd=((username)
?getpwnam(username)
:getpwuid(userid)))!=NULL) &&
!(pemutex && !pemutex->unlock()));
#endif
}
#else
bool passwdentry::initialize(const char *username, uid_t userid) {
if (pvt->_buffer) {
NetApiBufferFree(pvt->_buffer);
}
delete[] pvt->_name;
pvt->_name=NULL;
delete[] pvt->_fullname;
pvt->_fullname=NULL;
if (username) {
if (NetUserGetInfo(NULL,username,23,
reinterpret_cast<LPBYTE *>(&pvt->_buffer))!=
NERR_SUCCESS) {
return false;
}
pvt->_name=new char[charstring::length(
pvt->_buffer->usri23_name)]+1;
pvt->_fullname=new char[charstring::length(
pvt->_buffer->usri23_full_name)]+1;
wsprintf(pvt->_name,"%s",pvt->_buffer->usri23_name);
wsprintf(pvt->_fullname,"%s",pvt->_buffer->usri23_fullname);
} else {
#error implement me...
}
return true;
}
#endif
bool passwdentry::getName(uid_t userid, char **name) {
passwdentry pwd;
if (pwd.initialize(userid)) {
*name=charstring::duplicate(pwd.getName());
return true;
}
return false;
}
bool passwdentry::getPassword(uid_t userid, char **password) {
passwdentry pwd;
if (pwd.initialize(userid)) {
*password=charstring::duplicate(pwd.getPassword());
return true;
}
return false;
}
bool passwdentry::getPrimaryGroupId(uid_t userid, gid_t *groupid) {
passwdentry pwd;
if (pwd.initialize(userid)) {
*groupid=pwd.getPrimaryGroupId();
return true;
}
return false;
}
bool passwdentry::getRealName(uid_t userid, char **realname) {
passwdentry pwd;
if (pwd.initialize(userid)) {
*realname=charstring::duplicate(pwd.getRealName());
return true;
}
return false;
}
bool passwdentry::getHomeDirectory(uid_t userid, char **homedir) {
passwdentry pwd;
if (pwd.initialize(userid)) {
*homedir=charstring::duplicate(pwd.getHomeDirectory());
return true;
}
return false;
}
bool passwdentry::getShell(uid_t userid, char **shell) {
passwdentry pwd;
if (pwd.initialize(userid)) {
*shell=charstring::duplicate(pwd.getShell());
return true;
}
return false;
}
bool passwdentry::getUserId(const char *username, uid_t *userid) {
passwdentry pwd;
if (pwd.initialize(username)) {
*userid=pwd.getUserId();
return true;
}
return false;
}
bool passwdentry::getPassword(const char *username, char **password) {
passwdentry pwd;
if (pwd.initialize(username)) {
*password=charstring::duplicate(pwd.getPassword());
return true;
}
return false;
}
bool passwdentry::getPrimaryGroupId(const char *username, gid_t *groupid) {
passwdentry pwd;
if (pwd.initialize(username)) {
*groupid=pwd.getPrimaryGroupId();
return true;
}
return false;
}
bool passwdentry::getRealName(const char *username, char **realname) {
passwdentry pwd;
if (pwd.initialize(username)) {
*realname=charstring::duplicate(pwd.getRealName());
return true;
}
return false;
}
bool passwdentry::getHomeDirectory(const char *username, char **homedir) {
passwdentry pwd;
if (pwd.initialize(username)) {
*homedir=charstring::duplicate(pwd.getHomeDirectory());
return true;
}
return false;
}
bool passwdentry::getShell(const char *username, char **shell) {
passwdentry pwd;
if (pwd.initialize(username)) {
*shell=charstring::duplicate(pwd.getShell());
return true;
}
return false;
}
void passwdentry::print() const {
if (!pvt->_pwd) {
return;
}
printf("Name: %s\n",getName());
printf("Password: %s\n",getPassword());
printf("User Id: %d\n",getUserId());
printf("Primary Group Id: %d\n",getPrimaryGroupId());
printf("Real Name: %s\n",getRealName());
printf("Home Directory: %s\n",getHomeDirectory());
printf("Shell: %s\n",getShell());
}
#ifdef RUDIMENTS_NAMESPACE
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1