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 1536855Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1622095Smckusick */ 1722095Smckusick 1826560Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*41572Sedward static char sccsid[] = "@(#)getpwent.c 5.12 (Berkeley) 05/10/90"; 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 2836215Sbostic static DBM *_pw_db; 2936215Sbostic static FILE *_pw_fp; 3036215Sbostic static struct passwd _pw_passwd; 3139174Sbostic static int _pw_getfirstkey, _pw_stayopen; 32*41572Sedward static char _pw_flag, *_pw_file = _PATH_PASSWD, _pw_master; 332019Swnj 3436456Sbostic #define MAXLINELENGTH 1024 3536215Sbostic static char line[MAXLINELENGTH]; 3617759Sserge 3736855Sbostic struct passwd * 3836855Sbostic getpwent() 3936855Sbostic { 4036855Sbostic 41*41572Sedward if (!_pw_fp && !start_pw(1)) 4236855Sbostic return((struct passwd *)NULL); 43*41572Sedward if (!scanpw()) 44*41572Sedward return((struct passwd *)NULL); 45*41572Sedward getpw(); 46*41572Sedward return(&_pw_passwd); 4736855Sbostic } 4836855Sbostic 4936855Sbostic struct passwd * 5036855Sbostic getpwnam(nam) 5136855Sbostic char *nam; 5236855Sbostic { 5336855Sbostic int rval; 5436855Sbostic 55*41572Sedward if (!start_pw(0)) 5636855Sbostic return((struct passwd *)NULL); 5736855Sbostic if (_pw_db) { 5836855Sbostic datum key; 5936855Sbostic 6036855Sbostic key.dptr = nam; 6136855Sbostic key.dsize = strlen(nam); 6236855Sbostic rval = fetch_pw(key); 6336855Sbostic } else /* _pw_fp */ 6437243Sbostic for (rval = 0; scanpw();) 6536855Sbostic if (!strcmp(nam, _pw_passwd.pw_name)) { 6636855Sbostic rval = 1; 6736855Sbostic break; 6836855Sbostic } 6936855Sbostic if (!_pw_stayopen) 7036855Sbostic endpwent(); 7137243Sbostic if (rval) 7237243Sbostic getpw(); 7336855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 7436855Sbostic } 7536855Sbostic 7636855Sbostic struct passwd * 7736855Sbostic getpwuid(uid) 7836855Sbostic int uid; 7936855Sbostic { 8036855Sbostic int rval; 8136855Sbostic 82*41572Sedward if (!start_pw(0)) 8336855Sbostic return((struct passwd *)NULL); 8436855Sbostic if (_pw_db) { 8536855Sbostic datum key; 8636855Sbostic 8736855Sbostic key.dptr = (char *)&uid; 8836855Sbostic key.dsize = sizeof(uid); 8936855Sbostic rval = fetch_pw(key); 9036855Sbostic } else /* _pw_fp */ 9137243Sbostic for (rval = 0; scanpw();) 9236855Sbostic if (_pw_passwd.pw_uid == uid) { 9336855Sbostic rval = 1; 9436855Sbostic break; 9536855Sbostic } 9636855Sbostic if (!_pw_stayopen) 9736855Sbostic endpwent(); 9837243Sbostic if (rval) 9937243Sbostic getpw(); 10036855Sbostic return(rval ? &_pw_passwd : (struct passwd *)NULL); 10136855Sbostic } 10236855Sbostic 10336215Sbostic static 104*41572Sedward start_pw(want_fp) 105*41572Sedward char want_fp; /* open _pw_fp also */ 1062019Swnj { 10737196Sbostic char *p; 10837196Sbostic 10936855Sbostic if (_pw_db) { 11039174Sbostic _pw_getfirstkey = 1; 111*41572Sedward if (!want_fp) 112*41572Sedward return(1); 11336855Sbostic } 11436855Sbostic if (_pw_fp) { 11536855Sbostic rewind(_pw_fp); 11636855Sbostic return(1); 11736855Sbostic } 118*41572Sedward if (!_pw_db && (_pw_db = dbm_open(_pw_file, O_RDONLY, 0))) { 11939174Sbostic _pw_getfirstkey = 1; 120*41572Sedward if (!want_fp) 121*41572Sedward return(1); 12239174Sbostic } 12337196Sbostic /* 12437196Sbostic * special case; if it's the official password file, look in 12537196Sbostic * the master password file, otherwise, look in the file itself. 12637196Sbostic */ 12737196Sbostic p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 128*41572Sedward if (_pw_fp = fopen(p, "r")) { 129*41572Sedward _pw_master = 1; 13036855Sbostic return(1); 131*41572Sedward } 132*41572Sedward /* 133*41572Sedward * If we really want to set up _pw_fp, then try again 134*41572Sedward * with the old file. 135*41572Sedward */ 136*41572Sedward if (want_fp && p != _pw_file && (_pw_fp = fopen(_pw_file, "r"))) { 137*41572Sedward _pw_master = 0; 138*41572Sedward return(1); 139*41572Sedward } 14036855Sbostic return(0); 14136855Sbostic } 14236855Sbostic 14336855Sbostic setpwent() 14436855Sbostic { 14536855Sbostic return(setpassent(0)); 14636855Sbostic } 14736855Sbostic 14836855Sbostic setpassent(stayopen) 14936855Sbostic int stayopen; 15036855Sbostic { 151*41572Sedward if (!start_pw(0)) 15236855Sbostic return(0); 15336855Sbostic _pw_stayopen = stayopen; 15436855Sbostic return(1); 15536855Sbostic } 15636855Sbostic 15736855Sbostic void 15836855Sbostic endpwent() 15936855Sbostic { 16036855Sbostic if (_pw_db) { 16136855Sbostic dbm_close(_pw_db); 16236855Sbostic _pw_db = (DBM *)NULL; 163*41572Sedward } 164*41572Sedward if (_pw_fp) { 16536855Sbostic (void)fclose(_pw_fp); 16636855Sbostic _pw_fp = (FILE *)NULL; 16736855Sbostic } 16836855Sbostic } 16936855Sbostic 17036855Sbostic void 17136855Sbostic setpwfile(file) 17236855Sbostic char *file; 17336855Sbostic { 17436855Sbostic _pw_file = file; 17536855Sbostic } 17636855Sbostic 17736855Sbostic static 17836855Sbostic scanpw() 17936855Sbostic { 18036215Sbostic register char *cp; 18136855Sbostic long atol(); 18236456Sbostic char *fgets(), *strsep(), *index(); 18336215Sbostic 18436215Sbostic for (;;) { 18536855Sbostic if (!(fgets(line, sizeof(line), _pw_fp))) 18636215Sbostic return(0); 18736456Sbostic /* skip lines that are too big */ 18836855Sbostic if (!index(line, '\n')) { 18936456Sbostic int ch; 19036456Sbostic 19136456Sbostic while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 19236456Sbostic ; 19336456Sbostic continue; 19436456Sbostic } 19536855Sbostic _pw_passwd.pw_name = strsep(line, ":\n"); 19636215Sbostic _pw_passwd.pw_passwd = strsep((char *)NULL, ":\n"); 19736215Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 19836215Sbostic continue; 19936215Sbostic _pw_passwd.pw_uid = atoi(cp); 20036215Sbostic if (!(cp = strsep((char *)NULL, ":\n"))) 20136215Sbostic continue; 20236215Sbostic _pw_passwd.pw_gid = atoi(cp); 203*41572Sedward if (_pw_master) { 204*41572Sedward _pw_passwd.pw_class = strsep((char *)NULL, ":\n"); 205*41572Sedward if (!(cp = strsep((char *)NULL, ":\n"))) 206*41572Sedward continue; 207*41572Sedward _pw_passwd.pw_change = atol(cp); 208*41572Sedward if (!(cp = strsep((char *)NULL, ":\n"))) 209*41572Sedward continue; 210*41572Sedward _pw_passwd.pw_expire = atol(cp); 211*41572Sedward } 21236215Sbostic _pw_passwd.pw_gecos = strsep((char *)NULL, ":\n"); 21336215Sbostic _pw_passwd.pw_dir = strsep((char *)NULL, ":\n"); 21436215Sbostic _pw_passwd.pw_shell = strsep((char *)NULL, ":\n"); 21536855Sbostic if (!_pw_passwd.pw_shell) 21636855Sbostic continue; 21736855Sbostic return(1); 21836215Sbostic } 21936215Sbostic /* NOTREACHED */ 2202019Swnj } 2212019Swnj 22236215Sbostic static 22336855Sbostic fetch_pw(key) 22436215Sbostic datum key; 2252019Swnj { 22636855Sbostic register char *p, *t; 22736215Sbostic 22836855Sbostic /* 22936855Sbostic * the .dir file is LOCK_EX locked by programs that are 23036855Sbostic * renaming the various password files. 23136855Sbostic */ 23236855Sbostic if (flock(dbm_dirfno(_pw_db), LOCK_SH)) 23336215Sbostic return(0); 23436855Sbostic if (!key.dptr) 23539174Sbostic if (_pw_getfirstkey) { 23639174Sbostic _pw_getfirstkey = 0; 23736855Sbostic key = dbm_firstkey(_pw_db); 23836855Sbostic } else 23936855Sbostic key = dbm_nextkey(_pw_db); 24036855Sbostic if (key.dptr) 24136855Sbostic key = dbm_fetch(_pw_db, key); 24236215Sbostic (void)flock(dbm_dirfno(_pw_db), LOCK_UN); 24336855Sbostic if (!(p = key.dptr)) 24436215Sbostic return(0); 24536855Sbostic t = line; 24636855Sbostic #define EXPAND(e) e = t; while (*t++ = *p++); 24736855Sbostic EXPAND(_pw_passwd.pw_name); 24836855Sbostic EXPAND(_pw_passwd.pw_passwd); 24936855Sbostic bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 25036855Sbostic p += sizeof(int); 25136855Sbostic bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 25236855Sbostic p += sizeof(int); 25336855Sbostic bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 25436855Sbostic p += sizeof(time_t); 25536855Sbostic EXPAND(_pw_passwd.pw_class); 25636855Sbostic EXPAND(_pw_passwd.pw_gecos); 25736855Sbostic EXPAND(_pw_passwd.pw_dir); 25836855Sbostic EXPAND(_pw_passwd.pw_shell); 25936855Sbostic bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 26036855Sbostic p += sizeof(time_t); 26136855Sbostic _pw_flag = *p; 26236215Sbostic return(1); 2632019Swnj } 2642019Swnj 26538037Sbostic #define _MAX_PASSWD_SIZE 50 26638037Sbostic static char pwbuf[_MAX_PASSWD_SIZE]; 26738037Sbostic 26836855Sbostic static 26936855Sbostic getpw() 2702019Swnj { 27136855Sbostic long pos, atol(); 27237196Sbostic int fd, n; 27336855Sbostic char *p; 27438037Sbostic off_t lseek(); 2752019Swnj 27636868Sbostic if (geteuid()) 27736868Sbostic return; 27837196Sbostic /* 27937196Sbostic * special case; if it's the official password file, look in 28037196Sbostic * the master password file, otherwise, look in the file itself. 28137196Sbostic */ 28237196Sbostic p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; 28337196Sbostic if ((fd = open(p, O_RDONLY, 0)) < 0) 28437196Sbostic return; 28536855Sbostic pos = atol(_pw_passwd.pw_passwd); 28637196Sbostic if (lseek(fd, pos, L_SET) != pos) 28736855Sbostic goto bad; 28837196Sbostic if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0) 28936855Sbostic goto bad; 29036855Sbostic pwbuf[n] = '\0'; 29136855Sbostic for (p = pwbuf; *p; ++p) 29236855Sbostic if (*p == ':') { 29336855Sbostic *p = '\0'; 29436855Sbostic _pw_passwd.pw_passwd = pwbuf; 29536855Sbostic break; 29636855Sbostic } 29737196Sbostic bad: (void)close(fd); 2982019Swnj } 299