|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 8576 (0x2180)
Types: TextFile
Names: »pwcache.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦2fafebccf⟧ »EurOpenD3/mail/smail3.1.19.tar.Z«
└─⟦bcd2bc73f⟧
└─⟦this⟧ »src/pwcache.c«
/* @(#)pwcache.c 1.9 3/14/88 01:08:23 */
/*
* Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
*
* See the file COPYING, distributed with smail, for restriction
* and warranty information.
*
* namei master id: @(#)pwcache.c 1.9 3/14/88 01:08:23
*/
/*
* pwcache:
* manage a passwd and group entry cache.
*
* The mailer can make a large number of acesses to the passwd and
* group files while processing a message. To increase the efficiency
* of this, we maintain a cache of entries read from each of these
* files.
*/
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <ctype.h>
#include "defs.h"
#include "smail.h"
#include "hash.h"
#include "alloc.h"
#ifndef DEPEND
# include "extern.h"
#endif
/* functions imported from the C library */
extern struct passwd *getpwnam();
extern struct passwd *getpwuid();
extern struct group *getgrnam();
extern struct group *getgrgid();
/* functions local to this file */
static void fill_pw_cache();
static void fill_gr_cache();
/*
* There are separate caches for four mappings:
*
* uid->username gid->groupname username->uid groupname->gid
*/
/* number of entries in each cache */
#ifdef SMALL_MEMORY
# define N_CACHE 5
#else
# define N_CACHE 31
#endif
/* buffer size to hold user and group names (with ending nul byte) */
#define PW_SIZE 12
/* invalid names will begin with this char */
#define BAD_NAME ('@')
/* invalid id's are set to this unlikely id */
#define BAD_ID (-10101)
/* entries for the passwd file cache */
struct pw_cache {
char pw_name[PW_SIZE]; /* name of user */
int pw_uid; /* uid of user */
int pw_gid; /* base gid of user */
char *pw_dir; /* home directory */
int size_pw_dir; /* size allocated for home directory */
};
/* entries for the group file cache */
struct gr_cache {
char gr_name[PW_SIZE]; /* name of group */
int gr_gid; /* gid of group */
};
/* we rely on these being initialized to nulls */
static struct hash_table *uid_cache = NULL; /* uid->username cache */
static struct hash_table *gid_cache = NULL; /* gid->groupname cache */
static struct hash_table *user_cache = NULL; /* username->uid cache */
static struct hash_table *group_cache = NULL; /* groupname->gid cache */
\f
/*
* uid->username, through cache
*/
struct passwd *
getpwbyuid(uid)
int uid;
{
struct pw_cache *entp, ent;
static struct passwd ret;
static char uid_buf[50]; /* big enough to hold a number */
if (uid_cache == NULL) {
/* XXX - hash table should be associated with a block */
uid_cache = new_hash_table(N_CACHE,
(struct block *)NULL,
HASH_DEFAULT);
}
(void) sprintf(uid_buf, "%d", uid);
if (lookup_in_hash(uid_buf, (char **)&entp, (int *)NULL,
uid_cache) == ALREADY_HASHED)
{
if (entp->pw_name[0] == BAD_NAME) {
return NULL;
}
ret.pw_name = entp->pw_name;
ret.pw_uid = entp->pw_uid;
ret.pw_gid = entp->pw_gid;
ret.pw_dir = entp->pw_dir;
return &ret;
} else {
register struct passwd *pw;
setpwent();
pw = getpwuid(uid);
if (pw == NULL) {
ent.pw_uid = uid;
ent.pw_name[0] = BAD_NAME;
(void) add_to_hash(uid_buf, (char *)&ent, sizeof(ent), uid_cache);
return NULL;
}
if (user_cache == NULL) {
/* XXX - hash table should be associated with a block */
user_cache = new_hash_table(N_CACHE,
(struct block *)NULL,
HASH_DEFAULT);
}
fill_pw_cache(pw);
return pw;
}
}
/*
* gid->groupname, through cache
*/
struct group *
getgrbygid(gid)
int gid;
{
struct gr_cache *entp, ent;
static struct group ret;
static char gid_buf[50]; /* big enough to hold a number */
if (gid_cache == NULL) {
/* XXX - hash table should be associated with a block */
gid_cache = new_hash_table(N_CACHE,
(struct block *)NULL,
HASH_DEFAULT);
}
(void) sprintf(gid_buf, "%d", gid);
if (lookup_in_hash(gid_buf, (char **)&entp, (int *)NULL,
gid_cache) == ALREADY_HASHED)
{
if (entp->gr_name[0] == BAD_NAME) {
return NULL;
}
ret.gr_name = entp->gr_name;
ret.gr_gid = entp->gr_gid;
return &ret;
} else {
register struct group *gr;
setgrent();
gr = getgrgid(gid);
if (gr == NULL) {
ent.gr_gid = gid;
ent.gr_name[0] = BAD_NAME;
(void) add_to_hash(gid_buf, (char *)&ent, sizeof(ent), gid_cache);
return NULL;
}
if (group_cache == NULL) {
/* XXX - hash table should be associated with a block */
group_cache = new_hash_table(N_CACHE,
(struct block *)NULL,
HASH_DEFAULT);
}
fill_gr_cache(gr);
return gr;
}
}
/*
* username->uid, through cache
*/
struct passwd *
getpwbyname(user)
char *user;
{
struct pw_cache *entp, ent;
static struct passwd ret;
if (strlen(user) > PW_SIZE - 1) {
return NULL;
}
if (user_cache == NULL) {
/* XXX - hash table should be associated with a block */
user_cache = new_hash_table(N_CACHE,
(struct block *)NULL,
HASH_DEFAULT);
}
if (lookup_in_hash(user, (char **)&entp, (int *)NULL,
user_cache) == ALREADY_HASHED)
{
if (entp->pw_uid == BAD_ID) {
return NULL;
}
ret.pw_name = entp->pw_name;
ret.pw_uid = entp->pw_uid;
ret.pw_gid = entp->pw_gid;
ret.pw_dir = entp->pw_dir;
return &ret;
} else {
register struct passwd *pw;
register char *p;
(void) strncpy(ent.pw_name, user, PW_SIZE - 1);
for (p = ent.pw_name; *p; p++) {
*p = lowercase(*p);
}
setpwent();
pw = getpwnam(ent.pw_name);
if (pw == NULL) {
(void) strncpy(ent.pw_name, user, PW_SIZE - 1);
ent.pw_uid = BAD_ID;
(void) add_to_hash(user, (char *)&ent, sizeof(ent), user_cache);
return NULL;
}
if (uid_cache == NULL) {
/* XXX - hash table should be associated with a block */
uid_cache = new_hash_table(N_CACHE,
(struct block *)NULL,
HASH_DEFAULT);
}
fill_pw_cache(pw);
return pw;
}
}
/*
* groupname->gid, through cache
*/
struct group *
getgrbyname(group)
char *group;
{
struct gr_cache *entp, ent;
static struct group ret;
if (strlen(group) > PW_SIZE - 1) {
return NULL;
}
if (group_cache == NULL) {
/* XXX - hash table should be associated with a block */
group_cache = new_hash_table(N_CACHE,
(struct block *)NULL,
HASH_DEFAULT);
}
if (lookup_in_hash(group, (char **)&entp, (int *)NULL,
group_cache) == ALREADY_HASHED)
{
if (entp->gr_gid == BAD_ID) {
return NULL;
}
ret.gr_gid = entp->gr_gid;
ret.gr_name = entp->gr_name;
return &ret;
} else {
register struct group *gr;
register char *p;
(void) strncpy(ent.gr_name, group, PW_SIZE - 1);
for (p = ent.gr_name; *p; p++) {
*p = lowercase(*p);
}
setgrent();
gr = getgrnam(ent.gr_name);
if (gr == NULL) {
(void) strncpy(ent.gr_name, group, PW_SIZE - 1);
ent.gr_gid = BAD_ID;
(void) add_to_hash(group, (char *)&ent, sizeof(ent), group_cache);
return NULL;
}
if (gid_cache == NULL) {
/* XXX - hash table should be associated with a block */
gid_cache = new_hash_table(N_CACHE,
(struct block *)NULL,
HASH_DEFAULT);
}
fill_gr_cache(gr);
return gr;
}
}
/* fill the uid and username caches from a passwd file entry */
static void
fill_pw_cache(pw)
register struct passwd *pw;
{
struct pw_cache ent; /* fill this with pw info */
char uid_buf[50]; /* big enough to hold a number */
register char *p;
int size_pw_dir;
(void) strncpy(ent.pw_name, pw->pw_name, PW_SIZE - 1);
for (p = ent.pw_name; *p; p++) {
*p = lowercase(*p);
}
ent.pw_uid = pw->pw_uid;
ent.pw_gid = pw->pw_gid;
size_pw_dir = strlen(pw->pw_dir) + 1;
ent.pw_dir = xmalloc(size_pw_dir);
(void) strcpy(ent.pw_dir, pw->pw_dir);
(void) sprintf(uid_buf, "%d", pw->pw_uid);
(void) add_to_hash(uid_buf, (char *)&ent, sizeof(ent), uid_cache);
(void) add_to_hash(ent.pw_name, (char *)&ent, sizeof(ent), user_cache);
}
/* fill the gid and groupname caches from a group file entry */
static void
fill_gr_cache(gr)
register struct group *gr;
{
struct gr_cache ent; /* fill this with gr info */
char gid_buf[50]; /* big enough to hold a number */
register char *p;
(void) strncpy(ent.gr_name, gr->gr_name, PW_SIZE - 1);
for (p = ent.gr_name; *p; p++) {
*p = lowercase(*p);
}
ent.gr_gid = gr->gr_gid;
(void)sprintf(gid_buf, "%d", gr->gr_gid);
(void) add_to_hash(gid_buf, (char *)&ent, sizeof(ent), gid_cache);
(void) add_to_hash(ent.gr_name, (char *)&ent, sizeof(ent), group_cache);
}