#include "lib/fs/userdb.h"
#ifndef _WIN32
#include "lib/malloc/malloc.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include <pwd.h>
#include <stddef.h>
#include <string.h>
static struct passwd *passwd_cached = NULL;
static struct passwd *
tor_passwd_dup(const struct passwd *pw)
{
struct passwd *new_pw = tor_malloc_zero(sizeof(struct passwd));
if (pw->pw_name)
new_pw->pw_name = tor_strdup(pw->pw_name);
if (pw->pw_dir)
new_pw->pw_dir = tor_strdup(pw->pw_dir);
new_pw->pw_uid = pw->pw_uid;
new_pw->pw_gid = pw->pw_gid;
return new_pw;
}
#define tor_passwd_free(pw) \
FREE_AND_NULL(struct passwd, tor_passwd_free_, (pw))
static void
tor_passwd_free_(struct passwd *pw)
{
if (!pw)
return;
tor_free(pw->pw_name);
tor_free(pw->pw_dir);
tor_free(pw);
}
const struct passwd *
tor_getpwnam(const char *username)
{
struct passwd *pw;
if (username == NULL) {
tor_passwd_free(passwd_cached);
passwd_cached = NULL;
return NULL;
}
if ((pw = getpwnam(username))) {
tor_passwd_free(passwd_cached);
passwd_cached = tor_passwd_dup(pw);
log_info(LD_GENERAL, "Caching new entry %s for %s",
passwd_cached->pw_name, username);
return pw;
}
if (! passwd_cached || ! passwd_cached->pw_name)
return NULL;
if (! strcmp(username, passwd_cached->pw_name))
return passwd_cached;
return NULL;
}
const struct passwd *
tor_getpwuid(uid_t uid)
{
struct passwd *pw;
if ((pw = getpwuid(uid))) {
return pw;
}
if (! passwd_cached)
return NULL;
if (uid == passwd_cached->pw_uid)
return passwd_cached;
return NULL;
}
char *
get_user_homedir(const char *username)
{
const struct passwd *pw;
tor_assert(username);
if (!(pw = tor_getpwnam(username))) {
log_err(LD_CONFIG,"User \"%s\" not found.", username);
return NULL;
}
return tor_strdup(pw->pw_dir);
}
#endif