1# id.awk --- implement id in awk
2#
3# Requires user and group library functions and getopt
4#
5# Arnold Robbins, arnold@skeeve.com, Public Domain
6# May 1993
7# Revised February 1996
8# Revised May 2014
9# Revised September 2014
10# Revised September 2020
11
12# output is:
13# uid=12(foo) euid=34(bar) gid=3(baz) \
14#             egid=5(blat) groups=9(nine),2(two),1(one)
15
16# Options:
17#   -G Output all group ids as space separated numbers (ruid, euid, groups)
18#   -g Output only the euid as a number
19#   -n Output name instead of the numeric value (with -g/-G/-u)
20#   -r Output ruid/rguid instead of effective id
21#   -u Output only effective user id, as a number
22
23function usage()
24{
25    printf("Usage:\n" \
26           "\tid [user]\n" \
27           "\tid -G [-n] [user]\n" \
28           "\tid -g [-nr] [user]\n" \
29           "\tid -u [-nr] [user]\n") > "/dev/stderr"
30
31    exit 1
32}
33BEGIN {
34    # parse args
35    while ((c = getopt(ARGC, ARGV, "Ggnru")) != -1) {
36        if (c == "G")
37            groupset_only++
38        else if (c == "g")
39            egid_only++
40        else if (c == "n")
41            names_not_groups++
42        else if (c == "r")
43            real_ids_only++
44        else if (c == "u")
45            euid_only++
46        else
47            usage()
48    }
49    if (groupset_only && real_ids_only)
50        usage()
51    else if (ARGC - Optind > 1)
52        usage()
53    if (ARGC - Optind == 0) {
54        # gather info for current user
55        uid = PROCINFO["uid"]
56        euid = PROCINFO["euid"]
57        gid = PROCINFO["gid"]
58        egid = PROCINFO["egid"]
59        for (i = 1; ("group" i) in PROCINFO; i++)
60            groupset[i] = PROCINFO["group" i]
61    } else {
62        fill_info_for_user(ARGV[ARGC-1])
63        real_ids_only++
64    }
65    if (groupset_only) {
66        if (names_not_groups) {
67            for (i = 1; i in groupset; i++) {
68                entry = getgrgid(groupset[i])
69                name = get_first_field(entry)
70                printf("%s", name)
71                if ((i + 1) in groupset)
72                    printf(" ")
73            }
74        } else {
75            for (i = 1; i in groupset; i++) {
76                printf("%u", groupset[i])
77                if ((i + 1) in groupset)
78                    printf(" ")
79            }
80        }
81
82        print ""    # final newline
83        exit 0
84    }
85    else if (egid_only) {
86        id = real_ids_only ? gid : egid
87        if (names_not_groups) {
88            entry = getgrgid(id)
89            name = get_first_field(entry)
90            printf("%s\n", name)
91        } else {
92            printf("%u\n", id)
93        }
94
95        exit 0
96    }
97    else if (euid_only) {
98        id = real_ids_only ? uid : euid
99        if (names_not_groups) {
100            entry = getpwuid(id)
101            name = get_first_field(entry)
102            printf("%s\n", name)
103        } else {
104            printf("%u\n", id)
105        }
106
107        exit 0
108    }
109    printf("uid=%d", uid)
110    pw = getpwuid(uid)
111    print_first_field(pw)
112    if (euid != uid && ! real_ids_only) {
113        printf(" euid=%d", euid)
114        pw = getpwuid(euid)
115        print_first_field(pw)
116    }
117    printf(" gid=%d", gid)
118    pw = getgrgid(gid)
119    print_first_field(pw)
120
121    if (egid != gid && ! real_ids_only) {
122        printf(" egid=%d", egid)
123        pw = getgrgid(egid)
124        print_first_field(pw)
125    }
126    for (i = 1; i in groupset; i++) {
127        if (i == 1)
128            printf(" groups=")
129        group = groupset[i]
130        printf("%d", group)
131        pw = getgrgid(group)
132        print_first_field(pw)
133        if ((i + 1) in groupset)
134            printf(",")
135    }
136
137    print ""
138}
139function get_first_field(str,  a)
140{
141    if (str != "") {
142        split(str, a, ":")
143        return a[1]
144    }
145}
146function print_first_field(str)
147{
148    first = get_first_field(str)
149    printf("(%s)", first)
150}
151function fill_info_for_user(user,
152                            pwent, fields, groupnames, grent, groups, i)
153{
154    pwent = getpwnam(user)
155    if (pwent == "") {
156        printf("id: '%s': no such user\n", user) > "/dev/stderr"
157        exit 1
158    }
159
160    split(pwent, fields, ":")
161    uid = fields[3] + 0
162    gid = fields[4] + 0
163
164    groupnames = getgruser(user)
165    split(groupnames, groups, " ")
166    for (i = 1; i in groups; i++) {
167        grent = getgrnam(groups[i])
168        split(grent, fields, ":")
169        groupset[i] = fields[3] + 0
170    }
171}
172