Monday, September 1, 2014

Unix Prog: Group File

1. Group file in unix

Group file in unix contains all groups information in this operating system.

/etc/group:
 ubuntu@ip-172-31-23-227:~$ ls -lrt /etc/group  
 -rw-r--r-- 1 root root 701 Aug 2 14:29 /etc/group  
 ubuntu@ip-172-31-23-227:~$ less /etc/group  
 root:x:0:  
 daemon:x:1:  
 bin:x:2:  
 sys:x:3:  
 adm:x:4:syslog,ubuntu  
 ......  

1) 1st field: group name
2) 2nd field: encrypted group password
3) 3rd field: group id
4) 4th field: user list, which means who belong to this group.

2. System calls to handle group file in unix programming

Note: gr_mem is an array of string(user name), and this array is terminated by null pointer, normally in programming, we need to detect the null pointer to know the end of array.
 ubuntu@ip-172-31-23-227:~$ less /usr/include/grp.h  
 ......  
 /* The group structure. */  
 struct group  
  {  
   char *gr_name;       /* Group name. */  
   char *gr_passwd;      /* Password.  */  
   __gid_t gr_gid;       /* Group ID.  */  
   char **gr_mem;       /* Member list. */  
  };  
 ......  
 /* Rewind the group-file stream.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern void setgrent (void);  
 ......  
 /* Close the group-file stream.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern void endgrent (void);  
 /* Read an entry from the group-file stream, opening it if necessary.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern struct group *getgrent (void);  
 ......  
 /* Search for an entry with a matching group ID.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern struct group *getgrgid (__gid_t __gid);  
   
 /* Search for an entry with a matching group name.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern struct group *getgrnam (const char *__name);  
 ......  

3. Example:

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<grp.h>  
   
 void printGrp(struct group *pg)  
 {  
  printf("struct address: %p   ", pg);  
  printf("%s:%s:%d:", pg->gr_name, pg->gr_passwd, pg->gr_gid);  
   
  char **pc = pg->gr_mem;  
   
  // After the last user name is read(or there is no user name),  
  // the char pointer pc points to is NULL, note: pc is never NULL.  
  while(*pc != NULL) {  
   if(pc != pg->gr_mem) printf(",");  
   printf("%s", *pc);  
   pc++;  
  }  
   
  printf("\n");  
 }  
   
 int main(int argc, char* argv[])  
 {  
  struct group *pg;  
   
  // getgrgid example  
  if((pg = getgrgid(0)) == NULL) {  
   printf("getgrgid error!\n");  
   exit(1);  
  }  
   
  printGrp(pg);  
   
  // getgrnam example  
  if((pg = getgrnam("adm")) == NULL) {  
   printf("getgrnam error!\n");  
   exit(2);  
  }  
   
  // Itereate group entries  
  printf("Iterate each group entry: \n");  
  setgrent();  
  while((pg = getgrent()) != NULL) {  
   printGrp(pg);  
  }  
  endgrent();  
   
  printGrp(pg);  
   
  exit(0);  
 }  

shell:
Run the program, it will firstly output the group entry with gid 0, and then output the group entry with name "adm". Note that the struct addresses are same, so it indicate that getgrgid, and getgrnam just overwrite the information at the same place, instead of creating new struct grp.

And then it will iterate each entry in group file, also struct addresses are same.
 ubuntu@ip-172-31-23-227:~$ ./io.out  
 struct address: 0x7f2a09f1b0a0   root:x:0:  
 struct address: 0x7f2a09f1b0e0   adm:x:4:syslog,ubuntu  
 Iterate each group entry:  
 struct address: 0x7f2a09f1b060   root:x:0:  
 struct address: 0x7f2a09f1b060   daemon:x:1:  
 struct address: 0x7f2a09f1b060   bin:x:2:  
 struct address: 0x7f2a09f1b060   sys:x:3:  
 struct address: 0x7f2a09f1b060   adm:x:4:syslog,ubuntu  

No comments:

Post a Comment