xref: /illumos-gate/usr/src/cmd/id/id.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5a604d238Scf  * Common Development and Distribution License (the "License").
6a604d238Scf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*f48205beScasper  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <locale.h>
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <pwd.h>
337c478bd9Sstevel@tonic-gate #include <grp.h>
347c478bd9Sstevel@tonic-gate #include <sys/param.h>
357c478bd9Sstevel@tonic-gate #include <unistd.h>
367c478bd9Sstevel@tonic-gate #include <string.h>
377c478bd9Sstevel@tonic-gate #include <project.h>
387c478bd9Sstevel@tonic-gate #include <stdlib.h>
39*f48205beScasper #include <alloca.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #define	PWNULL  ((struct passwd *)0)
427c478bd9Sstevel@tonic-gate #define	GRNULL  ((struct group *)0)
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate typedef enum TYPE {
457c478bd9Sstevel@tonic-gate 	UID, EUID, GID, EGID, SGID
467c478bd9Sstevel@tonic-gate }	TYPE;
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate typedef enum PRINT {
497c478bd9Sstevel@tonic-gate 	CURR,		/* Print uid/gid only */
507c478bd9Sstevel@tonic-gate 	ALLGROUPS,	/* Print all groups */
517c478bd9Sstevel@tonic-gate 	GROUP,		/* Print only group */
527c478bd9Sstevel@tonic-gate 	USER		/* Print only uid */
537c478bd9Sstevel@tonic-gate }	PRINT;
547c478bd9Sstevel@tonic-gate static PRINT mode = CURR;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static int usage(void);
577c478bd9Sstevel@tonic-gate static void puid(uid_t);
587c478bd9Sstevel@tonic-gate static void pgid(gid_t);
597c478bd9Sstevel@tonic-gate static void prid(TYPE, uid_t);
607c478bd9Sstevel@tonic-gate static int getusergroups(int, gid_t *, char *, gid_t);
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate static int nflag = 0;		/* Output names, not numbers */
637c478bd9Sstevel@tonic-gate static int rflag = 0;		/* Output real, not effective IDs */
647c478bd9Sstevel@tonic-gate static char stdbuf[BUFSIZ];
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])677c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate 	gid_t *idp;
707c478bd9Sstevel@tonic-gate 	uid_t uid, euid;
717c478bd9Sstevel@tonic-gate 	gid_t gid, egid, prgid;
727c478bd9Sstevel@tonic-gate 	int c, aflag = 0, project_flag = 0;
737c478bd9Sstevel@tonic-gate 	struct passwd *pwp;
747c478bd9Sstevel@tonic-gate 	int i, j;
75*f48205beScasper 	int groupmax = sysconf(_SC_NGROUPS_MAX);
76*f48205beScasper 	gid_t *groupids = alloca(groupmax * sizeof (gid_t));
777c478bd9Sstevel@tonic-gate 	struct group *gr;
787c478bd9Sstevel@tonic-gate 	char *user = NULL;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
837c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
847c478bd9Sstevel@tonic-gate #endif
857c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
86a604d238Scf 	while ((c = getopt(argc, argv, "Ggunarp")) != EOF) {
877c478bd9Sstevel@tonic-gate 		switch (c) {
887c478bd9Sstevel@tonic-gate 			case 'G':
897c478bd9Sstevel@tonic-gate 				if (mode != CURR)
907c478bd9Sstevel@tonic-gate 					return (usage());
917c478bd9Sstevel@tonic-gate 				mode = ALLGROUPS;
927c478bd9Sstevel@tonic-gate 				break;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 			case 'g':
957c478bd9Sstevel@tonic-gate 				if (mode != CURR)
967c478bd9Sstevel@tonic-gate 					return (usage());
977c478bd9Sstevel@tonic-gate 				mode = GROUP;
987c478bd9Sstevel@tonic-gate 				break;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 			case 'a':
1017c478bd9Sstevel@tonic-gate 				aflag++;
1027c478bd9Sstevel@tonic-gate 				break;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 			case 'n':
1057c478bd9Sstevel@tonic-gate 				nflag++;
1067c478bd9Sstevel@tonic-gate 				break;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 			case 'r':
1097c478bd9Sstevel@tonic-gate 				rflag++;
1107c478bd9Sstevel@tonic-gate 				break;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 			case 'u':
1137c478bd9Sstevel@tonic-gate 				if (mode != CURR)
1147c478bd9Sstevel@tonic-gate 					return (usage());
1157c478bd9Sstevel@tonic-gate 				mode = USER;
1167c478bd9Sstevel@tonic-gate 				break;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 			case 'p':
1197c478bd9Sstevel@tonic-gate 				if (mode != CURR)
1207c478bd9Sstevel@tonic-gate 					return (usage());
1217c478bd9Sstevel@tonic-gate 				project_flag++;
1227c478bd9Sstevel@tonic-gate 				break;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 			case '?':
1257c478bd9Sstevel@tonic-gate 				return (usage());
1267c478bd9Sstevel@tonic-gate 		}
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate 	setbuf(stdout, stdbuf);
1297c478bd9Sstevel@tonic-gate 	argc -= optind-1;
1307c478bd9Sstevel@tonic-gate 	argv += optind-1;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	/* -n and -r must be combined with one of -[Ggu] */
1337c478bd9Sstevel@tonic-gate 	/* -r cannot be combined with -G */
134a604d238Scf 	/* -a and -p cannot be combined with -[Ggu] */
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	if ((mode == CURR && (nflag || rflag)) ||
1377c478bd9Sstevel@tonic-gate 		(mode == ALLGROUPS && rflag) ||
138a604d238Scf 		(argc != 1 && argc != 2) ||
139a604d238Scf 		(mode != CURR && (project_flag || aflag)))
1407c478bd9Sstevel@tonic-gate 		return (usage());
1417c478bd9Sstevel@tonic-gate 	if (argc == 2) {
1427c478bd9Sstevel@tonic-gate 		if ((pwp = getpwnam(argv[1])) == PWNULL) {
1437c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1447c478bd9Sstevel@tonic-gate 				gettext("id: invalid user name: \"%s\"\n"),
1457c478bd9Sstevel@tonic-gate 					argv[1]);
1467c478bd9Sstevel@tonic-gate 			return (1);
1477c478bd9Sstevel@tonic-gate 		}
1487c478bd9Sstevel@tonic-gate 		user = argv[1];
1497c478bd9Sstevel@tonic-gate 		uid = euid = pwp->pw_uid;
1507c478bd9Sstevel@tonic-gate 		prgid = gid = egid = pwp->pw_gid;
1517c478bd9Sstevel@tonic-gate 	} else {
1527c478bd9Sstevel@tonic-gate 		uid = getuid();
1537c478bd9Sstevel@tonic-gate 		gid = getgid();
1547c478bd9Sstevel@tonic-gate 		euid = geteuid();
1557c478bd9Sstevel@tonic-gate 		egid = getegid();
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	if (mode != CURR) {
1597c478bd9Sstevel@tonic-gate 		if (!rflag) {
1607c478bd9Sstevel@tonic-gate 			uid = euid;
1617c478bd9Sstevel@tonic-gate 			gid = egid;
1627c478bd9Sstevel@tonic-gate 		}
1637c478bd9Sstevel@tonic-gate 		if (mode == USER)
1647c478bd9Sstevel@tonic-gate 			puid(uid);
1657c478bd9Sstevel@tonic-gate 		else if (mode == GROUP)
1667c478bd9Sstevel@tonic-gate 			pgid(gid);
1677c478bd9Sstevel@tonic-gate 		else if (mode == ALLGROUPS) {
1687c478bd9Sstevel@tonic-gate 			pgid(gid);
1697c478bd9Sstevel@tonic-gate 			if (user)
170*f48205beScasper 				i = getusergroups(groupmax, groupids, user,
1717c478bd9Sstevel@tonic-gate 				    prgid);
1727c478bd9Sstevel@tonic-gate 			else
173*f48205beScasper 				i = getgroups(groupmax, groupids);
1747c478bd9Sstevel@tonic-gate 			if (i == -1)
1757c478bd9Sstevel@tonic-gate 				perror("getgroups");
1767c478bd9Sstevel@tonic-gate 			else if (i > 0) {
1777c478bd9Sstevel@tonic-gate 				for (j = 0; j < i; ++j) {
1787c478bd9Sstevel@tonic-gate 					if ((gid = groupids[j]) == egid)
1797c478bd9Sstevel@tonic-gate 						continue;
1807c478bd9Sstevel@tonic-gate 					(void) putchar(' ');
1817c478bd9Sstevel@tonic-gate 					pgid(gid);
1827c478bd9Sstevel@tonic-gate 				}
1837c478bd9Sstevel@tonic-gate 			}
1847c478bd9Sstevel@tonic-gate 		}
1857c478bd9Sstevel@tonic-gate 		(void) putchar('\n');
1867c478bd9Sstevel@tonic-gate 	} else {
1877c478bd9Sstevel@tonic-gate 		prid(UID, uid);
1887c478bd9Sstevel@tonic-gate 		prid(GID, gid);
1897c478bd9Sstevel@tonic-gate 		if (uid != euid)
1907c478bd9Sstevel@tonic-gate 			prid(EUID, euid);
1917c478bd9Sstevel@tonic-gate 		if (gid != egid)
1927c478bd9Sstevel@tonic-gate 			prid(EGID, egid);
193a604d238Scf 
1947c478bd9Sstevel@tonic-gate 		if (aflag) {
1957c478bd9Sstevel@tonic-gate 			if (user)
196*f48205beScasper 				i = getusergroups(groupmax, groupids, user,
1977c478bd9Sstevel@tonic-gate 				    prgid);
1987c478bd9Sstevel@tonic-gate 			else
199*f48205beScasper 				i = getgroups(groupmax, groupids);
2007c478bd9Sstevel@tonic-gate 			if (i == -1)
2017c478bd9Sstevel@tonic-gate 				perror("getgroups");
2027c478bd9Sstevel@tonic-gate 			else if (i > 0) {
2037c478bd9Sstevel@tonic-gate 				(void) printf(" groups=");
2047c478bd9Sstevel@tonic-gate 				for (idp = groupids; i--; idp++) {
205*f48205beScasper 					(void) printf("%u", *idp);
2067c478bd9Sstevel@tonic-gate 					if (gr = getgrgid(*idp))
2077c478bd9Sstevel@tonic-gate 						(void) printf("(%s)",
2087c478bd9Sstevel@tonic-gate 							gr->gr_name);
2097c478bd9Sstevel@tonic-gate 					if (i)
2107c478bd9Sstevel@tonic-gate 						(void) putchar(',');
2117c478bd9Sstevel@tonic-gate 				}
2127c478bd9Sstevel@tonic-gate 			}
2137c478bd9Sstevel@tonic-gate 		}
214a604d238Scf #ifdef XPG4
215a604d238Scf 		/*
216a604d238Scf 		 * POSIX requires us to show all supplementary groups
217a604d238Scf 		 * groups other than the effective group already listed.
218a604d238Scf 		 *
219a604d238Scf 		 * This differs from -a above, because -a always shows
220a604d238Scf 		 * all groups including the effective group in the group=
221a604d238Scf 		 * line.
222a604d238Scf 		 *
223a604d238Scf 		 * It would be simpler if SunOS could just adopt this
224a604d238Scf 		 * POSIX behavior, as it is so incredibly close to the
225a604d238Scf 		 * the norm already.
226a604d238Scf 		 *
227a604d238Scf 		 * Then the magic -a flag could just indicate whether or
228a604d238Scf 		 * not we are suppressing the effective group id.
229a604d238Scf 		 */
230a604d238Scf 		else {
231a604d238Scf 			if (user)
232*f48205beScasper 				i = getusergroups(groupmax, groupids, user,
233a604d238Scf 				    prgid);
234a604d238Scf 			else
235*f48205beScasper 				i = getgroups(groupmax, groupids);
236a604d238Scf 			if (i == -1)
237a604d238Scf 				perror("getgroups");
238a604d238Scf 			else if (i > 1) {
239a604d238Scf 				(void) printf(" groups=");
240a604d238Scf 				for (idp = groupids; i--; idp++) {
241a604d238Scf 					if (*idp == egid)
242a604d238Scf 						continue;
243*f48205beScasper 					(void) printf("%u", *idp);
244a604d238Scf 					if (gr = getgrgid(*idp))
245a604d238Scf 						(void) printf("(%s)",
246a604d238Scf 							gr->gr_name);
247a604d238Scf 					if (i)
248a604d238Scf 						(void) putchar(',');
249a604d238Scf 				}
2507c478bd9Sstevel@tonic-gate 			}
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate #endif
2537c478bd9Sstevel@tonic-gate 		if (project_flag) {
2547c478bd9Sstevel@tonic-gate 			struct project proj;
2557c478bd9Sstevel@tonic-gate 			void *projbuf;
2567c478bd9Sstevel@tonic-gate 			projid_t curprojid = getprojid();
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 			if ((projbuf = malloc(PROJECT_BUFSZ)) == NULL) {
2597c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, "unable to allocate "
2607c478bd9Sstevel@tonic-gate 				    "memory\n");
2617c478bd9Sstevel@tonic-gate 				return (2);
2627c478bd9Sstevel@tonic-gate 			}
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 			if (user) {
2657c478bd9Sstevel@tonic-gate 				if (getdefaultproj(user, &proj, projbuf,
2667c478bd9Sstevel@tonic-gate 				    PROJECT_BUFSZ) != NULL)
2677c478bd9Sstevel@tonic-gate 					(void) printf(" projid=%d(%s)",
2687c478bd9Sstevel@tonic-gate 					    (int)proj.pj_projid, proj.pj_name);
2697c478bd9Sstevel@tonic-gate 				else
2707c478bd9Sstevel@tonic-gate 					/*
2717c478bd9Sstevel@tonic-gate 					 * This can only happen if project
2727c478bd9Sstevel@tonic-gate 					 * "default" has been removed from
2737c478bd9Sstevel@tonic-gate 					 * /etc/project file or the whole
2747c478bd9Sstevel@tonic-gate 					 * project database file was removed.
2757c478bd9Sstevel@tonic-gate 					 */
2767c478bd9Sstevel@tonic-gate 					(void) printf(" projid=(NONE)");
2777c478bd9Sstevel@tonic-gate 			} else {
2787c478bd9Sstevel@tonic-gate 				if (getprojbyid(curprojid, &proj, projbuf,
2797c478bd9Sstevel@tonic-gate 				    PROJECT_BUFSZ) == NULL)
2807c478bd9Sstevel@tonic-gate 					(void) printf(" projid=%d",
2817c478bd9Sstevel@tonic-gate 					    (int)curprojid);
2827c478bd9Sstevel@tonic-gate 				else
2837c478bd9Sstevel@tonic-gate 					(void) printf(" projid=%d(%s)",
2847c478bd9Sstevel@tonic-gate 					    (int)curprojid, proj.pj_name);
2857c478bd9Sstevel@tonic-gate 			}
2867c478bd9Sstevel@tonic-gate 			free(projbuf);
2877c478bd9Sstevel@tonic-gate 		}
2887c478bd9Sstevel@tonic-gate 		(void) putchar('\n');
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 	return (0);
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate static int
usage()2947c478bd9Sstevel@tonic-gate usage()
2957c478bd9Sstevel@tonic-gate {
2967c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
297a604d238Scf 	    "Usage: id [-ap] [user]\n"
2987c478bd9Sstevel@tonic-gate 	    "       id -G [-n] [user]\n"
2997c478bd9Sstevel@tonic-gate 	    "       id -g [-nr] [user]\n"
3007c478bd9Sstevel@tonic-gate 	    "       id -u [-nr] [user]\n"));
3017c478bd9Sstevel@tonic-gate 	return (2);
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate static void
puid(uid_t uid)3057c478bd9Sstevel@tonic-gate puid(uid_t uid)
3067c478bd9Sstevel@tonic-gate {
3077c478bd9Sstevel@tonic-gate 	struct passwd *pw;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	if (nflag && (pw = getpwuid(uid)) != PWNULL)
3107c478bd9Sstevel@tonic-gate 		(void) printf("%s", pw->pw_name);
3117c478bd9Sstevel@tonic-gate 	else
312*f48205beScasper 		(void) printf("%u", uid);
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate static void
pgid(gid_t gid)3167c478bd9Sstevel@tonic-gate pgid(gid_t gid)
3177c478bd9Sstevel@tonic-gate {
3187c478bd9Sstevel@tonic-gate 	struct group *gr;
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	if (nflag && (gr = getgrgid(gid)) != GRNULL)
3217c478bd9Sstevel@tonic-gate 		(void) printf("%s", gr->gr_name);
3227c478bd9Sstevel@tonic-gate 	else
323*f48205beScasper 		(void) printf("%u", gid);
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate static void
prid(TYPE how,uid_t id)3277c478bd9Sstevel@tonic-gate prid(TYPE how, uid_t id)
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate 	char *s;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	switch ((int)how) {
3327c478bd9Sstevel@tonic-gate 		case UID:
3337c478bd9Sstevel@tonic-gate 			s = "uid";
3347c478bd9Sstevel@tonic-gate 			break;
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 		case EUID:
3377c478bd9Sstevel@tonic-gate 			s = " euid";
3387c478bd9Sstevel@tonic-gate 			break;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 		case GID:
3417c478bd9Sstevel@tonic-gate 			s = " gid";
3427c478bd9Sstevel@tonic-gate 			break;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 		case EGID:
3457c478bd9Sstevel@tonic-gate 			s = " egid";
3467c478bd9Sstevel@tonic-gate 			break;
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate 	if (s != NULL)
3507c478bd9Sstevel@tonic-gate 		(void) printf("%s=", s);
351*f48205beScasper 	(void) printf("%u", id);
3527c478bd9Sstevel@tonic-gate 	switch ((int)how) {
3537c478bd9Sstevel@tonic-gate 	case UID:
3547c478bd9Sstevel@tonic-gate 	case EUID:
3557c478bd9Sstevel@tonic-gate 		{
3567c478bd9Sstevel@tonic-gate 			struct passwd *pwp;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 			if ((pwp = getpwuid(id)) != PWNULL)
3597c478bd9Sstevel@tonic-gate 				(void) printf("(%s)", pwp->pw_name);
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 		}
3627c478bd9Sstevel@tonic-gate 		break;
3637c478bd9Sstevel@tonic-gate 	case GID:
3647c478bd9Sstevel@tonic-gate 	case EGID:
3657c478bd9Sstevel@tonic-gate 		{
3667c478bd9Sstevel@tonic-gate 			struct group *grp;
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 			if ((grp = getgrgid(id)) != GRNULL)
3697c478bd9Sstevel@tonic-gate 				(void) printf("(%s)", grp->gr_name);
3707c478bd9Sstevel@tonic-gate 		}
3717c478bd9Sstevel@tonic-gate 		break;
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /*
3767c478bd9Sstevel@tonic-gate  * Get the supplementary group affiliation for the user
3777c478bd9Sstevel@tonic-gate  */
getusergroups(gidsetsize,grouplist,user,prgid)3787c478bd9Sstevel@tonic-gate static int getusergroups(gidsetsize, grouplist, user, prgid)
3797c478bd9Sstevel@tonic-gate int	gidsetsize;
3807c478bd9Sstevel@tonic-gate gid_t	*grouplist;
3817c478bd9Sstevel@tonic-gate char	*user;
3827c478bd9Sstevel@tonic-gate gid_t	prgid;
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate 	struct group *group;
3857c478bd9Sstevel@tonic-gate 	char **gr_mem;
3867c478bd9Sstevel@tonic-gate 	int ngroups = 0;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	setgrent();
3897c478bd9Sstevel@tonic-gate 	while ((ngroups < gidsetsize) && ((group = getgrent()) != NULL))
3907c478bd9Sstevel@tonic-gate 		for (gr_mem = group->gr_mem; *gr_mem; gr_mem++)
3917c478bd9Sstevel@tonic-gate 			if (strcmp(user, *gr_mem) == 0) {
3927c478bd9Sstevel@tonic-gate 				if (gidsetsize)
3937c478bd9Sstevel@tonic-gate 					grouplist[ngroups] = group->gr_gid;
3947c478bd9Sstevel@tonic-gate 				ngroups++;
3957c478bd9Sstevel@tonic-gate 			}
3967c478bd9Sstevel@tonic-gate 	endgrent();
3977c478bd9Sstevel@tonic-gate 	if (gidsetsize && !ngroups)
3987c478bd9Sstevel@tonic-gate 		grouplist[ngroups++] = prgid;
3997c478bd9Sstevel@tonic-gate 	return (ngroups);
4007c478bd9Sstevel@tonic-gate }
401