xref: /openbsd-src/lib/libc/gen/pwcache.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*	$OpenBSD: pwcache.c,v 1.13 2015/11/25 23:16:01 jcs Exp $ */
2 /*
3  * Copyright (c) 1989, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/types.h>
32 
33 #include <grp.h>
34 #include <pwd.h>
35 #include <stdio.h>
36 #include <string.h>
37 
38 #define	NCACHE	16			/* power of 2 */
39 #define	NLINES	4			/* associativity */
40 #define	MASK	(NCACHE - 1)		/* bits to store with */
41 #define	IDX(x, i)	((x & MASK) + i * NCACHE)
42 
43 char *
44 user_from_uid(uid_t uid, int nouser)
45 {
46 	static struct ncache {
47 		uid_t	uid;
48 		short	noname;
49 		char	name[_PW_NAME_LEN + 1];
50 	} c_uid[NLINES * NCACHE];
51 	char pwbuf[_PW_BUF_LEN];
52 	struct passwd pwstore, *pw;
53 	struct ncache *cp;
54 	unsigned int i;
55 
56 	for (i = 0; i < NLINES; i++) {
57 		cp = &c_uid[IDX(uid, i)];
58 		if (!*cp->name) {
59 fillit:
60 			cp->uid = uid;
61 			pw = NULL;
62 			getpwuid_r(uid, &pwstore, pwbuf, sizeof(pwbuf), &pw);
63 			if (pw == NULL) {
64 				snprintf(cp->name, sizeof(cp->name), "%u", uid);
65 				cp->noname = 1;
66 			} else {
67 				strlcpy(cp->name, pw->pw_name, sizeof(cp->name));
68 			}
69 		}
70 		if (cp->uid == uid) {
71 			if (nouser && cp->noname)
72 				return NULL;
73 			return cp->name;
74 		}
75 	}
76 	/* move everybody down a slot */
77 	for (i = 0; i < NLINES - 1; i++) {
78 		struct ncache *next;
79 
80 		cp = &c_uid[IDX(uid, i)];
81 		next = &c_uid[IDX(uid, i + 1)];
82 		memcpy(next, cp, sizeof(*cp));
83 	}
84 	cp = &c_uid[IDX(uid, 0)];
85 	goto fillit;
86 }
87 
88 char *
89 group_from_gid(gid_t gid, int nogroup)
90 {
91 	static struct ncache {
92 		gid_t	gid;
93 		short 	noname;
94 		char	name[_PW_NAME_LEN + 1];
95 	} c_gid[NLINES * NCACHE];
96 	char grbuf[_GR_BUF_LEN];
97 	struct group grstore, *gr;
98 	struct ncache *cp;
99 	unsigned int i;
100 
101 	for (i = 0; i < NLINES; i++) {
102 		cp = &c_gid[IDX(gid, i)];
103 		if (!*cp->name) {
104 fillit:
105 			cp->gid = gid;
106 			gr = NULL;
107 			getgrgid_r(gid, &grstore, grbuf, sizeof(grbuf), &gr);
108 			if (gr == NULL) {
109 				snprintf(cp->name, sizeof(cp->name), "%u", gid);
110 				cp->noname = 1;
111 			} else {
112 				strlcpy(cp->name, gr->gr_name, sizeof(cp->name));
113 			}
114 		}
115 		if (cp->gid == gid) {
116 			if (nogroup && cp->noname)
117 				return NULL;
118 			return cp->name;
119 		}
120 	}
121 	/* move everybody down a slot */
122 	for (i = 0; i < NLINES - 1; i++) {
123 		struct ncache *next;
124 
125 		cp = &c_gid[IDX(gid, i)];
126 		next = &c_gid[IDX(gid, i + 1)];
127 		memcpy(next, cp, sizeof(*cp));
128 	}
129 	cp = &c_gid[IDX(gid, 0)];
130 	goto fillit;
131 }
132