Home | History | Annotate | Line # | Download | only in libhack
getpwent.c revision 1.8
      1 /*	$NetBSD: getpwent.c,v 1.8 2005/03/31 04:14:42 christos 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 
     48 __weak_alias(endpwent,_endpwent)
     49 __weak_alias(getpwent,_getpwent)
     50 __weak_alias(getpwuid,_getpwuid)
     51 __weak_alias(getpwnam,_getpwnam)
     52 __weak_alias(setpwent,_setpwent)
     53 __weak_alias(setpassent,_setpassent)
     54 #endif
     55 
     56 #include <sys/param.h>
     57 
     58 #include <limits.h>
     59 #include <pwd.h>
     60 #include <stdlib.h>
     61 #include <stdio.h>
     62 #include <string.h>
     63 
     64 static	int		pwstart(void);
     65 static	int		pwscan(int, uid_t, const char *, struct passwd *,
     66     char *, size_t);
     67 static	int		pwmatchline(int, uid_t, const char *, struct passwd *,
     68     char *);
     69 
     70 static	FILE		*_pw_fp;
     71 static	struct passwd	_pw_passwd;	/* password structure */
     72 static	int		_pw_stayopen;	/* keep fd's open */
     73 static	int		_pw_filesdone;
     74 
     75 #define	MAXLINELENGTH	1024
     76 
     77 static	char		pwline[MAXLINELENGTH];
     78 
     79 struct passwd *
     80 getpwent(void)
     81 {
     82 
     83 	if ((!_pw_fp && !pwstart()) ||
     84 	    !pwscan(0, 0, NULL, &_pw_passwd, pwline, sizeof(pwline)))
     85 		return (NULL);
     86 	return (&_pw_passwd);
     87 }
     88 
     89 struct passwd *
     90 getpwnam(const char *name)
     91 {
     92 	struct passwd *pwd;
     93 	return getpwnam_r(name, &_pw_passwd, pwline, sizeof(pwline),
     94 	    &pwd) == 0 ? pwd : NULL;
     95 }
     96 
     97 int
     98 getpwnam_r(const char *name, struct passwd *pwres, char *buf, size_t bufsiz,
     99     struct passwd **pwd)
    100 {
    101 	int rval;
    102 
    103 	if (!pwstart())
    104 		return 1;
    105 	rval = !pwscan(1, 0, name, pwres, buf, bufsiz);
    106 	if (!_pw_stayopen)
    107 		endpwent();
    108 	if (rval)
    109 		*pwd = NULL;
    110 	else
    111 		*pwd = pwres;
    112 	return rval;
    113 }
    114 
    115 struct passwd *
    116 getpwuid(uid_t uid)
    117 {
    118 	struct passwd *pwd;
    119 	return getpwuid_r(uid, &_pw_passwd, pwline, sizeof(pwline),
    120 	    &pwd) == 0 ? pwd : NULL;
    121 }
    122 
    123 int
    124 getpwuid_r(uid_t uid, struct passwd *pwres, char *buf, size_t bufsiz,
    125     struct passwd **pwd)
    126 {
    127 	int rval;
    128 
    129 	if (!pwstart())
    130 		return 1;
    131 	rval = !pwscan(1, uid, NULL, pwres, buf, bufsiz);
    132 	if (!_pw_stayopen)
    133 		endpwent();
    134 	if (rval)
    135 		*pwd = NULL;
    136 	else
    137 		*pwd = pwres;
    138 	return rval;
    139 }
    140 
    141 void
    142 setpwent(void)
    143 {
    144 
    145 	(void) setpassent(0);
    146 }
    147 
    148 int
    149 setpassent(int stayopen)
    150 {
    151 
    152 	if (!pwstart())
    153 		return 0;
    154 	_pw_stayopen = stayopen;
    155 	return 1;
    156 }
    157 
    158 void
    159 endpwent(void)
    160 {
    161 
    162 	_pw_filesdone = 0;
    163 	if (_pw_fp) {
    164 		(void)fclose(_pw_fp);
    165 		_pw_fp = NULL;
    166 	}
    167 }
    168 
    169 static int
    170 pwstart(void)
    171 {
    172 
    173 	_pw_filesdone = 0;
    174 	if (_pw_fp) {
    175 		rewind(_pw_fp);
    176 		return 1;
    177 	}
    178 	return (_pw_fp = fopen(_PATH_MASTERPASSWD, "r")) ? 1 : 0;
    179 }
    180 
    181 
    182 static int
    183 pwscan(int search, uid_t uid, const char *name, struct passwd *pwd, char *buf,
    184     size_t bufsiz)
    185 {
    186 
    187 	if (_pw_filesdone)
    188 		return 0;
    189 	for (;;) {
    190 		if (!fgets(buf, bufsiz, _pw_fp)) {
    191 			if (!search)
    192 				_pw_filesdone = 1;
    193 			return 0;
    194 		}
    195 		/* skip lines that are too big */
    196 		if (!strchr(buf, '\n')) {
    197 			int ch;
    198 
    199 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
    200 				;
    201 			continue;
    202 		}
    203 		if (pwmatchline(search, uid, name, pwd, buf))
    204 			return 1;
    205 	}
    206 	/* NOTREACHED */
    207 }
    208 
    209 static int
    210 pwmatchline(int search, uid_t uid, const char *name, struct passwd *pwd,
    211     char *buf)
    212 {
    213 	unsigned long	id;
    214 	char		*cp, *bp, *ep;
    215 
    216 	/* name may be NULL if search is nonzero */
    217 
    218 	bp = buf;
    219 	memset(pwd, 0, sizeof(*pwd));
    220 	pwd->pw_name = strsep(&bp, ":\n");		/* name */
    221 	if (search && name && strcmp(pwd->pw_name, name))
    222 		return 0;
    223 
    224 	pwd->pw_passwd = strsep(&bp, ":\n");		/* passwd */
    225 
    226 	if (!(cp = strsep(&bp, ":\n")))				/* uid */
    227 		return 0;
    228 	id = strtoul(cp, &ep, 10);
    229 	if (id > UID_MAX || *ep != '\0')
    230 		return 0;
    231 	pwd->pw_uid = (uid_t)id;
    232 	if (search && name == NULL && pwd->pw_uid != uid)
    233 		return 0;
    234 
    235 	if (!(cp = strsep(&bp, ":\n")))				/* gid */
    236 		return 0;
    237 	id = strtoul(cp, &ep, 10);
    238 	if (id > GID_MAX || *ep != '\0')
    239 		return 0;
    240 	pwd->pw_gid = (gid_t)id;
    241 
    242 	if (!(pwd->pw_class = strsep(&bp, ":")))		/* class */
    243 		return 0;
    244 	if (!(ep = strsep(&bp, ":")))				/* change */
    245 		return 0;
    246 	if (!(ep = strsep(&bp, ":")))				/* expire */
    247 		return 0;
    248 
    249 	if (!(pwd->pw_gecos = strsep(&bp, ":\n")))		/* gecos */
    250 		return 0;
    251 	if (!(pwd->pw_dir = strsep(&bp, ":\n")))		/* directory */
    252 		return 0;
    253 	if (!(pwd->pw_shell = strsep(&bp, ":\n")))		/* shell */
    254 		return 0;
    255 
    256 	if (strchr(bp, ':') != NULL)
    257 		return 0;
    258 
    259 	return 1;
    260 }
    261