110dd2532Schristos /*
210dd2532Schristos * Copyright (c) 1984 through 2008, William LeFebvre
310dd2532Schristos * All rights reserved.
410dd2532Schristos *
510dd2532Schristos * Redistribution and use in source and binary forms, with or without
610dd2532Schristos * modification, are permitted provided that the following conditions are met:
710dd2532Schristos *
810dd2532Schristos * * Redistributions of source code must retain the above copyright
910dd2532Schristos * notice, this list of conditions and the following disclaimer.
1010dd2532Schristos *
1110dd2532Schristos * * Redistributions in binary form must reproduce the above
1210dd2532Schristos * copyright notice, this list of conditions and the following disclaimer
1310dd2532Schristos * in the documentation and/or other materials provided with the
1410dd2532Schristos * distribution.
1510dd2532Schristos *
1610dd2532Schristos * * Neither the name of William LeFebvre nor the names of other
1710dd2532Schristos * contributors may be used to endorse or promote products derived from
1810dd2532Schristos * this software without specific prior written permission.
1910dd2532Schristos *
2010dd2532Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2110dd2532Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2210dd2532Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2310dd2532Schristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2410dd2532Schristos * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2510dd2532Schristos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2610dd2532Schristos * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2710dd2532Schristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2810dd2532Schristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2910dd2532Schristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3010dd2532Schristos * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3110dd2532Schristos */
3210dd2532Schristos
3310dd2532Schristos /*
3410dd2532Schristos * Top users/processes display for Unix
3510dd2532Schristos * Version 3
3610dd2532Schristos */
3710dd2532Schristos
3810dd2532Schristos /*
3910dd2532Schristos * Username translation code for top.
4010dd2532Schristos *
4110dd2532Schristos * These routines handle uid to username mapping. They use a hash table to
4210dd2532Schristos * reduce reading overhead. Entries are refreshed every EXPIRETIME seconds.
4310dd2532Schristos *
4410dd2532Schristos * The old ad-hoc hash functions have been replaced with something a little
4510dd2532Schristos * more formal and (hopefully) more robust (found in hash.c)
4610dd2532Schristos */
4710dd2532Schristos
4810dd2532Schristos #include "os.h"
4910dd2532Schristos
5010dd2532Schristos #include <pwd.h>
5110dd2532Schristos
5210dd2532Schristos #include "top.h"
5310dd2532Schristos #include "utils.h"
5410dd2532Schristos #include "hash.h"
55*213e7ef1Schristos #include "username.h"
5610dd2532Schristos
5710dd2532Schristos #define EXPIRETIME (60 * 5)
5810dd2532Schristos
5910dd2532Schristos /* we need some sort of idea how long usernames can be */
6010dd2532Schristos #ifndef MAXLOGNAME
6110dd2532Schristos #ifdef _POSIX_LOGIN_NAME_MAX
6210dd2532Schristos #define MAXLOGNAME _POSIX_LOGIN_NAME_MAX
6310dd2532Schristos #else
6410dd2532Schristos #define MAXLOGNAME 9
6510dd2532Schristos #endif
6610dd2532Schristos #endif
6710dd2532Schristos
6810dd2532Schristos struct hash_data {
6910dd2532Schristos int uid;
7010dd2532Schristos char name[MAXLOGNAME]; /* big enough? */
7110dd2532Schristos time_t expire;
7210dd2532Schristos };
7310dd2532Schristos
7410dd2532Schristos hash_table *userhash;
7510dd2532Schristos
7610dd2532Schristos
7710dd2532Schristos void
init_username(void)78*213e7ef1Schristos init_username(void)
7910dd2532Schristos
8010dd2532Schristos {
8110dd2532Schristos userhash = hash_create(211);
8210dd2532Schristos }
8310dd2532Schristos
8410dd2532Schristos char *
username(int xuid)85*213e7ef1Schristos username(int xuid)
8610dd2532Schristos
8710dd2532Schristos {
8810dd2532Schristos struct hash_data *data;
8910dd2532Schristos struct passwd *pw;
9010dd2532Schristos time_t now;
9110dd2532Schristos
9210dd2532Schristos /* what time is it? */
9310dd2532Schristos now = time(NULL);
9410dd2532Schristos
9510dd2532Schristos /* get whatever is in the cache */
96*213e7ef1Schristos data = hash_lookup_uint(userhash, (unsigned int)xuid);
9710dd2532Schristos
9810dd2532Schristos /* if we had a cache miss, then create space for a new entry */
9910dd2532Schristos if (data == NULL)
10010dd2532Schristos {
10110dd2532Schristos /* make space */
10256a682bfSchristos data = emalloc(sizeof(struct hash_data));
10310dd2532Schristos
10410dd2532Schristos /* fill in some data, including an already expired time */
105*213e7ef1Schristos data->uid = xuid;
10610dd2532Schristos data->expire = (time_t)0;
10710dd2532Schristos
10810dd2532Schristos /* add it to the hash: the rest gets filled in later */
109*213e7ef1Schristos hash_add_uint(userhash, xuid, data);
11010dd2532Schristos }
11110dd2532Schristos
112*213e7ef1Schristos /* Now data points to the correct hash entry for "xuid". If this is
11310dd2532Schristos a new entry, then expire is 0 and the next test will be true. */
11410dd2532Schristos if (data->expire <= now)
11510dd2532Schristos {
116*213e7ef1Schristos if ((pw = getpwuid(xuid)) != NULL)
11710dd2532Schristos {
11810dd2532Schristos strncpy(data->name, pw->pw_name, MAXLOGNAME-1);
11910dd2532Schristos data->expire = now + EXPIRETIME;
12010dd2532Schristos dprintf("username: updating %d with %s, expires %d\n",
12110dd2532Schristos data->uid, data->name, data->expire);
12210dd2532Schristos }
12310dd2532Schristos else
12410dd2532Schristos {
12510dd2532Schristos /* username doesnt exist ... so invent one */
126*213e7ef1Schristos snprintf(data->name, sizeof(data->name), "%d", xuid);
12710dd2532Schristos data->expire = now + EXPIRETIME;
12810dd2532Schristos dprintf("username: updating %d with %s, expires %d\n",
12910dd2532Schristos data->uid, data->name, data->expire);
13010dd2532Schristos }
13110dd2532Schristos }
13210dd2532Schristos
13310dd2532Schristos /* return what we have */
13410dd2532Schristos return data->name;
13510dd2532Schristos }
13610dd2532Schristos
13710dd2532Schristos int
userid(char * xusername)138*213e7ef1Schristos userid(char *xusername)
13910dd2532Schristos
14010dd2532Schristos {
14110dd2532Schristos struct passwd *pwd;
14210dd2532Schristos
143*213e7ef1Schristos if ((pwd = getpwnam(xusername)) == NULL)
14410dd2532Schristos {
14510dd2532Schristos return(-1);
14610dd2532Schristos }
14710dd2532Schristos
14810dd2532Schristos /* return our result */
14910dd2532Schristos return(pwd->pw_uid);
15010dd2532Schristos }
15110dd2532Schristos
152