id.c revision 83452
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
35static 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
42static char sccsid[] = "@(#)id.c	8.2 (Berkeley) 2/16/94";
43#endif
44static const char rcsid[] =
45  "$FreeBSD: head/usr.bin/id/id.c 83452 2001-09-14 14:04:08Z ru $";
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
58int	main __P((int, char *[]));
59void	current __P((void));
60void	pline __P((struct passwd *));
61void	pretty __P((struct passwd *));
62void	group __P((struct passwd *, int));
63void	usage __P((void));
64void	user __P((struct passwd *));
65struct passwd *
66	who __P((char *));
67
68int isgroups, iswhoami;
69
70int
71main(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
180void
181pretty(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
221void
222current()
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
262void
263user(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
290void
291group(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
327struct passwd *
328who(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
348void
349pline(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
366void
367usage()
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