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 "group
N"
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.