version 1.16, 2009/07/22 15:27:52 |
version 1.17, 2015/10/26 13:56:18 |
|
|
|
|
/* |
/* |
* Username translation code for top. |
* Username translation code for top. |
* |
|
* These routines handle uid to username mapping. |
|
* They use a hashing table scheme to reduce reading overhead. |
|
* For the time being, these are very straightforward hashing routines. |
|
* Maybe someday I'll put in something better. But with the advent of |
|
* "random access" password files, it might not be worth the effort. |
|
* |
|
* Changes to these have been provided by John Gilmore (gnu@toad.com). |
|
* |
|
* The hash has been simplified in this release, to avoid the |
|
* table overflow problems of previous releases. If the value |
|
* at the initial hash location is not right, it is replaced |
|
* by the right value. Collisions will cause us to call getpw* |
|
* but hey, this is a cache, not the Library of Congress. |
|
* This makes the table size independent of the passwd file size. |
|
*/ |
*/ |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
|
|
#include "top.h" |
#include "top.h" |
#include "utils.h" |
#include "utils.h" |
|
|
struct hash_el { |
|
uid_t uid; |
|
char name[_PW_NAME_LEN + 1]; |
|
}; |
|
|
|
static int enter_user(uid_t, char *); |
|
static int get_user(uid_t); |
|
|
|
#define is_empty_hash(x) (hash_table[x].name[0] == 0) |
|
|
|
/* |
|
* Simple minded hashing function, assumes i is unsigned. |
|
*/ |
|
#define hashit(i) (i % Table_size) |
|
|
|
struct hash_el hash_table[Table_size]; |
|
|
|
char * |
char * |
username(uid_t uid) |
username(uid_t uid) |
{ |
{ |
int hashindex; |
return user_from_uid(uid, 0); |
|
|
hashindex = hashit(uid); |
|
if (is_empty_hash(hashindex) || (hash_table[hashindex].uid != uid)) { |
|
/* not here or not right -- get it out of passwd */ |
|
hashindex = get_user(uid); |
|
} |
|
return (hash_table[hashindex].name); |
|
} |
} |
|
|
uid_t |
uid_t |
|
|
{ |
{ |
struct passwd *pwd; |
struct passwd *pwd; |
|
|
/* |
|
* Eventually we want this to enter everything in the hash table, but |
|
* for now we just do it simply and remember just the result. |
|
*/ |
|
if ((pwd = getpwnam(username)) == NULL) |
if ((pwd = getpwnam(username)) == NULL) |
return ((uid_t)-1); |
return ((uid_t)-1); |
|
|
/* enter the result in the hash table */ |
|
enter_user(pwd->pw_uid, username); |
|
|
|
/* return our result */ |
|
return (pwd->pw_uid); |
return (pwd->pw_uid); |
} |
|
|
|
static int |
|
enter_user(uid_t uid, char *name) |
|
{ |
|
int hashindex; |
|
|
|
#ifdef DEBUG |
|
fprintf(stderr, "enter_hash(%u, %s)\n", uid, name); |
|
#endif |
|
|
|
hashindex = hashit(uid); |
|
|
|
if (!is_empty_hash(hashindex)) { |
|
if (hash_table[hashindex].uid == uid) |
|
return (hashindex); /* Fortuitous find */ |
|
} |
|
/* empty or wrong slot -- fill it with new value */ |
|
hash_table[hashindex].uid = uid; |
|
(void) strlcpy(hash_table[hashindex].name, name, |
|
sizeof(hash_table[hashindex].name)); |
|
return (hashindex); |
|
} |
|
|
|
/* |
|
* Get a userid->name mapping from the system. |
|
*/ |
|
static int |
|
get_user(uid_t uid) |
|
{ |
|
struct passwd *pwd; |
|
|
|
/* no performance penalty for using getpwuid makes it easy */ |
|
if ((pwd = getpwuid(uid)) != NULL) |
|
return (enter_user(pwd->pw_uid, pwd->pw_name)); |
|
|
|
/* if we can't find the name at all, then use the uid as the name */ |
|
return (enter_user(uid, format_uid(uid))); |
|
} |
} |