From 617fb0e31acfabc17a733be8547ff50792f4ba6d Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 22 Mar 2010 09:54:10 -0400 Subject: [PATCH] getgrouplist(3) for those without it --- compat/getgrouplist.c | 86 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 compat/getgrouplist.c diff --git a/compat/getgrouplist.c b/compat/getgrouplist.c new file mode 100644 index 000000000..c054fbd90 --- /dev/null +++ b/compat/getgrouplist.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ + +#include + +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#include + +#include + +/* + * BSD-compatible getgrouplist(3) using getgrent(3) + */ +int +getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroupsp) +{ + int i, ngroups = 1; + int grpsize = *ngroupsp; + int rval = -1; + struct group *grp; + + /* We support BSD semantics where the first element is the base gid */ + if (grpsize <= 0) + return -1; + groups[0] = basegid; + + setgrent(); + while ((grp = getgrent()) != NULL) { + if (grp->gr_gid == basegid) + continue; + + for (i = 0; grp->gr_mem[i] != NULL; i++) { + if (strcmp(name, grp->gr_mem[i]) == 0) + break; + } + if (grp->gr_mem[i] == NULL) + continue; /* user not found */ + + /* Only add if it is not the same as an existing gid */ + for (i = 0; i < ngroups; i++) { + if (grp->gr_gid == groups[i]) + break; + } + if (i == ngroups) { + if (ngroups == grpsize) + goto done; + groups[ngroups++] = grp->gr_gid; + } + } + rval = 0; + +done: + endgrent(); + *ngroupsp = ngroups; + + return rval; +} -- 2.50.1