1 /* $NetBSD: getgrent.c,v 1.8 2003/10/13 15:36:33 agc Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 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 * Portions Copyright (c) 1994, Jason Downs. All Rights Reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS 45 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 46 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 47 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 48 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 49 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 50 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 51 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 */ 56 57 /* 58 * Copied from: lib/libc/gen/getgrent.c 59 * NetBSD: getgrent.c,v 1.46 2003/02/17 00:11:54 simonb Exp 60 * and then gutted, leaving only /etc/group support. 61 */ 62 63 #include <sys/cdefs.h> 64 65 #ifdef __weak_alias 66 #define endgrent _endgrent 67 #define getgrent _getgrent 68 #define getgrgid _getgrgid 69 #define getgrnam _getgrnam 70 #define setgrent _setgrent 71 #define setgroupent _setgroupent 72 73 __weak_alias(endgrent,_endgrent) 74 __weak_alias(getgrent,_getgrent) 75 __weak_alias(getgrgid,_getgrgid) 76 __weak_alias(getgrnam,_getgrnam) 77 __weak_alias(setgrent,_setgrent) 78 __weak_alias(setgroupent,_setgroupent) 79 #endif 80 81 #include <sys/types.h> 82 83 #include <grp.h> 84 #include <limits.h> 85 #include <stdio.h> 86 #include <stdlib.h> 87 #include <string.h> 88 89 struct group *_getgrent_user(const char *); 90 91 static FILE *_gr_fp; 92 static struct group _gr_group; 93 static int _gr_stayopen; 94 static int _gr_filesdone; 95 96 static int grscan(int, gid_t, const char *, const char *); 97 static int grstart(void); 98 static int grmatchline(int, gid_t, const char *, const char *); 99 100 #define MAXGRP 200 101 #define MAXLINELENGTH 1024 102 103 static __aconst char *members[MAXGRP]; 104 static char grline[MAXLINELENGTH]; 105 106 struct group * 107 getgrent(void) 108 { 109 110 if ((!_gr_fp && !grstart()) || !grscan(0, 0, NULL, NULL)) 111 return (NULL); 112 return &_gr_group; 113 } 114 115 /* 116 * _getgrent_user() is designed only to be called by getgrouplist(3) and 117 * hence makes no guarantees about filling the entire structure that it 118 * returns. It may only fill in the group name and gid fields. 119 */ 120 121 struct group * 122 _getgrent_user(const char *user) 123 { 124 125 if ((!_gr_fp && !grstart()) || !grscan(0, 0, NULL, user)) 126 return (NULL); 127 return &_gr_group; 128 } 129 130 struct group * 131 getgrnam(const char *name) 132 { 133 int rval; 134 135 if (!grstart()) 136 return NULL; 137 rval = grscan(1, 0, name, NULL); 138 if (!_gr_stayopen) 139 endgrent(); 140 return (rval) ? &_gr_group : NULL; 141 } 142 143 struct group * 144 getgrgid(gid_t gid) 145 { 146 int rval; 147 148 if (!grstart()) 149 return NULL; 150 rval = grscan(1, gid, NULL, NULL); 151 if (!_gr_stayopen) 152 endgrent(); 153 return (rval) ? &_gr_group : NULL; 154 } 155 156 static int 157 grstart(void) 158 { 159 160 _gr_filesdone = 0; 161 if (_gr_fp) { 162 rewind(_gr_fp); 163 return 1; 164 } 165 return (_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0; 166 } 167 168 void 169 setgrent(void) 170 { 171 172 (void) setgroupent(0); 173 } 174 175 int 176 setgroupent(int stayopen) 177 { 178 179 if (!grstart()) 180 return 0; 181 _gr_stayopen = stayopen; 182 return 1; 183 } 184 185 void 186 endgrent(void) 187 { 188 189 _gr_filesdone = 0; 190 if (_gr_fp) { 191 (void)fclose(_gr_fp); 192 _gr_fp = NULL; 193 } 194 } 195 196 static int 197 grscan(int search, gid_t gid, const char *name, const char *user) 198 { 199 200 if (_gr_filesdone) 201 return 0; 202 for (;;) { 203 if (!fgets(grline, sizeof(grline), _gr_fp)) { 204 if (!search) 205 _gr_filesdone = 1; 206 return 0; 207 } 208 /* skip lines that are too big */ 209 if (!strchr(grline, '\n')) { 210 int ch; 211 212 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 213 ; 214 continue; 215 } 216 if (grmatchline(search, gid, name, user)) 217 return 1; 218 } 219 /* NOTREACHED */ 220 } 221 222 static int 223 grmatchline(int search, gid_t gid, const char *name, const char *user) 224 { 225 unsigned long id; 226 __aconst char **m; 227 char *cp, *bp, *ep; 228 229 /* name may be NULL if search is nonzero */ 230 231 bp = grline; 232 _gr_group.gr_name = strsep(&bp, ":\n"); 233 if (search && name && strcmp(_gr_group.gr_name, name)) 234 return 0; 235 _gr_group.gr_passwd = strsep(&bp, ":\n"); 236 if (!(cp = strsep(&bp, ":\n"))) 237 return 0; 238 id = strtoul(cp, &ep, 10); 239 if (id > GID_MAX || *ep != '\0') 240 return 0; 241 _gr_group.gr_gid = (gid_t)id; 242 if (search && name == NULL && _gr_group.gr_gid != gid) 243 return 0; 244 cp = NULL; 245 if (bp == NULL) 246 return 0; 247 for (_gr_group.gr_mem = m = members;; bp++) { 248 if (m == &members[MAXGRP - 1]) 249 break; 250 if (*bp == ',') { 251 if (cp) { 252 *bp = '\0'; 253 *m++ = cp; 254 cp = NULL; 255 } 256 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 257 if (cp) { 258 *bp = '\0'; 259 *m++ = cp; 260 } 261 break; 262 } else if (cp == NULL) 263 cp = bp; 264 } 265 *m = NULL; 266 if (user) { 267 for (m = members; *m; m++) 268 if (!strcmp(user, *m)) 269 return 1; 270 return 0; 271 } 272 return 1; 273 } 274