ftp.nice.ch/pub/next/developer/resources/libraries/libcs.s.tar.gz#/libcs/getname.c

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.