#include #ifdef HAVE_SETGROUPS #include "prototypes.h" #include "defines.h" #include #include #include #ident "$Id$" #define SEP ",:" /* * Add groups with names from LIST (separated by commas or colons) * to the supplementary group set. Silently ignore groups which are * already there. Warning: uses strtok(). */ int add_groups (const char *list) { GETGROUPS_T *grouplist, *tmp; int i, ngroups, added; char *token; char buf[1024]; if (strlen (list) >= sizeof (buf)) { errno = EINVAL; return -1; } strcpy (buf, list); i = 16; for (;;) { grouplist = (gid_t *) malloc (i * sizeof (GETGROUPS_T)); if (!grouplist) return -1; ngroups = getgroups (i, grouplist); if (i > ngroups) break; /* not enough room, so try allocating a larger buffer */ free (grouplist); i *= 2; } if (ngroups < 0) { free (grouplist); return -1; } added = 0; for (token = strtok (buf, SEP); token; token = strtok (NULL, SEP)) { struct group *grp; grp = getgrnam (token); /* local, no need for xgetgrnam */ if (!grp) { fprintf (stderr, _("Warning: unknown group %s\n"), token); continue; } for (i = 0; i < ngroups && grouplist[i] != grp->gr_gid; i++); if (i < ngroups) continue; if (ngroups >= sysconf (_SC_NGROUPS_MAX)) { fprintf (stderr, _("Warning: too many groups\n")); break; } tmp = (gid_t *) realloc (grouplist, (ngroups + 1) * sizeof (GETGROUPS_T)); if (!tmp) { free (grouplist); return -1; } tmp[ngroups++] = grp->gr_gid; grouplist = tmp; added++; } if (added) return setgroups (ngroups, grouplist); return 0; } #endif