xref: /openbsd-src/usr.bin/id/id.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: id.c,v 1.21 2014/07/14 05:41:00 guenther 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 #include <sys/param.h>
33 
34 #include <err.h>
35 #include <errno.h>
36 #include <grp.h>
37 #include <pwd.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 
43 void	current(void);
44 void	pretty(struct passwd *);
45 void	group(struct passwd *, int);
46 void	usage(void);
47 void	user(struct passwd *);
48 struct passwd *
49 	who(char *);
50 
51 int
52 main(int argc, char *argv[])
53 {
54 	struct group *gr;
55 	struct passwd *pw;
56 	int Gflag, ch, gflag, nflag, pflag, rflag, uflag;
57 	uid_t uid;
58 	gid_t gid;
59 	const char *opts;
60 
61 	Gflag = gflag = nflag = pflag = rflag = uflag = 0;
62 
63 	if (strcmp(getprogname(), "groups") == 0) {
64 		Gflag = 1;
65 		nflag = 1;
66 		opts = "";
67 		if (argc > 2)
68 			usage();
69 	} else if (strcmp(getprogname(), "whoami") == 0) {
70 		uflag = 1;
71 		nflag = 1;
72 		opts = "";
73 		if (argc > 1)
74 			usage();
75 	} else
76 		opts = "Ggnpru";
77 
78 	while ((ch = getopt(argc, argv, opts)) != -1)
79 		switch(ch) {
80 		case 'G':
81 			Gflag = 1;
82 			break;
83 		case 'g':
84 			gflag = 1;
85 			break;
86 		case 'n':
87 			nflag = 1;
88 			break;
89 		case 'p':
90 			pflag = 1;
91 			break;
92 		case 'r':
93 			rflag = 1;
94 			break;
95 		case 'u':
96 			uflag = 1;
97 			break;
98 		case '?':
99 		default:
100 			usage();
101 		}
102 	argc -= optind;
103 	argv += optind;
104 
105 	switch (Gflag + gflag + pflag + uflag) {
106 	case 1:
107 		break;
108 	case 0:
109 		if (!nflag && !rflag)
110 			break;
111 		/* FALLTHROUGH */
112 	default:
113 		usage();
114 	}
115 
116 	if (strcmp(opts, "") != 0 && argc > 1)
117 		usage();
118 
119 	pw = *argv ? who(*argv) : NULL;
120 
121 	if (gflag) {
122 		gid = pw ? pw->pw_gid : rflag ? getgid() : getegid();
123 		if (nflag && (gr = getgrgid(gid)))
124 			(void)printf("%s\n", gr->gr_name);
125 		else
126 			(void)printf("%u\n", gid);
127 		exit(0);
128 	}
129 
130 	if (uflag) {
131 		uid = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
132 		if (nflag && (pw = getpwuid(uid)))
133 			(void)printf("%s\n", pw->pw_name);
134 		else
135 			(void)printf("%u\n", uid);
136 		exit(0);
137 	}
138 
139 	if (Gflag) {
140 		group(pw, nflag);
141 		exit(0);
142 	}
143 
144 	if (pflag) {
145 		pretty(pw);
146 		exit(0);
147 	}
148 
149 	if (pw)
150 		user(pw);
151 	else
152 		current();
153 	exit(0);
154 }
155 
156 void
157 pretty(struct passwd *pw)
158 {
159 	struct group *gr;
160 	uid_t eid, rid;
161 	char *login;
162 
163 	if (pw) {
164 		(void)printf("uid\t%s\n", pw->pw_name);
165 		(void)printf("groups\t");
166 		group(pw, 1);
167 	} else {
168 		if ((login = getlogin()) == NULL)
169 			err(1, "getlogin");
170 
171 		pw = getpwuid(rid = getuid());
172 		if (pw == NULL || strcmp(login, pw->pw_name))
173 			(void)printf("login\t%s\n", login);
174 		if (pw)
175 			(void)printf("uid\t%s\n", pw->pw_name);
176 		else
177 			(void)printf("uid\t%u\n", rid);
178 
179 		if ((eid = geteuid()) != rid) {
180 			if ((pw = getpwuid(eid)))
181 				(void)printf("euid\t%s\n", pw->pw_name);
182 			else
183 				(void)printf("euid\t%u\n", eid);
184 		}
185 		if ((rid = getgid()) != (eid = getegid())) {
186 			if ((gr = getgrgid(rid)))
187 				(void)printf("rgid\t%s\n", gr->gr_name);
188 			else
189 				(void)printf("rgid\t%u\n", rid);
190 		}
191 		(void)printf("groups\t");
192 		group(NULL, 1);
193 	}
194 }
195 
196 void
197 current(void)
198 {
199 	struct group *gr;
200 	struct passwd *pw;
201 	int cnt, ngroups;
202 	uid_t uid, euid;
203 	gid_t groups[NGROUPS], gid, egid, lastgid;
204 	char *prefix;
205 
206 	uid = getuid();
207 	(void)printf("uid=%u", uid);
208 	if ((pw = getpwuid(uid)))
209 		(void)printf("(%s)", pw->pw_name);
210 	if ((euid = geteuid()) != uid) {
211 		(void)printf(" euid=%u", euid);
212 		if ((pw = getpwuid(euid)))
213 			(void)printf("(%s)", pw->pw_name);
214 	}
215 	gid = getgid();
216 	(void)printf(" gid=%u", gid);
217 	if ((gr = getgrgid(gid)))
218 		(void)printf("(%s)", gr->gr_name);
219 	if ((egid = getegid()) != gid) {
220 		(void)printf(" egid=%u", egid);
221 		if ((gr = getgrgid(egid)))
222 			(void)printf("(%s)", gr->gr_name);
223 	}
224 	if ((ngroups = getgroups(NGROUPS, groups))) {
225 		for (prefix = " groups=", lastgid = (gid_t)-1, cnt = 0;
226 		    cnt < ngroups; prefix = ", ", lastgid = gid) {
227 			gid = groups[cnt++];
228 			if (lastgid == gid)
229 				continue;
230 			(void)printf("%s%u", prefix, gid);
231 			if ((gr = getgrgid(gid)))
232 				(void)printf("(%s)", gr->gr_name);
233 		}
234 	}
235 	(void)printf("\n");
236 }
237 
238 void
239 user(struct passwd *pw)
240 {
241 	gid_t gid, groups[NGROUPS + 1];
242 	int cnt, ngroups;
243 	uid_t uid;
244 	struct group *gr;
245 	char *prefix;
246 
247 	uid = pw->pw_uid;
248 	(void)printf("uid=%u(%s)", uid, pw->pw_name);
249 	(void)printf(" gid=%u", pw->pw_gid);
250 	if ((gr = getgrgid(pw->pw_gid)))
251 		(void)printf("(%s)", gr->gr_name);
252 	ngroups = NGROUPS + 1;
253 	(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
254 	prefix = " groups=";
255 	for (cnt = 0; cnt < ngroups;) {
256 		gid = groups[cnt];
257 		(void)printf("%s%u", prefix, gid);
258 		prefix = ", ";
259 		if ((gr = getgrgid(gid)))
260 			(void)printf("(%s)", gr->gr_name);
261 		/* Skip same gid entries. */
262 		while (++cnt < ngroups && gid == groups[cnt]);
263 	}
264 	(void)printf("\n");
265 }
266 
267 void
268 group(struct passwd *pw, int nflag)
269 {
270 	int cnt, ngroups;
271 	gid_t gid, groups[NGROUPS + 1];
272 	struct group *gr;
273 	char *prefix;
274 
275 	if (pw) {
276 		ngroups = NGROUPS + 1;
277 		(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
278 	} else {
279 		groups[0] = getgid();
280 		ngroups = getgroups(NGROUPS, groups + 1) + 1;
281 	}
282 	prefix = "";
283 	for (cnt = 0; cnt < ngroups;) {
284 		gid = groups[cnt];
285 		if (nflag) {
286 			if ((gr = getgrgid(gid)))
287 				(void)printf("%s%s", prefix, gr->gr_name);
288 			else
289 				(void)printf("%s%u", prefix, gid);
290 		} else {
291 			(void)printf("%s%u", prefix, gid);
292 		}
293 		prefix = " ";
294 		/* Skip same gid entries. */
295 		while (++cnt < ngroups && gid == groups[cnt]);
296 	}
297 	(void)printf("\n");
298 }
299 
300 struct passwd *
301 who(char *u)
302 {
303 	struct passwd *pw;
304 	uid_t uid;
305 	const char *errstr;
306 
307 	/*
308 	 * Translate user argument into a pw pointer.  First, try to
309 	 * get it as specified.  If that fails, try it as a number.
310 	 */
311 	if ((pw = getpwnam(u)))
312 		return(pw);
313 	uid = strtonum(u, 0, UID_MAX, &errstr);
314 	if (!errstr && (pw = getpwuid(uid)))
315 		return(pw);
316 	errx(1, "%s: No such user", u);
317 	/* NOTREACHED */
318 }
319 
320 void
321 usage(void)
322 {
323 	if (strcmp(getprogname(), "groups") == 0) {
324 		(void)fprintf(stderr, "usage: groups [user]\n");
325 	} else if (strcmp(getprogname(), "whoami") == 0) {
326 		(void)fprintf(stderr, "usage: whoami\n");
327 	} else {
328 		(void)fprintf(stderr, "usage: id [user]\n");
329 		(void)fprintf(stderr, "       id -G [-n] [user]\n");
330 		(void)fprintf(stderr, "       id -g [-nr] [user]\n");
331 		(void)fprintf(stderr, "       id -p [user]\n");
332 		(void)fprintf(stderr, "       id -u [-nr] [user]\n");
333 	}
334 	exit(1);
335 }
336