acpi.4: Add some missing references.
[dragonfly.git] / contrib / bind-9.3 / lib / bind / irs / gen_gr.c
blobe0c6dba529355ba878d18711412c3e484d86fe49
1 /*
2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (c) 1996-1999 by Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #if !defined(LINT) && !defined(CODECENTER)
19 static const char rcsid[] = "$Id: gen_gr.c,v 1.4.2.1.4.2 2004/05/17 07:48:56 marka Exp $";
20 #endif
22 /* Imports */
24 #include "port_before.h"
26 #ifndef WANT_IRS_GR
27 static int __bind_irs_gr_unneeded;
28 #else
30 #include <sys/types.h>
32 #include <isc/assertions.h>
33 #include <errno.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
38 #include <netinet/in.h>
39 #include <arpa/nameser.h>
40 #include <resolv.h>
42 #include <isc/memcluster.h>
43 #include <irs.h>
45 #include "port_after.h"
47 #include "irs_p.h"
48 #include "gen_p.h"
50 /* Definitions */
52 struct pvt {
53 struct irs_rule * rules;
54 struct irs_rule * rule;
55 struct irs_gr * gr;
57 * Need space to store the entries read from the group file.
58 * The members list also needs space per member, and the
59 * strings making up the user names must be allocated
60 * somewhere. Rather than doing lots of small allocations,
61 * we keep one buffer and resize it as needed.
63 struct group group;
64 size_t nmemb; /* Malloc'd max index of gr_mem[]. */
65 char * membuf;
66 size_t membufsize;
67 struct __res_state * res;
68 void (*free_res)(void *);
71 /* Forward */
73 static void gr_close(struct irs_gr *);
74 static struct group * gr_next(struct irs_gr *);
75 static struct group * gr_byname(struct irs_gr *, const char *);
76 static struct group * gr_bygid(struct irs_gr *, gid_t);
77 static void gr_rewind(struct irs_gr *);
78 static int gr_list(struct irs_gr *, const char *,
79 gid_t, gid_t *, int *);
80 static void gr_minimize(struct irs_gr *);
81 static struct __res_state * gr_res_get(struct irs_gr *);
82 static void gr_res_set(struct irs_gr *,
83 struct __res_state *,
84 void (*)(void *));
86 static int grmerge(struct irs_gr *gr, const struct group *src,
87 int preserve);
89 static int countvec(char **vec);
90 static int isnew(char **old, char *new);
91 static int countnew(char **old, char **new);
92 static size_t sizenew(char **old, char **new);
93 static int newgid(int, gid_t *, gid_t);
95 /* Macros */
97 #define FREE_IF(x) do { if ((x) != NULL) { free(x); (x) = NULL; } } while (0)
99 /* Public */
101 struct irs_gr *
102 irs_gen_gr(struct irs_acc *this) {
103 struct gen_p *accpvt = (struct gen_p *)this->private;
104 struct irs_gr *gr;
105 struct pvt *pvt;
107 if (!(gr = memget(sizeof *gr))) {
108 errno = ENOMEM;
109 return (NULL);
111 memset(gr, 0x5e, sizeof *gr);
112 if (!(pvt = memget(sizeof *pvt))) {
113 memput(gr, sizeof *gr);
114 errno = ENOMEM;
115 return (NULL);
117 memset(pvt, 0, sizeof *pvt);
118 pvt->rules = accpvt->map_rules[irs_gr];
119 pvt->rule = pvt->rules;
120 gr->private = pvt;
121 gr->close = gr_close;
122 gr->next = gr_next;
123 gr->byname = gr_byname;
124 gr->bygid = gr_bygid;
125 gr->rewind = gr_rewind;
126 gr->list = gr_list;
127 gr->minimize = gr_minimize;
128 gr->res_get = gr_res_get;
129 gr->res_set = gr_res_set;
130 return (gr);
133 /* Methods. */
135 static void
136 gr_close(struct irs_gr *this) {
137 struct pvt *pvt = (struct pvt *)this->private;
139 memput(pvt, sizeof *pvt);
140 memput(this, sizeof *this);
143 static struct group *
144 gr_next(struct irs_gr *this) {
145 struct pvt *pvt = (struct pvt *)this->private;
146 struct group *rval;
147 struct irs_gr *gr;
149 while (pvt->rule) {
150 gr = pvt->rule->inst->gr;
151 rval = (*gr->next)(gr);
152 if (rval)
153 return (rval);
154 if (!(pvt->rule->flags & IRS_CONTINUE))
155 break;
156 pvt->rule = pvt->rule->next;
157 if (pvt->rule) {
158 gr = pvt->rule->inst->gr;
159 (*gr->rewind)(gr);
162 return (NULL);
165 static struct group *
166 gr_byname(struct irs_gr *this, const char *name) {
167 struct pvt *pvt = (struct pvt *)this->private;
168 struct irs_rule *rule;
169 struct group *tval;
170 struct irs_gr *gr;
171 int dirty;
173 dirty = 0;
174 for (rule = pvt->rules; rule; rule = rule->next) {
175 gr = rule->inst->gr;
176 tval = (*gr->byname)(gr, name);
177 if (tval) {
178 if (!grmerge(this, tval, dirty++))
179 return (NULL);
180 if (!(rule->flags & IRS_MERGE))
181 break;
182 } else {
183 if (!(rule->flags & IRS_CONTINUE))
184 break;
187 if (dirty)
188 return (&pvt->group);
189 return (NULL);
192 static struct group *
193 gr_bygid(struct irs_gr *this, gid_t gid) {
194 struct pvt *pvt = (struct pvt *)this->private;
195 struct irs_rule *rule;
196 struct group *tval;
197 struct irs_gr *gr;
198 int dirty;
200 dirty = 0;
201 for (rule = pvt->rules; rule; rule = rule->next) {
202 gr = rule->inst->gr;
203 tval = (*gr->bygid)(gr, gid);
204 if (tval) {
205 if (!grmerge(this, tval, dirty++))
206 return (NULL);
207 if (!(rule->flags & IRS_MERGE))
208 break;
209 } else {
210 if (!(rule->flags & IRS_CONTINUE))
211 break;
214 if (dirty)
215 return (&pvt->group);
216 return (NULL);
219 static void
220 gr_rewind(struct irs_gr *this) {
221 struct pvt *pvt = (struct pvt *)this->private;
222 struct irs_gr *gr;
224 pvt->rule = pvt->rules;
225 if (pvt->rule) {
226 gr = pvt->rule->inst->gr;
227 (*gr->rewind)(gr);
231 static int
232 gr_list(struct irs_gr *this, const char *name,
233 gid_t basegid, gid_t *groups, int *ngroups)
235 struct pvt *pvt = (struct pvt *)this->private;
236 struct irs_rule *rule;
237 struct irs_gr *gr;
238 int t_ngroups, maxgroups;
239 gid_t *t_groups;
240 int n, t, rval = 0;
242 maxgroups = *ngroups;
243 *ngroups = 0;
244 t_groups = (gid_t *)malloc(maxgroups * sizeof(gid_t));
245 if (!t_groups) {
246 errno = ENOMEM;
247 return (-1);
250 for (rule = pvt->rules; rule; rule = rule->next) {
251 t_ngroups = maxgroups;
252 gr = rule->inst->gr;
253 t = (*gr->list)(gr, name, basegid, t_groups, &t_ngroups);
254 for (n = 0; n < t_ngroups; n++) {
255 if (newgid(*ngroups, groups, t_groups[n])) {
256 if (*ngroups == maxgroups) {
257 rval = -1;
258 goto done;
260 groups[(*ngroups)++] = t_groups[n];
263 if (t == 0) {
264 if (!(rule->flags & IRS_MERGE))
265 break;
266 } else {
267 if (!(rule->flags & IRS_CONTINUE))
268 break;
271 done:
272 free(t_groups);
273 return (rval);
276 static void
277 gr_minimize(struct irs_gr *this) {
278 struct pvt *pvt = (struct pvt *)this->private;
279 struct irs_rule *rule;
281 for (rule = pvt->rules; rule != NULL; rule = rule->next) {
282 struct irs_gr *gr = rule->inst->gr;
284 (*gr->minimize)(gr);
288 static struct __res_state *
289 gr_res_get(struct irs_gr *this) {
290 struct pvt *pvt = (struct pvt *)this->private;
292 if (!pvt->res) {
293 struct __res_state *res;
294 res = (struct __res_state *)malloc(sizeof *res);
295 if (!res) {
296 errno = ENOMEM;
297 return (NULL);
299 memset(res, 0, sizeof *res);
300 gr_res_set(this, res, free);
303 return (pvt->res);
306 static void
307 gr_res_set(struct irs_gr *this, struct __res_state *res,
308 void (*free_res)(void *)) {
309 struct pvt *pvt = (struct pvt *)this->private;
310 struct irs_rule *rule;
312 if (pvt->res && pvt->free_res) {
313 res_nclose(pvt->res);
314 (*pvt->free_res)(pvt->res);
317 pvt->res = res;
318 pvt->free_res = free_res;
320 for (rule = pvt->rules; rule != NULL; rule = rule->next) {
321 struct irs_gr *gr = rule->inst->gr;
323 if (gr->res_set)
324 (*gr->res_set)(gr, pvt->res, NULL);
328 /* Private. */
330 static int
331 grmerge(struct irs_gr *this, const struct group *src, int preserve) {
332 struct pvt *pvt = (struct pvt *)this->private;
333 char *cp, **m, **p, *oldmembuf, *ep;
334 int n, ndst, nnew;
335 size_t used;
337 if (!preserve) {
338 pvt->group.gr_gid = src->gr_gid;
339 if (pvt->nmemb < 1) {
340 m = malloc(sizeof *m);
341 if (m == NULL) {
342 /* No harm done, no work done. */
343 return (0);
345 pvt->group.gr_mem = m;
346 pvt->nmemb = 1;
348 pvt->group.gr_mem[0] = NULL;
350 ndst = countvec(pvt->group.gr_mem);
351 nnew = countnew(pvt->group.gr_mem, src->gr_mem);
354 * Make sure destination member array is large enough.
355 * p points to new portion.
357 n = ndst + nnew + 1;
358 if ((size_t)n > pvt->nmemb) {
359 m = realloc(pvt->group.gr_mem, n * sizeof *m);
360 if (m == NULL) {
361 /* No harm done, no work done. */
362 return (0);
364 pvt->group.gr_mem = m;
365 pvt->nmemb = n;
367 p = pvt->group.gr_mem + ndst;
370 * Enlarge destination membuf; cp points at new portion.
372 n = sizenew(pvt->group.gr_mem, src->gr_mem);
373 INSIST((nnew == 0) == (n == 0));
374 if (!preserve) {
375 n += strlen(src->gr_name) + 1;
376 n += strlen(src->gr_passwd) + 1;
378 if (n == 0) {
379 /* No work to do. */
380 return (1);
382 used = preserve ? pvt->membufsize : 0;
383 cp = malloc(used + n);
384 if (cp == NULL) {
385 /* No harm done, no work done. */
386 return (0);
388 ep = cp + used + n;
389 if (used != 0)
390 memcpy(cp, pvt->membuf, used);
391 oldmembuf = pvt->membuf;
392 pvt->membuf = cp;
393 pvt->membufsize = used + n;
394 cp += used;
397 * Adjust group.gr_mem.
399 if (pvt->membuf != oldmembuf)
400 for (m = pvt->group.gr_mem; *m; m++)
401 *m = pvt->membuf + (*m - oldmembuf);
404 * Add new elements.
406 for (m = src->gr_mem; *m; m++)
407 if (isnew(pvt->group.gr_mem, *m)) {
408 *p++ = cp;
409 *p = NULL;
410 n = strlen(*m) + 1;
411 if (n > ep - cp) {
412 FREE_IF(oldmembuf);
413 return (0);
415 strcpy(cp, *m); /* (checked) */
416 cp += n;
418 if (preserve) {
419 pvt->group.gr_name = pvt->membuf +
420 (pvt->group.gr_name - oldmembuf);
421 pvt->group.gr_passwd = pvt->membuf +
422 (pvt->group.gr_passwd - oldmembuf);
423 } else {
424 pvt->group.gr_name = cp;
425 n = strlen(src->gr_name) + 1;
426 if (n > ep - cp) {
427 FREE_IF(oldmembuf);
428 return (0);
430 strcpy(cp, src->gr_name); /* (checked) */
431 cp += n;
433 pvt->group.gr_passwd = cp;
434 n = strlen(src->gr_passwd) + 1;
435 if (n > ep - cp) {
436 FREE_IF(oldmembuf);
437 return (0);
439 strcpy(cp, src->gr_passwd); /* (checked) */
440 cp += n;
442 FREE_IF(oldmembuf);
443 INSIST(cp >= pvt->membuf && cp <= &pvt->membuf[pvt->membufsize]);
444 return (1);
447 static int
448 countvec(char **vec) {
449 int n = 0;
451 while (*vec++)
452 n++;
453 return (n);
456 static int
457 isnew(char **old, char *new) {
458 for (; *old; old++)
459 if (strcmp(*old, new) == 0)
460 return (0);
461 return (1);
464 static int
465 countnew(char **old, char **new) {
466 int n = 0;
468 for (; *new; new++)
469 n += isnew(old, *new);
470 return (n);
473 static size_t
474 sizenew(char **old, char **new) {
475 size_t n = 0;
477 for (; *new; new++)
478 if (isnew(old, *new))
479 n += strlen(*new) + 1;
480 return (n);
483 static int
484 newgid(int ngroups, gid_t *groups, gid_t group) {
485 ngroups--, groups++;
486 for (; ngroups-- > 0; groups++)
487 if (*groups == group)
488 return (0);
489 return (1);
492 #endif /* WANT_IRS_GR */