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