Search code examples
csystem

How to use getgrnam() with getgrent() in C


Let's review the my code first.

#include <stdio.h>
#include <grp.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>

int main(int argc, char** argv){
    struct group *grp;
    struct group *tmpGrp;
    struct passwd *pw;

    int n;
    gid_t gid;

    pw=getpwnam(argv[1]);
    gid=pw->pw_gid;

    printf(“%s”,pw->pw_name);
    printf(“\n”);
    grp = getgrgid(gid);
    char *mainGrp = grp->grame;
    printf(“out : %s\t”, mainGrp);

    while((tmpGrp=getgrgent())!=NULL){
        n=0;
        printf(“in : %s\t”,mainGrp);
    }
    printf(“\n”);
    return 0;
}

and it's output is like:

root
out : root    in : root    in : other    in : bin    in : sys   ....

As you see, when using the getgrnam() and getgrent() at the same time, group name is changed, even though assigned at string.

I want result like

root
out : root    in : root    in : root    in : root  ....

Code routine getgrgent() is just after at assigning into string, but why this happen? And how to fix it?

Test Operating System : Solaris 10

Test Compiler : GCC


Solution

  • From this (Linux) manual page for getgrent:

    The return value may point to a static area, and may be overwritten by subsequent calls to getgrent(), getgrgid(3), or getgrnam(3).

    So you get different names even though you use the same pointer, because the data returned by those functions is a single static and shared buffer.

    This is also hinted to by the POSIX getgrent reference specification.

    If you want mainGrp to not change, you need to copy the actual contents. E.g. make mainGrp an array and use strcpy.