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