Next: , Previous: Egrep Program, Up: Clones



13.2.3 Printing out User Information

The id utility lists a user's real and effective user ID numbers, real and effective group ID numbers, and the user's group set, if any. id only prints the effective user ID and group ID if they are different from the real ones. If possible, id also supplies the corresponding user and group names. The output might look like this:

     $ id
     -| uid=2076(arnold) gid=10(staff) groups=10(staff),4(tty)

This information is part of what is provided by gawk's PROCINFO array (see Built-in Variables). However, the id utility provides a more palatable output than just individual numbers.

Here is a simple version of id written in awk. It uses the user database library functions (see Passwd Functions) and the group database library functions (see Group Functions):

The program is fairly straightforward. All the work is done in the BEGIN rule. The user and group ID numbers are obtained from PROCINFO. The code is repetitive. The entry in the user database for the real user ID number is split into parts at the `:'. The name is the first field. Similar code is used for the effective user ID number and the group numbers:

     
     # id.awk --- implement id in awk
     #
     # Requires user and group library functions
     
     
     # output is:
     # uid=12(foo) euid=34(bar) gid=3(baz) \
     #             egid=5(blat) groups=9(nine),2(two),1(one)
     
     BEGIN    \
     {
         uid = PROCINFO["uid"]
         euid = PROCINFO["euid"]
         gid = PROCINFO["gid"]
         egid = PROCINFO["egid"]
     
         printf("uid=%d", uid)
         pw = getpwuid(uid)
         if (pw != "") {
             split(pw, a, ":")
             printf("(%s)", a[1])
         }
     
         if (euid != uid) {
             printf(" euid=%d", euid)
             pw = getpwuid(euid)
             if (pw != "") {
                 split(pw, a, ":")
                 printf("(%s)", a[1])
             }
         }
     
         printf(" gid=%d", gid)
         pw = getgrgid(gid)
         if (pw != "") {
             split(pw, a, ":")
             printf("(%s)", a[1])
         }
     
         if (egid != gid) {
             printf(" egid=%d", egid)
             pw = getgrgid(egid)
             if (pw != "") {
                 split(pw, a, ":")
                 printf("(%s)", a[1])
             }
         }
     
         for (i = 1; ("group" i) in PROCINFO; i++) {
             if (i == 1)
                 printf(" groups=")
             group = PROCINFO["group" i]
             printf("%d", group)
             pw = getgrgid(group)
             if (pw != "") {
                 split(pw, a, ":")
                 printf("(%s)", a[1])
             }
             if (("group" (i+1)) in PROCINFO)
                 printf(",")
         }
     
         print ""
     }
     

The test in the for loop is worth noting. Any supplementary groups in the PROCINFO array have the indices "group1" through "groupN" for some N, i.e., the total number of supplementary groups. However, we don't know in advance how many of these groups there are.

This loop works by starting at one, concatenating the value with "group", and then using in to see if that value is in the array. Eventually, i is incremented past the last group in the array and the loop exits.

The loop is also correct if there are no supplementary groups; then the condition is false the first time it's tested, and the loop body never executes.