| @@ -1,416 +1,402 @@ | | | @@ -1,416 +1,402 @@ |
1 | /* $NetBSD: ktrace.c,v 1.45 2011/09/16 15:39:26 joerg Exp $ */ | | 1 | /* $NetBSD: ktrace.c,v 1.46 2013/01/24 17:47:58 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1988, 1993 | | 4 | * Copyright (c) 1988, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. Neither the name of the University nor the names of its contributors | | 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 | | 16 | * may be used to endorse or promote products derived from this software |
17 | * without specific prior written permission. | | 17 | * without specific prior written permission. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 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 | | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 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 | | 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 | | 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 | | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | #ifndef lint | | 33 | #ifndef lint |
34 | __COPYRIGHT("@(#) Copyright (c) 1988, 1993\ | | 34 | __COPYRIGHT("@(#) Copyright (c) 1988, 1993\ |
35 | The Regents of the University of California. All rights reserved."); | | 35 | The Regents of the University of California. All rights reserved."); |
36 | #endif /* not lint */ | | 36 | #endif /* not lint */ |
37 | | | 37 | |
38 | #ifndef lint | | 38 | #ifndef lint |
39 | #if 0 | | 39 | #if 0 |
40 | static char sccsid[] = "@(#)ktrace.c 8.2 (Berkeley) 4/28/95"; | | 40 | static char sccsid[] = "@(#)ktrace.c 8.2 (Berkeley) 4/28/95"; |
41 | #else | | 41 | #else |
42 | __RCSID("$NetBSD: ktrace.c,v 1.45 2011/09/16 15:39:26 joerg Exp $"); | | 42 | __RCSID("$NetBSD: ktrace.c,v 1.46 2013/01/24 17:47:58 christos Exp $"); |
43 | #endif | | 43 | #endif |
44 | #endif /* not lint */ | | 44 | #endif /* not lint */ |
45 | | | 45 | |
46 | #include <sys/param.h> | | 46 | #include <sys/param.h> |
47 | #include <sys/stat.h> | | 47 | #include <sys/stat.h> |
48 | #include <sys/wait.h> | | 48 | #include <sys/wait.h> |
49 | #include <sys/file.h> | | 49 | #include <sys/file.h> |
50 | #include <sys/time.h> | | 50 | #include <sys/time.h> |
51 | #include <sys/uio.h> | | 51 | #include <sys/uio.h> |
52 | #include <sys/ktrace.h> | | 52 | #include <sys/ktrace.h> |
53 | #include <sys/socket.h> | | 53 | #include <sys/socket.h> |
54 | | | 54 | |
55 | #include <err.h> | | 55 | #include <err.h> |
56 | #include <errno.h> | | 56 | #include <errno.h> |
57 | #include <stdio.h> | | 57 | #include <stdio.h> |
58 | #include <stdlib.h> | | 58 | #include <stdlib.h> |
59 | #include <string.h> | | 59 | #include <string.h> |
60 | #include <unistd.h> | | 60 | #include <unistd.h> |
61 | #include <signal.h> | | 61 | #include <signal.h> |
62 | | | 62 | |
63 | #include "ktrace.h" | | 63 | #include "ktrace.h" |
64 | | | 64 | |
65 | #ifdef KTRUSS | | 65 | #ifdef KTRUSS |
66 | #include "setemul.h" | | 66 | #include "setemul.h" |
67 | #endif | | 67 | #endif |
68 | | | 68 | |
69 | static int rpid(char *); | | 69 | static int rpid(char *); |
70 | __dead static void usage(void); | | 70 | __dead static void usage(void); |
71 | static int do_ktrace(const char *, int, int, int, int, int); | | 71 | static int do_ktrace(const char *, int, int, int, int, int); |
72 | __dead static void no_ktrace(int); | | 72 | __dead static void no_ktrace(int); |
73 | static void fset(int fd, int flag); | | | |
74 | static void fclear(int fd, int flag); | | 73 | static void fclear(int fd, int flag); |
75 | | | 74 | |
76 | #ifdef KTRUSS | | 75 | #ifdef KTRUSS |
77 | extern int timestamp, decimal, fancy, tail, maxdata; | | 76 | extern int timestamp, decimal, fancy, tail, maxdata; |
78 | #endif | | 77 | #endif |
79 | | | 78 | |
80 | int | | 79 | int |
81 | main(int argc, char *argv[]) | | 80 | main(int argc, char *argv[]) |
82 | { | | 81 | { |
83 | enum { NOTSET, CLEAR, CLEARALL } clear; | | 82 | enum { NOTSET, CLEAR, CLEARALL } clear; |
84 | int block, append, ch, fd, trset, ops, pid, pidset, synclog, trpoints; | | 83 | int block, append, ch, fd, trset, ops, pid, pidset, synclog, trpoints; |
85 | int vers; | | 84 | int vers; |
86 | const char *outfile; | | 85 | const char *outfile; |
87 | #ifdef KTRUSS | | 86 | #ifdef KTRUSS |
88 | const char *infile; | | 87 | const char *infile; |
89 | const char *emul_name = "netbsd"; | | 88 | const char *emul_name = "netbsd"; |
90 | #endif | | 89 | #endif |
91 | | | 90 | |
92 | clear = NOTSET; | | 91 | clear = NOTSET; |
93 | append = ops = pidset = trset = synclog = 0; | | 92 | append = ops = pidset = trset = synclog = 0; |
94 | trpoints = 0; | | 93 | trpoints = 0; |
95 | block = 1; | | 94 | block = 1; |
96 | vers = 2; | | 95 | vers = 2; |
97 | pid = 0; /* Appease GCC */ | | 96 | pid = 0; /* Appease GCC */ |
98 | | | 97 | |
99 | #ifdef KTRUSS | | 98 | #ifdef KTRUSS |
100 | # define OPTIONS "aCce:df:g:ilm:no:p:RTt:v:" | | 99 | # define OPTIONS "aCce:df:g:ilm:no:p:RTt:v:" |
101 | outfile = infile = NULL; | | 100 | outfile = infile = NULL; |
102 | #else | | 101 | #else |
103 | # define OPTIONS "aCcdf:g:ip:st:v:" | | 102 | # define OPTIONS "aCcdf:g:ip:st:v:" |
104 | outfile = DEF_TRACEFILE; | | 103 | outfile = DEF_TRACEFILE; |
105 | #endif | | 104 | #endif |
106 | | | 105 | |
107 | while ((ch = getopt(argc, argv, OPTIONS)) != -1) | | 106 | while ((ch = getopt(argc, argv, OPTIONS)) != -1) |
108 | switch (ch) { | | 107 | switch (ch) { |
109 | case 'a': | | 108 | case 'a': |
110 | append = 1; | | 109 | append = 1; |
111 | break; | | 110 | break; |
112 | case 'C': | | 111 | case 'C': |
113 | clear = CLEARALL; | | 112 | clear = CLEARALL; |
114 | pidset = 1; | | 113 | pidset = 1; |
115 | break; | | 114 | break; |
116 | case 'c': | | 115 | case 'c': |
117 | clear = CLEAR; | | 116 | clear = CLEAR; |
118 | pidset = 1; | | 117 | pidset = 1; |
119 | break; | | 118 | break; |
120 | case 'd': | | 119 | case 'd': |
121 | ops |= KTRFLAG_DESCEND; | | 120 | ops |= KTRFLAG_DESCEND; |
122 | break; | | 121 | break; |
123 | #ifdef KTRUSS | | 122 | #ifdef KTRUSS |
124 | case 'e': | | 123 | case 'e': |
125 | emul_name = strdup(optarg); /* it's safer to copy it */ | | 124 | emul_name = strdup(optarg); /* it's safer to copy it */ |
126 | break; | | 125 | break; |
127 | case 'f': | | 126 | case 'f': |
128 | infile = optarg; | | 127 | infile = optarg; |
129 | break; | | 128 | break; |
130 | #else | | 129 | #else |
131 | case 'f': | | 130 | case 'f': |
132 | outfile = optarg; | | 131 | outfile = optarg; |
133 | break; | | 132 | break; |
134 | #endif | | 133 | #endif |
135 | case 'g': | | 134 | case 'g': |
136 | pid = -rpid(optarg); | | 135 | pid = -rpid(optarg); |
137 | pidset = 1; | | 136 | pidset = 1; |
138 | break; | | 137 | break; |
139 | case 'i': | | 138 | case 'i': |
140 | trpoints |= KTRFAC_INHERIT; | | 139 | trpoints |= KTRFAC_INHERIT; |
141 | break; | | 140 | break; |
142 | #ifdef KTRUSS | | 141 | #ifdef KTRUSS |
143 | case 'l': | | 142 | case 'l': |
144 | tail = 1; | | 143 | tail = 1; |
145 | break; | | 144 | break; |
146 | case 'm': | | 145 | case 'm': |
147 | maxdata = atoi(optarg); | | 146 | maxdata = atoi(optarg); |
148 | break; | | 147 | break; |
149 | case 'o': | | 148 | case 'o': |
150 | outfile = optarg; | | 149 | outfile = optarg; |
151 | break; | | 150 | break; |
152 | #endif | | 151 | #endif |
153 | case 'n': | | 152 | case 'n': |
154 | block = 0; | | 153 | block = 0; |
155 | break; | | 154 | break; |
156 | case 'p': | | 155 | case 'p': |
157 | pid = rpid(optarg); | | 156 | pid = rpid(optarg); |
158 | pidset = 1; | | 157 | pidset = 1; |
159 | break; | | 158 | break; |
160 | #ifdef KTRUSS | | 159 | #ifdef KTRUSS |
161 | case 'R': | | 160 | case 'R': |
162 | timestamp = 2; /* relative timestamp */ | | 161 | timestamp = 2; /* relative timestamp */ |
163 | break; | | 162 | break; |
164 | #else | | 163 | #else |
165 | case 's': | | 164 | case 's': |
166 | synclog = 1; | | 165 | synclog = 1; |
167 | break; | | 166 | break; |
168 | #endif | | 167 | #endif |
169 | #ifdef KTRUSS | | 168 | #ifdef KTRUSS |
170 | case 'T': | | 169 | case 'T': |
171 | timestamp = 1; | | 170 | timestamp = 1; |
172 | break; | | 171 | break; |
173 | #endif | | 172 | #endif |
174 | case 't': | | 173 | case 't': |
175 | trset = 1; | | 174 | trset = 1; |
176 | trpoints = getpoints(trpoints, optarg); | | 175 | trpoints = getpoints(trpoints, optarg); |
177 | if (trpoints < 0) { | | 176 | if (trpoints < 0) { |
178 | warnx("unknown facility in %s", optarg); | | 177 | warnx("unknown facility in %s", optarg); |
179 | usage(); | | 178 | usage(); |
180 | } | | 179 | } |
181 | break; | | 180 | break; |
182 | case 'v': | | 181 | case 'v': |
183 | vers = atoi(optarg); | | 182 | vers = atoi(optarg); |
184 | break; | | 183 | break; |
185 | default: | | 184 | default: |
186 | usage(); | | 185 | usage(); |
187 | } | | 186 | } |
188 | argv += optind; | | 187 | argv += optind; |
189 | argc -= optind; | | 188 | argc -= optind; |
190 | | | 189 | |
191 | if (!trset) | | 190 | if (!trset) |
192 | trpoints |= clear == NOTSET ? DEF_POINTS : ALL_POINTS; | | 191 | trpoints |= clear == NOTSET ? DEF_POINTS : ALL_POINTS; |
193 | | | 192 | |
194 | if ((pidset && *argv) || (!pidset && !*argv)) { | | 193 | if ((pidset && *argv) || (!pidset && !*argv)) { |
195 | #ifdef KTRUSS | | 194 | #ifdef KTRUSS |
196 | if (!infile) | | 195 | if (!infile) |
197 | #endif | | 196 | #endif |
198 | usage(); | | 197 | usage(); |
199 | } | | 198 | } |
200 | | | 199 | |
201 | #ifdef KTRUSS | | 200 | #ifdef KTRUSS |
202 | if (clear == CLEAR && outfile == NULL && pid == 0) | | 201 | if (clear == CLEAR && outfile == NULL && pid == 0) |
203 | usage(); | | 202 | usage(); |
204 | | | 203 | |
205 | if (infile) { | | 204 | if (infile) { |
206 | dumpfile(infile, 0, trpoints); | | 205 | dumpfile(infile, 0, trpoints); |
207 | exit(0); | | 206 | exit(0); |
208 | } | | 207 | } |
209 | | | 208 | |
210 | setemul(emul_name, 0, 0); | | 209 | setemul(emul_name, 0, 0); |
211 | #endif | | 210 | #endif |
212 | | | 211 | |
213 | /* | | 212 | /* |
214 | * For cleaner traces, initialize malloc now rather | | 213 | * For cleaner traces, initialize malloc now rather |
215 | * than in a traced subprocess. | | 214 | * than in a traced subprocess. |
216 | */ | | 215 | */ |
217 | free(malloc(1)); | | 216 | free(malloc(1)); |
218 | | | 217 | |
219 | (void)signal(SIGSYS, no_ktrace); | | 218 | (void)signal(SIGSYS, no_ktrace); |
220 | if (clear != NOTSET) { | | 219 | if (clear != NOTSET) { |
221 | if (clear == CLEARALL) { | | 220 | if (clear == CLEARALL) { |
222 | ops = KTROP_CLEAR | KTRFLAG_DESCEND; | | 221 | ops = KTROP_CLEAR | KTRFLAG_DESCEND; |
223 | trpoints = ALL_POINTS; | | 222 | trpoints = ALL_POINTS; |
224 | pid = 1; | | 223 | pid = 1; |
225 | } else | | 224 | } else |
226 | ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE; | | 225 | ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE; |
227 | | | 226 | |
228 | (void)do_ktrace(outfile, vers, ops, trpoints, pid, block); | | 227 | (void)do_ktrace(outfile, vers, ops, trpoints, pid, block); |
229 | exit(0); | | 228 | exit(0); |
230 | } | | 229 | } |
231 | | | 230 | |
232 | if (outfile && strcmp(outfile, "-")) { | | 231 | if (outfile && strcmp(outfile, "-")) { |
233 | if ((fd = open(outfile, O_CREAT | O_WRONLY | | | 232 | if ((fd = open(outfile, O_CREAT | O_WRONLY | |
234 | (append ? 0 : O_TRUNC) | (synclog ? 0 : O_SYNC), | | 233 | (append ? 0 : O_TRUNC) | (synclog ? 0 : O_SYNC), |
235 | DEFFILEMODE)) < 0) | | 234 | DEFFILEMODE)) < 0) |
236 | err(EXIT_FAILURE, "%s", outfile); | | 235 | err(EXIT_FAILURE, "%s", outfile); |
237 | (void)close(fd); | | 236 | (void)close(fd); |
238 | } | | 237 | } |
239 | | | 238 | |
240 | if (*argv) { | | 239 | if (*argv) { |
241 | #ifdef KTRUSS | | 240 | #ifdef KTRUSS |
242 | if (do_ktrace(outfile, vers, ops, trpoints, getpid(), block) == 1) { | | 241 | if (do_ktrace(outfile, vers, ops, trpoints, getpid(), block) == 1) { |
243 | execvp(argv[0], &argv[0]); | | 242 | execvp(argv[0], &argv[0]); |
244 | err(EXIT_FAILURE, "exec of '%s' failed", argv[0]); | | 243 | err(EXIT_FAILURE, "exec of '%s' failed", argv[0]); |
245 | } | | 244 | } |
246 | #else | | 245 | #else |
247 | (void)do_ktrace(outfile, vers, ops, trpoints, getpid(), block); | | 246 | (void)do_ktrace(outfile, vers, ops, trpoints, getpid(), block); |
248 | execvp(argv[0], &argv[0]); | | 247 | execvp(argv[0], &argv[0]); |
249 | err(EXIT_FAILURE, "exec of '%s' failed", argv[0]); | | 248 | err(EXIT_FAILURE, "exec of '%s' failed", argv[0]); |
250 | #endif | | 249 | #endif |
251 | } else | | 250 | } else |
252 | (void)do_ktrace(outfile, vers, ops, trpoints, pid, block); | | 251 | (void)do_ktrace(outfile, vers, ops, trpoints, pid, block); |
253 | return 0; | | 252 | return 0; |
254 | } | | 253 | } |
255 | | | 254 | |
256 | static int | | 255 | static int |
257 | rpid(char *p) | | 256 | rpid(char *p) |
258 | { | | 257 | { |
259 | static int first; | | 258 | static int first; |
260 | | | 259 | |
261 | if (first++) { | | 260 | if (first++) { |
262 | warnx("only one -g or -p flag is permitted."); | | 261 | warnx("only one -g or -p flag is permitted."); |
263 | usage(); | | 262 | usage(); |
264 | } | | 263 | } |
265 | if (!*p) { | | 264 | if (!*p) { |
266 | warnx("illegal process id."); | | 265 | warnx("illegal process id."); |
267 | usage(); | | 266 | usage(); |
268 | } | | 267 | } |
269 | return (atoi(p)); | | 268 | return (atoi(p)); |
270 | } | | 269 | } |
271 | | | 270 | |
272 | static void | | 271 | static void |
273 | fset(int fd, int flag) | | | |
274 | { | | | |
275 | int oflag = fcntl(fd, F_GETFL, 0); | | | |
276 | | | | |
277 | if (oflag == -1) | | | |
278 | err(EXIT_FAILURE, "Cannot get file flags"); | | | |
279 | if (fcntl(fd, F_SETFL, oflag | flag) == -1) | | | |
280 | err(EXIT_FAILURE, "Cannot set file flags"); | | | |
281 | } | | | |
282 | | | | |
283 | static void | | | |
284 | fclear(int fd, int flag) | | 272 | fclear(int fd, int flag) |
285 | { | | 273 | { |
286 | int oflag = fcntl(fd, F_GETFL, 0); | | 274 | int oflag = fcntl(fd, F_GETFL, 0); |
287 | | | 275 | |
288 | if (oflag == -1) | | 276 | if (oflag == -1) |
289 | err(EXIT_FAILURE, "Cannot get file flags"); | | 277 | err(EXIT_FAILURE, "Cannot get file flags"); |
290 | if (fcntl(fd, F_SETFL, oflag & ~flag) == -1) | | 278 | if (fcntl(fd, F_SETFL, oflag & ~flag) == -1) |
291 | err(EXIT_FAILURE, "Cannot set file flags"); | | 279 | err(EXIT_FAILURE, "Cannot set file flags"); |
292 | } | | 280 | } |
293 | | | 281 | |
294 | static void | | 282 | static void |
295 | usage(void) | | 283 | usage(void) |
296 | { | | 284 | { |
297 | | | 285 | |
298 | #define TRPOINTS "[AaceilmnSsuvw+-]" | | 286 | #define TRPOINTS "[AaceilmnSsuvw+-]" |
299 | #ifdef KTRUSS | | 287 | #ifdef KTRUSS |
300 | (void)fprintf(stderr, "usage:\t%s " | | 288 | (void)fprintf(stderr, "usage:\t%s " |
301 | "[-aCcdilnRT] [-e emulation] [-f infile] [-g pgrp] " | | 289 | "[-aCcdilnRT] [-e emulation] [-f infile] [-g pgrp] " |
302 | "[-m maxdata]\n\t " | | 290 | "[-m maxdata]\n\t " |
303 | "[-o outfile] [-p pid] [-t " TRPOINTS "]\n", getprogname()); | | 291 | "[-o outfile] [-p pid] [-t " TRPOINTS "]\n", getprogname()); |
304 | (void)fprintf(stderr, "\t%s " | | 292 | (void)fprintf(stderr, "\t%s " |
305 | "[-adinRT] [-e emulation] [-m maxdata] [-o outfile]\n\t " | | 293 | "[-adinRT] [-e emulation] [-m maxdata] [-o outfile]\n\t " |
306 | "[-t " TRPOINTS "] [-v vers] command\n", | | 294 | "[-t " TRPOINTS "] [-v vers] command\n", |
307 | getprogname()); | | 295 | getprogname()); |
308 | #else | | 296 | #else |
309 | (void)fprintf(stderr, "usage:\t%s " | | 297 | (void)fprintf(stderr, "usage:\t%s " |
310 | "[-aCcdins] [-f trfile] [-g pgrp] [-p pid] [-t " TRPOINTS "]\n", | | 298 | "[-aCcdins] [-f trfile] [-g pgrp] [-p pid] [-t " TRPOINTS "]\n", |
311 | getprogname()); | | 299 | getprogname()); |
312 | (void)fprintf(stderr, "\t%s " | | 300 | (void)fprintf(stderr, "\t%s " |
313 | "[-adis] [-f trfile] [-t " TRPOINTS "] command\n", | | 301 | "[-adis] [-f trfile] [-t " TRPOINTS "] command\n", |
314 | getprogname()); | | 302 | getprogname()); |
315 | #endif | | 303 | #endif |
316 | exit(1); | | 304 | exit(1); |
317 | } | | 305 | } |
318 | | | 306 | |
319 | static const char *ktracefile = NULL; | | 307 | static const char *ktracefile = NULL; |
320 | static void | | 308 | static void |
321 | /*ARGSUSED*/ | | 309 | /*ARGSUSED*/ |
322 | no_ktrace(int sig) | | 310 | no_ktrace(int sig) |
323 | { | | 311 | { |
324 | | | 312 | |
325 | if (ktracefile) | | 313 | if (ktracefile) |
326 | (void)unlink(ktracefile); | | 314 | (void)unlink(ktracefile); |
327 | (void)errx(EXIT_FAILURE, | | 315 | (void)errx(EXIT_FAILURE, |
328 | "ktrace(2) system call not supported in the running" | | 316 | "ktrace(2) system call not supported in the running" |
329 | " kernel; re-compile kernel with `options KTRACE'"); | | 317 | " kernel; re-compile kernel with `options KTRACE'"); |
330 | } | | 318 | } |
331 | | | 319 | |
332 | static int | | 320 | static int |
333 | do_ktrace(const char *tracefile, int vers, int ops, int trpoints, int pid, | | 321 | do_ktrace(const char *tracefile, int vers, int ops, int trpoints, int pid, |
334 | int block) | | 322 | int block) |
335 | { | | 323 | { |
336 | int ret; | | 324 | int ret; |
337 | ops |= vers << KTRFAC_VER_SHIFT; | | 325 | ops |= vers << KTRFAC_VER_SHIFT; |
338 | | | 326 | |
339 | if (KTROP(ops) == KTROP_SET && | | 327 | if (KTROP(ops) == KTROP_SET && |
340 | (!tracefile || strcmp(tracefile, "-") == 0)) { | | 328 | (!tracefile || strcmp(tracefile, "-") == 0)) { |
341 | int pi[2], dofork; | | 329 | int pi[2], dofork; |
342 | | | 330 | |
343 | if (pipe(pi) < 0) | | 331 | if (pipe2(pi, O_CLOEXEC) == -1) |
344 | err(EXIT_FAILURE, "pipe(2)"); | | 332 | err(EXIT_FAILURE, "pipe(2)"); |
345 | | | 333 | |
346 | fset(pi[0], FD_CLOEXEC); | | | |
347 | fset(pi[1], FD_CLOEXEC); | | | |
348 | dofork = (pid == getpid()); | | 334 | dofork = (pid == getpid()); |
349 | | | 335 | |
350 | if (dofork) { | | 336 | if (dofork) { |
351 | #ifdef KTRUSS | | 337 | #ifdef KTRUSS |
352 | /* | | 338 | /* |
353 | * Create a child process and trace it. | | 339 | * Create a child process and trace it. |
354 | */ | | 340 | */ |
355 | pid = fork(); | | 341 | pid = fork(); |
356 | if (pid == -1) | | 342 | if (pid == -1) |
357 | err(EXIT_FAILURE, "fork"); | | 343 | err(EXIT_FAILURE, "fork"); |
358 | else if (pid == 0) { | | 344 | else if (pid == 0) { |
359 | pid = getpid(); | | 345 | pid = getpid(); |
360 | goto trace_and_exec; | | 346 | goto trace_and_exec; |
361 | } | | 347 | } |
362 | #else | | 348 | #else |
363 | int fpid; | | 349 | int fpid; |
364 | | | 350 | |
365 | /* | | 351 | /* |
366 | * Create a dumper process and we will be | | 352 | * Create a dumper process and we will be |
367 | * traced. | | 353 | * traced. |
368 | */ | | 354 | */ |
369 | fpid = fork(); | | 355 | fpid = fork(); |
370 | if (fpid == -1) | | 356 | if (fpid == -1) |
371 | err(EXIT_FAILURE, "fork"); | | 357 | err(EXIT_FAILURE, "fork"); |
372 | else if (fpid != 0) | | 358 | else if (fpid != 0) |
373 | goto trace_and_exec; | | 359 | goto trace_and_exec; |
374 | #endif | | 360 | #endif |
375 | (void)close(pi[1]); | | 361 | (void)close(pi[1]); |
376 | } else { | | 362 | } else { |
377 | ret = fktrace(pi[1], ops, trpoints, pid); | | 363 | ret = fktrace(pi[1], ops, trpoints, pid); |
378 | if (ret == -1) | | 364 | if (ret == -1) |
379 | err(EXIT_FAILURE, "fd %d, pid %d", | | 365 | err(EXIT_FAILURE, "fd %d, pid %d", |
380 | pi[1], pid); | | 366 | pi[1], pid); |
381 | if (block) | | 367 | if (block) |
382 | fclear(pi[1], O_NONBLOCK); | | 368 | fclear(pi[1], O_NONBLOCK); |
383 | } | | 369 | } |
384 | #ifdef KTRUSS | | 370 | #ifdef KTRUSS |
385 | dumpfile(NULL, pi[0], trpoints); | | 371 | dumpfile(NULL, pi[0], trpoints); |
386 | waitpid(pid, NULL, 0); | | 372 | waitpid(pid, NULL, 0); |
387 | #else | | 373 | #else |
388 | { | | 374 | { |
389 | char buf[BUFSIZ]; | | 375 | char buf[BUFSIZ]; |
390 | int n; | | 376 | int n; |
391 | | | 377 | |
392 | while ((n = | | 378 | while ((n = |
393 | read(pi[0], buf, sizeof(buf))) > 0) | | 379 | read(pi[0], buf, sizeof(buf))) > 0) |
394 | if (write(STDOUT_FILENO, buf, (size_t)n) == -1) | | 380 | if (write(STDOUT_FILENO, buf, (size_t)n) == -1) |
395 | warn("write failed"); | | 381 | warn("write failed"); |
396 | } | | 382 | } |
397 | if (dofork) | | 383 | if (dofork) |
398 | _exit(0); | | 384 | _exit(0); |
399 | #endif | | 385 | #endif |
400 | return 0; | | 386 | return 0; |
401 | | | 387 | |
402 | trace_and_exec: | | 388 | trace_and_exec: |
403 | (void)close(pi[0]); | | 389 | (void)close(pi[0]); |
404 | ret = fktrace(pi[1], ops, trpoints, pid); | | 390 | ret = fktrace(pi[1], ops, trpoints, pid); |
405 | if (ret == -1) | | 391 | if (ret == -1) |
406 | err(EXIT_FAILURE, "fd %d, pid %d", pi[1], pid); | | 392 | err(EXIT_FAILURE, "fd %d, pid %d", pi[1], pid); |
407 | if (block) | | 393 | if (block) |
408 | fclear(pi[1], O_NONBLOCK); | | 394 | fclear(pi[1], O_NONBLOCK); |
409 | } else { | | 395 | } else { |
410 | ret = ktrace(ktracefile = tracefile, ops, trpoints, pid); | | 396 | ret = ktrace(ktracefile = tracefile, ops, trpoints, pid); |
411 | if (ret == -1) | | 397 | if (ret == -1) |
412 | err(EXIT_FAILURE, "file %s, pid %d", | | 398 | err(EXIT_FAILURE, "file %s, pid %d", |
413 | tracefile != NULL ? tracefile : "NULL", pid); | | 399 | tracefile != NULL ? tracefile : "NULL", pid); |
414 | } | | 400 | } |
415 | return 1; | | 401 | return 1; |
416 | } | | 402 | } |