xref: /netbsd/usr.bin/id/id.c (revision 4624cd84)
161f28255Scgd /*-
287dc7098Scgd  * Copyright (c) 1991, 1993
387dc7098Scgd  *	The Regents of the University of California.  All rights reserved.
461f28255Scgd  *
561f28255Scgd  * Redistribution and use in source and binary forms, with or without
661f28255Scgd  * modification, are permitted provided that the following conditions
761f28255Scgd  * are met:
861f28255Scgd  * 1. Redistributions of source code must retain the above copyright
961f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1061f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1261f28255Scgd  *    documentation and/or other materials provided with the distribution.
1389aaa1bbSagc  * 3. Neither the name of the University nor the names of its contributors
1461f28255Scgd  *    may be used to endorse or promote products derived from this software
1561f28255Scgd  *    without specific prior written permission.
1661f28255Scgd  *
1761f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1861f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1961f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2061f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2161f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2261f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2361f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2461f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2561f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2661f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2761f28255Scgd  * SUCH DAMAGE.
2861f28255Scgd  */
2961f28255Scgd 
30f371ce2cSlukem #include <sys/cdefs.h>
3161f28255Scgd #ifndef lint
3298e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1991, 1993\
3398e5374cSlukem  The Regents of the University of California.  All rights reserved.");
3461f28255Scgd #endif /* not lint */
3561f28255Scgd 
3661f28255Scgd #ifndef lint
37f371ce2cSlukem #if 0
38f371ce2cSlukem static char sccsid[] = "@(#)id.c	8.3 (Berkeley) 4/28/95";
39f371ce2cSlukem #else
40*4624cd84Sjoerg __RCSID("$NetBSD: id.c,v 1.32 2011/09/16 15:39:26 joerg Exp $");
41f371ce2cSlukem #endif
4261f28255Scgd #endif /* not lint */
4361f28255Scgd 
4461f28255Scgd #include <sys/param.h>
4561f28255Scgd 
46f371ce2cSlukem #include <err.h>
4787dc7098Scgd #include <errno.h>
4887dc7098Scgd #include <grp.h>
4987dc7098Scgd #include <pwd.h>
5087dc7098Scgd #include <stdio.h>
5187dc7098Scgd #include <stdlib.h>
5287dc7098Scgd #include <string.h>
5387dc7098Scgd #include <unistd.h>
5461f28255Scgd 
5552f94719Speter static void current(void);
5652f94719Speter static void pretty(struct passwd *);
5752f94719Speter static void group(struct passwd *, int);
58*4624cd84Sjoerg __dead static void usage(void);
5952f94719Speter static void user(struct passwd *);
6052f94719Speter static struct passwd *who(char *);
616ccac2c3Schristos 
626ccac2c3Schristos static int maxgroups;
636ccac2c3Schristos static gid_t *groups;
6461f28255Scgd 
6587dc7098Scgd int
main(int argc,char * argv[])6652f94719Speter main(int argc, char *argv[])
6761f28255Scgd {
6887dc7098Scgd 	struct group *gr;
6987dc7098Scgd 	struct passwd *pw;
70a6e937b0Swsanchez 	int ch, id;
71a6e937b0Swsanchez 	int Gflag, gflag, nflag, pflag, rflag, uflag;
7202921c77Sjmmv 	const char *opts;
7361f28255Scgd 
7487dc7098Scgd 	Gflag = gflag = nflag = pflag = rflag = uflag = 0;
75a6e937b0Swsanchez 
7652f94719Speter 	if (strcmp(getprogname(), "groups") == 0) {
77a6e937b0Swsanchez 		Gflag = 1;
78a6e937b0Swsanchez 		nflag = 1;
7902921c77Sjmmv 		opts = "";
8002921c77Sjmmv 		if (argc > 2)
8102921c77Sjmmv 			usage();
8252f94719Speter 	} else if (strcmp(getprogname(), "whoami") == 0) {
83a6e937b0Swsanchez 		uflag = 1;
84a6e937b0Swsanchez 		nflag = 1;
8502921c77Sjmmv 		opts = "";
8602921c77Sjmmv 		if (argc > 1)
8702921c77Sjmmv 			usage();
8802921c77Sjmmv 	} else
8902921c77Sjmmv 		opts = "Ggnpru";
90a6e937b0Swsanchez 
9102921c77Sjmmv 	while ((ch = getopt(argc, argv, opts)) != -1)
9261f28255Scgd 		switch (ch) {
9361f28255Scgd 		case 'G':
9461f28255Scgd 			Gflag = 1;
9561f28255Scgd 			break;
9661f28255Scgd 		case 'g':
9761f28255Scgd 			gflag = 1;
9861f28255Scgd 			break;
9961f28255Scgd 		case 'n':
10061f28255Scgd 			nflag = 1;
10161f28255Scgd 			break;
10287dc7098Scgd 		case 'p':
10387dc7098Scgd 			pflag = 1;
10487dc7098Scgd 			break;
10561f28255Scgd 		case 'r':
10661f28255Scgd 			rflag = 1;
10761f28255Scgd 			break;
10861f28255Scgd 		case 'u':
10961f28255Scgd 			uflag = 1;
11061f28255Scgd 			break;
11161f28255Scgd 		case '?':
11261f28255Scgd 		default:
11361f28255Scgd 			usage();
11461f28255Scgd 		}
11561f28255Scgd 	argc -= optind;
11661f28255Scgd 	argv += optind;
11761f28255Scgd 
11887dc7098Scgd 	switch (Gflag + gflag + pflag + uflag) {
11987dc7098Scgd 	case 1:
12087dc7098Scgd 		break;
12187dc7098Scgd 	case 0:
12287dc7098Scgd 		if (!nflag && !rflag)
12387dc7098Scgd 			break;
12487dc7098Scgd 		/* FALLTHROUGH */
12587dc7098Scgd 	default:
12661f28255Scgd 		usage();
12761f28255Scgd 	}
12861f28255Scgd 
12902921c77Sjmmv 	if (strcmp(opts, "") != 0 && argc > 1)
13002921c77Sjmmv 		usage();
13102921c77Sjmmv 
13287dc7098Scgd 	pw = *argv ? who(*argv) : NULL;
13387dc7098Scgd 
1346ccac2c3Schristos 	maxgroups = sysconf(_SC_NGROUPS_MAX);
1356ccac2c3Schristos 	if ((groups = malloc((maxgroups + 1) * sizeof(gid_t))) == NULL)
13685cbf55dSdrochner 		err(1, NULL);
1376ccac2c3Schristos 
13861f28255Scgd 	if (gflag) {
13961f28255Scgd 		id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
14087dc7098Scgd 		if (nflag && (gr = getgrgid(id)))
14161f28255Scgd 			(void)printf("%s\n", gr->gr_name);
14287dc7098Scgd 		else
14361f28255Scgd 			(void)printf("%u\n", id);
1446ccac2c3Schristos 		goto done;
14561f28255Scgd 	}
14661f28255Scgd 
14761f28255Scgd 	if (uflag) {
14861f28255Scgd 		id = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
14987dc7098Scgd 		if (nflag && (pw = getpwuid(id)))
15061f28255Scgd 			(void)printf("%s\n", pw->pw_name);
15187dc7098Scgd 		else
15287dc7098Scgd 			(void)printf("%u\n", id);
1536ccac2c3Schristos 		goto done;
15461f28255Scgd 	}
15587dc7098Scgd 
15687dc7098Scgd 	if (Gflag) {
15787dc7098Scgd 		group(pw, nflag);
1586ccac2c3Schristos 		goto done;
15987dc7098Scgd 	}
16087dc7098Scgd 
16187dc7098Scgd 	if (pflag) {
16287dc7098Scgd 		pretty(pw);
1636ccac2c3Schristos 		goto done;
16461f28255Scgd 	}
16561f28255Scgd 
16661f28255Scgd 	if (pw)
16761f28255Scgd 		user(pw);
16861f28255Scgd 	else
16961f28255Scgd 		current();
1706ccac2c3Schristos done:
1716ccac2c3Schristos 	free(groups);
17252f94719Speter 
17352f94719Speter 	return 0;
17461f28255Scgd }
17561f28255Scgd 
1766ccac2c3Schristos static void
pretty(struct passwd * pw)17752f94719Speter pretty(struct passwd *pw)
17861f28255Scgd {
17987dc7098Scgd 	struct group *gr;
18087dc7098Scgd 	u_int eid, rid;
18187dc7098Scgd 	char *login;
18261f28255Scgd 
18361f28255Scgd 	if (pw) {
18487dc7098Scgd 		(void)printf("uid\t%s\n", pw->pw_name);
18587dc7098Scgd 		(void)printf("groups\t");
18687dc7098Scgd 		group(pw, 1);
18761f28255Scgd 	} else {
18887dc7098Scgd 		if ((login = getlogin()) == NULL)
189f371ce2cSlukem 			err(1, "getlogin");
19061f28255Scgd 
19187dc7098Scgd 		pw = getpwuid(rid = getuid());
19287dc7098Scgd 		if (pw == NULL || strcmp(login, pw->pw_name))
19387dc7098Scgd 			(void)printf("login\t%s\n", login);
19487dc7098Scgd 		if (pw)
19587dc7098Scgd 			(void)printf("uid\t%s\n", pw->pw_name);
19661f28255Scgd 		else
19787dc7098Scgd 			(void)printf("uid\t%u\n", rid);
19861f28255Scgd 
199f670fa10Sross 		if ((eid = geteuid()) != rid) {
200f371ce2cSlukem 			if ((pw = getpwuid(eid)) != NULL)
2017d6cc9c5Sitohy 				(void)printf("euid\t%s\n", pw->pw_name);
20287dc7098Scgd 			else
2037d6cc9c5Sitohy 				(void)printf("euid\t%u\n", eid);
204f670fa10Sross 		}
205f670fa10Sross 		if ((rid = getgid()) != (eid = getegid())) {
206f371ce2cSlukem 			if ((gr = getgrgid(rid)) != NULL)
20787dc7098Scgd 				(void)printf("rgid\t%s\n", gr->gr_name);
20887dc7098Scgd 			else
20987dc7098Scgd 				(void)printf("rgid\t%u\n", rid);
210f670fa10Sross 		}
21187dc7098Scgd 		(void)printf("groups\t");
21287dc7098Scgd 		group(NULL, 1);
21361f28255Scgd 	}
21461f28255Scgd }
21561f28255Scgd 
2166ccac2c3Schristos static void
current(void)21752f94719Speter current(void)
21861f28255Scgd {
21987dc7098Scgd 	struct group *gr;
22087dc7098Scgd 	struct passwd *pw;
221db01b090Sliamjfoy 	gid_t gid, egid, lastid;
222db01b090Sliamjfoy 	uid_t uid, euid;
223db01b090Sliamjfoy 	int cnt, ngroups;
224cd2105a4Speter 	const char *fmt;
22561f28255Scgd 
226db01b090Sliamjfoy 	uid = getuid();
227db01b090Sliamjfoy 	(void)printf("uid=%ju", (uintmax_t)uid);
228db01b090Sliamjfoy 	if ((pw = getpwuid(uid)) != NULL)
22961f28255Scgd 		(void)printf("(%s)", pw->pw_name);
230db01b090Sliamjfoy 	gid = getgid();
231db01b090Sliamjfoy 	(void)printf(" gid=%ju", (uintmax_t)gid);
232db01b090Sliamjfoy 	if ((gr = getgrgid(gid)) != NULL)
233db01b090Sliamjfoy 		(void)printf("(%s)", gr->gr_name);
234db01b090Sliamjfoy 	if ((euid = geteuid()) != uid) {
235db01b090Sliamjfoy 		(void)printf(" euid=%ju", (uintmax_t)euid);
236db01b090Sliamjfoy 		if ((pw = getpwuid(euid)) != NULL)
23761f28255Scgd 			(void)printf("(%s)", pw->pw_name);
23861f28255Scgd 	}
239db01b090Sliamjfoy 	if ((egid = getegid()) != gid) {
240db01b090Sliamjfoy 		(void)printf(" egid=%ju", (uintmax_t)egid);
241db01b090Sliamjfoy 		if ((gr = getgrgid(egid)) != NULL)
24261f28255Scgd 			(void)printf("(%s)", gr->gr_name);
24361f28255Scgd 	}
244c4aacce6Sfvdl 	if ((ngroups = getgroups(maxgroups, groups)) != 0) {
245db01b090Sliamjfoy 		for (fmt = " groups=%ju", lastid = -1, cnt = 0; cnt < ngroups;
246db01b090Sliamjfoy 		    fmt = ",%ju", lastid = gid, cnt++) {
247db01b090Sliamjfoy 			gid = groups[cnt];
248db01b090Sliamjfoy 			if (lastid == gid)
24961f28255Scgd 				continue;
250db01b090Sliamjfoy 			(void)printf(fmt, (uintmax_t)gid);
251db01b090Sliamjfoy 			if ((gr = getgrgid(gid)) != NULL)
25261f28255Scgd 				(void)printf("(%s)", gr->gr_name);
25361f28255Scgd 		}
25461f28255Scgd 	}
25561f28255Scgd 	(void)printf("\n");
25661f28255Scgd }
25761f28255Scgd 
2586ccac2c3Schristos static void
user(struct passwd * pw)25952f94719Speter user(struct passwd *pw)
26061f28255Scgd {
261f371ce2cSlukem 	struct group *gr;
262cd2105a4Speter 	const char *fmt;
2636ccac2c3Schristos 	int cnt, id, lastid, ngroups;
2649b39088eSdrochner 	gid_t *glist = groups;
26561f28255Scgd 
26661f28255Scgd 	id = pw->pw_uid;
26761f28255Scgd 	(void)printf("uid=%u(%s)", id, pw->pw_name);
2686ccac2c3Schristos 	(void)printf(" gid=%lu", (u_long)pw->pw_gid);
269f371ce2cSlukem 	if ((gr = getgrgid(pw->pw_gid)) != NULL)
27061f28255Scgd 		(void)printf("(%s)", gr->gr_name);
2716ccac2c3Schristos 	ngroups = maxgroups + 1;
2729b39088eSdrochner 	if (getgrouplist(pw->pw_name, pw->pw_gid, glist, &ngroups) == -1) {
2739b39088eSdrochner 		glist = malloc(ngroups * sizeof(gid_t));
2749b39088eSdrochner 		(void) getgrouplist(pw->pw_name, pw->pw_gid, glist, &ngroups);
2759b39088eSdrochner 	}
276b6fad0e3Smycroft 	for (fmt = " groups=%u", lastid = -1, cnt = 0; cnt < ngroups;
277b6fad0e3Smycroft 	    fmt=",%u", lastid = id, cnt++) {
2789b39088eSdrochner 		id = glist[cnt];
279b6fad0e3Smycroft 		if (lastid == id)
28061f28255Scgd 			continue;
28187dc7098Scgd 		(void)printf(fmt, id);
282f371ce2cSlukem 		if ((gr = getgrgid(id)) != NULL)
28387dc7098Scgd 			(void)printf("(%s)", gr->gr_name);
28461f28255Scgd 	}
28561f28255Scgd 	(void)printf("\n");
2869b39088eSdrochner 	if (glist != groups)
2879b39088eSdrochner 		free(glist);
28861f28255Scgd }
28961f28255Scgd 
2906ccac2c3Schristos static void
group(struct passwd * pw,int nflag)29152f94719Speter group(struct passwd *pw, int nflag)
29287dc7098Scgd {
29387dc7098Scgd 	struct group *gr;
29410e84421Slukem 	int cnt, ngroups;
29510e84421Slukem 	gid_t id, lastid;
296cd2105a4Speter 	const char *fmt;
2979b39088eSdrochner 	gid_t *glist = groups;
29887dc7098Scgd 
29987dc7098Scgd 	if (pw) {
3006ccac2c3Schristos 		ngroups = maxgroups;
3019b39088eSdrochner 		if (getgrouplist(pw->pw_name, pw->pw_gid, glist, &ngroups)
3029b39088eSdrochner 		    == -1) {
3039b39088eSdrochner 			glist = malloc(ngroups * sizeof(gid_t));
3049b39088eSdrochner 			(void) getgrouplist(pw->pw_name, pw->pw_gid, glist,
3059b39088eSdrochner 					    &ngroups);
3069b39088eSdrochner 		}
30787dc7098Scgd 	} else {
3089b39088eSdrochner 		glist[0] = getgid();
3099b39088eSdrochner 		ngroups = getgroups(maxgroups, glist + 1) + 1;
31087dc7098Scgd 	}
31187dc7098Scgd 	fmt = nflag ? "%s" : "%u";
31287dc7098Scgd 	for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
313bc3a1c65Schristos 		if (lastid == (id = glist[cnt]) || (cnt && id == glist[0]))
31487dc7098Scgd 			continue;
31587dc7098Scgd 		if (nflag) {
316f371ce2cSlukem 			if ((gr = getgrgid(id)) != NULL)
31787dc7098Scgd 				(void)printf(fmt, gr->gr_name);
31887dc7098Scgd 			else
31987dc7098Scgd 				(void)printf(*fmt == ' ' ? " %u" : "%u",
32087dc7098Scgd 				    id);
32187dc7098Scgd 			fmt = " %s";
32287dc7098Scgd 		} else {
32387dc7098Scgd 			(void)printf(fmt, id);
32487dc7098Scgd 			fmt = " %u";
32587dc7098Scgd 		}
32687dc7098Scgd 		lastid = id;
32787dc7098Scgd 	}
32887dc7098Scgd 	(void)printf("\n");
3299b39088eSdrochner 	if (glist != groups)
3309b39088eSdrochner 		free(glist);
33187dc7098Scgd }
33287dc7098Scgd 
333cd2105a4Speter static struct passwd *
who(char * u)33452f94719Speter who(char *u)
33561f28255Scgd {
33687dc7098Scgd 	struct passwd *pw;
33761f28255Scgd 	long id;
33861f28255Scgd 	char *ep;
33961f28255Scgd 
34061f28255Scgd 	/*
34161f28255Scgd 	 * Translate user argument into a pw pointer.  First, try to
34261f28255Scgd 	 * get it as specified.  If that fails, try it as a number.
34361f28255Scgd 	 */
344f371ce2cSlukem 	if ((pw = getpwnam(u)) != NULL)
34552f94719Speter 		return pw;
34661f28255Scgd 	id = strtol(u, &ep, 10);
34761f28255Scgd 	if (*u && !*ep && (pw = getpwuid(id)))
34852f94719Speter 		return pw;
349f371ce2cSlukem 	errx(1, "%s: No such user", u);
35061f28255Scgd 	/* NOTREACHED */
35152f94719Speter 	return NULL;
35261f28255Scgd }
35361f28255Scgd 
354cd2105a4Speter static void
usage(void)35552f94719Speter usage(void)
35661f28255Scgd {
3573a0b5da4Speter 
3583a0b5da4Speter 	if (strcmp(getprogname(), "groups") == 0) {
3593a0b5da4Speter 		(void)fprintf(stderr, "usage: groups [user]\n");
3603a0b5da4Speter 	} else if (strcmp(getprogname(), "whoami") == 0) {
3613a0b5da4Speter 		(void)fprintf(stderr, "usage: whoami\n");
3623a0b5da4Speter 	} else {
36361f28255Scgd 		(void)fprintf(stderr, "usage: id [user]\n");
36461f28255Scgd 		(void)fprintf(stderr, "       id -G [-n] [user]\n");
36561f28255Scgd 		(void)fprintf(stderr, "       id -g [-nr] [user]\n");
366e8ec0dc1Speter 		(void)fprintf(stderr, "       id -p [user]\n");
36761f28255Scgd 		(void)fprintf(stderr, "       id -u [-nr] [user]\n");
3683a0b5da4Speter 	}
36961f28255Scgd 	exit(1);
37061f28255Scgd }
371