1/* See LICENSE file for copyright and license details. */
2
3
4#include <sys/types.h>
5
6#include <ctype.h>
7#include <errno.h>
8#include <grp.h>
9#include <limits.h>
10#include <pwd.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14
15#include "util.h"
16
17static void groupid(struct passwd *pw);
18static void user(struct passwd *pw);
19static void userid(uid_t id);
20static void usernam(const char *nam);
21
22static int gflag = 0;
23static int uflag = 0;
24static int Gflag = 0;
25static int nflag = 0;
26
27static void
28groupid(struct passwd *pw)
29{
30 gid_t gid, groups[NGROUPS_MAX];
31 struct group *gr;
32 int ngroups;
33 int i;
34
35 ngroups = NGROUPS_MAX;
36 getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
37 for (i = 0; i < ngroups; i++) {
38 gid = groups[i];
39 if (nflag) {
40 if (!(gr = getgrgid(gid)))
41 eprintf("getgrgid:");
42 printf("%s", gr->gr_name);
43 } else
44 printf("%u", gid);
45
46 if (i < ngroups - 1)
47 putchar(' ');
48 }
49 putchar('\n');
50}
51
52static void
53user(struct passwd *pw)
54{
55 struct group *gr;
56 gid_t gid, groups[NGROUPS_MAX];
57 int ngroups;
58 int i;
59
60 if (uflag) {
61 if (nflag)
62 printf("%s\n", pw->pw_name);
63 else
64 printf("%u\n", pw->pw_uid);
65 return;
66 } else if (gflag) {
67 if (nflag) {
68 if (!(gr = getgrgid(pw->pw_gid)))
69 eprintf("getgrgid:");
70 printf("%s\n", gr->gr_name);
71 } else
72 printf("%u\n", pw->pw_gid);
73 return;
74 }
75
76 printf("uid=%u(%s)", pw->pw_uid, pw->pw_name);
77 printf(" gid=%u", pw->pw_gid);
78 if (!(gr = getgrgid(pw->pw_gid)))
79 eprintf("getgrgid:");
80 printf("(%s)", gr->gr_name);
81
82 ngroups = NGROUPS_MAX;
83 getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
84 for (i = 0; i < ngroups; i++) {
85 gid = groups[i];
86 printf("%s%u", !i ? " groups=" : ",", gid);
87 if (!(gr = getgrgid(gid)))
88 eprintf("getgrgid:");
89 printf("(%s)", gr->gr_name);
90 }
91 putchar('\n');
92}
93
94static void
95usernam(const char *nam)
96{
97 struct passwd *pw;
98
99 errno = 0;
100 pw = getpwnam(nam);
101 if (!pw) {
102 if (errno)
103 eprintf("getpwnam %s:", nam);
104 else
105 eprintf("getpwnam %s: no such user\n", nam);
106 }
107 if (Gflag)
108 groupid(pw);
109 else
110 user(pw);
111}
112
113static void
114userid(uid_t id)
115{
116 struct passwd *pw;
117
118 errno = 0;
119 pw = getpwuid(id);
120 if (!pw) {
121 if (errno)
122 eprintf("getpwuid %d:", id);
123 else
124 eprintf("getpwuid %d: no such user\n", id);
125 }
126 if (Gflag)
127 groupid(pw);
128 else
129 user(pw);
130}
131
132static void
133usage(void)
134{
135 eprintf("usage: %s [-n] [-g | -u | -G] [user | uid]\n", argv0);
136}
137
138// ?man id: print user and group ids
139// ?man arguments: user | uid
140// ?man display real and effective user and group identities
141int
142main(int argc, char *argv[])
143{
144 ARGBEGIN {
145 // ?man -g: specify option flag
146 case 'g':
147 gflag = 1;
148 break;
149 // ?man -u: unbuffered output
150 case 'u':
151 uflag = 1;
152 break;
153 // ?man -G: specify option flag
154 case 'G':
155 Gflag = 1;
156 break;
157 // ?man -n: print line numbers or counts
158 case 'n':
159 nflag = 1;
160 break;
161 default:
162 usage();
163 } ARGEND;
164
165 /* ensure that only one of -g, -u, or -G was specified */
166 if (gflag + uflag + Gflag > 1)
167 usage();
168
169 switch (argc) {
170 case 0:
171 userid(getuid());
172 break;
173 case 1:
174 /* user names can't begin [0-9] */
175 if (isdigit(argv[0][0]))
176 userid(estrtol(argv[0], 0));
177 else
178 usernam(argv[0]);
179 break;
180 default:
181 usage();
182 }
183
184 return 0;
185}