xref: /freebsd-src/usr.bin/top/username.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
13be6ef06SEitan Adler /*
23be6ef06SEitan Adler  *  Top users/processes display for Unix
33be6ef06SEitan Adler  *
43be6ef06SEitan Adler  *  This program may be freely redistributed,
53be6ef06SEitan Adler  *  but this entire comment MUST remain intact.
63be6ef06SEitan Adler  *
73be6ef06SEitan Adler  *  Copyright (c) 1984, 1989, William LeFebvre, Rice University
83be6ef06SEitan Adler  *  Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
93be6ef06SEitan Adler  */
103be6ef06SEitan Adler 
113be6ef06SEitan Adler /*
123be6ef06SEitan Adler  *  Username translation code for top.
133be6ef06SEitan Adler  *
143be6ef06SEitan Adler  *  These routines handle uid to username mapping.
153be6ef06SEitan Adler  *  They use a hashing table scheme to reduce reading overhead.
163be6ef06SEitan Adler  *  For the time being, these are very straightforward hashing routines.
173be6ef06SEitan Adler  *  Maybe someday I'll put in something better.  But with the advent of
183be6ef06SEitan Adler  *  "random access" password files, it might not be worth the effort.
193be6ef06SEitan Adler  *
203be6ef06SEitan Adler  *  Changes to these have been provided by John Gilmore (gnu@toad.com).
213be6ef06SEitan Adler  *
223be6ef06SEitan Adler  *  The hash has been simplified in this release, to avoid the
233be6ef06SEitan Adler  *  table overflow problems of previous releases.  If the value
243be6ef06SEitan Adler  *  at the initial hash location is not right, it is replaced
253be6ef06SEitan Adler  *  by the right value.  Collisions will cause us to call getpw*
263be6ef06SEitan Adler  *  but hey, this is a cache, not the Library of Congress.
273be6ef06SEitan Adler  *  This makes the table size independent of the passwd file size.
283be6ef06SEitan Adler  */
293be6ef06SEitan Adler 
303be6ef06SEitan Adler #include <sys/param.h>
313be6ef06SEitan Adler 
323be6ef06SEitan Adler #include <pwd.h>
33f6234b51SEitan Adler #include <stdbool.h>
343be6ef06SEitan Adler #include <stdio.h>
353be6ef06SEitan Adler #include <stdlib.h>
363be6ef06SEitan Adler #include <string.h>
373be6ef06SEitan Adler 
383be6ef06SEitan Adler #include "utils.h"
393be6ef06SEitan Adler #include "username.h"
403be6ef06SEitan Adler 
413be6ef06SEitan Adler struct hash_el {
4201a55f00SEitan Adler     int  uid;
433be6ef06SEitan Adler     char name[MAXLOGNAME];
443be6ef06SEitan Adler };
453be6ef06SEitan Adler 
463be6ef06SEitan Adler #define    is_empty_hash(x)	(hash_table[x].name[0] == 0)
473be6ef06SEitan Adler 
483be6ef06SEitan Adler /* simple minded hashing function */
4901a55f00SEitan Adler #define    hashit(i)	(abs(i) % Table_size)
503be6ef06SEitan Adler 
513be6ef06SEitan Adler /* K&R requires that statically declared tables be initialized to zero. */
523be6ef06SEitan Adler /* We depend on that for hash_table and YOUR compiler had BETTER do it! */
531b7645c6SEitan Adler static struct hash_el hash_table[Table_size];
543be6ef06SEitan Adler 
553be6ef06SEitan Adler 
561de63842SEitan Adler char *
username(int uid)571de63842SEitan Adler username(int uid)
583be6ef06SEitan Adler {
5998c299e0SEitan Adler     int hashindex;
603be6ef06SEitan Adler 
613be6ef06SEitan Adler     hashindex = hashit(uid);
623be6ef06SEitan Adler     if (is_empty_hash(hashindex) || (hash_table[hashindex].uid != uid))
633be6ef06SEitan Adler     {
643be6ef06SEitan Adler 	/* not here or not right -- get it out of passwd */
653be6ef06SEitan Adler 	hashindex = get_user(uid);
663be6ef06SEitan Adler     }
673be6ef06SEitan Adler     return(hash_table[hashindex].name);
683be6ef06SEitan Adler }
693be6ef06SEitan Adler 
701de63842SEitan Adler int
userid(char username_[])71*2f301637SDimitry Andric userid(char username_[])
723be6ef06SEitan Adler {
733be6ef06SEitan Adler     struct passwd *pwd;
743be6ef06SEitan Adler 
753be6ef06SEitan Adler     /* Eventually we want this to enter everything in the hash table,
763be6ef06SEitan Adler        but for now we just do it simply and remember just the result.
773be6ef06SEitan Adler      */
783be6ef06SEitan Adler 
79*2f301637SDimitry Andric     if ((pwd = getpwnam(username_)) == NULL)
803be6ef06SEitan Adler     {
813be6ef06SEitan Adler 	return(-1);
823be6ef06SEitan Adler     }
833be6ef06SEitan Adler 
843be6ef06SEitan Adler     /* enter the result in the hash table */
85*2f301637SDimitry Andric     enter_user(pwd->pw_uid, username_, 1);
863be6ef06SEitan Adler 
873be6ef06SEitan Adler     /* return our result */
883be6ef06SEitan Adler     return(pwd->pw_uid);
893be6ef06SEitan Adler }
903be6ef06SEitan Adler 
91f6234b51SEitan Adler /* wecare 1 = enter it always, 0 = nice to have */
921de63842SEitan Adler int
enter_user(int uid,char name[],bool wecare)931de63842SEitan Adler enter_user(int uid, char name[], bool wecare)
943be6ef06SEitan Adler {
9598c299e0SEitan Adler     int hashindex;
963be6ef06SEitan Adler 
973be6ef06SEitan Adler #ifdef DEBUG
983be6ef06SEitan Adler     fprintf(stderr, "enter_hash(%d, %s, %d)\n", uid, name, wecare);
993be6ef06SEitan Adler #endif
1003be6ef06SEitan Adler 
1013be6ef06SEitan Adler     hashindex = hashit(uid);
1023be6ef06SEitan Adler 
1033be6ef06SEitan Adler     if (!is_empty_hash(hashindex))
1043be6ef06SEitan Adler     {
1053be6ef06SEitan Adler 	if (!wecare)
106d408c8f7SEitan Adler 	    return (0);		/* Don't clobber a slot for trash */
1073be6ef06SEitan Adler 	if (hash_table[hashindex].uid == uid)
1083be6ef06SEitan Adler 	    return(hashindex);	/* Fortuitous find */
1093be6ef06SEitan Adler     }
1103be6ef06SEitan Adler 
1113be6ef06SEitan Adler     /* empty or wrong slot -- fill it with new value */
1123be6ef06SEitan Adler     hash_table[hashindex].uid = uid;
1133be6ef06SEitan Adler     (void) strncpy(hash_table[hashindex].name, name, MAXLOGNAME - 1);
1143be6ef06SEitan Adler     return(hashindex);
1153be6ef06SEitan Adler }
1163be6ef06SEitan Adler 
1173be6ef06SEitan Adler /*
1183be6ef06SEitan Adler  * Get a userid->name mapping from the system.
1193be6ef06SEitan Adler  */
1203be6ef06SEitan Adler 
121668af25dSEitan Adler int
get_user(int uid)12201a55f00SEitan Adler get_user(int uid)
1233be6ef06SEitan Adler {
1243be6ef06SEitan Adler     struct passwd *pwd;
1253be6ef06SEitan Adler 
1263be6ef06SEitan Adler     /* no performance penalty for using getpwuid makes it easy */
1273be6ef06SEitan Adler     if ((pwd = getpwuid(uid)) != NULL)
1283be6ef06SEitan Adler     {
1293be6ef06SEitan Adler 		return(enter_user(pwd->pw_uid, pwd->pw_name, 1));
1303be6ef06SEitan Adler     }
1313be6ef06SEitan Adler 
1323be6ef06SEitan Adler     /* if we can't find the name at all, then use the uid as the name */
1333be6ef06SEitan Adler     return(enter_user(uid, itoa7(uid), 1));
1343be6ef06SEitan Adler }
135