|
|
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.