1 /* $OpenBSD: id.c,v 1.17 2004/11/16 13:51:35 jmc Exp $ */
2
3 /*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #ifndef lint
33 static char copyright[] =
34 "@(#) Copyright (c) 1991, 1993\n\
35 The Regents of the University of California. All rights reserved.\n";
36 #endif /* not lint */
37
38 #ifndef lint
39 /*static char sccsid[] = "@(#)id.c 8.3 (Berkeley) 4/28/95";*/
40 static char rcsid[] = "$OpenBSD: id.c,v 1.17 2004/11/16 13:51:35 jmc Exp $";
41 #endif /* not lint */
42
43 #include <sys/param.h>
44
45 #include <errno.h>
46 #include <grp.h>
47 #include <pwd.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <err.h>
53
54 void current(void);
55 void pretty(struct passwd *);
56 void group(struct passwd *, int);
57 void usage(void);
58 void user(struct passwd *);
59 struct passwd *
60 who(char *);
61
62 int
main(int argc,char * argv[])63 main(int argc, char *argv[])
64 {
65 struct group *gr;
66 struct passwd *pw;
67 int Gflag, ch, gflag, nflag, pflag, rflag, uflag;
68 uid_t uid;
69 gid_t gid;
70
71 Gflag = gflag = nflag = pflag = rflag = uflag = 0;
72 while ((ch = getopt(argc, argv, "Ggnpru")) != -1)
73 switch(ch) {
74 case 'G':
75 Gflag = 1;
76 break;
77 case 'g':
78 gflag = 1;
79 break;
80 case 'n':
81 nflag = 1;
82 break;
83 case 'p':
84 pflag = 1;
85 break;
86 case 'r':
87 rflag = 1;
88 break;
89 case 'u':
90 uflag = 1;
91 break;
92 case '?':
93 default:
94 usage();
95 }
96 argc -= optind;
97 argv += optind;
98
99 switch(Gflag + gflag + pflag + uflag) {
100 case 1:
101 break;
102 case 0:
103 if (!nflag && !rflag)
104 break;
105 /* FALLTHROUGH */
106 default:
107 usage();
108 }
109
110 pw = *argv ? who(*argv) : NULL;
111
112 if (gflag) {
113 gid = pw ? pw->pw_gid : rflag ? getgid() : getegid();
114 if (nflag && (gr = getgrgid(gid)))
115 (void)printf("%s\n", gr->gr_name);
116 else
117 (void)printf("%u\n", gid);
118 exit(0);
119 }
120
121 if (uflag) {
122 uid = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
123 if (nflag && (pw = getpwuid(uid)))
124 (void)printf("%s\n", pw->pw_name);
125 else
126 (void)printf("%u\n", uid);
127 exit(0);
128 }
129
130 if (Gflag) {
131 group(pw, nflag);
132 exit(0);
133 }
134
135 if (pflag) {
136 pretty(pw);
137 exit(0);
138 }
139
140 if (pw)
141 user(pw);
142 else
143 current();
144 exit(0);
145 }
146
147 void
pretty(struct passwd * pw)148 pretty(struct passwd *pw)
149 {
150 struct group *gr;
151 uid_t eid, rid;
152 char *login;
153
154 if (pw) {
155 (void)printf("uid\t%s\n", pw->pw_name);
156 (void)printf("groups\t");
157 group(pw, 1);
158 } else {
159 if ((login = getlogin()) == NULL)
160 err(1, "getlogin");
161
162 pw = getpwuid(rid = getuid());
163 if (pw == NULL || strcmp(login, pw->pw_name))
164 (void)printf("login\t%s\n", login);
165 if (pw)
166 (void)printf("uid\t%s\n", pw->pw_name);
167 else
168 (void)printf("uid\t%u\n", rid);
169
170 if ((eid = geteuid()) != rid) {
171 if ((pw = getpwuid(eid)))
172 (void)printf("euid\t%s\n", pw->pw_name);
173 else
174 (void)printf("euid\t%u\n", eid);
175 }
176 if ((rid = getgid()) != (eid = getegid())) {
177 if ((gr = getgrgid(rid)))
178 (void)printf("rgid\t%s\n", gr->gr_name);
179 else
180 (void)printf("rgid\t%u\n", rid);
181 }
182 (void)printf("groups\t");
183 group(NULL, 1);
184 }
185 }
186
187 void
current(void)188 current(void)
189 {
190 struct group *gr;
191 struct passwd *pw;
192 int cnt, ngroups;
193 uid_t uid, euid;
194 gid_t groups[NGROUPS], gid, egid, lastgid;
195 char *fmt;
196
197 uid = getuid();
198 (void)printf("uid=%u", uid);
199 if ((pw = getpwuid(uid)))
200 (void)printf("(%s)", pw->pw_name);
201 if ((euid = geteuid()) != uid) {
202 (void)printf(" euid=%u", euid);
203 if ((pw = getpwuid(euid)))
204 (void)printf("(%s)", pw->pw_name);
205 }
206 gid = getgid();
207 (void)printf(" gid=%u", gid);
208 if ((gr = getgrgid(gid)))
209 (void)printf("(%s)", gr->gr_name);
210 if ((egid = getegid()) != gid) {
211 (void)printf(" egid=%u", egid);
212 if ((gr = getgrgid(egid)))
213 (void)printf("(%s)", gr->gr_name);
214 }
215 if ((ngroups = getgroups(NGROUPS, groups))) {
216 for (fmt = " groups=%u", lastgid = (gid_t)-1, cnt = 0; cnt < ngroups;
217 fmt = ", %u", lastgid = gid) {
218 gid = groups[cnt++];
219 if (lastgid == gid)
220 continue;
221 (void)printf(fmt, gid);
222 if ((gr = getgrgid(gid)))
223 (void)printf("(%s)", gr->gr_name);
224 }
225 }
226 (void)printf("\n");
227 }
228
229 void
user(struct passwd * pw)230 user(struct passwd *pw)
231 {
232 gid_t gid, groups[NGROUPS + 1];
233 int cnt, ngroups;
234 uid_t uid;
235 struct group *gr;
236 char *fmt;
237
238 uid = pw->pw_uid;
239 (void)printf("uid=%u(%s)", uid, pw->pw_name);
240 (void)printf(" gid=%u", pw->pw_gid);
241 if ((gr = getgrgid(pw->pw_gid)))
242 (void)printf("(%s)", gr->gr_name);
243 ngroups = NGROUPS + 1;
244 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
245 fmt = " groups=%u";
246 for (cnt = 0; cnt < ngroups;) {
247 gid = groups[cnt];
248 (void)printf(fmt, gid);
249 fmt = ", %u";
250 if ((gr = getgrgid(gid)))
251 (void)printf("(%s)", gr->gr_name);
252 /* Skip same gid entries. */
253 while (++cnt < ngroups && gid == groups[cnt]);
254 }
255 (void)printf("\n");
256 }
257
258 void
group(struct passwd * pw,int nflag)259 group(struct passwd *pw, int nflag)
260 {
261 int cnt, ngroups;
262 gid_t gid, groups[NGROUPS + 1];
263 struct group *gr;
264 char *fmt;
265
266 if (pw) {
267 ngroups = NGROUPS + 1;
268 (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
269 } else {
270 groups[0] = getgid();
271 ngroups = getgroups(NGROUPS, groups + 1) + 1;
272 }
273 fmt = nflag ? "%s" : "%u";
274 for (cnt = 0; cnt < ngroups;) {
275 gid = groups[cnt];
276 if (nflag) {
277 if ((gr = getgrgid(gid)))
278 (void)printf(fmt, gr->gr_name);
279 else
280 (void)printf(*fmt == ' ' ? " %u" : "%u",
281 gid);
282 fmt = " %s";
283 } else {
284 (void)printf(fmt, gid);
285 fmt = " %u";
286 }
287 /* Skip same gid entries. */
288 while (++cnt < ngroups && gid == groups[cnt]);
289 }
290 (void)printf("\n");
291 }
292
293 struct passwd *
who(char * u)294 who(char *u)
295 {
296 struct passwd *pw;
297 uid_t uid;
298 const char *errstr;
299
300 /*
301 * Translate user argument into a pw pointer. First, try to
302 * get it as specified. If that fails, try it as a number.
303 */
304 if ((pw = getpwnam(u)))
305 return(pw);
306 uid = strtonum(u, 0, UID_MAX, &errstr);
307 if (!errstr && (pw = getpwuid(uid)))
308 return(pw);
309 errx(1, "%s: No such user", u);
310 /* NOTREACHED */
311 }
312
313 void
usage(void)314 usage(void)
315 {
316 (void)fprintf(stderr, "usage: id [user]\n"
317 " id -G [-n] [user]\n"
318 " id -g [-nr] [user]\n"
319 " id -p [user]\n"
320 " id -u [-nr] [user]\n");
321 exit(1);
322 }
323