xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/_getpw.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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
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 
43 	if(!pname)
44 		return 0;
45 	if(au == NULL){
46 		char cd[DIRLEN];
47 		if(_STAT(admusers, cd) < 0)
48 			return 0;
49 		convM2D(cd, &d);
50 		if((au = (char *)malloc(d.length+2)) == NULL)
51 			return 0;
52 		f = open(admusers, O_RDONLY);
53 		if(f < 0)
54 			return 0;
55 		n = read(f, au, d.length);
56 		close(f);
57 		if(n < 0)
58 			return 0;
59 		au[n] = 0;
60 	}
61 	matchnum = (*pname == NULL);
62 	matched = 0;
63 	/* try using memo */
64 	for(i = 0; i<nmemo; i++) {
65 		mem = memo[i];
66 		if(matchnum)
67 			matched = (mem->num == *pnum);
68 		else
69 			matched = (strcmp(mem->name, *pname) == 0);
70 		if(matched) {
71 			break;
72 		}
73 	}
74 	if(!matched)
75 		for(f1 = au, eline = au; !matched && *eline; f1 = eline+1){
76 			eline = strchr(f1, '\n');
77 			if(!eline)
78 				eline = strchr(f1, 0);
79 			if(*f1 == '#' || *f1 == '\n')
80 				continue;
81 			n = eline-f1;
82 			f2 = memchr(f1, ':', n);
83 			if(!f2)
84 				continue;
85 			f2++;
86 			f3 = memchr(f2, ':', n-(f2-f1));
87 			if(!f3)
88 				continue;
89 			f3++;
90 			f4 = memchr(f3, ':', n-(f3-f1));
91 			if(!f4)
92 				continue;
93 			f4++;
94 			if(matchnum)
95 				matched = (atoi(f1) == *pnum);
96 			else
97 				matched = (memcmp(*pname, f2, (f3-f2)-1)==0);
98 			if(matched){
99 				/* allocate and fill in a Memo structure */
100 				mem = (Memo*)malloc(sizeof(struct Memo));
101 				if(!mem)
102 					return 0;
103 				m = (f3-f2)-1;
104 				if(m > NAMEMAX-1)
105 					m = NAMEMAX-1;
106 				memcpy(mem->name, f2, m);
107 				mem->name[m] = 0;
108 				mem->num = atoi(f1);
109 				m = n-(f4-f1);
110 				if(m > 0){
111 					mem->glist = (char*)malloc(m+1);
112 					if(mem->glist) {
113 						memcpy(mem->glist, f4, m);
114 						mem->glist[m] = 0;
115 					}
116 				} else
117 					mem->glist = 0;
118 				/* prepare for following move-to-front */
119 				if(nmemo == MEMOMAX) {
120 					free(memo[nmemo-1]);
121 					i = nmemo-1;
122 				} else {
123 					i = nmemo++;
124 				}
125 			}
126 		}
127 	if(matched) {
128 		if(matchnum)
129 			*pname = mem->name;
130 		else
131 			*pnum = mem->num;
132 		if(plist)
133 			*plist = mem->glist;
134 		if(i > 0) {
135 			/* make room at front */
136 			for(j = i; j > 0; j--)
137 				memo[j] = memo[j-1];
138 		}
139 		memo[0] = mem;
140 		return 1;
141 	}
142 	return 0;
143 }
144 
145 char **
146 _grpmems(char *list)
147 {
148 	char **v;
149 	char *p;
150 	static char *holdvec[200];
151 	static char holdlist[1000];
152 
153 	p = list;
154 	v = holdvec;
155 	if(p) {
156 		strncpy(holdlist, list, sizeof(holdlist));
157 		while(v< &holdvec[sizeof(holdvec)]-1 && *p){
158 			*v++ = p;
159 			p = strchr(p, ',');
160 			if(p){
161 				p++;
162 				*p = 0;
163 			}else
164 				break;
165 		}
166 	}
167 	*v = 0;
168 	return holdvec;
169 }
170