xref: /netbsd-src/external/bsd/top/dist/username.c (revision 213e7ef10b646bf1aa9d15d47768bae62394cb55)
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