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