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