id.c revision 102944
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
44#endif /* not lint */
45#include <sys/cdefs.h>
46__FBSDID("$FreeBSD: head/usr.bin/id/id.c 102944 2002-09-04 23:29:10Z dwmalone $");
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
58void	current(void);
59void	pline(struct passwd *);
60void	pretty(struct passwd *);
61void	group(struct passwd *, int);
62void	usage(void);
63void	user(struct passwd *);
64struct passwd *
65	who(char *);
66
67int isgroups, iswhoami;
68
69int
70main(int argc, char *argv[])
71{
72	struct group *gr;
73	struct passwd *pw;
74	int Gflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
75	const char *myname;
76
77	Gflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
78
79	myname = strrchr(argv[0], '/');
80	myname = (myname != NULL) ? myname + 1 : argv[0];
81	if (strcmp(myname, "groups") == 0) {
82		isgroups = 1;
83		Gflag = nflag = 1;
84	}
85	else if (strcmp(myname, "whoami") == 0) {
86		iswhoami = 1;
87		uflag = nflag = 1;
88	}
89
90	while ((ch = getopt(argc, argv,
91	    (isgroups || iswhoami) ? "" : "PGgnpru")) != -1)
92		switch(ch) {
93		case 'G':
94			Gflag = 1;
95			break;
96		case 'P':
97			Pflag = 1;
98			break;
99		case 'g':
100			gflag = 1;
101			break;
102		case 'n':
103			nflag = 1;
104			break;
105		case 'p':
106			pflag = 1;
107			break;
108		case 'r':
109			rflag = 1;
110			break;
111		case 'u':
112			uflag = 1;
113			break;
114		case '?':
115		default:
116			usage();
117		}
118	argc -= optind;
119	argv += optind;
120
121	if (iswhoami && argc > 0)
122		usage();
123
124	switch(Gflag + Pflag + gflag + pflag + uflag) {
125	case 1:
126		break;
127	case 0:
128		if (!nflag && !rflag)
129			break;
130		/* FALLTHROUGH */
131	default:
132		usage();
133	}
134
135	pw = *argv ? who(*argv) : NULL;
136
137	if (gflag) {
138		id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
139		if (nflag && (gr = getgrgid(id)))
140			(void)printf("%s\n", gr->gr_name);
141		else
142			(void)printf("%u\n", id);
143		exit(0);
144	}
145
146	if (uflag) {
147		id = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
148		if (nflag && (pw = getpwuid(id)))
149			(void)printf("%s\n", pw->pw_name);
150		else
151			(void)printf("%u\n", id);
152		exit(0);
153	}
154
155	if (Gflag) {
156		group(pw, nflag);
157		exit(0);
158	}
159
160	if (Pflag) {
161		pline(pw);
162		exit(0);
163	}
164
165	if (pflag) {
166		pretty(pw);
167		exit(0);
168	}
169
170	if (pw)
171		user(pw);
172	else
173		current();
174	exit(0);
175}
176
177void
178pretty(struct passwd *pw)
179{
180	struct group *gr;
181	u_int eid, rid;
182	char *login;
183
184	if (pw) {
185		(void)printf("uid\t%s\n", pw->pw_name);
186		(void)printf("groups\t");
187		group(pw, 1);
188	} else {
189		if ((login = getlogin()) == NULL)
190			err(1, "getlogin");
191
192		pw = getpwuid(rid = getuid());
193		if (pw == NULL || strcmp(login, pw->pw_name))
194			(void)printf("login\t%s\n", login);
195		if (pw)
196			(void)printf("uid\t%s\n", pw->pw_name);
197		else
198			(void)printf("uid\t%u\n", rid);
199
200		if ((eid = geteuid()) != rid) {
201			if ((pw = getpwuid(eid)))
202				(void)printf("euid\t%s\n", pw->pw_name);
203			else
204				(void)printf("euid\t%u\n", eid);
205		}
206		if ((rid = getgid()) != (eid = getegid())) {
207			if ((gr = getgrgid(rid)))
208				(void)printf("rgid\t%s\n", gr->gr_name);
209			else
210				(void)printf("rgid\t%u\n", rid);
211		}
212		(void)printf("groups\t");
213		group(NULL, 1);
214	}
215}
216
217void
218current(void)
219{
220	struct group *gr;
221	struct passwd *pw;
222	int cnt, id, eid, lastid, ngroups;
223	gid_t groups[NGROUPS];
224	const char *fmt;
225
226	id = getuid();
227	(void)printf("uid=%u", id);
228	if ((pw = getpwuid(id)))
229		(void)printf("(%s)", pw->pw_name);
230	if ((eid = geteuid()) != id) {
231		(void)printf(" euid=%u", eid);
232		if ((pw = getpwuid(eid)))
233			(void)printf("(%s)", pw->pw_name);
234	}
235	id = getgid();
236	(void)printf(" gid=%u", id);
237	if ((gr = getgrgid(id)))
238		(void)printf("(%s)", gr->gr_name);
239	if ((eid = getegid()) != id) {
240		(void)printf(" egid=%u", eid);
241		if ((gr = getgrgid(eid)))
242			(void)printf("(%s)", gr->gr_name);
243	}
244	if ((ngroups = getgroups(NGROUPS, groups))) {
245		for (fmt = " groups=%u", lastid = -1, cnt = 0; cnt < ngroups;
246		    fmt = ", %u", lastid = id) {
247			id = groups[cnt++];
248			if (lastid == id)
249				continue;
250			(void)printf(fmt, id);
251			if ((gr = getgrgid(id)))
252				(void)printf("(%s)", gr->gr_name);
253		}
254	}
255	(void)printf("\n");
256}
257
258void
259user(struct passwd *pw)
260{
261	struct group *gr;
262	const char *fmt;
263	int cnt, gid, lastgid, ngroups, groups[NGROUPS + 1];
264
265	(void)printf("uid=%u(%s)", pw->pw_uid, pw->pw_name);
266	gid = pw->pw_gid;
267	(void)printf(" gid=%u", gid);
268	if ((gr = getgrgid(gid)))
269		(void)printf("(%s)", gr->gr_name);
270	ngroups = NGROUPS + 1;
271	(void) getgrouplist(pw->pw_name, gid, groups, &ngroups);
272	fmt = " groups=%u";
273	for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
274		if (lastgid == (gid = groups[cnt]))
275			continue;
276		(void)printf(fmt, gid);
277		fmt = ", %u";
278		if ((gr = getgrgid(gid)))
279			(void)printf("(%s)", gr->gr_name);
280		lastgid = gid;
281	}
282	(void)printf("\n");
283}
284
285void
286group(struct passwd *pw, int nflag)
287{
288	struct group *gr;
289	int cnt, id, lastid, ngroups;
290	gid_t groups[NGROUPS + 1];
291	const char *fmt;
292
293	if (pw) {
294		ngroups = NGROUPS + 1;
295		(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
296	} else {
297		groups[0] = getgid();
298		ngroups = getgroups(NGROUPS, groups + 1) + 1;
299	}
300	fmt = nflag ? "%s" : "%u";
301	for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
302		if (lastid == (id = groups[cnt]))
303			continue;
304		if (nflag) {
305			if ((gr = getgrgid(id)))
306				(void)printf(fmt, gr->gr_name);
307			else
308				(void)printf(*fmt == ' ' ? " %u" : "%u",
309				    id);
310			fmt = " %s";
311		} else {
312			(void)printf(fmt, id);
313			fmt = " %u";
314		}
315		lastid = id;
316	}
317	(void)printf("\n");
318}
319
320struct passwd *
321who(char *u)
322{
323	struct passwd *pw;
324	long id;
325	char *ep;
326
327	/*
328	 * Translate user argument into a pw pointer.  First, try to
329	 * get it as specified.  If that fails, try it as a number.
330	 */
331	if ((pw = getpwnam(u)))
332		return(pw);
333	id = strtol(u, &ep, 10);
334	if (*u && !*ep && (pw = getpwuid(id)))
335		return(pw);
336	errx(1, "%s: no such user", u);
337	/* NOTREACHED */
338}
339
340void
341pline(struct passwd *pw)
342{
343	u_int rid;
344
345	if (!pw) {
346		if ((pw = getpwuid(rid = getuid())) == NULL)
347			err(1, "getpwuid");
348	}
349
350	(void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
351			pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
352			(long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
353			pw->pw_dir, pw->pw_shell);
354}
355
356
357void
358usage(void)
359{
360
361	if (isgroups)
362		(void)fprintf(stderr, "usage: groups [user]\n");
363	else if (iswhoami)
364		(void)fprintf(stderr, "usage: whoami\n");
365	else
366		(void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
367		    "usage: id [user]",
368		    "       id -G [-n] [user]",
369		    "       id -P [user]",
370		    "       id -g [-nr] [user]",
371		    "       id -p [user]",
372		    "       id -u [-nr] [user]");
373	exit(1);
374}
375