1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright (c) 1996, by Sun Microsystems, Inc. 25 * All rights reserved. 26 */ 27 28 #ident "%Z%%M% %I% %E% SMI" /* SMI4.1 1.5 */ 29 30 #include <stdio.h> 31 #include <ctype.h> 32 #include <string.h> 33 #include "table.h" 34 #include "util.h" 35 #include "getgroup.h" 36 37 #define MAXGROUPLEN 1024 38 39 /* 40 * Stolen mostly, from getnetgrent.c 41 * 42 * my_getgroup() performs the same function as _getgroup(), but operates 43 * on /etc/netgroup directly, rather than doing yp lookups. 44 * 45 * /etc/netgroup must first loaded into a hash table so the matching 46 * function can look up lines quickly. 47 */ 48 49 50 /* To check for cycles in netgroups */ 51 struct list { 52 char *name; 53 struct list *nxt; 54 }; 55 56 57 extern stringtable ngtable; /* stored info from /etc/netgroup */ 58 59 static struct grouplist *grouplist; /* stores a list of users in a group */ 60 61 static char *any(); 62 static char *match(); 63 static char *fill(); 64 static void freegrouplist(); 65 static void doit(); 66 67 68 69 static void 70 freegrouplist() 71 { 72 struct grouplist *gl; 73 74 for (gl = grouplist; gl != NULL; gl = gl->gl_nxt) { 75 FREE(gl->gl_name); 76 FREE(gl->gl_domain); 77 FREE(gl->gl_machine); 78 FREE(gl); 79 } 80 grouplist = NULL; 81 } 82 83 84 85 86 struct grouplist * 87 my_getgroup(group) 88 char *group; 89 { 90 freegrouplist(); 91 doit(group, (struct list *) NULL); 92 return (grouplist); 93 } 94 95 96 97 98 99 /* 100 * recursive function to find the members of netgroup "group". "list" is 101 * the path followed through the netgroups so far, to check for cycles. 102 */ 103 static void 104 doit(group, list) 105 char *group; 106 struct list *list; 107 { 108 register char *p, *q; 109 register struct list *ls; 110 struct list tmplist; 111 char *val; 112 struct grouplist *gpls; 113 114 115 /* 116 * check for non-existing groups 117 */ 118 if ((val = match(group)) == NULL) { 119 return; 120 } 121 122 123 /* 124 * check for cycles 125 */ 126 for (ls = list; ls != NULL; ls = ls->nxt) { 127 if (strcmp(ls->name, group) == 0) { 128 (void) fprintf(stderr, 129 "Cycle detected in /etc/netgroup: %s.\n", 130 group); 131 return; 132 } 133 } 134 135 136 ls = &tmplist; 137 ls->name = group; 138 ls->nxt = list; 139 list = ls; 140 141 p = val; 142 while (p != NULL) { 143 while (*p == ' ' || *p == '\t') 144 p++; 145 if (*p == EOS || *p == '#') 146 break; 147 if (*p == '(') { 148 gpls = MALLOC(struct grouplist); 149 p++; 150 151 if (!(p = fill(p, &gpls->gl_machine, ','))) { 152 goto syntax_error; 153 } 154 if (!(p = fill(p, &gpls->gl_name, ','))) { 155 goto syntax_error; 156 } 157 if (!(p = fill(p, &gpls->gl_domain, ')'))) { 158 goto syntax_error; 159 } 160 gpls->gl_nxt = grouplist; 161 grouplist = gpls; 162 } else { 163 q = any(p, " \t\n#"); 164 if (q && *q == '#') 165 break; 166 *q = EOS; 167 doit(p, list); 168 *q = ' '; 169 } 170 p = any(p, " \t"); 171 } 172 return; 173 174 syntax_error: 175 (void) fprintf(stderr, "syntax error in /etc/netgroup\n"); 176 (void) fprintf(stderr, "--- %s %s\n", group, val); 177 } 178 179 180 181 182 /* 183 * Fill a buffer "target" selectively from buffer "start". 184 * "termchar" terminates the information in start, and preceding 185 * or trailing white space is ignored. If the buffer "start" is 186 * empty, "target" is filled with "*". The location just after the 187 * terminating character is returned. 188 */ 189 static char * 190 fill(start, target, termchar) 191 char *start; 192 char **target; 193 char termchar; 194 { 195 register char *p; 196 register char *q; 197 register char *r; 198 int size; 199 200 for (p = start; *p == ' ' || *p == '\t'; p++) 201 ; 202 r = strchr(p, termchar); 203 if (r == (char *)NULL) { 204 return ((char *)NULL); 205 } 206 if (p == r) { 207 *target = NULL; 208 } else { 209 for (q = r-1; *q == ' ' || *q == '\t'; q--) 210 ; 211 size = q-p+1; 212 STRNCPY(*target, p, size); 213 } 214 return (r+1); 215 } 216 217 218 /* 219 * scans cp, looking for a match with any character 220 * in match. Returns pointer to place in cp that matched 221 * (or NULL if no match) 222 */ 223 static char * 224 any(cp, match) 225 register char *cp; 226 char *match; 227 { 228 register char *mp, c; 229 230 while (c = *cp) { 231 for (mp = match; *mp; mp++) 232 if (*mp == c) 233 return (cp); 234 cp++; 235 } 236 return (NULL); 237 } 238 239 240 241 /* 242 * The equivalent of yp_match. Returns the match, or NULL if there is none. 243 */ 244 static char * 245 match(group) 246 char *group; 247 { 248 return (lookup(ngtable, group)); 249 } 250