This is getname.c in view mode; [Download] [Up]
/*
* Copyright (c) 1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT
* SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Users of this software agree to return to Carnegie Mellon any
* improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
* Export of this software is permitted only after complying with the
* regulations of the U.S. Deptartment of Commerce relating to the
* Export of Technical Data.
*/
/*
* This file contains the code for the following getname routine:
*
* getname:
* purpose:
* getname returns the user from the password file
* associated with a specified user-id. The user-id
* is passed as an integer parameter to the routine.
*
* If a user whose id matches the parameter uid is found in the
* password file, the name corresponding to that user is returned.
* If no match is found, NULL is returned. If malloc() fails,
* NULL is returned. If id is -1, all allocated memory is freed.
*
* During the search for a particular user-id, a hash table names
* is built for storing user-id's and their corresponding names
* from the password file. When the routine is first called, entries
* are read from the password file until a match for uid, or the
* end of the password file, is found. Any entries not matching uid
* and not already stored in the names structure are then stored in
* names.
*
* On subsequent calls to getname, the structure names is checked
* first for a match for uid. If no match is found, and if the entire
* password file has not been stored, entries from it are stored in
* names as before.
*
* When the entire password file has been stored, only names
* is checked for a matching user-id on subsequent calls to getname.
**********************************************************************
* HISTORY
* $Log: getname.c,v $
* Revision 1.2 90/12/11 17:54:56 mja
* Add copyright/disclaimer for distribution.
*
* 25-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Ran through lint and fixed bad routine calls and returns. Added
* register variables where apropriate. Added code to detect malloc
* failures. Added special call value (-1) to free hash table for
* cleaning up allocated memory.
*
**********************************************************************
*/
#include <pwd.h> /* passwd struct include file */
#include <utmp.h> /* utmp struct include file */
#include <stdio.h>
#define HASHBITS 6 /* number of bits to hash */
#define HASHSIZE (1<<HASHBITS) /* limit on the number of buckets
in the hash table */
#define HASHMASK (HASHSIZE-1) /* mask of bits to hash */
#define hash(uid) ((uid)&HASHMASK) /* determines in which of the HASHSIZE
buckets uid would belong */
static struct utmp ut;
#define NMAX (sizeof ut.ut_name) /* maximum length for a name */
/* struct for storing an entry of the hash table */
struct entry {
char a_name[NMAX+1]; /* stores the name of the user */
int a_uid; /* stores the uid of the user */
struct entry *next; /* stores the pointer to the
next entry of the hash table */
};
static struct entry *names[HASHSIZE]; /* the hash table of users */
/* returns the entry of names that stores the user of id uid if
one exists in names, else NULL is returned */
static struct entry *inset(uid)
register int uid;
{
register struct entry *temp;
for (temp = names[hash(uid)]; temp != NULL; temp = temp->next)
if (temp->a_uid == uid)
return(temp);
return(NULL);
}
/* allocates space for an entry in names, setting next field to NULL */
static struct entry *make_blank_entry()
{
register struct entry *blank_entry;
blank_entry = (struct entry*)(malloc(sizeof(struct entry)));
if (blank_entry == NULL)
return(NULL);
blank_entry->next = NULL;
return(blank_entry);
}
/* inserts a blank entry into the correct position of names for a user
whose id is uid */
static struct entry *place_blank_entry(uid)
register int uid;
{
register struct entry **temp;
struct entry *make_blank_entry();
temp = &names[hash(uid)];
while (*temp != NULL)
temp = &((*temp)->next);
return(*temp = make_blank_entry());
}
/* inserts the data of an entry from the password file (stored in pw_entry)
into an entry of names (the parameter blank_entry) */
static fill_in(blank_entry, pw_entry)
register struct entry *blank_entry;
register struct passwd *pw_entry;
{
strncpy(blank_entry->a_name, pw_entry->pw_name, NMAX);
blank_entry->a_name[NMAX] = '\0';
blank_entry->a_uid = pw_entry->pw_uid;
}
/* creates an entry in names storing the data of an entry from the
password file which stored in the paramter passwd_entry */
static struct entry *create_names_entry(passwd_entry)
register struct passwd *passwd_entry;
{
register struct entry *new_entry;
struct entry *place_blank_entry();
new_entry = place_blank_entry(passwd_entry->pw_uid);
if (new_entry == NULL)
return(NULL);
fill_in(new_entry, passwd_entry);
return(new_entry);
}
/* initializes hash table */
static set_hash_table()
{
register int i;
for (i = 0; i < HASHSIZE; i++)
names[i] = NULL;
}
/* free hash table */
static free_hash_table()
{
register int i;
register struct entry *temp;
for (i = 0; i < HASHSIZE; i++)
while ((temp = names[i]) != NULL) {
names[i] = temp->next;
free((char *)temp);
}
}
/* returns the name of the user in the passwords file whose id is uid.
NULL is returned if none exists */
char *getname(uid)
register uid;
{
register struct passwd *pw; /* pre-defined struct */
static init; /* indicates status of the password file
0 = file unopen
1 = file open
2 = file entirely read
*/
/* pre-defined routines for accessing the password routine */
struct passwd *getpwent();
int setpwent();
int endpwent();
struct entry *inset();
register struct entry *Location;
if (uid == -1) {
if (init != 0)
free_hash_table();
if (init == 1)
endpwent();
init = 0;
return(NULL);
}
if (init == 0) {
set_hash_table();
setpwent();
init = 1;
}
Location = inset(uid); /* check if user is in names */
if (Location != NULL)
return(Location->a_name); /* user already stored in names */
if (init == 2)
return(NULL); /* entire password file has been
stored in names */
/* continue reading entries from the password file, storing any in
names whose uid is not already located in names, stopping when
a match is found for the uid or the entire password file has
been stored */
while ((pw = getpwent()) != NULL) {
Location = inset(pw->pw_uid);
if (Location != NULL)
continue;
if (create_names_entry(pw) == NULL)
return(NULL);
if (pw->pw_uid == uid)
return(pw->pw_name);
}
init = 2;
endpwent();
return(NULL);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.