|
|
1.1 root 1: /*
2: * pwsearch(name, uid, pwline)
3: * search for name (if non null) or uid in password.
4: return ptr to passwd structure.
5: if pwline is non null return whole password line.
6: */
7: #include <stdio.h>
8: #include <sys/types.h>
9: #include <sys/stat.h>
10: #include <pwd.h>
11:
12: #define PASSWD "/etc/passwd"
13: #define PWLINE 500
14: #define CHUNK 64 /* allocation of hint table -- must be a power of two */
15:
16: static struct hint {
17: long hint;
18: char *name;
19: short uid;
20: } *htab;
21:
22: static int htabsize = 0;
23: char buf[PWLINE];
24: static FILE *pwf;
25: static time_t pwtime;
26:
27: struct passwd *pwdecode();
28: char *malloc(), *realloc(), *strcpy();
29:
30: struct passwd *
31: pwsearch(name, uid, pwline)
32: char *name, *pwline;
33: {
34: register int min, max, mid;
35: register struct passwd *pw;
36: int ntries = 0;
37: struct stat sbuf;
38:
39: again:
40: if (ntries>1)
41: return(NULL);
42: if (pwf)
43: fstat(fileno(pwf), &sbuf);
44: if (pwf==NULL || ntries || pwtime < sbuf.st_ctime) {
45: buildtable();
46: pwtime = sbuf.st_ctime;
47: }
48: ntries++;
49: if (name) {
50: /* binary search for name */
51: min = 0;
52: max = htabsize - 1;
53: while (min <= max) {
54: register n;
55: mid = (min + max) >> 1;
56: n = strcmp (name, htab[mid].name);
57: if (n == 0)
58: break;
59: if (n < 0)
60: max = mid - 1;
61: else
62: min = mid + 1;
63: }
64: if (min > max)
65: goto again;
66: } else {
67: /* linear search for uid */
68: for (mid = 0; mid <htabsize; mid++)
69: if (htab[mid].uid == uid)
70: break;
71: if (mid == htabsize)
72: goto again;
73: }
74: /*
75: * We have a hint. Seek to the given point in the file.
76: * If it's not the very beginning, ensure it is the start
77: * of a line by peeking at the preceding character.
78: */
79: if (htab[mid].hint) {
80: fseek(pwf, htab[mid].hint-1, 0);
81: if (getc(pwf) != '\n')
82: goto again;
83: } else
84: fseek(pwf, htab[mid].hint, 0);
85: if (fgets(buf, PWLINE, pwf) == NULL)
86: goto again;
87: if (pwline)
88: strcpy(pwline, buf);
89: pw = pwdecode(buf);
90: if (name) {
91: if (strcmp(name, pw->pw_name))
92: goto again;
93: } else if (uid != pw->pw_uid)
94: goto again;
95: return(pw);
96: }
97:
98: /* comparison function for call to qsort */
99: static int
100: comp (p, q)
101: struct hint *p, *q;
102: {
103: return(strcmp (p->name, q->name));
104: }
105:
106: static int
107: buildtable()
108: {
109: long where;
110: register int i;
111:
112: /* free the old hint table */
113: for (i = 0; i < htabsize; i++) {
114: if (htab[i].name) {
115: (void)free((char *)htab[i].name);
116: htab[i].name = NULL;
117: }
118: }
119: if (htab) {
120: (void)free((char *)htab);
121: htab = NULL;
122: }
123: htabsize = 0;
124: if (pwf)
125: fclose(pwf);
126: pwf = fopen(PASSWD, "r");
127: if (pwf == NULL)
128: return;
129: while (where = ftell(pwf), fgets(buf, PWLINE, pwf) != NULL) {
130: register struct passwd *pw = pwdecode(buf);
131: register char *p = malloc(strlen(pw->pw_name) + 1);
132:
133: if (p == NULL)
134: return;
135: /* time to expand the hint table? */
136: if ((htabsize & (CHUNK - 1)) == 0) {
137: unsigned s = (htabsize + CHUNK) * sizeof(struct hint);
138: if (htab)
139: htab = (struct hint *) realloc(htab, s);
140: else
141: htab = (struct hint *) malloc(s);
142: if (htab == NULL) {
143: htabsize = 0;
144: return;
145: }
146: }
147: htab[htabsize].name = strcpy(p, pw->pw_name);
148: htab[htabsize].uid = pw->pw_uid;
149: htab[htabsize].hint = where;
150: htabsize++;
151: }
152: qsort((char *) htab, htabsize, sizeof (struct hint), comp);
153: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.