GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/who/who.c Lines: 0 130 0.0 %
Date: 2017-11-07 Branches: 0 104 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: who.c,v 1.27 2015/10/21 16:06:57 millert Exp $	*/
2
/*	$NetBSD: who.c,v 1.4 1994/12/07 04:28:49 jtc Exp $	*/
3
4
/*
5
 * Copyright (c) 1989, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * This code is derived from software contributed to Berkeley by
9
 * Michael Fischbein.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the University nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 */
35
36
#include <sys/types.h>
37
#include <sys/stat.h>
38
#include <paths.h>
39
#include <pwd.h>
40
#include <utmp.h>
41
#include <stdio.h>
42
#include <string.h>
43
#include <stdlib.h>
44
#include <unistd.h>
45
#include <time.h>
46
#include <err.h>
47
#include <locale.h>
48
49
void  output(struct utmp *);
50
void  output_labels(void);
51
void  who_am_i(FILE *);
52
void  usage(void);
53
FILE *file(char *);
54
55
int only_current_term;		/* show info about the current terminal only */
56
int show_term;			/* show term state */
57
int show_idle;			/* show idle time */
58
int show_labels;		/* show column labels */
59
int show_quick;			/* quick, names only */
60
61
#define NAME_WIDTH	8
62
#define HOST_WIDTH	45
63
64
int hostwidth = HOST_WIDTH;
65
char *mytty;
66
67
int
68
main(int argc, char *argv[])
69
{
70
	struct utmp usr;
71
	FILE *ufp;
72
	char *t;
73
	int c;
74
75
	setlocale(LC_ALL, "");
76
77
	if (pledge("stdio rpath getpw flock cpath wpath", NULL) == -1)
78
		err(1, "pledge");
79
80
	if ((mytty = ttyname(0))) {
81
		/* strip any directory component */
82
		if ((t = strrchr(mytty, '/')))
83
			mytty = t + 1;
84
	}
85
86
	only_current_term = show_term = show_idle = show_labels = 0;
87
	show_quick = 0;
88
	while ((c = getopt(argc, argv, "HmqTu")) != -1) {
89
		switch (c) {
90
		case 'H':
91
			show_labels = 1;
92
			break;
93
		case 'm':
94
			only_current_term = 1;
95
			break;
96
		case 'q':
97
			show_quick = 1;
98
			break;
99
		case 'T':
100
			show_term = 1;
101
			break;
102
		case 'u':
103
			show_idle = 1;
104
			break;
105
		default:
106
			usage();
107
			/* NOTREACHED */
108
		}
109
	}
110
	argc -= optind;
111
	argv += optind;
112
113
	if (show_quick) {
114
		only_current_term = show_term = show_idle = show_labels = 0;
115
	}
116
117
	if (show_term)
118
		hostwidth -= 2;
119
	if (show_idle)
120
		hostwidth -= 6;
121
122
	if (show_labels)
123
		output_labels();
124
125
	switch (argc) {
126
	case 0:					/* who */
127
		ufp = file(_PATH_UTMP);
128
129
		if (only_current_term) {
130
			who_am_i(ufp);
131
		} else if (show_quick) {
132
			int count = 0;
133
134
			while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1) {
135
				if (*usr.ut_name && *usr.ut_line) {
136
					(void)printf("%-*.*s ", NAME_WIDTH,
137
						UT_NAMESIZE, usr.ut_name);
138
					if ((++count % 8) == 0)
139
						(void) printf("\n");
140
				}
141
			}
142
			if (count % 8)
143
				(void) printf("\n");
144
			(void) printf ("# users=%d\n", count);
145
		} else {
146
			/* only entries with both name and line fields */
147
			while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
148
				if (*usr.ut_name && *usr.ut_line)
149
					output(&usr);
150
		}
151
		break;
152
	case 1:					/* who utmp_file */
153
		ufp = file(*argv);
154
155
		if (only_current_term) {
156
			who_am_i(ufp);
157
		} else if (show_quick) {
158
			int count = 0;
159
160
			while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1) {
161
				if (*usr.ut_name && *usr.ut_line) {
162
					(void)printf("%-*.*s ", NAME_WIDTH,
163
						UT_NAMESIZE, usr.ut_name);
164
					if ((++count % 8) == 0)
165
						(void) printf("\n");
166
				}
167
			}
168
			if (count % 8)
169
				(void) printf("\n");
170
			(void) printf ("# users=%d\n", count);
171
		} else {
172
			/* all entries */
173
			while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
174
				output(&usr);
175
		}
176
		break;
177
	case 2:					/* who am i */
178
		ufp = file(_PATH_UTMP);
179
		who_am_i(ufp);
180
		break;
181
	default:
182
		usage();
183
		/* NOTREACHED */
184
	}
185
	exit(0);
186
}
187
188
void
189
who_am_i(FILE *ufp)
190
{
191
	struct utmp usr;
192
	struct passwd *pw;
193
194
	/* search through the utmp and find an entry for this tty */
195
	if (mytty) {
196
		while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
197
			if (*usr.ut_name && !strcmp(usr.ut_line, mytty)) {
198
				output(&usr);
199
				return;
200
			}
201
		/* well, at least we know what the tty is */
202
		(void)strncpy(usr.ut_line, mytty, UT_LINESIZE);
203
	} else
204
		(void)strncpy(usr.ut_line, "tty??", UT_LINESIZE);
205
206
	pw = getpwuid(getuid());
207
	(void)strncpy(usr.ut_name, pw ? pw->pw_name : "?", UT_NAMESIZE);
208
	(void)time(&usr.ut_time);
209
	*usr.ut_host = '\0';
210
	output(&usr);
211
}
212
213
void
214
output(struct utmp *up)
215
{
216
	struct stat sb;
217
	char line[sizeof(_PATH_DEV) + sizeof (up->ut_line)];
218
	char state = '?';
219
	static time_t now = 0;
220
	time_t idle = 0;
221
222
	if (show_term || show_idle) {
223
		if (now == 0)
224
			time(&now);
225
226
		memset(line, 0, sizeof line);
227
		strlcpy(line, _PATH_DEV, sizeof line);
228
		strlcat(line, up->ut_line, sizeof line);
229
230
		if (stat(line, &sb) == 0) {
231
			state = (sb.st_mode & 020) ? '+' : '-';
232
			idle = now - sb.st_atime;
233
		} else {
234
			state = '?';
235
			idle = 0;
236
		}
237
238
	}
239
240
	(void)printf("%-*.*s ", NAME_WIDTH, UT_NAMESIZE, up->ut_name);
241
242
	if (show_term) {
243
		(void)printf("%c ", state);
244
	}
245
246
	(void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, up->ut_line);
247
	(void)printf("%.12s ", ctime(&up->ut_time) + 4);
248
249
	if (show_idle) {
250
		if (idle < 60)
251
			(void)printf("  .   ");
252
		else if (idle < (24 * 60 * 60))
253
			(void)printf("%02d:%02d ",
254
				     ((int)idle / (60 * 60)),
255
				     ((int)idle % (60 * 60)) / 60);
256
		else
257
			(void)printf(" old  ");
258
	}
259
260
	if (*up->ut_host)
261
		printf("  (%.*s)", hostwidth, up->ut_host);
262
	(void)putchar('\n');
263
}
264
265
void
266
output_labels(void)
267
{
268
	(void)printf("%-*.*s ", NAME_WIDTH, UT_NAMESIZE, "USER");
269
270
	if (show_term)
271
		(void)printf("S ");
272
273
	(void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, "LINE");
274
	(void)printf("WHEN         ");
275
276
	if (show_idle)
277
		(void)printf("IDLE  ");
278
279
	(void)printf("  %.*s", hostwidth, "FROM");
280
281
	(void)putchar('\n');
282
}
283
284
FILE *
285
file(char *name)
286
{
287
	FILE *ufp;
288
289
	if (!(ufp = fopen(name, "r"))) {
290
		err(1, "%s", name);
291
		/* NOTREACHED */
292
	}
293
	if (show_term || show_idle) {
294
		if (pledge("stdio rpath getpw flock cpath wpath", NULL) == -1)
295
			err(1, "pledge");
296
	} else {
297
		if (pledge("stdio getpw flock rpath cpath wpath", NULL) == -1)
298
			err(1, "pledge");
299
	}
300
	return(ufp);
301
}
302
303
void
304
usage(void)
305
{
306
	(void)fprintf(stderr, "usage: who [-HmqTu] [file]\n       who am i\n");
307
	exit(1);
308
}