GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/id/id.c Lines: 78 166 47.0 %
Date: 2017-11-13 Branches: 62 144 43.1 %

Line Branch Exec Source
1
/*	$OpenBSD: id.c,v 1.28 2017/05/30 15:29:53 tedu 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 <sys/types.h>
33
#include <sys/socket.h> /* getrtable() lives here */
34
35
#include <err.h>
36
#include <errno.h>
37
#include <grp.h>
38
#include <pwd.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
#include <unistd.h>
43
#include <limits.h>
44
#include <login_cap.h>
45
46
void	current(void);
47
void	pretty(struct passwd *);
48
void	group(struct passwd *, int);
49
void	usage(void);
50
void	user(struct passwd *);
51
struct passwd *
52
	who(char *);
53
54
int
55
main(int argc, char *argv[])
56
{
57
	struct group *gr;
58
	struct passwd *pw;
59
	int ch, cflag, Gflag, gflag, nflag, pflag, Rflag, rflag, uflag;
60
	uid_t uid;
61
	gid_t gid;
62
	const char *opts;
63
64
2750
	if (pledge("stdio getpw flock rpath cpath wpath", NULL) == -1)
65
		err(1, "pledge");
66
67
	cflag = Gflag = gflag = nflag = pflag = Rflag = rflag = uflag = 0;
68
69
1375
	if (strcmp(getprogname(), "groups") == 0) {
70
		Gflag = 1;
71
		nflag = 1;
72
		opts = "";
73
		if (argc > 2)
74
			usage();
75
1375
	} else if (strcmp(getprogname(), "whoami") == 0) {
76
		uflag = 1;
77
		nflag = 1;
78
		opts = "";
79
		if (argc > 1)
80
			usage();
81
	} else
82
		opts = "cGgnpRru";
83
84
5492
	while ((ch = getopt(argc, argv, opts)) != -1)
85


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

1172
		gid = pw ? pw->pw_gid : rflag ? getgid() : getegid();
150

298
		if (nflag && (gr = getgrgid(gid)))
151
5
			(void)printf("%s\n", gr->gr_name);
152
		else
153
288
			(void)printf("%u\n", gid);
154
		exit(0);
155
	}
156
157
1082
	if (uflag) {
158

4248
		uid = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
159

1068
		if (nflag && (pw = getpwuid(uid)))
160
6
			(void)printf("%s\n", pw->pw_name);
161
		else
162
1056
			(void)printf("%u\n", uid);
163
		exit(0);
164
	}
165
166
20
	if (Gflag) {
167
		group(pw, nflag);
168
		exit(0);
169
	}
170
171
20
	if (pflag) {
172
		pretty(pw);
173
		exit(0);
174
	}
175
176
15
	if (pw)
177
		user(pw);
178
	else
179
15
		current();
180
	exit(0);
181
}
182
183
void
184
pretty(struct passwd *pw)
185
{
186
	struct group *gr;
187
	uid_t eid, rid;
188
	char *login;
189
190
10
	if (pw) {
191
		(void)printf("uid\t%s\n", pw->pw_name);
192
		(void)printf("groups\t");
193
		group(pw, 1);
194
	} else {
195
5
		if ((login = getlogin()) == NULL)
196
			err(1, "getlogin");
197
198
5
		pw = getpwuid(rid = getuid());
199

10
		if (pw == NULL || strcmp(login, pw->pw_name))
200
			(void)printf("login\t%s\n", login);
201
5
		if (pw)
202
5
			(void)printf("uid\t%s\n", pw->pw_name);
203
		else
204
			(void)printf("uid\t%u\n", rid);
205
206
5
		if ((eid = geteuid()) != rid) {
207
			if ((pw = getpwuid(eid)))
208
				(void)printf("euid\t%s\n", pw->pw_name);
209
			else
210
				(void)printf("euid\t%u\n", eid);
211
		}
212
5
		if ((rid = getgid()) != (eid = getegid())) {
213
			if ((gr = getgrgid(rid)))
214
				(void)printf("rgid\t%s\n", gr->gr_name);
215
			else
216
				(void)printf("rgid\t%u\n", rid);
217
		}
218
5
		(void)printf("groups\t");
219
5
		group(NULL, 1);
220
	}
221

15
	if (pw != NULL && pw->pw_class != NULL && *pw->pw_class != '\0')
222
5
		(void)printf("class\t%s\n", pw->pw_class);
223
5
}
224
225
void
226
current(void)
227
{
228
	struct group *gr;
229
	struct passwd *pw;
230
	int cnt, ngroups;
231
	uid_t uid, euid;
232
30
	gid_t groups[NGROUPS_MAX], gid, egid, lastgid;
233
	char *prefix;
234
235
15
	uid = getuid();
236
15
	(void)printf("uid=%u", uid);
237
15
	if ((pw = getpwuid(uid)))
238
15
		(void)printf("(%s)", pw->pw_name);
239
15
	if ((euid = geteuid()) != uid) {
240
		(void)printf(" euid=%u", euid);
241
		if ((pw = getpwuid(euid)))
242
			(void)printf("(%s)", pw->pw_name);
243
	}
244
15
	gid = getgid();
245
15
	(void)printf(" gid=%u", gid);
246
15
	if ((gr = getgrgid(gid)))
247
15
		(void)printf("(%s)", gr->gr_name);
248
15
	if ((egid = getegid()) != gid) {
249
		(void)printf(" egid=%u", egid);
250
		if ((gr = getgrgid(egid)))
251
			(void)printf("(%s)", gr->gr_name);
252
	}
253
15
	if ((ngroups = getgroups(NGROUPS_MAX, groups))) {
254
240
		for (prefix = " groups=", lastgid = (gid_t)-1, cnt = 0;
255
120
		    cnt < ngroups; prefix = ", ", lastgid = gid) {
256
105
			gid = groups[cnt++];
257
105
			if (lastgid == gid)
258
				continue;
259
105
			(void)printf("%s%u", prefix, gid);
260
105
			if ((gr = getgrgid(gid)))
261
105
				(void)printf("(%s)", gr->gr_name);
262
		}
263
	}
264
15
	(void)printf("\n");
265
15
}
266
267
void
268
user(struct passwd *pw)
269
{
270
	gid_t gid, groups[NGROUPS_MAX + 1];
271
	int cnt, ngroups;
272
	uid_t uid;
273
	struct group *gr;
274
	char *prefix;
275
276
	uid = pw->pw_uid;
277
	(void)printf("uid=%u(%s)", uid, pw->pw_name);
278
	(void)printf(" gid=%u", pw->pw_gid);
279
	if ((gr = getgrgid(pw->pw_gid)))
280
		(void)printf("(%s)", gr->gr_name);
281
	ngroups = NGROUPS_MAX + 1;
282
	(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
283
	prefix = " groups=";
284
	for (cnt = 0; cnt < ngroups;) {
285
		gid = groups[cnt];
286
		(void)printf("%s%u", prefix, gid);
287
		prefix = ", ";
288
		if ((gr = getgrgid(gid)))
289
			(void)printf("(%s)", gr->gr_name);
290
		/* Skip same gid entries. */
291
		while (++cnt < ngroups && gid == groups[cnt])
292
			;
293
	}
294
	(void)printf("\n");
295
}
296
297
void
298
group(struct passwd *pw, int nflag)
299
{
300
10
	int cnt, ngroups;
301
5
	gid_t gid, groups[NGROUPS_MAX + 1];
302
	struct group *gr;
303
	char *prefix;
304
305
5
	if (pw) {
306
		ngroups = NGROUPS_MAX + 1;
307
		(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
308
	} else {
309
5
		groups[0] = getgid();
310
5
		ngroups = getgroups(NGROUPS_MAX, groups + 1) + 1;
311
	}
312
	prefix = "";
313
80
	for (cnt = 0; cnt < ngroups;) {
314
35
		gid = groups[cnt];
315
35
		if (nflag) {
316
35
			if ((gr = getgrgid(gid)))
317
35
				(void)printf("%s%s", prefix, gr->gr_name);
318
			else
319
				(void)printf("%s%u", prefix, gid);
320
		} else {
321
			(void)printf("%s%u", prefix, gid);
322
		}
323
		prefix = " ";
324
		/* Skip same gid entries. */
325

115
		while (++cnt < ngroups && gid == groups[cnt])
326
			;
327
	}
328
5
	(void)printf("\n");
329
5
}
330
331
struct passwd *
332
who(char *u)
333
{
334
	struct passwd *pw;
335
	uid_t uid;
336
	const char *errstr;
337
338
	/*
339
	 * Translate user argument into a pw pointer.  First, try to
340
	 * get it as specified.  If that fails, try it as a number.
341
	 */
342
	if ((pw = getpwnam(u)))
343
		return(pw);
344
	uid = strtonum(u, 0, UID_MAX, &errstr);
345
	if (!errstr && (pw = getpwuid(uid)))
346
		return(pw);
347
	errx(1, "%s: No such user", u);
348
	/* NOTREACHED */
349
}
350
351
void
352
usage(void)
353
{
354
	if (strcmp(getprogname(), "groups") == 0) {
355
		(void)fprintf(stderr, "usage: groups [user]\n");
356
	} else if (strcmp(getprogname(), "whoami") == 0) {
357
		(void)fprintf(stderr, "usage: whoami\n");
358
	} else {
359
		(void)fprintf(stderr, "usage: id [user]\n");
360
		(void)fprintf(stderr, "       id -c [user]\n");
361
		(void)fprintf(stderr, "       id -G [-n] [user]\n");
362
		(void)fprintf(stderr, "       id -g [-nr] [user]\n");
363
		(void)fprintf(stderr, "       id -p [user]\n");
364
		(void)fprintf(stderr, "       id -R\n");
365
		(void)fprintf(stderr, "       id -u [-nr] [user]\n");
366
	}
367
	exit(1);
368
}