1 /* $NetBSD: ktrace.c,v 1.42.6.1 2008/12/29 01:14:15 christos Exp $ */
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1988, 1993\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)ktrace.c 8.2 (Berkeley) 4/28/95";
42 __RCSID("$NetBSD: ktrace.c,v 1.42.6.1 2008/12/29 01:14:15 christos Exp $");
46 #include <sys/param.h>
52 #include <sys/ktrace.h>
53 #include <sys/socket.h>
69 int main(int, char *[]);
70 static int rpid(char *);
71 static void usage(void);
72 static int do_ktrace(const char *, int, int, int, int, int);
73 static void no_ktrace(int);
74 static void fset(int fd
, int flag
);
75 static void fclear(int fd
, int flag
);
78 extern int timestamp
, decimal
, fancy
, tail
, maxdata
;
82 main(int argc
, char *argv
[])
84 enum { NOTSET
, CLEAR
, CLEARALL
} clear
;
85 int block
, append
, ch
, fd
, trset
, ops
, pid
, pidset
, synclog
, trpoints
;
90 const char *emul_name
= "netbsd";
94 append
= ops
= pidset
= trset
= synclog
= 0;
98 pid
= 0; /* Appease GCC */
101 # define OPTIONS "aCce:df:g:ilm:no:p:RTt:v:"
102 outfile
= infile
= NULL
;
104 # define OPTIONS "aCcdf:g:ip:st:v:"
105 outfile
= DEF_TRACEFILE
;
108 while ((ch
= getopt(argc
, argv
, OPTIONS
)) != -1)
122 ops
|= KTRFLAG_DESCEND
;
126 emul_name
= strdup(optarg
); /* it's safer to copy it */
141 trpoints
|= KTRFAC_INHERIT
;
148 maxdata
= atoi(optarg
);
163 timestamp
= 2; /* relative timestamp */
177 trpoints
= getpoints(trpoints
, optarg
);
179 warnx("unknown facility in %s", optarg
);
193 trpoints
|= clear
== NOTSET
? DEF_POINTS
: ALL_POINTS
;
195 if ((pidset
&& *argv
) || (!pidset
&& !*argv
)) {
203 if (clear
== CLEAR
&& outfile
== NULL
&& pid
== 0)
207 dumpfile(infile
, 0, trpoints
);
211 setemul(emul_name
, 0, 0);
215 * For cleaner traces, initialize malloc now rather
216 * than in a traced subprocess.
220 (void)signal(SIGSYS
, no_ktrace
);
221 if (clear
!= NOTSET
) {
222 if (clear
== CLEARALL
) {
223 ops
= KTROP_CLEAR
| KTRFLAG_DESCEND
;
224 trpoints
= ALL_POINTS
;
227 ops
|= pid
? KTROP_CLEAR
: KTROP_CLEARFILE
;
229 (void)do_ktrace(outfile
, vers
, ops
, trpoints
, pid
, block
);
233 if (outfile
&& strcmp(outfile
, "-")) {
234 if ((fd
= open(outfile
, O_CREAT
| O_WRONLY
|
235 (append
? 0 : O_TRUNC
) | (synclog
? 0 : O_SYNC
),
237 err(EXIT_FAILURE
, "%s", outfile
);
243 if (do_ktrace(outfile
, vers
, ops
, trpoints
, getpid(), block
) == 1) {
244 execvp(argv
[0], &argv
[0]);
245 err(EXIT_FAILURE
, "exec of '%s' failed", argv
[0]);
248 (void)do_ktrace(outfile
, vers
, ops
, trpoints
, getpid(), block
);
249 execvp(argv
[0], &argv
[0]);
250 err(EXIT_FAILURE
, "exec of '%s' failed", argv
[0]);
253 (void)do_ktrace(outfile
, vers
, ops
, trpoints
, pid
, block
);
263 warnx("only one -g or -p flag is permitted.");
267 warnx("illegal process id.");
274 fset(int fd
, int flag
)
276 int oflag
= fcntl(fd
, F_GETFL
, 0);
279 err(EXIT_FAILURE
, "Cannot get file flags");
280 if (fcntl(fd
, F_SETFL
, oflag
| flag
) == -1)
281 err(EXIT_FAILURE
, "Cannot set file flags");
285 fclear(int fd
, int flag
)
287 int oflag
= fcntl(fd
, F_GETFL
, 0);
290 err(EXIT_FAILURE
, "Cannot get file flags");
291 if (fcntl(fd
, F_SETFL
, oflag
& ~flag
) == -1)
292 err(EXIT_FAILURE
, "Cannot set file flags");
299 #define TRPOINTS "[AaceilmnsUuvw+-]"
301 (void)fprintf(stderr
, "usage:\t%s "
302 "[-aCcdilnRT] [-e emulation] [-f infile] [-g pgrp] "
304 "[-o outfile] [-p pid] [-t " TRPOINTS
"]\n", getprogname());
305 (void)fprintf(stderr
, "\t%s "
306 "[-adinRT] [-e emulation] [-m maxdata] [-o outfile]\n\t "
307 "[-t " TRPOINTS
"] [-v vers] command\n",
310 (void)fprintf(stderr
, "usage:\t%s "
311 "[-aCcdins] [-f trfile] [-g pgrp] [-p pid] [-t " TRPOINTS
"]\n",
313 (void)fprintf(stderr
, "\t%s "
314 "[-adis] [-f trfile] [-t " TRPOINTS
"] command\n",
320 static const char *ktracefile
= NULL
;
327 (void)unlink(ktracefile
);
328 (void)errx(EXIT_FAILURE
,
329 "ktrace(2) system call not supported in the running"
330 " kernel; re-compile kernel with `options KTRACE'");
334 do_ktrace(const char *tracefile
, int vers
, int ops
, int trpoints
, int pid
,
338 ops
|= vers
<< KTRFAC_VER_SHIFT
;
340 if (KTROP(ops
) == KTROP_SET
&&
341 (!tracefile
|| strcmp(tracefile
, "-") == 0)) {
345 err(EXIT_FAILURE
, "pipe(2)");
347 fset(pi
[0], FD_CLOEXEC
);
348 fset(pi
[1], FD_CLOEXEC
);
349 dofork
= (pid
== getpid());
354 * Create a child process and trace it.
358 err(EXIT_FAILURE
, "fork");
367 * Create a dumper process and we will be
372 err(EXIT_FAILURE
, "fork");
378 ret
= fktrace(pi
[1], ops
, trpoints
, pid
);
380 err(EXIT_FAILURE
, "fd %d, pid %d",
383 fclear(pi
[1], O_NONBLOCK
);
386 dumpfile(NULL
, pi
[0], trpoints
);
387 waitpid(pid
, NULL
, 0);
394 read(pi
[0], buf
, sizeof(buf
))) > 0)
395 if (write(STDOUT_FILENO
, buf
, (size_t)n
) == -1)
396 warn("write failed");
405 ret
= fktrace(pi
[1], ops
, trpoints
, pid
);
407 err(EXIT_FAILURE
, "fd %d, pid %d", pi
[1], pid
);
409 fclear(pi
[1], O_NONBLOCK
);
411 ret
= ktrace(ktracefile
= tracefile
, ops
, trpoints
, pid
);
413 err(EXIT_FAILURE
, "file %s, pid %d",
414 tracefile
!= NULL
? tracefile
: "NULL", pid
);