xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/_getpw.c (revision 781103c4074deb8af160e8a0da2742ba6b29dc2b)
1 #include "lib.h"
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include "sys9.h"
9 #include "dir.h"
10 
11 /*
12  * Search /adm/users for line with second field ==  *pname (if
13  * not NULL), else with first field == *pnum.  Return non-zero
14  * if found, and fill in *pnum, *pname, and *plist to fields
15  * 1, 2, and 4
16  */
17 
18 enum {NAMEMAX = 20, MEMOMAX = 40 };
19 
20 static char *admusers = "/adm/users";
21 
22 /* we hold a fixed-length memo list of past lookups, and use a move-to-front
23     strategy to organize the list
24 */
25 typedef struct Memo {
26 	char		name[NAMEMAX];
27 	int		num;
28 	char		*glist;
29 } Memo;
30 
31 static Memo *memo[MEMOMAX];
32 static int nmemo = 0;
33 
34 int
_getpw(int * pnum,char ** pname,char ** plist)35 _getpw(int *pnum, char **pname, char **plist)
36 {
37 	Dir *d;
38 	int f, n, i, j, matchnum, m, matched;
39 	char *eline, *f1, *f2, *f3, *f4;
40 	Memo *mem;
41 	static char *au = NULL;
42 	vlong length;
43 
44 	if(!pname)
45 		return 0;
46 	if(au == NULL){
47 		d = _dirstat(admusers);
48 		if(d == nil)
49 			return 0;
50 		length = d->length;
51 		free(d);
52 		if((au = (char *)malloc(length+2)) == NULL)
53 			return 0;
54 		f = open(admusers, O_RDONLY);
55 		if(f < 0)
56 			return 0;
57 		n = read(f, au, length);
58 		if(n < 0)
59 			return 0;
60 		au[n] = 0;
61 	}
62 	matchnum = (*pname == NULL);
63 	matched = 0;
64 	mem = nil;
65 	/* try using memo */
66 	for(i = 0; i<nmemo; i++) {
67 		mem = memo[i];
68 		if(matchnum)
69 			matched = (mem->num == *pnum);
70 		else
71 			matched = (strcmp(mem->name, *pname) == 0);
72 		if(matched) {
73 			break;
74 		}
75 	}
76 	if(!matched)
77 		for(f1 = au, eline = au; !matched && *eline; f1 = eline+1){
78 			eline = strchr(f1, '\n');
79 			if(!eline)
80 				eline = strchr(f1, 0);
81 			if(*f1 == '#' || *f1 == '\n')
82 				continue;
83 			n = eline-f1;
84 			f2 = memchr(f1, ':', n);
85 			if(!f2)
86 				continue;
87 			f2++;
88 			f3 = memchr(f2, ':', n-(f2-f1));
89 			if(!f3)
90 				continue;
91 			f3++;
92 			f4 = memchr(f3, ':', n-(f3-f1));
93 			if(!f4)
94 				continue;
95 			f4++;
96 			if(matchnum)
97 				matched = (atoi(f1) == *pnum);
98 			else{
99 				int length;
100 
101 				length = f3-f2-1;
102 				matched = length==strlen(*pname) && memcmp(*pname, f2, length)==0;
103 			}
104 			if(matched){
105 				/* allocate and fill in a Memo structure */
106 				mem = (Memo*)malloc(sizeof(struct Memo));
107 				if(!mem)
108 					return 0;
109 				m = (f3-f2)-1;
110 				if(m > NAMEMAX-1)
111 					m = NAMEMAX-1;
112 				memcpy(mem->name, f2, m);
113 				mem->name[m] = 0;
114 				mem->num = atoi(f1);
115 				m = n-(f4-f1);
116 				if(m > 0){
117 					mem->glist = (char*)malloc(m+1);
118 					if(mem->glist) {
119 						memcpy(mem->glist, f4, m);
120 						mem->glist[m] = 0;
121 					}
122 				} else
123 					mem->glist = 0;
124 				/* prepare for following move-to-front */
125 				if(nmemo == MEMOMAX) {
126 					free(memo[nmemo-1]);
127 					i = nmemo-1;
128 				} else {
129 					i = nmemo++;
130 				}
131 			}
132 		}
133 	if(matched) {
134 		if(matchnum)
135 			*pname = mem->name;
136 		else
137 			*pnum = mem->num;
138 		if(plist)
139 			*plist = mem->glist;
140 		if(i > 0) {
141 			/* make room at front */
142 			for(j = i; j > 0; j--)
143 				memo[j] = memo[j-1];
144 		}
145 		memo[0] = mem;
146 		return 1;
147 	}
148 	return 0;
149 }
150 
151 char **
_grpmems(char * list)152 _grpmems(char *list)
153 {
154 	char **v;
155 	char *p;
156 	static char *holdvec[200];
157 	static char holdlist[1000];
158 
159 	p = list;
160 	v = holdvec;
161 	if(p) {
162 		strncpy(holdlist, list, sizeof(holdlist));
163 		while(v< &holdvec[sizeof(holdvec)]-1 && *p){
164 			*v++ = p;
165 			p = strchr(p, ',');
166 			if(p){
167 				p++;
168 				*p = 0;
169 			}else
170 				break;
171 		}
172 	}
173 	*v = 0;
174 	return holdvec;
175 }
176