1 /* 2 * Copyright (c) 1984 through 2008, William LeFebvre 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * * Neither the name of William LeFebvre nor the names of other 17 * contributors may be used to endorse or promote products derived from 18 * this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Top users/processes display for Unix 35 * Version 3 36 */ 37 38 /* 39 * Username translation code for top. 40 * 41 * These routines handle uid to username mapping. They use a hash table to 42 * reduce reading overhead. Entries are refreshed every EXPIRETIME seconds. 43 * 44 * The old ad-hoc hash functions have been replaced with something a little 45 * more formal and (hopefully) more robust (found in hash.c) 46 */ 47 48 #include "os.h" 49 50 #include <pwd.h> 51 52 #include "top.h" 53 #include "utils.h" 54 #include "hash.h" 55 #include "username.h" 56 57 #define EXPIRETIME (60 * 5) 58 59 /* we need some sort of idea how long usernames can be */ 60 #ifndef MAXLOGNAME 61 #ifdef _POSIX_LOGIN_NAME_MAX 62 #define MAXLOGNAME _POSIX_LOGIN_NAME_MAX 63 #else 64 #define MAXLOGNAME 9 65 #endif 66 #endif 67 68 struct hash_data { 69 int uid; 70 char name[MAXLOGNAME]; /* big enough? */ 71 time_t expire; 72 }; 73 74 hash_table *userhash; 75 76 77 void 78 init_username(void) 79 80 { 81 userhash = hash_create(211); 82 } 83 84 char * 85 username(int xuid) 86 87 { 88 struct hash_data *data; 89 struct passwd *pw; 90 time_t now; 91 92 /* what time is it? */ 93 now = time(NULL); 94 95 /* get whatever is in the cache */ 96 data = hash_lookup_uint(userhash, (unsigned int)xuid); 97 98 /* if we had a cache miss, then create space for a new entry */ 99 if (data == NULL) 100 { 101 /* make space */ 102 data = emalloc(sizeof(struct hash_data)); 103 104 /* fill in some data, including an already expired time */ 105 data->uid = xuid; 106 data->expire = (time_t)0; 107 108 /* add it to the hash: the rest gets filled in later */ 109 hash_add_uint(userhash, xuid, data); 110 } 111 112 /* Now data points to the correct hash entry for "xuid". If this is 113 a new entry, then expire is 0 and the next test will be true. */ 114 if (data->expire <= now) 115 { 116 if ((pw = getpwuid(xuid)) != NULL) 117 { 118 strncpy(data->name, pw->pw_name, MAXLOGNAME-1); 119 data->expire = now + EXPIRETIME; 120 dprintf("username: updating %d with %s, expires %d\n", 121 data->uid, data->name, data->expire); 122 } 123 else 124 { 125 /* username doesnt exist ... so invent one */ 126 snprintf(data->name, sizeof(data->name), "%d", xuid); 127 data->expire = now + EXPIRETIME; 128 dprintf("username: updating %d with %s, expires %d\n", 129 data->uid, data->name, data->expire); 130 } 131 } 132 133 /* return what we have */ 134 return data->name; 135 } 136 137 int 138 userid(char *xusername) 139 140 { 141 struct passwd *pwd; 142 143 if ((pwd = getpwnam(xusername)) == NULL) 144 { 145 return(-1); 146 } 147 148 /* return our result */ 149 return(pwd->pw_uid); 150 } 151 152