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