ref: 578af37678b2ea16e29d950cbc352823cd2491ab
dir: /sys/src/ape/lib/ap/plan9/_getpw.c/
#include "lib.h" #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "sys9.h" #include "dir.h" /* * Search /adm/users for line with second field == *pname (if * not NULL), else with first field == *pnum. Return non-zero * if found, and fill in *pnum, *pname, and *plist to fields * 1, 2, and 4 */ enum {NAMEMAX = 20, MEMOMAX = 40 }; static char *admusers = "/adm/users"; /* we hold a fixed-length memo list of past lookups, and use a move-to-front strategy to organize the list */ typedef struct Memo { char name[NAMEMAX]; int num; char *glist; } Memo; static Memo *memo[MEMOMAX]; static int nmemo = 0; int _getpw(int *pnum, char **pname, char **plist) { Dir *d; int f, n, i, j, matchnum, m, matched; char *eline, *f1, *f2, *f3, *f4; Memo *mem; static char *au = NULL; vlong length; if(!pname) return 0; if(au == NULL){ d = _dirstat(admusers); if(d == nil) return 0; length = d->length; free(d); if((au = (char *)malloc(length+2)) == NULL) return 0; f = open(admusers, O_RDONLY); if(f < 0) return 0; n = read(f, au, length); if(n < 0) return 0; au[n] = 0; } mem = nil; matchnum = (*pname == NULL); matched = 0; /* try using memo */ for(i = 0; i<nmemo; i++) { mem = memo[i]; if(matchnum) matched = (mem->num == *pnum); else matched = (strcmp(mem->name, *pname) == 0); if(matched) break; } if(!matched) for(f1 = au, eline = au; !matched && *eline; f1 = eline+1){ eline = strchr(f1, '\n'); if(!eline) eline = strchr(f1, 0); if(*f1 == '#' || *f1 == '\n') continue; n = eline-f1; f2 = memchr(f1, ':', n); if(!f2) continue; f2++; f3 = memchr(f2, ':', n-(f2-f1)); if(!f3) continue; f3++; f4 = memchr(f3, ':', n-(f3-f1)); if(!f4) continue; f4++; if(matchnum) matched = (atoi(f1) == *pnum); else{ int length; length = f3-f2-1; matched = length==strlen(*pname) && memcmp(*pname, f2, length)==0; } if(matched){ /* allocate and fill in a Memo structure */ mem = (Memo*)malloc(sizeof(struct Memo)); if(!mem) return 0; m = (f3-f2)-1; if(m > NAMEMAX-1) m = NAMEMAX-1; memcpy(mem->name, f2, m); mem->name[m] = 0; mem->num = atoi(f1); m = n-(f4-f1); if(m > 0){ mem->glist = (char*)malloc(m+1); if(mem->glist) { memcpy(mem->glist, f4, m); mem->glist[m] = 0; } } else mem->glist = 0; /* prepare for following move-to-front */ if(nmemo == MEMOMAX) { free(memo[nmemo-1]); i = nmemo-1; } else { i = nmemo++; } } } if(matched) { if(matchnum) *pname = mem->name; else *pnum = mem->num; if(plist) *plist = mem->glist; if(i > 0) { /* make room at front */ for(j = i; j > 0; j--) memo[j] = memo[j-1]; } memo[0] = mem; return 1; } return 0; } char ** _grpmems(char *list) { char **v; char *p; static char *holdvec[200]; static char holdlist[1024]; v = holdvec; if(list != 0){ memset(holdlist, 0, sizeof(holdlist)); strncpy(holdlist, list, sizeof(holdlist)-1); p = holdlist; while(v< &holdvec[sizeof(holdvec)]-1 && *p){ *v++ = p; p = strchr(p, ','); if(p == 0) break; *p++ = 0; } } *v = 0; return holdvec; }