122095Smckusick /* 236215Sbostic * Copyright (c) 1988 The Regents of the University of California. 336215Sbostic * All rights reserved. 436215Sbostic * 536215Sbostic * Redistribution and use in source and binary forms are permitted 636215Sbostic * provided that the above copyright notice and this paragraph are 736215Sbostic * duplicated in all such forms and that any documentation, 836215Sbostic * advertising materials, and other materials related to such 936215Sbostic * distribution and use acknowledge that the software was developed 1036215Sbostic * by the University of California, Berkeley. The name of the 1136215Sbostic * University may not be used to endorse or promote products derived 1236215Sbostic * from this software without specific prior written permission. 1336215Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1436215Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*36855Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1622095Smckusick */ 1722095Smckusick 1826560Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*36855Sbostic static char sccsid[] = "@(#)getpwent.c 5.5 (Berkeley) 02/22/89"; 2036215Sbostic #endif /* LIBC_SCCS and not lint */ 2122095Smckusick 2236215Sbostic #include <sys/types.h> 2336215Sbostic #include <sys/file.h> 242019Swnj #include <stdio.h> 252019Swnj #include <pwd.h> 2616416Sralph #include <ndbm.h> 272019Swnj 28*36855Sbostic #define static 2936215Sbostic static DBM *_pw_db; 3036215Sbostic static FILE *_pw_fp; 3136215Sbostic static struct passwd _pw_passwd; 32*36855Sbostic static int _pw_euid = -1, _pw_fd, _pw_rewind = 1, _pw_set, _pw_stayopen; 33*36855Sbostic static char _pw_flag, *_pw_file = _PATH_MASTERPASSWD; 342019Swnj 3536456Sbostic #define MAXLINELENGTH 1024 3636215Sbostic static char line[MAXLINELENGTH]; 3717759Sserge 38*36855Sbostic struct passwd * 39*36855Sbostic getpwent() 40*36855Sbostic { 41*36855Sbostic datum key; 42*36855Sbostic int rval; 43*36855Sbostic 44*36855Sbostic if (!_pw_db && !_pw_fp && !start_pw()) 45*36855Sbostic return((struct passwd *)NULL); 46*36855Sbostic do { 47*36855Sbostic if (_pw_db) { 48*36855Sbostic key.dptr = NULL; 49*36855Sbostic rval = fetch_pw(key); 50*36855Sbostic } else /* _pw_fp */ 51*36855Sbostic rval = scanpw(); 52*36855Sbostic } while (rval && _pw_flag != _PW_KEYBYNAME); 53*36855Sbostic if (_pw_euid == -1) 54*36855Sbostic _pw_euid = geteuid(); 55*36855Sbostic if (!_pw_euid) 56*36855Sbostic getpw(); 57*36855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 58*36855Sbostic } 59*36855Sbostic 60*36855Sbostic struct passwd * 61*36855Sbostic getpwnam(nam) 62*36855Sbostic char *nam; 63*36855Sbostic { 64*36855Sbostic int rval; 65*36855Sbostic 66*36855Sbostic if (!start_pw()) 67*36855Sbostic return((struct passwd *)NULL); 68*36855Sbostic if (_pw_db) { 69*36855Sbostic datum key; 70*36855Sbostic 71*36855Sbostic key.dptr = nam; 72*36855Sbostic key.dsize = strlen(nam); 73*36855Sbostic rval = fetch_pw(key); 74*36855Sbostic } else /* _pw_fp */ 75*36855Sbostic while (scanpw()) 76*36855Sbostic if (!strcmp(nam, _pw_passwd.pw_name)) { 77*36855Sbostic rval = 1; 78*36855Sbostic break; 79*36855Sbostic } 80*36855Sbostic if (!_pw_stayopen) 81*36855Sbostic endpwent(); 82*36855Sbostic if (_pw_euid == -1) 83*36855Sbostic _pw_euid = geteuid(); 84*36855Sbostic if (!_pw_euid) 85*36855Sbostic getpw(); 86*36855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 87*36855Sbostic } 88*36855Sbostic 89*36855Sbostic struct passwd * 90*36855Sbostic getpwuid(uid) 91*36855Sbostic int uid; 92*36855Sbostic { 93*36855Sbostic int rval; 94*36855Sbostic 95*36855Sbostic if (!start_pw()) 96*36855Sbostic return((struct passwd *)NULL); 97*36855Sbostic if (_pw_db) { 98*36855Sbostic datum key; 99*36855Sbostic 100*36855Sbostic key.dptr = (char *)&uid; 101*36855Sbostic key.dsize = sizeof(uid); 102*36855Sbostic rval = fetch_pw(key); 103*36855Sbostic } else /* _pw_fp */ 104*36855Sbostic while (scanpw()) 105*36855Sbostic if (_pw_passwd.pw_uid == uid) { 106*36855Sbostic rval = 1; 107*36855Sbostic break; 108*36855Sbostic } 109*36855Sbostic if (!_pw_stayopen) 110*36855Sbostic endpwent(); 111*36855Sbostic if (_pw_euid == -1) 112*36855Sbostic _pw_euid = geteuid(); 113*36855Sbostic if (!_pw_euid) 114*36855Sbostic getpw(); 115*36855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 116*36855Sbostic } 117*36855Sbostic 11836215Sbostic static 119*36855Sbostic start_pw() 1202019Swnj { 121*36855Sbostic if (_pw_db) { 122*36855Sbostic _pw_rewind = 1; 123*36855Sbostic return(1); 124*36855Sbostic } 125*36855Sbostic if (_pw_fp) { 126*36855Sbostic rewind(_pw_fp); 127*36855Sbostic return(1); 128*36855Sbostic } 129*36855Sbostic if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0)) 130*36855Sbostic return(1); 131*36855Sbostic if (_pw_fp = fopen(_pw_file, "r")) 132*36855Sbostic return(1); 133*36855Sbostic return(0); 134*36855Sbostic } 135*36855Sbostic 136*36855Sbostic setpwent() 137*36855Sbostic { 138*36855Sbostic return(setpassent(0)); 139*36855Sbostic } 140*36855Sbostic 141*36855Sbostic setpassent(stayopen) 142*36855Sbostic int stayopen; 143*36855Sbostic { 144*36855Sbostic if (!start_pw()) 145*36855Sbostic return(0); 146*36855Sbostic _pw_stayopen = stayopen; 147*36855Sbostic return(1); 148*36855Sbostic } 149*36855Sbostic 150*36855Sbostic void 151*36855Sbostic endpwent() 152*36855Sbostic { 153*36855Sbostic if (_pw_db) { 154*36855Sbostic dbm_close(_pw_db); 155*36855Sbostic _pw_db = (DBM *)NULL; 156*36855Sbostic } else if (_pw_fp) { 157*36855Sbostic (void)fclose(_pw_fp); 158*36855Sbostic _pw_fp = (FILE *)NULL; 159*36855Sbostic } 160*36855Sbostic if (_pw_fd) { 161*36855Sbostic (void)close(_pw_fd); 162*36855Sbostic _pw_fd = NULL; 163*36855Sbostic } 164*36855Sbostic } 165*36855Sbostic 166*36855Sbostic void 167*36855Sbostic setpwfile(file) 168*36855Sbostic char *file; 169*36855Sbostic { 170*36855Sbostic _pw_file = file; 171*36855Sbostic _pw_set = 1; 172*36855Sbostic } 173*36855Sbostic 174*36855Sbostic static 175*36855Sbostic scanpw() 176*36855Sbostic { 17736215Sbostic register char *cp; 178*36855Sbostic long atol(); 17936456Sbostic char *fgets(), *strsep(), *index(); 18036215Sbostic 18136215Sbostic for (;;) { 182*36855Sbostic if (!(fgets(line, sizeof(line), _pw_fp))) 18336215Sbostic return(0); 18436456Sbostic /* skip lines that are too big */ 185*36855Sbostic if (!index(line, '\n')) { 18636456Sbostic int ch; 18736456Sbostic 18836456Sbostic while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 18936456Sbostic ; 19036456Sbostic continue; 19136456Sbostic } 192*36855Sbostic _pw_passwd.pw_name = strsep(line, ":\n"); 19336215Sbostic _pw_passwd.pw_passwd = strsep((char *)NULL, ":\n"); 19436215Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19536215Sbostic continue; 19636215Sbostic _pw_passwd.pw_uid = atoi(cp); 19736215Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19836215Sbostic continue; 19936215Sbostic _pw_passwd.pw_gid = atoi(cp); 200*36855Sbostic _pw_passwd.pw_class = strsep((char *)NULL, ":\n"); 201*36855Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 202*36855Sbostic continue; 203*36855Sbostic _pw_passwd.pw_change = atol(cp); 204*36855Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 205*36855Sbostic continue; 206*36855Sbostic _pw_passwd.pw_expire = atol(cp); 20736215Sbostic _pw_passwd.pw_gecos = strsep((char *)NULL, ":\n"); 20836215Sbostic _pw_passwd.pw_dir = strsep((char *)NULL, ":\n"); 20936215Sbostic _pw_passwd.pw_shell = strsep((char *)NULL, ":\n"); 210*36855Sbostic if (!_pw_passwd.pw_shell) 211*36855Sbostic continue; 212*36855Sbostic return(1); 21336215Sbostic } 21436215Sbostic /* NOTREACHED */ 2152019Swnj } 2162019Swnj 21736215Sbostic static 218*36855Sbostic fetch_pw(key) 21936215Sbostic datum key; 2202019Swnj { 221*36855Sbostic register char *p, *t; 22236215Sbostic 223*36855Sbostic /* 224*36855Sbostic * the .dir file is LOCK_EX locked by programs that are 225*36855Sbostic * renaming the various password files. 226*36855Sbostic */ 227*36855Sbostic if (flock(dbm_dirfno(_pw_db), LOCK_SH)) 22836215Sbostic return(0); 229*36855Sbostic if (!key.dptr) 230*36855Sbostic if (_pw_rewind) { 231*36855Sbostic _pw_rewind = 0; 232*36855Sbostic key = dbm_firstkey(_pw_db); 233*36855Sbostic } else 234*36855Sbostic key = dbm_nextkey(_pw_db); 235*36855Sbostic if (key.dptr) 236*36855Sbostic key = dbm_fetch(_pw_db, key); 23736215Sbostic (void)flock(dbm_dirfno(_pw_db), LOCK_UN); 238*36855Sbostic if (!(p = key.dptr)) 23936215Sbostic return(0); 240*36855Sbostic t = line; 241*36855Sbostic #define EXPAND(e) e = t; while (*t++ = *p++); 242*36855Sbostic EXPAND(_pw_passwd.pw_name); 243*36855Sbostic EXPAND(_pw_passwd.pw_passwd); 244*36855Sbostic bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 245*36855Sbostic p += sizeof(int); 246*36855Sbostic bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 247*36855Sbostic p += sizeof(int); 248*36855Sbostic bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 249*36855Sbostic p += sizeof(time_t); 250*36855Sbostic EXPAND(_pw_passwd.pw_class); 251*36855Sbostic EXPAND(_pw_passwd.pw_gecos); 252*36855Sbostic EXPAND(_pw_passwd.pw_dir); 253*36855Sbostic EXPAND(_pw_passwd.pw_shell); 254*36855Sbostic bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 255*36855Sbostic p += sizeof(time_t); 256*36855Sbostic _pw_flag = *p; 25736215Sbostic return(1); 2582019Swnj } 2592019Swnj 260*36855Sbostic static 261*36855Sbostic getpw() 2622019Swnj { 263*36855Sbostic static char pwbuf[50]; 264*36855Sbostic long pos, atol(); 265*36855Sbostic int n; 266*36855Sbostic char *p; 2672019Swnj 268*36855Sbostic if (!_pw_fd && (_pw_fd = open(_pw_file, O_RDONLY, 0)) < 0) 269*36855Sbostic goto bad; 270*36855Sbostic pos = atol(_pw_passwd.pw_passwd); 271*36855Sbostic if (lseek(_pw_fd, pos, L_SET) != pos) 272*36855Sbostic goto bad; 273*36855Sbostic if ((n = read(_pw_fd, pwbuf, sizeof(pwbuf) - 1)) < 0) 274*36855Sbostic goto bad; 275*36855Sbostic pwbuf[n] = '\0'; 276*36855Sbostic for (p = pwbuf; *p; ++p) 277*36855Sbostic if (*p == ':') { 278*36855Sbostic *p = '\0'; 279*36855Sbostic _pw_passwd.pw_passwd = pwbuf; 280*36855Sbostic break; 281*36855Sbostic } 282*36855Sbostic if (!_pw_stayopen) 283*36855Sbostic bad: (void)close(_pw_fd); 2842019Swnj } 285