/* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getpwent.c 5.9.1 (2.11BSD) 1996/1/12"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include static DBM *_pw_db; static FILE *_pw_fp; static struct passwd _pw_passwd; static int _pw_rewind = 1, _pw_stayopen; static char _pw_flag, *_pw_file = _PATH_PASSWD; #define MAXLINELENGTH 256 static char line[MAXLINELENGTH]; struct passwd * getpwent() { datum key; register int rval; if (!_pw_db && !_pw_fp && !start_pw()) return((struct passwd *)NULL); do { if (_pw_db) { key.dptr = NULL; rval = fetch_pw(key); } else /* _pw_fp */ rval = scanpw(); } while (rval && _pw_flag != _PW_KEYBYNAME); if (rval) getpw(); return(rval ? &_pw_passwd : (struct passwd *)NULL); } struct passwd * getpwnam(nam) char *nam; { register int rval; if (!start_pw()) return((struct passwd *)NULL); if (_pw_db) { datum key; key.dptr = nam; key.dsize = strlen(nam); rval = fetch_pw(key); } else /* _pw_fp */ for (rval = 0; scanpw();) if (!strcmp(nam, _pw_passwd.pw_name)) { rval = 1; break; } if (!_pw_stayopen) endpwent(); if (rval) getpw(); return(rval ? &_pw_passwd : (struct passwd *)NULL); } struct passwd * getpwuid(uid) int uid; { register int rval; if (!start_pw()) return((struct passwd *)NULL); if (_pw_db) { datum key; key.dptr = (char *)&uid; key.dsize = sizeof(uid); rval = fetch_pw(key); } else /* _pw_fp */ for (rval = 0; scanpw();) if (_pw_passwd.pw_uid == uid) { rval = 1; break; } if (!_pw_stayopen) endpwent(); if (rval) getpw(); return(rval ? &_pw_passwd : (struct passwd *)NULL); } static start_pw() { register char *p; if (_pw_db) { _pw_rewind = 1; return(1); } if (_pw_fp) { rewind(_pw_fp); return(1); } if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0)) { _pw_rewind = 1; return(1); } /* * special case; if it's the official password file, look in * the master password file, otherwise, look in the file itself. */ p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; if (_pw_fp = fopen(p, "r")) return(1); return(0); } setpwent() { return(setpassent(0)); } setpassent(stayopen) int stayopen; { if (!start_pw()) return(0); _pw_stayopen = stayopen; return(1); } void endpwent() { if (_pw_db) { dbm_close(_pw_db); _pw_db = (DBM *)NULL; } else if (_pw_fp) { (void)fclose(_pw_fp); _pw_fp = (FILE *)NULL; } } void setpwfile(file) char *file; { _pw_file = file; } static scanpw() { register char *cp; char *bp = line; register int ch; for (;;) { if (!(fgets(line, sizeof(line), _pw_fp))) return(0); /* skip lines that are too big */ if (!(cp = index(line, '\n'))) { while ((ch = fgetc(_pw_fp)) != '\n' && ch != EOF) ; continue; } *cp = '\0'; _pw_passwd.pw_name = strsep(&bp, ":"); _pw_passwd.pw_passwd = strsep(&bp, ":"); if (!(cp = strsep(&bp, ":"))) continue; _pw_passwd.pw_uid = atoi(cp); if (!(cp = strsep(&bp, ":"))) continue; _pw_passwd.pw_gid = atoi(cp); _pw_passwd.pw_class = strsep(&bp, ":"); if (!(cp = strsep(&bp, ":"))) continue; _pw_passwd.pw_change = atol(cp); if (!(cp = strsep(&bp, ":"))) continue; _pw_passwd.pw_expire = atol(cp); _pw_passwd.pw_gecos = strsep(&bp, ":"); _pw_passwd.pw_dir = strsep(&bp, ":"); _pw_passwd.pw_shell = strsep(&bp, ":"); if (!_pw_passwd.pw_shell) continue; return(1); } /* NOTREACHED */ } static fetch_pw(key) datum key; { register char *p, *t; /* * the .dir file is LOCK_EX locked by programs that are * renaming the various password files. */ if (flock(dbm_dirfno(_pw_db), LOCK_SH)) return(0); if (!key.dptr) if (_pw_rewind) { _pw_rewind = 0; key = dbm_firstkey(_pw_db); } else key = dbm_nextkey(_pw_db); if (key.dptr) key = dbm_fetch(_pw_db, key); (void)flock(dbm_dirfno(_pw_db), LOCK_UN); if (!(p = key.dptr)) return(0); t = line; #define EXPAND(e) e = t; while (*t++ = *p++); EXPAND(_pw_passwd.pw_name); EXPAND(_pw_passwd.pw_passwd); bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); p += sizeof(int); bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); p += sizeof(int); bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); p += sizeof(time_t); EXPAND(_pw_passwd.pw_class); EXPAND(_pw_passwd.pw_gecos); EXPAND(_pw_passwd.pw_dir); EXPAND(_pw_passwd.pw_shell); bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); p += sizeof(time_t); _pw_flag = *p; return(1); } static getpw() { static char pwbuf[50]; off_t lseek(); long pos; int fd, n; register char *p; if (geteuid()) return; /* * special case; if it's the official password file, look in * the master password file, otherwise, look in the file itself. */ p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD; if ((fd = open(p, O_RDONLY, 0)) < 0) return; pos = atol(_pw_passwd.pw_passwd); if (lseek(fd, pos, L_SET) != pos) goto bad; if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0) goto bad; pwbuf[n] = '\0'; for (p = pwbuf; *p; ++p) if (*p == ':') { *p = '\0'; _pw_passwd.pw_passwd = pwbuf; break; } bad: (void)close(fd); }