GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ktrace/ktrace.c Lines: 25 114 21.9 %
Date: 2016-12-06 Branches: 15 89 16.9 %

Line Branch Exec Source
1
/*	$OpenBSD: ktrace.c,v 1.33 2016/07/18 09:36:50 guenther Exp $	*/
2
/*	$NetBSD: ktrace.c,v 1.4 1995/08/31 23:01:44 jtc Exp $	*/
3
4
/*-
5
 * Copyright (c) 1988, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/param.h>	/* MAXCOMLEN */
34
#include <sys/signal.h>
35
#include <sys/stat.h>
36
#include <sys/time.h>
37
#include <sys/uio.h>
38
#include <sys/ktrace.h>
39
40
#include <err.h>
41
#include <errno.h>
42
#include <fcntl.h>
43
#include <stdlib.h>
44
#include <stdio.h>
45
#include <string.h>
46
#include <unistd.h>
47
48
#include "ktrace.h"
49
#include "extern.h"
50
51
extern char *__progname;
52
53
static int rpid(const char *);
54
static void no_ktrace(int);
55
static void usage(void);
56
57
int	is_ltrace;
58
59
int
60
main(int argc, char *argv[])
61
1
{
62
	enum { NOTSET, CLEAR, CLEARALL } clear;
63
	int append, ch, fd, inherit, ops, pidset, trpoints;
64
	pid_t pid;
65
	char *tracefile, *tracespec;
66
	mode_t omask;
67
	struct stat sb;
68
69
1
	is_ltrace = strcmp(__progname, "ltrace") == 0;
70
71
1
	clear = NOTSET;
72
1
	append = ops = pidset = inherit = pid = 0;
73
1
	trpoints = is_ltrace ? KTRFAC_USER : DEF_POINTS;
74
1
	tracefile = DEF_TRACEFILE;
75
1
	tracespec = NULL;
76
77
1
	if (is_ltrace) {
78
		while ((ch = getopt(argc, argv, "af:it:u:")) != -1)
79
			switch ((char)ch) {
80
			case 'a':
81
				append = 1;
82
				break;
83
			case 'f':
84
				tracefile = optarg;
85
				break;
86
			case 'i':
87
				inherit = 1;
88
				break;
89
			case 't':
90
				trpoints = getpoints(optarg, KTRFAC_USER);
91
				if (trpoints < 0) {
92
					warnx("unknown facility in %s", optarg);
93
					usage();
94
				}
95
				break;
96
			case 'u':
97
				tracespec = optarg;
98
				break;
99
			default:
100
				usage();
101
			}
102
	} else {
103
1
		while ((ch = getopt(argc, argv, "aBCcdf:g:ip:t:")) != -1)
104
			switch ((char)ch) {
105
			case 'a':
106
				append = 1;
107
				break;
108
			case 'B':
109
				putenv("LD_BIND_NOW=");
110
				break;
111
			case 'C':
112
				clear = CLEARALL;
113
				pidset = 1;
114
				break;
115
			case 'c':
116
				clear = CLEAR;
117
				break;
118
			case 'd':
119
				ops |= KTRFLAG_DESCEND;
120
				break;
121
			case 'f':
122
				tracefile = optarg;
123
				break;
124
			case 'g':
125
				pid = -rpid(optarg);
126
				pidset = 1;
127
				break;
128
			case 'i':
129
				inherit = 1;
130
				break;
131
			case 'p':
132
				pid = rpid(optarg);
133
				pidset = 1;
134
				break;
135
			case 't':
136
				trpoints = getpoints(optarg, DEF_POINTS);
137
				if (trpoints < 0) {
138
					warnx("unknown facility in %s", optarg);
139
					usage();
140
				}
141
				break;
142
			default:
143
				usage();
144
			}
145
	}
146
147
1
	argv += optind;
148
1
	argc -= optind;
149
150


1
	if ((pidset && *argv) || (!pidset && !*argv && clear != CLEAR))
151
		usage();
152
153
1
	if (inherit)
154
		trpoints |= KTRFAC_INHERIT;
155
156
1
	(void)signal(SIGSYS, no_ktrace);
157
1
	if (clear != NOTSET) {
158
		if (clear == CLEARALL) {
159
			ops = KTROP_CLEAR | KTRFLAG_DESCEND;
160
			trpoints = ALL_POINTS;
161
			pid = 1;
162
		} else
163
			ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE;
164
165
		if (ktrace(tracefile, ops, trpoints, pid) < 0) {
166
			if (errno == ESRCH)
167
				err(1, "%d", pid);
168
			err(1, "%s", tracefile);
169
		}
170
		exit(0);
171
	}
172
173
1
	omask = umask(S_IRWXG|S_IRWXO);
174
1
	if (append) {
175
		if ((fd = open(tracefile, O_CREAT | O_WRONLY, DEFFILEMODE)) < 0)
176
			err(1, "%s", tracefile);
177
		if (fstat(fd, &sb) != 0 || sb.st_uid != getuid())
178
			errx(1, "Refuse to append to %s: not owned by you.",
179
			    tracefile);
180
	} else {
181

1
		if (unlink(tracefile) == -1 && errno != ENOENT)
182
			err(1, "unlink %s", tracefile);
183
1
		if ((fd = open(tracefile, O_CREAT | O_EXCL | O_WRONLY,
184
		    DEFFILEMODE)) < 0)
185
			err(1, "%s", tracefile);
186
	}
187
1
	(void)umask(omask);
188
1
	(void)close(fd);
189
190
1
	if (*argv) {
191
1
		if (is_ltrace) {
192
			if (setenv("LD_TRACE_PLT", inherit ? "i" : "", 1) < 0)
193
				err(1, "setenv(LD_TRACE_PLT)");
194
			if (tracespec &&
195
			    setenv("LD_TRACE_PLTSPEC", tracespec, 1) < 0)
196
				err(1, "setenv(LD_TRACE_PLTSPEC)");
197
		}
198
1
		if (ktrace(tracefile, ops, trpoints, getpid()) < 0)
199
			err(1, "%s", tracefile);
200
1
		execvp(argv[0], &argv[0]);
201
		err(1, "exec of '%s' failed", argv[0]);
202
	}
203
	else if (ktrace(tracefile, ops, trpoints, pid) < 0) {
204
		if (errno == ESRCH)
205
			err(1, "%d", pid);
206
		err(1, "%s", tracefile);
207
	}
208
	exit(0);
209
}
210
211
static int
212
rpid(const char *p)
213
{
214
	const char *errstr;
215
	static int first;
216
	pid_t pid;
217
218
	if (first++) {
219
		warnx("only one -g or -p flag is permitted.");
220
		usage();
221
	}
222
	if (!*p) {
223
		warnx("illegal process id.");
224
		usage();
225
	}
226
	pid = strtonum(p, 1, INT_MAX, &errstr);
227
	if (errstr) {
228
		warnx("illegal process id: %s", errstr);
229
		usage();
230
	}
231
	return pid;
232
}
233
234
static void
235
usage(void)
236
{
237
	if (is_ltrace)
238
		fprintf(stderr, "usage: %s [-ai] [-f trfile] [-t trstr]"
239
		    " [-u trspec] command\n",
240
		    __progname);
241
	else
242
		fprintf(stderr, "usage: %s [-aBCcdi] [-f trfile] [-g pgid]"
243
		    " [-p pid] [-t trstr]\n"
244
		    "       %s [-adi] [-f trfile] [-t trstr] command\n",
245
		    __progname, __progname);
246
	exit(1);
247
}
248
249
/* ARGSUSED */
250
static void
251
no_ktrace(int signo)
252
{
253
	char buf[8192];
254
255
	snprintf(buf, sizeof(buf),
256
"error:\tktrace() system call not supported in the running kernel\n\tre-compile kernel with 'option KTRACE'\n");
257
	write(STDERR_FILENO, buf, strlen(buf));
258
	_exit(1);
259
}