xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/_getpw.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include "lib.h"
23e12c5d1SDavid du Colombier #include <sys/types.h>
33e12c5d1SDavid du Colombier #include <sys/stat.h>
43e12c5d1SDavid du Colombier #include <fcntl.h>
53e12c5d1SDavid du Colombier #include <stdlib.h>
63e12c5d1SDavid du Colombier #include <string.h>
73e12c5d1SDavid du Colombier #include <unistd.h>
83e12c5d1SDavid du Colombier #include "sys9.h"
93e12c5d1SDavid du Colombier #include "dir.h"
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier /*
123e12c5d1SDavid du Colombier  * Search /adm/users for line with second field ==  *pname (if
133e12c5d1SDavid du Colombier  * not NULL), else with first field == *pnum.  Return non-zero
143e12c5d1SDavid du Colombier  * if found, and fill in *pnum, *pname, and *plist to fields
153e12c5d1SDavid du Colombier  * 1, 2, and 4
163e12c5d1SDavid du Colombier  */
173e12c5d1SDavid du Colombier 
18*219b2ee8SDavid du Colombier enum {NAMEMAX = 20, MEMOMAX = 40 };
19*219b2ee8SDavid du Colombier 
203e12c5d1SDavid du Colombier static char *admusers = "/adm/users";
21*219b2ee8SDavid du Colombier 
22*219b2ee8SDavid du Colombier /* we hold a fixed-length memo list of past lookups, and use a move-to-front
23*219b2ee8SDavid du Colombier     strategy to organize the list
24*219b2ee8SDavid du Colombier */
25*219b2ee8SDavid du Colombier typedef struct Memo {
26*219b2ee8SDavid du Colombier 	char		name[NAMEMAX];
27*219b2ee8SDavid du Colombier 	int		num;
28*219b2ee8SDavid du Colombier 	char		*glist;
29*219b2ee8SDavid du Colombier } Memo;
30*219b2ee8SDavid du Colombier 
31*219b2ee8SDavid du Colombier static Memo *memo[MEMOMAX];
32*219b2ee8SDavid du Colombier static int nmemo = 0;
333e12c5d1SDavid du Colombier 
343e12c5d1SDavid du Colombier int
353e12c5d1SDavid du Colombier _getpw(int *pnum, char **pname, char **plist)
363e12c5d1SDavid du Colombier {
373e12c5d1SDavid du Colombier 	Dir d;
38*219b2ee8SDavid du Colombier 	int f, n, i, j, matchnum, m, matched;
393e12c5d1SDavid du Colombier 	char *eline, *f1, *f2, *f3, *f4;
40*219b2ee8SDavid du Colombier 	Memo *mem;
413e12c5d1SDavid du Colombier 	static char *au = NULL;
423e12c5d1SDavid du Colombier 
433e12c5d1SDavid du Colombier 	if(!pname)
443e12c5d1SDavid du Colombier 		return 0;
453e12c5d1SDavid du Colombier 	if(au == NULL){
463e12c5d1SDavid du Colombier 		char cd[DIRLEN];
473e12c5d1SDavid du Colombier 		if(_STAT(admusers, cd) < 0)
483e12c5d1SDavid du Colombier 			return 0;
493e12c5d1SDavid du Colombier 		convM2D(cd, &d);
503e12c5d1SDavid du Colombier 		if((au = (char *)malloc(d.length+2)) == NULL)
513e12c5d1SDavid du Colombier 			return 0;
523e12c5d1SDavid du Colombier 		f = open(admusers, O_RDONLY);
533e12c5d1SDavid du Colombier 		if(f < 0)
543e12c5d1SDavid du Colombier 			return 0;
553e12c5d1SDavid du Colombier 		n = read(f, au, d.length);
563e12c5d1SDavid du Colombier 		close(f);
573e12c5d1SDavid du Colombier 		if(n < 0)
583e12c5d1SDavid du Colombier 			return 0;
593e12c5d1SDavid du Colombier 		au[n] = 0;
603e12c5d1SDavid du Colombier 	}
613e12c5d1SDavid du Colombier 	matchnum = (*pname == NULL);
623e12c5d1SDavid du Colombier 	matched = 0;
63*219b2ee8SDavid du Colombier 	/* try using memo */
64*219b2ee8SDavid du Colombier 	for(i = 0; i<nmemo; i++) {
65*219b2ee8SDavid du Colombier 		mem = memo[i];
66*219b2ee8SDavid du Colombier 		if(matchnum)
67*219b2ee8SDavid du Colombier 			matched = (mem->num == *pnum);
68*219b2ee8SDavid du Colombier 		else
69*219b2ee8SDavid du Colombier 			matched = (strcmp(mem->name, *pname) == 0);
70*219b2ee8SDavid du Colombier 		if(matched) {
71*219b2ee8SDavid du Colombier 			break;
72*219b2ee8SDavid du Colombier 		}
73*219b2ee8SDavid du Colombier 	}
74*219b2ee8SDavid du Colombier 	if(!matched)
75*219b2ee8SDavid du Colombier 		for(f1 = au, eline = au; !matched && *eline; f1 = eline+1){
763e12c5d1SDavid du Colombier 			eline = strchr(f1, '\n');
773e12c5d1SDavid du Colombier 			if(!eline)
783e12c5d1SDavid du Colombier 				eline = strchr(f1, 0);
793e12c5d1SDavid du Colombier 			if(*f1 == '#' || *f1 == '\n')
803e12c5d1SDavid du Colombier 				continue;
813e12c5d1SDavid du Colombier 			n = eline-f1;
823e12c5d1SDavid du Colombier 			f2 = memchr(f1, ':', n);
833e12c5d1SDavid du Colombier 			if(!f2)
843e12c5d1SDavid du Colombier 				continue;
853e12c5d1SDavid du Colombier 			f2++;
863e12c5d1SDavid du Colombier 			f3 = memchr(f2, ':', n-(f2-f1));
873e12c5d1SDavid du Colombier 			if(!f3)
883e12c5d1SDavid du Colombier 				continue;
893e12c5d1SDavid du Colombier 			f3++;
903e12c5d1SDavid du Colombier 			f4 = memchr(f3, ':', n-(f3-f1));
913e12c5d1SDavid du Colombier 			if(!f4)
923e12c5d1SDavid du Colombier 				continue;
933e12c5d1SDavid du Colombier 			f4++;
94*219b2ee8SDavid du Colombier 			if(matchnum)
95*219b2ee8SDavid du Colombier 				matched = (atoi(f1) == *pnum);
96*219b2ee8SDavid du Colombier 			else
97*219b2ee8SDavid du Colombier 				matched = (memcmp(*pname, f2, (f3-f2)-1)==0);
98*219b2ee8SDavid du Colombier 			if(matched){
99*219b2ee8SDavid du Colombier 				/* allocate and fill in a Memo structure */
100*219b2ee8SDavid du Colombier 				mem = (Memo*)malloc(sizeof(struct Memo));
101*219b2ee8SDavid du Colombier 				if(!mem)
102*219b2ee8SDavid du Colombier 					return 0;
1033e12c5d1SDavid du Colombier 				m = (f3-f2)-1;
104*219b2ee8SDavid du Colombier 				if(m > NAMEMAX-1)
105*219b2ee8SDavid du Colombier 					m = NAMEMAX-1;
106*219b2ee8SDavid du Colombier 				memcpy(mem->name, f2, m);
107*219b2ee8SDavid du Colombier 				mem->name[m] = 0;
108*219b2ee8SDavid du Colombier 				mem->num = atoi(f1);
109*219b2ee8SDavid du Colombier 				m = n-(f4-f1);
110*219b2ee8SDavid du Colombier 				if(m > 0){
111*219b2ee8SDavid du Colombier 					mem->glist = (char*)malloc(m+1);
112*219b2ee8SDavid du Colombier 					if(mem->glist) {
113*219b2ee8SDavid du Colombier 						memcpy(mem->glist, f4, m);
114*219b2ee8SDavid du Colombier 						mem->glist[m] = 0;
1153e12c5d1SDavid du Colombier 					}
116*219b2ee8SDavid du Colombier 				} else
117*219b2ee8SDavid du Colombier 					mem->glist = 0;
118*219b2ee8SDavid du Colombier 				/* prepare for following move-to-front */
119*219b2ee8SDavid du Colombier 				if(nmemo == MEMOMAX) {
120*219b2ee8SDavid du Colombier 					free(memo[nmemo-1]);
121*219b2ee8SDavid du Colombier 					i = nmemo-1;
1223e12c5d1SDavid du Colombier 				} else {
123*219b2ee8SDavid du Colombier 					i = nmemo++;
124*219b2ee8SDavid du Colombier 				}
1253e12c5d1SDavid du Colombier 			}
1263e12c5d1SDavid du Colombier 		}
1273e12c5d1SDavid du Colombier 	if(matched) {
128*219b2ee8SDavid du Colombier 		if(matchnum)
129*219b2ee8SDavid du Colombier 			*pname = mem->name;
130*219b2ee8SDavid du Colombier 		else
131*219b2ee8SDavid du Colombier 			*pnum = mem->num;
132*219b2ee8SDavid du Colombier 		if(plist)
133*219b2ee8SDavid du Colombier 			*plist = mem->glist;
134*219b2ee8SDavid du Colombier 		if(i > 0) {
135*219b2ee8SDavid du Colombier 			/* make room at front */
136*219b2ee8SDavid du Colombier 			for(j = i; j > 0; j--)
137*219b2ee8SDavid du Colombier 				memo[j] = memo[j-1];
1383e12c5d1SDavid du Colombier 		}
139*219b2ee8SDavid du Colombier 		memo[0] = mem;
140*219b2ee8SDavid du Colombier 		return 1;
1413e12c5d1SDavid du Colombier 	}
1423e12c5d1SDavid du Colombier 	return 0;
1433e12c5d1SDavid du Colombier }
1443e12c5d1SDavid du Colombier 
1453e12c5d1SDavid du Colombier char **
1463e12c5d1SDavid du Colombier _grpmems(char *list)
1473e12c5d1SDavid du Colombier {
1483e12c5d1SDavid du Colombier 	char **v;
1493e12c5d1SDavid du Colombier 	char *p;
150*219b2ee8SDavid du Colombier 	static char *holdvec[200];
151*219b2ee8SDavid du Colombier 	static char holdlist[1000];
1523e12c5d1SDavid du Colombier 
1533e12c5d1SDavid du Colombier 	p = list;
1543e12c5d1SDavid du Colombier 	v = holdvec;
155*219b2ee8SDavid du Colombier 	if(p) {
156*219b2ee8SDavid du Colombier 		strncpy(holdlist, list, sizeof(holdlist));
1573e12c5d1SDavid du Colombier 		while(v< &holdvec[sizeof(holdvec)]-1 && *p){
1583e12c5d1SDavid du Colombier 			*v++ = p;
1593e12c5d1SDavid du Colombier 			p = strchr(p, ',');
1603e12c5d1SDavid du Colombier 			if(p){
1613e12c5d1SDavid du Colombier 				p++;
1623e12c5d1SDavid du Colombier 				*p = 0;
1633e12c5d1SDavid du Colombier 			}else
1643e12c5d1SDavid du Colombier 				break;
1653e12c5d1SDavid du Colombier 		}
166*219b2ee8SDavid du Colombier 	}
1673e12c5d1SDavid du Colombier 	*v = 0;
1683e12c5d1SDavid du Colombier 	return holdvec;
1693e12c5d1SDavid du Colombier }
170