/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct pvt {
struct irs_rule * rules;
struct irs_rule * rule;
struct irs_gr * gr;
/*
* Need space to store the entries read from the group file.
* The members list also needs space per member, and the
* strings making up the user names must be allocated
* somewhere. Rather than doing lots of small allocations,
* we keep one buffer and resize it as needed.
*/
struct group group;
size_t nmemb; /*%< Malloc'd max index of gr_mem[]. */
char * membuf;
size_t membufsize;
struct __res_state * res;
void (*free_res)(void *);
};
if (gr->res_set)
(*gr->res_set)(gr, pvt->res, NULL);
}
}
/* Private. */
static int
grmerge(struct irs_gr *this, const struct group *src, int preserve) {
struct pvt *pvt = (struct pvt *)this->private;
char *cp, **m, **p, *oldmembuf, *ep;
int n, ndst, nnew;
size_t used;
if (!preserve) {
pvt->group.gr_gid = src->gr_gid;
if (pvt->nmemb < 1) {
m = malloc(sizeof *m);
if (m == NULL) {
/* No harm done, no work done. */
return (0);
}
pvt->group.gr_mem = m;
pvt->nmemb = 1;
}
pvt->group.gr_mem[0] = NULL;
}
ndst = countvec(pvt->group.gr_mem);
nnew = countnew(pvt->group.gr_mem, src->gr_mem);
/*
* Make sure destination member array is large enough.
* p points to new portion.
*/
n = ndst + nnew + 1;
if ((size_t)n > pvt->nmemb) {
m = realloc(pvt->group.gr_mem, n * sizeof *m);
if (m == NULL) {
/* No harm done, no work done. */
return (0);
}
pvt->group.gr_mem = m;
pvt->nmemb = n;
}
p = pvt->group.gr_mem + ndst;
/*
* Enlarge destination membuf; cp points at new portion.
*/
n = sizenew(pvt->group.gr_mem, src->gr_mem);
INSIST((nnew == 0) == (n == 0));
if (!preserve) {
n += strlen(src->gr_name) + 1;
n += strlen(src->gr_passwd) + 1;
}
if (n == 0) {
/* No work to do. */
return (1);
}
used = preserve ? pvt->membufsize : 0;
cp = malloc(used + n);
if (cp == NULL) {
/* No harm done, no work done. */
return (0);
}
ep = cp + used + n;
if (used != 0)
memcpy(cp, pvt->membuf, used);
oldmembuf = pvt->membuf;
pvt->membuf = cp;
pvt->membufsize = used + n;
cp += used;