hi , I have a problem about getgroups usage on linux. getgroups can get supplementary groups of a process but if i run a process with root account and I want to get supplementary groups of nobody then what i should do to realize that.
You have to seteuid to the user, get the group, then return to uid 0. Because setuid() will change all of the uid settings (real, effective, etc.) you may think you can call seteuid() instead, so that you can later call setuid to root. But seteuid() does not change groups. Which does not work for what you want....
So, you have to exec(), setuid() to nobody, write the result of getgroups to shared memory, exit the child process.
IMO, It is probably less complicated to try this:
char *
get_gid(char *dest, const char *uid)
{
FILE *sh=NULL;
char cmd[40]={0x0};
char result[80]={0x0};
sprintf(cmd, "/usr/bin/id -G %s";, uid);
sh=popen(cmd, "r");
if(fgets(result, sizeof(result), sh)!=NULL)
strcpy(dest, result);
pclose(sh);
return dest;
}
Then parse out the uids, usually nobody is a single group so one atoi call returns the group.
I find Jim's solution nice.
How about this:
#include <grp.h>
#include <string.h>
gid_t *getGroups( const char *username, int *count )
{
struct group *grp;
gid_t *list = NULL;
*count = 0;
setgrent();
for ( ;; )
{
int ii;
grp = getgrent();
if ( NULL == grp )
{
break;
}
if ( ( NULL == grp->gr_mem ) ||
( NULL == grp->gr_mem[ 0 ] ) )
{
continue;
}
ii = 0;
for ( ii = 0;
NULL != grp->gr_mem[ ii ];
ii++ )
{
if ( 0 == strcmp( grp->gr_mem[ ii ], username ) )
{
list = ( gid_t * ) realloc( list,
( *count + 1 ) * sizeof( gid_t ) );
if ( NULL == list )
{
endgrent();
return( NULL );
}
list[ *count ] = grp->gr_gid;
( *count )++;
break;
}
}
}
endgrent();
return( list );
}
Not very efficient with all those realloc()'s, and it's not reentrant, but it works.
On Solaris, you can cheat and use this:
Cross Reference: /onnv/onnv-gate/usr/src/lib/libc/port/gen/getgrnam_r.c
Depends if you're measuring in terms of LOCs or CPU cycles burned ![]()
If you want to go that way, then I'd go for getgrouplist(). Alright, this is BSDish, but you can find the source on the net...
Cheers, Lo�c