diff --git a/include/unistd.h b/include/unistd.h index 012e385d7..3e06537ec 100755 --- a/include/unistd.h +++ b/include/unistd.h @@ -185,6 +185,7 @@ _PROTOTYPE( int devctl, (int ctl_req, int driver, int device, int style)); /* For compatibility with other Unix systems */ _PROTOTYPE( int getpagesize, (void) ); _PROTOTYPE( int setgroups, (int ngroups, const gid_t *gidset) ); +_PROTOTYPE( int initgroups, (const char *name, gid_t basegid) ); #endif diff --git a/lib/other/setgroups.c b/lib/other/setgroups.c index 23a364417..a1f199feb 100644 --- a/lib/other/setgroups.c +++ b/lib/other/setgroups.c @@ -4,12 +4,48 @@ setgroups.c #include #include +#include +#include int setgroups(int ngroups, const gid_t *gidset) { - /* Not implemented */ + if(!gidset || ngroups > 1) { + /* Supplementary groups not implemented */ + errno= EINVAL; + return -1; + } - errno= ENOSYS; - return -1; + if(ngroups == 1) + return setgid(gidset[0]); + + return 0; +} + +int initgroups(const char *name, gid_t basegid) +{ + struct group *gr; + int r, found = 0; + if((r = setgid(basegid)) < 0) + return r; + + setgrent(); + while (!found && (gr = getgrent()) != NULL) { + char **mem; + for(mem = gr->gr_mem; mem && *mem; mem++) { + if(!strcmp(name, *mem)) { + found = 1; + break; + } + } + } + endgrent(); + + /* Because supplemental groups aren't implemented, this call + * should fail if the user is in any supplemental groups. + */ + if(found) + return EINVAL; + + return 0; }