GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/id/id.c Lines: 31 171 18.1 %
Date: 2016-12-06 Branches: 24 141 17.0 %

Line Branch Exec Source
1
/*	$OpenBSD: id.c,v 1.26 2015/10/09 01:37:07 deraadt Exp $	*/
2
3
/*-
4
 * Copyright (c) 1991, 1993
5
 *	The Regents of the University of California.  All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 * 3. Neither the name of the University nor the names of its contributors
16
 *    may be used to endorse or promote products derived from this software
17
 *    without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 */
31
32
#include <err.h>
33
#include <errno.h>
34
#include <grp.h>
35
#include <pwd.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40
#include <limits.h>
41
#include <login_cap.h>
42
43
void	current(void);
44
void	pretty(struct passwd *);
45
void	group(struct passwd *, int);
46
void	usage(void);
47
void	user(struct passwd *);
48
struct passwd *
49
	who(char *);
50
51
int
52
main(int argc, char *argv[])
53
135
{
54
	struct group *gr;
55
	struct passwd *pw;
56
	int ch, cflag, Gflag, gflag, nflag, pflag, rflag, uflag;
57
	uid_t uid;
58
	gid_t gid;
59
	const char *opts;
60
61
135
	if (pledge("stdio getpw wpath cpath rpath", NULL) == -1)
62
		err(1, "pledge");
63
64
135
	cflag = Gflag = gflag = nflag = pflag = rflag = uflag = 0;
65
66
135
	if (strcmp(getprogname(), "groups") == 0) {
67
		Gflag = 1;
68
		nflag = 1;
69
		opts = "";
70
		if (argc > 2)
71
			usage();
72
135
	} else if (strcmp(getprogname(), "whoami") == 0) {
73
		uflag = 1;
74
		nflag = 1;
75
		opts = "";
76
		if (argc > 1)
77
			usage();
78
	} else
79
135
		opts = "cGgnpru";
80
81
273
	while ((ch = getopt(argc, argv, opts)) != -1)
82


138
		switch(ch) {
83
		case 'c':
84
			cflag = 1;
85
			break;
86
		case 'G':
87
			Gflag = 1;
88
			break;
89
		case 'g':
90
1
			gflag = 1;
91
1
			break;
92
		case 'n':
93
3
			nflag = 1;
94
3
			break;
95
		case 'p':
96
			pflag = 1;
97
			break;
98
		case 'r':
99
			rflag = 1;
100
			break;
101
		case 'u':
102
134
			uflag = 1;
103
134
			break;
104
		case '?':
105
		default:
106
			usage();
107
		}
108
135
	argc -= optind;
109
135
	argv += optind;
110
111
135
	switch (cflag + Gflag + gflag + pflag + uflag) {
112
	case 1:
113
		break;
114
	case 0:
115
		if (!nflag && !rflag)
116
			break;
117
		/* FALLTHROUGH */
118
	default:
119
		usage();
120
	}
121
122
135
	if (strcmp(opts, "") != 0 && argc > 1)
123
		usage();
124
125
135
	pw = *argv ? who(*argv) : NULL;
126
127
135
	if (cflag) {
128
		if (pw == NULL)
129
			pw = getpwuid(getuid());
130
		if (pw != NULL && pw->pw_class != NULL && *pw->pw_class != '\0')
131
			(void)printf("%s\n", pw->pw_class);
132
		else
133
			(void)printf("%s\n", LOGIN_DEFCLASS);
134
		exit(0);
135
	}
136
137
135
	if (gflag) {
138

1
		gid = pw ? pw->pw_gid : rflag ? getgid() : getegid();
139

2
		if (nflag && (gr = getgrgid(gid)))
140
1
			(void)printf("%s\n", gr->gr_name);
141
		else
142
			(void)printf("%u\n", gid);
143
1
		exit(0);
144
	}
145
146
134
	if (uflag) {
147

134
		uid = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
148

136
		if (nflag && (pw = getpwuid(uid)))
149
2
			(void)printf("%s\n", pw->pw_name);
150
		else
151
132
			(void)printf("%u\n", uid);
152
134
		exit(0);
153
	}
154
155
	if (Gflag) {
156
		group(pw, nflag);
157
		exit(0);
158
	}
159
160
	if (pflag) {
161
		pretty(pw);
162
		exit(0);
163
	}
164
165
	if (pw)
166
		user(pw);
167
	else
168
		current();
169
	exit(0);
170
}
171
172
void
173
pretty(struct passwd *pw)
174
{
175
	struct group *gr;
176
	uid_t eid, rid;
177
	char *login;
178
179
	if (pw) {
180
		(void)printf("uid\t%s\n", pw->pw_name);
181
		(void)printf("groups\t");
182
		group(pw, 1);
183
	} else {
184
		if ((login = getlogin()) == NULL)
185
			err(1, "getlogin");
186
187
		pw = getpwuid(rid = getuid());
188
		if (pw == NULL || strcmp(login, pw->pw_name))
189
			(void)printf("login\t%s\n", login);
190
		if (pw)
191
			(void)printf("uid\t%s\n", pw->pw_name);
192
		else
193
			(void)printf("uid\t%u\n", rid);
194
195
		if ((eid = geteuid()) != rid) {
196
			if ((pw = getpwuid(eid)))
197
				(void)printf("euid\t%s\n", pw->pw_name);
198
			else
199
				(void)printf("euid\t%u\n", eid);
200
		}
201
		if ((rid = getgid()) != (eid = getegid())) {
202
			if ((gr = getgrgid(rid)))
203
				(void)printf("rgid\t%s\n", gr->gr_name);
204
			else
205
				(void)printf("rgid\t%u\n", rid);
206
		}
207
		(void)printf("groups\t");
208
		group(NULL, 1);
209
	}
210
	if (pw != NULL && pw->pw_class != NULL && *pw->pw_class != '\0')
211
		(void)printf("class\t%s\n", pw->pw_class);
212
}
213
214
void
215
current(void)
216
{
217
	struct group *gr;
218
	struct passwd *pw;
219
	int cnt, ngroups;
220
	uid_t uid, euid;
221
	gid_t groups[NGROUPS_MAX], gid, egid, lastgid;
222
	char *prefix;
223
224
	uid = getuid();
225
	(void)printf("uid=%u", uid);
226
	if ((pw = getpwuid(uid)))
227
		(void)printf("(%s)", pw->pw_name);
228
	if ((euid = geteuid()) != uid) {
229
		(void)printf(" euid=%u", euid);
230
		if ((pw = getpwuid(euid)))
231
			(void)printf("(%s)", pw->pw_name);
232
	}
233
	gid = getgid();
234
	(void)printf(" gid=%u", gid);
235
	if ((gr = getgrgid(gid)))
236
		(void)printf("(%s)", gr->gr_name);
237
	if ((egid = getegid()) != gid) {
238
		(void)printf(" egid=%u", egid);
239
		if ((gr = getgrgid(egid)))
240
			(void)printf("(%s)", gr->gr_name);
241
	}
242
	if ((ngroups = getgroups(NGROUPS_MAX, groups))) {
243
		for (prefix = " groups=", lastgid = (gid_t)-1, cnt = 0;
244
		    cnt < ngroups; prefix = ", ", lastgid = gid) {
245
			gid = groups[cnt++];
246
			if (lastgid == gid)
247
				continue;
248
			(void)printf("%s%u", prefix, gid);
249
			if ((gr = getgrgid(gid)))
250
				(void)printf("(%s)", gr->gr_name);
251
		}
252
	}
253
	(void)printf("\n");
254
}
255
256
void
257
user(struct passwd *pw)
258
{
259
	gid_t gid, groups[NGROUPS_MAX + 1];
260
	int cnt, ngroups;
261
	uid_t uid;
262
	struct group *gr;
263
	char *prefix;
264
265
	uid = pw->pw_uid;
266
	(void)printf("uid=%u(%s)", uid, pw->pw_name);
267
	(void)printf(" gid=%u", pw->pw_gid);
268
	if ((gr = getgrgid(pw->pw_gid)))
269
		(void)printf("(%s)", gr->gr_name);
270
	ngroups = NGROUPS_MAX + 1;
271
	(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
272
	prefix = " groups=";
273
	for (cnt = 0; cnt < ngroups;) {
274
		gid = groups[cnt];
275
		(void)printf("%s%u", prefix, gid);
276
		prefix = ", ";
277
		if ((gr = getgrgid(gid)))
278
			(void)printf("(%s)", gr->gr_name);
279
		/* Skip same gid entries. */
280
		while (++cnt < ngroups && gid == groups[cnt])
281
			;
282
	}
283
	(void)printf("\n");
284
}
285
286
void
287
group(struct passwd *pw, int nflag)
288
{
289
	int cnt, ngroups;
290
	gid_t gid, groups[NGROUPS_MAX + 1];
291
	struct group *gr;
292
	char *prefix;
293
294
	if (pw) {
295
		ngroups = NGROUPS_MAX + 1;
296
		(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
297
	} else {
298
		groups[0] = getgid();
299
		ngroups = getgroups(NGROUPS_MAX, groups + 1) + 1;
300
	}
301
	prefix = "";
302
	for (cnt = 0; cnt < ngroups;) {
303
		gid = groups[cnt];
304
		if (nflag) {
305
			if ((gr = getgrgid(gid)))
306
				(void)printf("%s%s", prefix, gr->gr_name);
307
			else
308
				(void)printf("%s%u", prefix, gid);
309
		} else {
310
			(void)printf("%s%u", prefix, gid);
311
		}
312
		prefix = " ";
313
		/* Skip same gid entries. */
314
		while (++cnt < ngroups && gid == groups[cnt])
315
			;
316
	}
317
	(void)printf("\n");
318
}
319
320
struct passwd *
321
who(char *u)
322
{
323
	struct passwd *pw;
324
	uid_t uid;
325
	const char *errstr;
326
327
	/*
328
	 * Translate user argument into a pw pointer.  First, try to
329
	 * get it as specified.  If that fails, try it as a number.
330
	 */
331
	if ((pw = getpwnam(u)))
332
		return(pw);
333
	uid = strtonum(u, 0, UID_MAX, &errstr);
334
	if (!errstr && (pw = getpwuid(uid)))
335
		return(pw);
336
	errx(1, "%s: No such user", u);
337
	/* NOTREACHED */
338
}
339
340
void
341
usage(void)
342
{
343
	if (strcmp(getprogname(), "groups") == 0) {
344
		(void)fprintf(stderr, "usage: groups [user]\n");
345
	} else if (strcmp(getprogname(), "whoami") == 0) {
346
		(void)fprintf(stderr, "usage: whoami\n");
347
	} else {
348
		(void)fprintf(stderr, "usage: id [user]\n");
349
		(void)fprintf(stderr, "       id -c [user]\n");
350
		(void)fprintf(stderr, "       id -G [-n] [user]\n");
351
		(void)fprintf(stderr, "       id -g [-nr] [user]\n");
352
		(void)fprintf(stderr, "       id -p [user]\n");
353
		(void)fprintf(stderr, "       id -u [-nr] [user]\n");
354
	}
355
	exit(1);
356
}