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
freegrouplist()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 *
my_getgroup(group)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
doit(group,list)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 *
fill(start,target,termchar)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 *
any(cp,match)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 *
match(group)245 match(group)
246 char *group;
247 {
248 return (lookup(ngtable, group));
249 }
250