1 /* $NetBSD: getgrent.c,v 1.13 1995/07/28 05:43:57 phil Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * Portions Copyright (c) 1994, Jason Downs. All Rights Reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #if defined(LIBC_SCCS) && !defined(lint) 38 #if 0 39 static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94"; 40 #else 41 static char rcsid[] = "$NetBSD: getgrent.c,v 1.13 1995/07/28 05:43:57 phil Exp $"; 42 #endif 43 #endif /* LIBC_SCCS and not lint */ 44 45 #include <sys/types.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <grp.h> 50 #ifdef YP 51 #include <rpc/rpc.h> 52 #include <rpcsvc/yp_prot.h> 53 #include <rpcsvc/ypclnt.h> 54 #endif 55 56 static FILE *_gr_fp; 57 static struct group _gr_group; 58 static int _gr_stayopen; 59 static int grscan(), start_gr(); 60 61 #define MAXGRP 200 62 static char *members[MAXGRP]; 63 #define MAXLINELENGTH 1024 64 static char line[MAXLINELENGTH]; 65 66 #ifdef YP 67 enum _ypmode { YPMODE_NONE, YPMODE_FULL, YPMODE_NAME }; 68 static enum _ypmode __ypmode; 69 static char *__ypcurrent, *__ypdomain; 70 static int __ypcurrentlen; 71 #endif 72 73 struct group * 74 getgrent() 75 { 76 if (!_gr_fp && !start_gr() || !grscan(0, 0, NULL)) 77 return(NULL); 78 return(&_gr_group); 79 } 80 81 struct group * 82 getgrnam(name) 83 const char *name; 84 { 85 int rval; 86 87 if (!start_gr()) 88 return(NULL); 89 rval = grscan(1, 0, name); 90 if (!_gr_stayopen) 91 endgrent(); 92 return(rval ? &_gr_group : NULL); 93 } 94 95 struct group * 96 #ifdef __STDC__ 97 getgrgid(gid_t gid) 98 #else 99 getgrgid(gid) 100 gid_t gid; 101 #endif 102 { 103 int rval; 104 105 if (!start_gr()) 106 return(NULL); 107 rval = grscan(1, gid, NULL); 108 if (!_gr_stayopen) 109 endgrent(); 110 return(rval ? &_gr_group : NULL); 111 } 112 113 static int 114 start_gr() 115 { 116 if (_gr_fp) { 117 rewind(_gr_fp); 118 #ifdef YP 119 __ypmode = YPMODE_NONE; 120 if(__ypcurrent) 121 free(__ypcurrent); 122 __ypcurrent = NULL; 123 #endif 124 return(1); 125 } 126 return((_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0); 127 } 128 129 void 130 setgrent() 131 { 132 (void) setgroupent(0); 133 } 134 135 int 136 setgroupent(stayopen) 137 int stayopen; 138 { 139 if (!start_gr()) 140 return(0); 141 _gr_stayopen = stayopen; 142 return(1); 143 } 144 145 void 146 endgrent() 147 { 148 if (_gr_fp) { 149 (void)fclose(_gr_fp); 150 _gr_fp = NULL; 151 #ifdef YP 152 __ypmode = YPMODE_NONE; 153 if(__ypcurrent) 154 free(__ypcurrent); 155 __ypcurrent = NULL; 156 #endif 157 } 158 } 159 160 static int 161 grscan(search, gid, name) 162 register int search, gid; 163 register char *name; 164 { 165 register char *cp, **m; 166 char *bp; 167 #ifdef YP 168 char *grname = (char *)NULL; 169 #endif 170 171 for (;;) { 172 #ifdef YP 173 if(__ypmode != YPMODE_NONE) { 174 char *key, *data; 175 int keylen, datalen; 176 int r; 177 178 if(!__ypdomain) { 179 if(yp_get_default_domain(&__ypdomain)) { 180 __ypmode = YPMODE_NONE; 181 if(grname != (char *)NULL) { 182 free(grname); 183 grname = (char *)NULL; 184 } 185 continue; 186 } 187 } 188 switch(__ypmode) { 189 case YPMODE_FULL: 190 if(__ypcurrent) { 191 r = yp_next(__ypdomain, "group.byname", 192 __ypcurrent, __ypcurrentlen, 193 &key, &keylen, &data, &datalen); 194 free(__ypcurrent); 195 if(r != 0) { 196 __ypcurrent = NULL; 197 __ypmode = YPMODE_NONE; 198 free(data); 199 continue; 200 } 201 __ypcurrent = key; 202 __ypcurrentlen = keylen; 203 bcopy(data, line, datalen); 204 free(data); 205 } else { 206 r = yp_first(__ypdomain, "group.byname", 207 &__ypcurrent, &__ypcurrentlen, 208 &data, &datalen); 209 if(r != 0) { 210 __ypmode = YPMODE_NONE; 211 free(data); 212 continue; 213 } 214 bcopy(data, line, datalen); 215 free(data); 216 } 217 break; 218 case YPMODE_NAME: 219 if(grname != (char *)NULL) { 220 r = yp_match(__ypdomain, "group.byname", 221 grname, strlen(grname), 222 &data, &datalen); 223 __ypmode = YPMODE_NONE; 224 free(grname); 225 grname = (char *)NULL; 226 if(r != 0) { 227 free(data); 228 continue; 229 } 230 bcopy(data, line, datalen); 231 free(data); 232 } else { 233 __ypmode = YPMODE_NONE; /* ??? */ 234 continue; 235 } 236 break; 237 } 238 line[datalen] = '\0'; 239 bp = line; 240 goto parse; 241 } 242 #endif 243 if (!fgets(line, sizeof(line), _gr_fp)) 244 return(0); 245 bp = line; 246 /* skip lines that are too big */ 247 if (!strchr(line, '\n')) { 248 int ch; 249 250 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 251 ; 252 continue; 253 } 254 #ifdef YP 255 if (line[0] == '+') { 256 switch(line[1]) { 257 case ':': 258 case '\0': 259 case '\n': 260 if(_yp_check(NULL)) { 261 __ypmode = YPMODE_FULL; 262 continue; 263 } 264 break; 265 default: 266 if(_yp_check(NULL)) { 267 register char *tptr; 268 269 __ypmode = YPMODE_NAME; 270 tptr = strsep(&bp, ":\n"); 271 grname = strdup(tptr + 1); 272 continue; 273 } 274 break; 275 } 276 } 277 parse: 278 #endif 279 _gr_group.gr_name = strsep(&bp, ":\n"); 280 if (search && name && strcmp(_gr_group.gr_name, name)) 281 continue; 282 _gr_group.gr_passwd = strsep(&bp, ":\n"); 283 if (!(cp = strsep(&bp, ":\n"))) 284 continue; 285 _gr_group.gr_gid = atoi(cp); 286 if (search && name == NULL && _gr_group.gr_gid != gid) 287 continue; 288 cp = NULL; 289 if (bp == NULL) 290 continue; 291 for (m = _gr_group.gr_mem = members;; bp++) { 292 if (m == &members[MAXGRP - 1]) 293 break; 294 if (*bp == ',') { 295 if (cp) { 296 *bp = '\0'; 297 *m++ = cp; 298 cp = NULL; 299 } 300 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 301 if (cp) { 302 *bp = '\0'; 303 *m++ = cp; 304 } 305 break; 306 } else if (cp == NULL) 307 cp = bp; 308 } 309 *m = NULL; 310 return(1); 311 } 312 /* NOTREACHED */ 313 } 314