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