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