id.c revision 159008
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 159008 2006-05-28 12:32:30Z stefanf $");
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, 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, 1, 0, 0);
184	}
185	else {
186		id = getuid();
187		if ((pw = getpwuid(id)) != NULL)
188			id_print(pw, 0, 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 use_ggl, 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	if (use_ggl) {
247		ngroups = NGROUPS + 1;
248		getgrouplist(pw->pw_name, gid, groups, &ngroups);
249	}
250	else {
251		ngroups = getgroups(NGROUPS + 1, groups);
252	}
253
254	printf("uid=%u(%s)", uid, pw->pw_name);
255	printf(" gid=%u", gid);
256	if ((gr = getgrgid(gid)))
257		(void)printf("(%s)", gr->gr_name);
258	if (p_euid && (euid = geteuid()) != uid) {
259		(void)printf(" euid=%u", euid);
260		if ((pw = getpwuid(euid)))
261			(void)printf("(%s)", pw->pw_name);
262	}
263	if (p_egid && (egid = getegid()) != gid) {
264		(void)printf(" egid=%u", egid);
265		if ((gr = getgrgid(egid)))
266			(void)printf("(%s)", gr->gr_name);
267	}
268	fmt = " groups=%u";
269	for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
270		if (lastgid == (gid = groups[cnt]))
271			continue;
272		printf(fmt, gid);
273		fmt = ", %u";
274		if ((gr = getgrgid(gid)))
275			printf("(%s)", gr->gr_name);
276		lastgid = gid;
277	}
278	printf("\n");
279}
280
281void
282group(struct passwd *pw, int nflag)
283{
284	struct group *gr;
285	int cnt, id, lastid, ngroups;
286	gid_t groups[NGROUPS + 1];
287	const char *fmt;
288
289	if (pw) {
290		ngroups = NGROUPS + 1;
291		(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
292	} else {
293		groups[0] = getgid();
294		ngroups = getgroups(NGROUPS, groups + 1) + 1;
295	}
296	fmt = nflag ? "%s" : "%u";
297	for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
298		if (lastid == (id = groups[cnt]))
299			continue;
300		if (nflag) {
301			if ((gr = getgrgid(id)))
302				(void)printf(fmt, gr->gr_name);
303			else
304				(void)printf(*fmt == ' ' ? " %u" : "%u",
305				    id);
306			fmt = " %s";
307		} else {
308			(void)printf(fmt, id);
309			fmt = " %u";
310		}
311		lastid = id;
312	}
313	(void)printf("\n");
314}
315
316void
317maclabel(void)
318{
319	char *string;
320	mac_t label;
321	int error;
322
323	error = mac_prepare_process_label(&label);
324	if (error == -1)
325		errx(1, "mac_prepare_type: %s", strerror(errno));
326
327	error = mac_get_proc(label);
328	if (error == -1)
329		errx(1, "mac_get_proc: %s", strerror(errno));
330
331	error = mac_to_text(label, &string);
332	if (error == -1)
333		errx(1, "mac_to_text: %s", strerror(errno));
334
335	(void)printf("%s\n", string);
336	mac_free(label);
337	free(string);
338}
339
340struct passwd *
341who(char *u)
342{
343	struct passwd *pw;
344	long id;
345	char *ep;
346
347	/*
348	 * Translate user argument into a pw pointer.  First, try to
349	 * get it as specified.  If that fails, try it as a number.
350	 */
351	if ((pw = getpwnam(u)))
352		return(pw);
353	id = strtol(u, &ep, 10);
354	if (*u && !*ep && (pw = getpwuid(id)))
355		return(pw);
356	errx(1, "%s: no such user", u);
357	/* NOTREACHED */
358}
359
360void
361pline(struct passwd *pw)
362{
363
364	if (!pw) {
365		if ((pw = getpwuid(getuid())) == NULL)
366			err(1, "getpwuid");
367	}
368
369	(void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
370			pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
371			(long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
372			pw->pw_dir, pw->pw_shell);
373}
374
375
376void
377usage(void)
378{
379
380	if (isgroups)
381		(void)fprintf(stderr, "usage: groups [user]\n");
382	else if (iswhoami)
383		(void)fprintf(stderr, "usage: whoami\n");
384	else
385		(void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
386		    "usage: id [user]",
387		    "       id -G [-n] [user]",
388		    "       id -M",
389		    "       id -P [user]",
390		    "       id -g [-nr] [user]",
391		    "       id -p [user]",
392		    "       id -u [-nr] [user]");
393	exit(1);
394}
395