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.