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