Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / libbind / dist / irs / gen_gr.c
blob80e19f113c8ee10989ecf16927ff472e8fd4f817
1 /* $NetBSD$ */
3 /*
4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1996-1999 by Internet Software Consortium.
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #if !defined(LINT) && !defined(CODECENTER)
21 static const char rcsid[] = "Id: gen_gr.c,v 1.8 2005/04/27 04:56:23 sra Exp";
22 #endif
24 /* Imports */
26 #include "port_before.h"
28 #ifndef WANT_IRS_GR
29 static int __bind_irs_gr_unneeded;
30 #else
32 #include <sys/types.h>
34 #include <isc/assertions.h>
35 #include <errno.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
40 #include <netinet/in.h>
41 #include <arpa/nameser.h>
42 #include <resolv.h>
44 #include <isc/memcluster.h>
45 #include <irs.h>
47 #include "port_after.h"
49 #include "irs_p.h"
50 #include "gen_p.h"
52 /* Definitions */
54 struct pvt {
55 struct irs_rule * rules;
56 struct irs_rule * rule;
57 struct irs_gr * gr;
59 * Need space to store the entries read from the group file.
60 * The members list also needs space per member, and the
61 * strings making up the user names must be allocated
62 * somewhere. Rather than doing lots of small allocations,
63 * we keep one buffer and resize it as needed.
65 struct group group;
66 size_t nmemb; /*%< Malloc'd max index of gr_mem[]. */
67 char * membuf;
68 size_t membufsize;
69 struct __res_state * res;
70 void (*free_res)(void *);
73 /* Forward */
75 static void gr_close(struct irs_gr *);
76 static struct group * gr_next(struct irs_gr *);
77 static struct group * gr_byname(struct irs_gr *, const char *);
78 static struct group * gr_bygid(struct irs_gr *, gid_t);
79 static void gr_rewind(struct irs_gr *);
80 static int gr_list(struct irs_gr *, const char *,
81 gid_t, gid_t *, int *);
82 static void gr_minimize(struct irs_gr *);
83 static struct __res_state * gr_res_get(struct irs_gr *);
84 static void gr_res_set(struct irs_gr *,
85 struct __res_state *,
86 void (*)(void *));
88 static int grmerge(struct irs_gr *gr, const struct group *src,
89 int preserve);
91 static int countvec(char **vec);
92 static int isnew(char **old, char *new);
93 static int countnew(char **old, char **new);
94 static size_t sizenew(char **old, char **new);
95 static int newgid(int, gid_t *, gid_t);
97 /* Macros */
99 #define FREE_IF(x) do { if ((x) != NULL) { free(x); (x) = NULL; } } while (0)
101 /* Public */
103 struct irs_gr *
104 irs_gen_gr(struct irs_acc *this) {
105 struct gen_p *accpvt = (struct gen_p *)this->private;
106 struct irs_gr *gr;
107 struct pvt *pvt;
109 if (!(gr = memget(sizeof *gr))) {
110 errno = ENOMEM;
111 return (NULL);
113 memset(gr, 0x5e, sizeof *gr);
114 if (!(pvt = memget(sizeof *pvt))) {
115 memput(gr, sizeof *gr);
116 errno = ENOMEM;
117 return (NULL);
119 memset(pvt, 0, sizeof *pvt);
120 pvt->rules = accpvt->map_rules[irs_gr];
121 pvt->rule = pvt->rules;
122 gr->private = pvt;
123 gr->close = gr_close;
124 gr->next = gr_next;
125 gr->byname = gr_byname;
126 gr->bygid = gr_bygid;
127 gr->rewind = gr_rewind;
128 gr->list = gr_list;
129 gr->minimize = gr_minimize;
130 gr->res_get = gr_res_get;
131 gr->res_set = gr_res_set;
132 return (gr);
135 /* Methods. */
137 static void
138 gr_close(struct irs_gr *this) {
139 struct pvt *pvt = (struct pvt *)this->private;
141 memput(pvt, sizeof *pvt);
142 memput(this, sizeof *this);
145 static struct group *
146 gr_next(struct irs_gr *this) {
147 struct pvt *pvt = (struct pvt *)this->private;
148 struct group *rval;
149 struct irs_gr *gr;
151 while (pvt->rule) {
152 gr = pvt->rule->inst->gr;
153 rval = (*gr->next)(gr);
154 if (rval)
155 return (rval);
156 if (!(pvt->rule->flags & IRS_CONTINUE))
157 break;
158 pvt->rule = pvt->rule->next;
159 if (pvt->rule) {
160 gr = pvt->rule->inst->gr;
161 (*gr->rewind)(gr);
164 return (NULL);
167 static struct group *
168 gr_byname(struct irs_gr *this, const char *name) {
169 struct pvt *pvt = (struct pvt *)this->private;
170 struct irs_rule *rule;
171 struct group *tval;
172 struct irs_gr *gr;
173 int dirty;
175 dirty = 0;
176 for (rule = pvt->rules; rule; rule = rule->next) {
177 gr = rule->inst->gr;
178 tval = (*gr->byname)(gr, name);
179 if (tval) {
180 if (!grmerge(this, tval, dirty++))
181 return (NULL);
182 if (!(rule->flags & IRS_MERGE))
183 break;
184 } else {
185 if (!(rule->flags & IRS_CONTINUE))
186 break;
189 if (dirty)
190 return (&pvt->group);
191 return (NULL);
194 static struct group *
195 gr_bygid(struct irs_gr *this, gid_t gid) {
196 struct pvt *pvt = (struct pvt *)this->private;
197 struct irs_rule *rule;
198 struct group *tval;
199 struct irs_gr *gr;
200 int dirty;
202 dirty = 0;
203 for (rule = pvt->rules; rule; rule = rule->next) {
204 gr = rule->inst->gr;
205 tval = (*gr->bygid)(gr, gid);
206 if (tval) {
207 if (!grmerge(this, tval, dirty++))
208 return (NULL);
209 if (!(rule->flags & IRS_MERGE))
210 break;
211 } else {
212 if (!(rule->flags & IRS_CONTINUE))
213 break;
216 if (dirty)
217 return (&pvt->group);
218 return (NULL);
221 static void
222 gr_rewind(struct irs_gr *this) {
223 struct pvt *pvt = (struct pvt *)this->private;
224 struct irs_gr *gr;
226 pvt->rule = pvt->rules;
227 if (pvt->rule) {
228 gr = pvt->rule->inst->gr;
229 (*gr->rewind)(gr);
233 static int
234 gr_list(struct irs_gr *this, const char *name,
235 gid_t basegid, gid_t *groups, int *ngroups)
237 struct pvt *pvt = (struct pvt *)this->private;
238 struct irs_rule *rule;
239 struct irs_gr *gr;
240 int t_ngroups, maxgroups;
241 gid_t *t_groups;
242 int n, t, rval = 0;
244 maxgroups = *ngroups;
245 *ngroups = 0;
246 t_groups = (gid_t *)malloc(maxgroups * sizeof(gid_t));
247 if (!t_groups) {
248 errno = ENOMEM;
249 return (-1);
252 for (rule = pvt->rules; rule; rule = rule->next) {
253 t_ngroups = maxgroups;
254 gr = rule->inst->gr;
255 t = (*gr->list)(gr, name, basegid, t_groups, &t_ngroups);
256 for (n = 0; n < t_ngroups; n++) {
257 if (newgid(*ngroups, groups, t_groups[n])) {
258 if (*ngroups == maxgroups) {
259 rval = -1;
260 goto done;
262 groups[(*ngroups)++] = t_groups[n];
265 if (t == 0) {
266 if (!(rule->flags & IRS_MERGE))
267 break;
268 } else {
269 if (!(rule->flags & IRS_CONTINUE))
270 break;
273 done:
274 free(t_groups);
275 return (rval);
278 static void
279 gr_minimize(struct irs_gr *this) {
280 struct pvt *pvt = (struct pvt *)this->private;
281 struct irs_rule *rule;
283 for (rule = pvt->rules; rule != NULL; rule = rule->next) {
284 struct irs_gr *gr = rule->inst->gr;
286 (*gr->minimize)(gr);
290 static struct __res_state *
291 gr_res_get(struct irs_gr *this) {
292 struct pvt *pvt = (struct pvt *)this->private;
294 if (!pvt->res) {
295 struct __res_state *res;
296 res = (struct __res_state *)malloc(sizeof *res);
297 if (!res) {
298 errno = ENOMEM;
299 return (NULL);
301 memset(res, 0, sizeof *res);
302 gr_res_set(this, res, free);
305 return (pvt->res);
308 static void
309 gr_res_set(struct irs_gr *this, struct __res_state *res,
310 void (*free_res)(void *)) {
311 struct pvt *pvt = (struct pvt *)this->private;
312 struct irs_rule *rule;
314 if (pvt->res && pvt->free_res) {
315 res_nclose(pvt->res);
316 (*pvt->free_res)(pvt->res);
319 pvt->res = res;
320 pvt->free_res = free_res;
322 for (rule = pvt->rules; rule != NULL; rule = rule->next) {
323 struct irs_gr *gr = rule->inst->gr;
325 if (gr->res_set)
326 (*gr->res_set)(gr, pvt->res, NULL);
330 /* Private. */
332 static int
333 grmerge(struct irs_gr *this, const struct group *src, int preserve) {
334 struct pvt *pvt = (struct pvt *)this->private;
335 char *cp, **m, **p, *oldmembuf, *ep;
336 int n, ndst, nnew;
337 size_t used;
339 if (!preserve) {
340 pvt->group.gr_gid = src->gr_gid;
341 if (pvt->nmemb < 1) {
342 m = malloc(sizeof *m);
343 if (m == NULL) {
344 /* No harm done, no work done. */
345 return (0);
347 pvt->group.gr_mem = m;
348 pvt->nmemb = 1;
350 pvt->group.gr_mem[0] = NULL;
352 ndst = countvec(pvt->group.gr_mem);
353 nnew = countnew(pvt->group.gr_mem, src->gr_mem);
356 * Make sure destination member array is large enough.
357 * p points to new portion.
359 n = ndst + nnew + 1;
360 if ((size_t)n > pvt->nmemb) {
361 m = realloc(pvt->group.gr_mem, n * sizeof *m);
362 if (m == NULL) {
363 /* No harm done, no work done. */
364 return (0);
366 pvt->group.gr_mem = m;
367 pvt->nmemb = n;
369 p = pvt->group.gr_mem + ndst;
372 * Enlarge destination membuf; cp points at new portion.
374 n = sizenew(pvt->group.gr_mem, src->gr_mem);
375 INSIST((nnew == 0) == (n == 0));
376 if (!preserve) {
377 n += strlen(src->gr_name) + 1;
378 n += strlen(src->gr_passwd) + 1;
380 if (n == 0) {
381 /* No work to do. */
382 return (1);
384 used = preserve ? pvt->membufsize : 0;
385 cp = malloc(used + n);
386 if (cp == NULL) {
387 /* No harm done, no work done. */
388 return (0);
390 ep = cp + used + n;
391 if (used != 0)
392 memcpy(cp, pvt->membuf, used);
393 oldmembuf = pvt->membuf;
394 pvt->membuf = cp;
395 pvt->membufsize = used + n;
396 cp += used;
399 * Adjust group.gr_mem.
401 if (pvt->membuf != oldmembuf)
402 for (m = pvt->group.gr_mem; *m; m++)
403 *m = pvt->membuf + (*m - oldmembuf);
406 * Add new elements.
408 for (m = src->gr_mem; *m; m++)
409 if (isnew(pvt->group.gr_mem, *m)) {
410 *p++ = cp;
411 *p = NULL;
412 n = strlen(*m) + 1;
413 if (n > ep - cp) {
414 FREE_IF(oldmembuf);
415 return (0);
417 strcpy(cp, *m); /* (checked) */
418 cp += n;
420 if (preserve) {
421 pvt->group.gr_name = pvt->membuf +
422 (pvt->group.gr_name - oldmembuf);
423 pvt->group.gr_passwd = pvt->membuf +
424 (pvt->group.gr_passwd - oldmembuf);
425 } else {
426 pvt->group.gr_name = cp;
427 n = strlen(src->gr_name) + 1;
428 if (n > ep - cp) {
429 FREE_IF(oldmembuf);
430 return (0);
432 strcpy(cp, src->gr_name); /* (checked) */
433 cp += n;
435 pvt->group.gr_passwd = cp;
436 n = strlen(src->gr_passwd) + 1;
437 if (n > ep - cp) {
438 FREE_IF(oldmembuf);
439 return (0);
441 strcpy(cp, src->gr_passwd); /* (checked) */
442 cp += n;
444 FREE_IF(oldmembuf);
445 INSIST(cp >= pvt->membuf && cp <= &pvt->membuf[pvt->membufsize]);
446 return (1);
449 static int
450 countvec(char **vec) {
451 int n = 0;
453 while (*vec++)
454 n++;
455 return (n);
458 static int
459 isnew(char **old, char *new) {
460 for (; *old; old++)
461 if (strcmp(*old, new) == 0)
462 return (0);
463 return (1);
466 static int
467 countnew(char **old, char **new) {
468 int n = 0;
470 for (; *new; new++)
471 n += isnew(old, *new);
472 return (n);
475 static size_t
476 sizenew(char **old, char **new) {
477 size_t n = 0;
479 for (; *new; new++)
480 if (isnew(old, *new))
481 n += strlen(*new) + 1;
482 return (n);
485 static int
486 newgid(int ngroups, gid_t *groups, gid_t group) {
487 ngroups--, groups++;
488 for (; ngroups-- > 0; groups++)
489 if (*groups == group)
490 return (0);
491 return (1);
494 #endif /* WANT_IRS_GR */
495 /*! \file */