gawk: Id Program
1
1 11.2.3 Printing Out User Information
1 ------------------------------------
1
1 The 'id' utility lists a user's real and effective user ID numbers, real
1 and effective group ID numbers, and the user's group set, if any. 'id'
1 only prints the effective user ID and group ID if they are different
1 from the real ones. If possible, 'id' also supplies the corresponding
1 user and group names. The output might look like this:
1
1 $ id
1 -| uid=1000(arnold) gid=1000(arnold) groups=1000(arnold),4(adm),7(lp),27(sudo)
1
1 This information is part of what is provided by 'gawk''s 'PROCINFO'
1 array (⇒Built-in Variables). However, the 'id' utility provides
1 a more palatable output than just individual numbers.
1
1 Here is a simple version of 'id' written in 'awk'. It uses the user
1 database library functions (⇒Passwd Functions) and the group
DONTPRINTYET 1 database library functions (⇒Group Functions) from *noteLibrary
1DONTPRINTYET 1 database library functions (⇒Group Functions) from ⇒Library
Functions.
1
1 The program is fairly straightforward. All the work is done in the
1 'BEGIN' rule. The user and group ID numbers are obtained from
1 'PROCINFO'. The code is repetitive. The entry in the user database for
1 the real user ID number is split into parts at the ':'. The name is the
1 first field. Similar code is used for the effective user ID number and
1 the group numbers:
1
1 # id.awk --- implement id in awk
1 #
1 # Requires user and group library functions
1 # output is:
1 # uid=12(foo) euid=34(bar) gid=3(baz) \
1 # egid=5(blat) groups=9(nine),2(two),1(one)
1
1 BEGIN {
1 uid = PROCINFO["uid"]
1 euid = PROCINFO["euid"]
1 gid = PROCINFO["gid"]
1 egid = PROCINFO["egid"]
1
1 printf("uid=%d", uid)
1 pw = getpwuid(uid)
1 pr_first_field(pw)
1
1 if (euid != uid) {
1 printf(" euid=%d", euid)
1 pw = getpwuid(euid)
1 pr_first_field(pw)
1 }
1
1 printf(" gid=%d", gid)
1 pw = getgrgid(gid)
1 pr_first_field(pw)
1
1 if (egid != gid) {
1 printf(" egid=%d", egid)
1 pw = getgrgid(egid)
1 pr_first_field(pw)
1 }
1
1 for (i = 1; ("group" i) in PROCINFO; i++) {
1 if (i == 1)
1 printf(" groups=")
1 group = PROCINFO["group" i]
1 printf("%d", group)
1 pw = getgrgid(group)
1 pr_first_field(pw)
1 if (("group" (i+1)) in PROCINFO)
1 printf(",")
1 }
1
1 print ""
1 }
1
1 function pr_first_field(str, a)
1 {
1 if (str != "") {
1 split(str, a, ":")
1 printf("(%s)", a[1])
1 }
1 }
1
1 The test in the 'for' loop is worth noting. Any supplementary groups
1 in the 'PROCINFO' array have the indices '"group1"' through '"groupN"'
1 for some N (i.e., the total number of supplementary groups). However,
1 we don't know in advance how many of these groups there are.
1
1 This loop works by starting at one, concatenating the value with
1 '"group"', and then using 'in' to see if that value is in the array
1 (⇒Reference to Elements). Eventually, 'i' is incremented past
1 the last group in the array and the loop exits.
1
1 The loop is also correct if there are _no_ supplementary groups; then
1 the condition is false the first time it's tested, and the loop body
1 never executes.
1
1 The 'pr_first_field()' function simply isolates out some code that is
1 used repeatedly, making the whole program shorter and cleaner. In
1 particular, moving the check for the empty string into this function
1 saves several lines of code.
1