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