Home | History | Annotate | Line # | Download | only in libhack
getpwent.c revision 1.9
      1 /*	$NetBSD: getpwent.c,v 1.9 2005/03/31 12:56:49 he Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Copied from:  lib/libc/gen/getpwent.c
     34  *	NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp
     35  * and then gutted, leaving only /etc/master.passwd support.
     36  */
     37 
     38 #include <sys/cdefs.h>
     39 
     40 #ifdef __weak_alias
     41 #define endpwent		_endpwent
     42 #define getpwent		_getpwent
     43 #define getpwuid		_getpwuid
     44 #define getpwnam		_getpwnam
     45 #define setpwent		_setpwent
     46 #define setpassent		_setpassent
     47 #define getpwuid_r		_getpwuid_r
     48 #define getpwnam_r		_getpwnam_r
     49 
     50 __weak_alias(endpwent,_endpwent)
     51 __weak_alias(getpwent,_getpwent)
     52 __weak_alias(getpwuid,_getpwuid)
     53 __weak_alias(getpwnam,_getpwnam)
     54 __weak_alias(setpwent,_setpwent)
     55 __weak_alias(setpassent,_setpassent)
     56 __weak_alias(getpwuid_r,_getpwuid_r)
     57 __weak_alias(getpwnam_r,_getpwnam_r)
     58 #endif
     59 
     60 #include <sys/param.h>
     61 
     62 #include <limits.h>
     63 #include <pwd.h>
     64 #include <stdlib.h>
     65 #include <stdio.h>
     66 #include <string.h>
     67 
     68 static	int		pwstart(void);
     69 static	int		pwscan(int, uid_t, const char *, struct passwd *,
     70     char *, size_t);
     71 static	int		pwmatchline(int, uid_t, const char *, struct passwd *,
     72     char *);
     73 
     74 static	FILE		*_pw_fp;
     75 static	struct passwd	_pw_passwd;	/* password structure */
     76 static	int		_pw_stayopen;	/* keep fd's open */
     77 static	int		_pw_filesdone;
     78 
     79 #define	MAXLINELENGTH	1024
     80 
     81 static	char		pwline[MAXLINELENGTH];
     82 
     83 struct passwd *
     84 getpwent(void)
     85 {
     86 
     87 	if ((!_pw_fp && !pwstart()) ||
     88 	    !pwscan(0, 0, NULL, &_pw_passwd, pwline, sizeof(pwline)))
     89 		return (NULL);
     90 	return (&_pw_passwd);
     91 }
     92 
     93 struct passwd *
     94 getpwnam(const char *name)
     95 {
     96 	struct passwd *pwd;
     97 	return getpwnam_r(name, &_pw_passwd, pwline, sizeof(pwline),
     98 	    &pwd) == 0 ? pwd : NULL;
     99 }
    100 
    101 int
    102 getpwnam_r(const char *name, struct passwd *pwres, char *buf, size_t bufsiz,
    103     struct passwd **pwd)
    104 {
    105 	int rval;
    106 
    107 	if (!pwstart())
    108 		return 1;
    109 	rval = !pwscan(1, 0, name, pwres, buf, bufsiz);
    110 	if (!_pw_stayopen)
    111 		endpwent();
    112 	if (rval)
    113 		*pwd = NULL;
    114 	else
    115 		*pwd = pwres;
    116 	return rval;
    117 }
    118 
    119 struct passwd *
    120 getpwuid(uid_t uid)
    121 {
    122 	struct passwd *pwd;
    123 	return getpwuid_r(uid, &_pw_passwd, pwline, sizeof(pwline),
    124 	    &pwd) == 0 ? pwd : NULL;
    125 }
    126 
    127 int
    128 getpwuid_r(uid_t uid, struct passwd *pwres, char *buf, size_t bufsiz,
    129     struct passwd **pwd)
    130 {
    131 	int rval;
    132 
    133 	if (!pwstart())
    134 		return 1;
    135 	rval = !pwscan(1, uid, NULL, pwres, buf, bufsiz);
    136 	if (!_pw_stayopen)
    137 		endpwent();
    138 	if (rval)
    139 		*pwd = NULL;
    140 	else
    141 		*pwd = pwres;
    142 	return rval;
    143 }
    144 
    145 void
    146 setpwent(void)
    147 {
    148 
    149 	(void) setpassent(0);
    150 }
    151 
    152 int
    153 setpassent(int stayopen)
    154 {
    155 
    156 	if (!pwstart())
    157 		return 0;
    158 	_pw_stayopen = stayopen;
    159 	return 1;
    160 }
    161 
    162 void
    163 endpwent(void)
    164 {
    165 
    166 	_pw_filesdone = 0;
    167 	if (_pw_fp) {
    168 		(void)fclose(_pw_fp);
    169 		_pw_fp = NULL;
    170 	}
    171 }
    172 
    173 static int
    174 pwstart(void)
    175 {
    176 
    177 	_pw_filesdone = 0;
    178 	if (_pw_fp) {
    179 		rewind(_pw_fp);
    180 		return 1;
    181 	}
    182 	return (_pw_fp = fopen(_PATH_MASTERPASSWD, "r")) ? 1 : 0;
    183 }
    184 
    185 
    186 static int
    187 pwscan(int search, uid_t uid, const char *name, struct passwd *pwd, char *buf,
    188     size_t bufsiz)
    189 {
    190 
    191 	if (_pw_filesdone)
    192 		return 0;
    193 	for (;;) {
    194 		if (!fgets(buf, bufsiz, _pw_fp)) {
    195 			if (!search)
    196 				_pw_filesdone = 1;
    197 			return 0;
    198 		}
    199 		/* skip lines that are too big */
    200 		if (!strchr(buf, '\n')) {
    201 			int ch;
    202 
    203 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
    204 				;
    205 			continue;
    206 		}
    207 		if (pwmatchline(search, uid, name, pwd, buf))
    208 			return 1;
    209 	}
    210 	/* NOTREACHED */
    211 }
    212 
    213 static int
    214 pwmatchline(int search, uid_t uid, const char *name, struct passwd *pwd,
    215     char *buf)
    216 {
    217 	unsigned long	id;
    218 	char		*cp, *bp, *ep;
    219 
    220 	/* name may be NULL if search is nonzero */
    221 
    222 	bp = buf;
    223 	memset(pwd, 0, sizeof(*pwd));
    224 	pwd->pw_name = strsep(&bp, ":\n");		/* name */
    225 	if (search && name && strcmp(pwd->pw_name, name))
    226 		return 0;
    227 
    228 	pwd->pw_passwd = strsep(&bp, ":\n");		/* passwd */
    229 
    230 	if (!(cp = strsep(&bp, ":\n")))				/* uid */
    231 		return 0;
    232 	id = strtoul(cp, &ep, 10);
    233 	if (id > UID_MAX || *ep != '\0')
    234 		return 0;
    235 	pwd->pw_uid = (uid_t)id;
    236 	if (search && name == NULL && pwd->pw_uid != uid)
    237 		return 0;
    238 
    239 	if (!(cp = strsep(&bp, ":\n")))				/* gid */
    240 		return 0;
    241 	id = strtoul(cp, &ep, 10);
    242 	if (id > GID_MAX || *ep != '\0')
    243 		return 0;
    244 	pwd->pw_gid = (gid_t)id;
    245 
    246 	if (!(pwd->pw_class = strsep(&bp, ":")))		/* class */
    247 		return 0;
    248 	if (!(ep = strsep(&bp, ":")))				/* change */
    249 		return 0;
    250 	if (!(ep = strsep(&bp, ":")))				/* expire */
    251 		return 0;
    252 
    253 	if (!(pwd->pw_gecos = strsep(&bp, ":\n")))		/* gecos */
    254 		return 0;
    255 	if (!(pwd->pw_dir = strsep(&bp, ":\n")))		/* directory */
    256 		return 0;
    257 	if (!(pwd->pw_shell = strsep(&bp, ":\n")))		/* shell */
    258 		return 0;
    259 
    260 	if (strchr(bp, ':') != NULL)
    261 		return 0;
    262 
    263 	return 1;
    264 }
    265