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";
26 #include "port_before.h"
29 static int __bind_irs_gr_unneeded
;
32 #include <sys/types.h>
34 #include <isc/assertions.h>
40 #include <netinet/in.h>
41 #include <arpa/nameser.h>
44 #include <isc/memcluster.h>
47 #include "port_after.h"
55 struct irs_rule
* rules
;
56 struct irs_rule
* rule
;
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.
66 size_t nmemb
; /*%< Malloc'd max index of gr_mem[]. */
69 struct __res_state
* res
;
70 void (*free_res
)(void *);
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
*,
88 static int grmerge(struct irs_gr
*gr
, const struct group
*src
,
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
);
99 #define FREE_IF(x) do { if ((x) != NULL) { free(x); (x) = NULL; } } while (0)
104 irs_gen_gr(struct irs_acc
*this) {
105 struct gen_p
*accpvt
= (struct gen_p
*)this->private;
109 if (!(gr
= memget(sizeof *gr
))) {
113 memset(gr
, 0x5e, sizeof *gr
);
114 if (!(pvt
= memget(sizeof *pvt
))) {
115 memput(gr
, sizeof *gr
);
119 memset(pvt
, 0, sizeof *pvt
);
120 pvt
->rules
= accpvt
->map_rules
[irs_gr
];
121 pvt
->rule
= pvt
->rules
;
123 gr
->close
= gr_close
;
125 gr
->byname
= gr_byname
;
126 gr
->bygid
= gr_bygid
;
127 gr
->rewind
= gr_rewind
;
129 gr
->minimize
= gr_minimize
;
130 gr
->res_get
= gr_res_get
;
131 gr
->res_set
= gr_res_set
;
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;
152 gr
= pvt
->rule
->inst
->gr
;
153 rval
= (*gr
->next
)(gr
);
156 if (!(pvt
->rule
->flags
& IRS_CONTINUE
))
158 pvt
->rule
= pvt
->rule
->next
;
160 gr
= pvt
->rule
->inst
->gr
;
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
;
176 for (rule
= pvt
->rules
; rule
; rule
= rule
->next
) {
178 tval
= (*gr
->byname
)(gr
, name
);
180 if (!grmerge(this, tval
, dirty
++))
182 if (!(rule
->flags
& IRS_MERGE
))
185 if (!(rule
->flags
& IRS_CONTINUE
))
190 return (&pvt
->group
);
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
;
203 for (rule
= pvt
->rules
; rule
; rule
= rule
->next
) {
205 tval
= (*gr
->bygid
)(gr
, gid
);
207 if (!grmerge(this, tval
, dirty
++))
209 if (!(rule
->flags
& IRS_MERGE
))
212 if (!(rule
->flags
& IRS_CONTINUE
))
217 return (&pvt
->group
);
222 gr_rewind(struct irs_gr
*this) {
223 struct pvt
*pvt
= (struct pvt
*)this->private;
226 pvt
->rule
= pvt
->rules
;
228 gr
= pvt
->rule
->inst
->gr
;
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
;
240 int t_ngroups
, maxgroups
;
244 maxgroups
= *ngroups
;
246 t_groups
= (gid_t
*)malloc(maxgroups
* sizeof(gid_t
));
252 for (rule
= pvt
->rules
; rule
; rule
= rule
->next
) {
253 t_ngroups
= maxgroups
;
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
) {
262 groups
[(*ngroups
)++] = t_groups
[n
];
266 if (!(rule
->flags
& IRS_MERGE
))
269 if (!(rule
->flags
& IRS_CONTINUE
))
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
;
290 static struct __res_state
*
291 gr_res_get(struct irs_gr
*this) {
292 struct pvt
*pvt
= (struct pvt
*)this->private;
295 struct __res_state
*res
;
296 res
= (struct __res_state
*)malloc(sizeof *res
);
301 memset(res
, 0, sizeof *res
);
302 gr_res_set(this, res
, free
);
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
);
320 pvt
->free_res
= free_res
;
322 for (rule
= pvt
->rules
; rule
!= NULL
; rule
= rule
->next
) {
323 struct irs_gr
*gr
= rule
->inst
->gr
;
326 (*gr
->res_set
)(gr
, pvt
->res
, NULL
);
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
;
340 pvt
->group
.gr_gid
= src
->gr_gid
;
341 if (pvt
->nmemb
< 1) {
342 m
= malloc(sizeof *m
);
344 /* No harm done, no work done. */
347 pvt
->group
.gr_mem
= m
;
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.
360 if ((size_t)n
> pvt
->nmemb
) {
361 m
= realloc(pvt
->group
.gr_mem
, n
* sizeof *m
);
363 /* No harm done, no work done. */
366 pvt
->group
.gr_mem
= m
;
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));
377 n
+= strlen(src
->gr_name
) + 1;
378 n
+= strlen(src
->gr_passwd
) + 1;
384 used
= preserve
? pvt
->membufsize
: 0;
385 cp
= malloc(used
+ n
);
387 /* No harm done, no work done. */
392 memcpy(cp
, pvt
->membuf
, used
);
393 oldmembuf
= pvt
->membuf
;
395 pvt
->membufsize
= used
+ n
;
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
);
408 for (m
= src
->gr_mem
; *m
; m
++)
409 if (isnew(pvt
->group
.gr_mem
, *m
)) {
417 strcpy(cp
, *m
); /* (checked) */
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
);
426 pvt
->group
.gr_name
= cp
;
427 n
= strlen(src
->gr_name
) + 1;
432 strcpy(cp
, src
->gr_name
); /* (checked) */
435 pvt
->group
.gr_passwd
= cp
;
436 n
= strlen(src
->gr_passwd
) + 1;
441 strcpy(cp
, src
->gr_passwd
); /* (checked) */
445 INSIST(cp
>= pvt
->membuf
&& cp
<= &pvt
->membuf
[pvt
->membufsize
]);
450 countvec(char **vec
) {
459 isnew(char **old
, char *new) {
461 if (strcmp(*old
, new) == 0)
467 countnew(char **old
, char **new) {
471 n
+= isnew(old
, *new);
476 sizenew(char **old
, char **new) {
480 if (isnew(old
, *new))
481 n
+= strlen(*new) + 1;
486 newgid(int ngroups
, gid_t
*groups
, gid_t group
) {
488 for (; ngroups
-- > 0; groups
++)
489 if (*groups
== group
)
494 #endif /* WANT_IRS_GR */