|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.