xref: /illumos-gate/usr/src/cmd/id/id.c (revision 4de2612967d06c4fdbf524a62556a1e8118a006f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
30 /*	  All Rights Reserved  	*/
31 
32 
33 #include <locale.h>
34 #include <stdio.h>
35 #include <pwd.h>
36 #include <grp.h>
37 #include <sys/param.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <project.h>
41 #include <stdlib.h>
42 
43 #define	PWNULL  ((struct passwd *)0)
44 #define	GRNULL  ((struct group *)0)
45 
46 typedef enum TYPE {
47 	UID, EUID, GID, EGID, SGID
48 }	TYPE;
49 
50 typedef enum PRINT {
51 	CURR,		/* Print uid/gid only */
52 	ALLGROUPS,	/* Print all groups */
53 	GROUP,		/* Print only group */
54 	USER		/* Print only uid */
55 }	PRINT;
56 static PRINT mode = CURR;
57 
58 static int usage(void);
59 static void puid(uid_t);
60 static void pgid(gid_t);
61 static void prid(TYPE, uid_t);
62 static int getusergroups(int, gid_t *, char *, gid_t);
63 
64 static int nflag = 0;		/* Output names, not numbers */
65 static int rflag = 0;		/* Output real, not effective IDs */
66 static char stdbuf[BUFSIZ];
67 
68 int
69 main(int argc, char *argv[])
70 {
71 	gid_t *idp;
72 	uid_t uid, euid;
73 	gid_t gid, egid, prgid;
74 	int c, aflag = 0, project_flag = 0;
75 	struct passwd *pwp;
76 	int i, j;
77 	gid_t groupids[NGROUPS_UMAX];
78 	struct group *gr;
79 	char *user = NULL;
80 
81 	(void) setlocale(LC_ALL, "");
82 
83 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
84 #define	TEXT_DOMAIN "SYS_TEST"
85 #endif
86 	(void) textdomain(TEXT_DOMAIN);
87 #ifdef XPG4
88 	while ((c = getopt(argc, argv, "Ggunrp")) != EOF) {
89 #else
90 	while ((c = getopt(argc, argv, "ap")) != EOF) {
91 #endif
92 		switch (c) {
93 			case 'G':
94 				if (mode != CURR)
95 					return (usage());
96 				mode = ALLGROUPS;
97 				break;
98 
99 			case 'g':
100 				if (mode != CURR)
101 					return (usage());
102 				mode = GROUP;
103 				break;
104 
105 #ifndef XPG4
106 			case 'a':
107 				aflag++;
108 				break;
109 #endif
110 
111 			case 'n':
112 				nflag++;
113 				break;
114 
115 			case 'r':
116 				rflag++;
117 				break;
118 
119 			case 'u':
120 				if (mode != CURR)
121 					return (usage());
122 				mode = USER;
123 				break;
124 
125 			case 'p':
126 				if (mode != CURR)
127 					return (usage());
128 				project_flag++;
129 				break;
130 
131 			case '?':
132 				return (usage());
133 		}
134 	}
135 	setbuf(stdout, stdbuf);
136 	argc -= optind-1;
137 	argv += optind-1;
138 
139 	/* -n and -r must be combined with one of -[Ggu] */
140 	/* -r cannot be combined with -G */
141 
142 	if ((mode == CURR && (nflag || rflag)) ||
143 		(mode == ALLGROUPS && rflag) ||
144 		(argc != 1 && argc != 2))
145 		return (usage());
146 	if (argc == 2) {
147 		if ((pwp = getpwnam(argv[1])) == PWNULL) {
148 			(void) fprintf(stderr,
149 				gettext("id: invalid user name: \"%s\"\n"),
150 					argv[1]);
151 			return (1);
152 		}
153 		user = argv[1];
154 		uid = euid = pwp->pw_uid;
155 		prgid = gid = egid = pwp->pw_gid;
156 	} else {
157 		uid = getuid();
158 		gid = getgid();
159 		euid = geteuid();
160 		egid = getegid();
161 	}
162 
163 	if (mode != CURR) {
164 		if (!rflag) {
165 			uid = euid;
166 			gid = egid;
167 		}
168 		if (mode == USER)
169 			puid(uid);
170 		else if (mode == GROUP)
171 			pgid(gid);
172 		else if (mode == ALLGROUPS) {
173 			pgid(gid);
174 			if (user)
175 				i = getusergroups(NGROUPS_UMAX, groupids, user,
176 				    prgid);
177 			else
178 				i = getgroups(NGROUPS_UMAX, groupids);
179 			if (i == -1)
180 				perror("getgroups");
181 			else if (i > 0) {
182 				for (j = 0; j < i; ++j) {
183 					if ((gid = groupids[j]) == egid)
184 						continue;
185 					(void) putchar(' ');
186 					pgid(gid);
187 				}
188 			}
189 		}
190 		(void) putchar('\n');
191 	} else {
192 		prid(UID, uid);
193 		prid(GID, gid);
194 		if (uid != euid)
195 			prid(EUID, euid);
196 		if (gid != egid)
197 			prid(EGID, egid);
198 #ifndef XPG4
199 		if (aflag) {
200 			if (user)
201 				i = getusergroups(NGROUPS_UMAX, groupids, user,
202 				    prgid);
203 			else
204 				i = getgroups(NGROUPS_UMAX, groupids);
205 			if (i == -1)
206 				perror("getgroups");
207 			else if (i > 0) {
208 				(void) printf(" groups=");
209 				for (idp = groupids; i--; idp++) {
210 					(void) printf("%d", (int)*idp);
211 					if (gr = getgrgid(*idp))
212 						(void) printf("(%s)",
213 							gr->gr_name);
214 					if (i)
215 						(void) putchar(',');
216 				}
217 			}
218 		}
219 #else
220 		if (user)
221 			i = getusergroups(NGROUPS_UMAX, groupids, user, prgid);
222 		else
223 			i = getgroups(NGROUPS_UMAX, groupids);
224 		if (i == -1)
225 			perror("getgroups");
226 		else if (i > 1) {
227 			(void) printf(" groups=");
228 			for (idp = groupids; i--; idp++) {
229 				if (*idp == egid)
230 					continue;
231 				(void) printf("%d", (int)*idp);
232 				if (gr = getgrgid(*idp))
233 					(void) printf("(%s)", gr->gr_name);
234 				if (i)
235 					(void) putchar(',');
236 			}
237 		}
238 #endif
239 		if (project_flag) {
240 			struct project proj;
241 			void *projbuf;
242 			projid_t curprojid = getprojid();
243 
244 			if ((projbuf = malloc(PROJECT_BUFSZ)) == NULL) {
245 				(void) fprintf(stderr, "unable to allocate "
246 				    "memory\n");
247 				return (2);
248 			}
249 
250 			if (user) {
251 				if (getdefaultproj(user, &proj, projbuf,
252 				    PROJECT_BUFSZ) != NULL)
253 					(void) printf(" projid=%d(%s)",
254 					    (int)proj.pj_projid, proj.pj_name);
255 				else
256 					/*
257 					 * This can only happen if project
258 					 * "default" has been removed from
259 					 * /etc/project file or the whole
260 					 * project database file was removed.
261 					 */
262 					(void) printf(" projid=(NONE)");
263 			} else {
264 				if (getprojbyid(curprojid, &proj, projbuf,
265 				    PROJECT_BUFSZ) == NULL)
266 					(void) printf(" projid=%d",
267 					    (int)curprojid);
268 				else
269 					(void) printf(" projid=%d(%s)",
270 					    (int)curprojid, proj.pj_name);
271 			}
272 			free(projbuf);
273 		}
274 		(void) putchar('\n');
275 	}
276 	return (0);
277 }
278 
279 static int
280 usage()
281 {
282 #ifdef XPG4
283 	(void) fprintf(stderr, gettext(
284 	    "Usage: id [-p] [user]\n"
285 	    "       id -G [-n] [user]\n"
286 	    "       id -g [-nr] [user]\n"
287 	    "       id -u [-nr] [user]\n"));
288 #else
289 	(void) fprintf(stderr, gettext("Usage: id [-ap] [user]\n"));
290 #endif
291 	return (2);
292 }
293 
294 static void
295 puid(uid_t uid)
296 {
297 	struct passwd *pw;
298 
299 	if (nflag && (pw = getpwuid(uid)) != PWNULL)
300 		(void) printf("%s", pw->pw_name);
301 	else
302 		(void) printf("%u", (int)uid);
303 }
304 
305 static void
306 pgid(gid_t gid)
307 {
308 	struct group *gr;
309 
310 	if (nflag && (gr = getgrgid(gid)) != GRNULL)
311 		(void) printf("%s", gr->gr_name);
312 	else
313 		(void) printf("%u", (int)gid);
314 }
315 
316 static void
317 prid(TYPE how, uid_t id)
318 {
319 	char *s;
320 
321 	switch ((int)how) {
322 		case UID:
323 			s = "uid";
324 			break;
325 
326 		case EUID:
327 			s = " euid";
328 			break;
329 
330 		case GID:
331 			s = " gid";
332 			break;
333 
334 		case EGID:
335 			s = " egid";
336 			break;
337 
338 	}
339 	if (s != NULL)
340 		(void) printf("%s=", s);
341 	(void) printf("%u", (int)id);
342 	switch ((int)how) {
343 	case UID:
344 	case EUID:
345 		{
346 			struct passwd *pwp;
347 
348 			if ((pwp = getpwuid(id)) != PWNULL)
349 				(void) printf("(%s)", pwp->pw_name);
350 
351 		}
352 		break;
353 	case GID:
354 	case EGID:
355 		{
356 			struct group *grp;
357 
358 			if ((grp = getgrgid(id)) != GRNULL)
359 				(void) printf("(%s)", grp->gr_name);
360 		}
361 		break;
362 	}
363 }
364 
365 /*
366  * Get the supplementary group affiliation for the user
367  */
368 static int getusergroups(gidsetsize, grouplist, user, prgid)
369 int	gidsetsize;
370 gid_t	*grouplist;
371 char	*user;
372 gid_t	prgid;
373 {
374 	struct group *group;
375 	char **gr_mem;
376 	int ngroups = 0;
377 
378 	setgrent();
379 	while ((ngroups < gidsetsize) && ((group = getgrent()) != NULL))
380 		for (gr_mem = group->gr_mem; *gr_mem; gr_mem++)
381 			if (strcmp(user, *gr_mem) == 0) {
382 				if (gidsetsize)
383 					grouplist[ngroups] = group->gr_gid;
384 				ngroups++;
385 			}
386 	endgrent();
387 	if (gidsetsize && !ngroups)
388 		grouplist[ngroups++] = prgid;
389 	return (ngroups);
390 }
391