19b50d902SRodney W. Grimes /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 49b50d902SRodney W. Grimes * Copyright (c) 1988, 1993 59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 69b50d902SRodney W. Grimes * 79b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 89b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 99b50d902SRodney W. Grimes * are met: 109b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 129b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 139b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 149b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 169b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 179b50d902SRodney W. Grimes * without specific prior written permission. 189b50d902SRodney W. Grimes * 199b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 209b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 219b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 229b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 239b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 249b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 259b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 269b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 279b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 289b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 299b50d902SRodney W. Grimes * SUCH DAMAGE. 309b50d902SRodney W. Grimes */ 319b50d902SRodney W. Grimes 329b50d902SRodney W. Grimes #ifndef lint 33ebdb213bSDavid Malone static const char copyright[] = 349b50d902SRodney W. Grimes "@(#) Copyright (c) 1988, 1993\n\ 359b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 369b50d902SRodney W. Grimes #endif /* not lint */ 379b50d902SRodney W. Grimes 380bff6132SJames Raynard #if 0 3965b386f1SPhilippe Charnier #ifndef lint 409b50d902SRodney W. Grimes static char sccsid[] = "@(#)ktrace.c 8.1 (Berkeley) 6/6/93"; 419b50d902SRodney W. Grimes #endif /* not lint */ 4265b386f1SPhilippe Charnier #endif 4365b386f1SPhilippe Charnier 44ebdb213bSDavid Malone #include <sys/cdefs.h> 45ebdb213bSDavid Malone __FBSDID("$FreeBSD$"); 46ebdb213bSDavid Malone 479b50d902SRodney W. Grimes #include <sys/param.h> 489b50d902SRodney W. Grimes #include <sys/file.h> 4999afdfe5SDag-Erling Smørgrav #include <sys/stat.h> 509b50d902SRodney W. Grimes #include <sys/time.h> 519b50d902SRodney W. Grimes #include <sys/uio.h> 529b50d902SRodney W. Grimes #include <sys/ktrace.h> 530bff6132SJames Raynard 540bff6132SJames Raynard #include <err.h> 5599afdfe5SDag-Erling Smørgrav #include <errno.h> 5699afdfe5SDag-Erling Smørgrav #include <inttypes.h> 579b50d902SRodney W. Grimes #include <stdio.h> 58ebdb213bSDavid Malone #include <stdlib.h> 590bff6132SJames Raynard #include <unistd.h> 600bff6132SJames Raynard 619b50d902SRodney W. Grimes #include "ktrace.h" 629b50d902SRodney W. Grimes 6301588bbdSMark Murray static char def_tracefile[] = DEF_TRACEFILE; 6401588bbdSMark Murray 6599afdfe5SDag-Erling Smørgrav static enum clear { NOTSET, CLEAR, CLEARALL } clear = NOTSET; 6699afdfe5SDag-Erling Smørgrav static int pid; 6799afdfe5SDag-Erling Smørgrav 68ebdb213bSDavid Malone static void no_ktrace(int); 6999afdfe5SDag-Erling Smørgrav static void set_pid_clear(const char *, enum clear); 70ebdb213bSDavid Malone static void usage(void); 71b0130767SAndreas Schulz 72ebdb213bSDavid Malone int 7301588bbdSMark Murray main(int argc, char *argv[]) 749b50d902SRodney W. Grimes { 7599afdfe5SDag-Erling Smørgrav int append, ch, fd, inherit, ops, trpoints; 76ebdb213bSDavid Malone const char *tracefile; 774ac5adf0SJoerg Wunsch mode_t omask; 789bedbe6cSJoerg Wunsch struct stat sb; 799b50d902SRodney W. Grimes 8099afdfe5SDag-Erling Smørgrav append = ops = inherit = 0; 819b50d902SRodney W. Grimes trpoints = DEF_POINTS; 8201588bbdSMark Murray tracefile = def_tracefile; 831c8af878SWarner Losh while ((ch = getopt(argc,argv,"aCcdf:g:ip:t:")) != -1) 849b50d902SRodney W. Grimes switch((char)ch) { 859b50d902SRodney W. Grimes case 'a': 869b50d902SRodney W. Grimes append = 1; 879b50d902SRodney W. Grimes break; 889b50d902SRodney W. Grimes case 'C': 8999afdfe5SDag-Erling Smørgrav set_pid_clear("1", CLEARALL); 909b50d902SRodney W. Grimes break; 919b50d902SRodney W. Grimes case 'c': 9299afdfe5SDag-Erling Smørgrav set_pid_clear(NULL, CLEAR); 939b50d902SRodney W. Grimes break; 949b50d902SRodney W. Grimes case 'd': 959b50d902SRodney W. Grimes ops |= KTRFLAG_DESCEND; 969b50d902SRodney W. Grimes break; 979b50d902SRodney W. Grimes case 'f': 989b50d902SRodney W. Grimes tracefile = optarg; 999b50d902SRodney W. Grimes break; 1009b50d902SRodney W. Grimes case 'g': 10199afdfe5SDag-Erling Smørgrav set_pid_clear(optarg, NOTSET); 10299afdfe5SDag-Erling Smørgrav pid = -pid; 1039b50d902SRodney W. Grimes break; 1049b50d902SRodney W. Grimes case 'i': 1059b50d902SRodney W. Grimes inherit = 1; 1069b50d902SRodney W. Grimes break; 1079b50d902SRodney W. Grimes case 'p': 10899afdfe5SDag-Erling Smørgrav set_pid_clear(optarg, NOTSET); 1099b50d902SRodney W. Grimes break; 1109b50d902SRodney W. Grimes case 't': 1119b50d902SRodney W. Grimes trpoints = getpoints(optarg); 1129b50d902SRodney W. Grimes if (trpoints < 0) { 1130bff6132SJames Raynard warnx("unknown facility in %s", optarg); 1149b50d902SRodney W. Grimes usage(); 1159b50d902SRodney W. Grimes } 1169b50d902SRodney W. Grimes break; 1179b50d902SRodney W. Grimes default: 1189b50d902SRodney W. Grimes usage(); 1199b50d902SRodney W. Grimes } 12099afdfe5SDag-Erling Smørgrav 1219b50d902SRodney W. Grimes argv += optind; 1229b50d902SRodney W. Grimes argc -= optind; 1239b50d902SRodney W. Grimes 12499afdfe5SDag-Erling Smørgrav /* must have either -[Cc], a pid or a command */ 12599afdfe5SDag-Erling Smørgrav if (clear == NOTSET && pid == 0 && argc == 0) 1269b50d902SRodney W. Grimes usage(); 12799afdfe5SDag-Erling Smørgrav /* can't have both a pid and a command */ 12899afdfe5SDag-Erling Smørgrav /* (note that -C sets pid to 1) */ 12999afdfe5SDag-Erling Smørgrav if (pid != 0 && argc > 0) { 13099afdfe5SDag-Erling Smørgrav usage(); 13199afdfe5SDag-Erling Smørgrav } 1329b50d902SRodney W. Grimes 1339b50d902SRodney W. Grimes if (inherit) 1349b50d902SRodney W. Grimes trpoints |= KTRFAC_INHERIT; 1359b50d902SRodney W. Grimes 1360bff6132SJames Raynard (void)signal(SIGSYS, no_ktrace); 1379b50d902SRodney W. Grimes if (clear != NOTSET) { 1389b50d902SRodney W. Grimes if (clear == CLEARALL) { 1399b50d902SRodney W. Grimes ops = KTROP_CLEAR | KTRFLAG_DESCEND; 1409b50d902SRodney W. Grimes trpoints = ALL_POINTS; 14199afdfe5SDag-Erling Smørgrav } else { 14299afdfe5SDag-Erling Smørgrav ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE; 14399afdfe5SDag-Erling Smørgrav } 1449b50d902SRodney W. Grimes if (ktrace(tracefile, ops, trpoints, pid) < 0) 1450c4d24a7SKris Kennaway err(1, "%s", tracefile); 1469b50d902SRodney W. Grimes exit(0); 1479b50d902SRodney W. Grimes } 1489b50d902SRodney W. Grimes 1494ac5adf0SJoerg Wunsch omask = umask(S_IRWXG|S_IRWXO); 1509bedbe6cSJoerg Wunsch if (append) { 1519e92c8d4SRobert Watson if ((fd = open(tracefile, O_CREAT | O_WRONLY | O_NONBLOCK, 1529e92c8d4SRobert Watson DEFFILEMODE)) < 0) 1530c4d24a7SKris Kennaway err(1, "%s", tracefile); 1549bedbe6cSJoerg Wunsch if (fstat(fd, &sb) != 0 || sb.st_uid != getuid()) 15565b386f1SPhilippe Charnier errx(1, "refuse to append to %s not owned by you", 1569bedbe6cSJoerg Wunsch tracefile); 1579e92c8d4SRobert Watson if (!(S_ISREG(sb.st_mode))) 1589e92c8d4SRobert Watson errx(1, "%s not regular file", tracefile); 1599bedbe6cSJoerg Wunsch } else { 1609bedbe6cSJoerg Wunsch if (unlink(tracefile) == -1 && errno != ENOENT) 1619bedbe6cSJoerg Wunsch err(1, "unlink %s", tracefile); 1629bedbe6cSJoerg Wunsch if ((fd = open(tracefile, O_CREAT | O_EXCL | O_WRONLY, 1639b50d902SRodney W. Grimes DEFFILEMODE)) < 0) 1640c4d24a7SKris Kennaway err(1, "%s", tracefile); 1659bedbe6cSJoerg Wunsch } 1664ac5adf0SJoerg Wunsch (void)umask(omask); 1679b50d902SRodney W. Grimes (void)close(fd); 1689b50d902SRodney W. Grimes 1697144d36fSDmitry Chagin trpoints |= PROC_ABI_POINTS; 1707144d36fSDmitry Chagin 17199afdfe5SDag-Erling Smørgrav if (argc > 0) { 1729b50d902SRodney W. Grimes if (ktrace(tracefile, ops, trpoints, getpid()) < 0) 1730c4d24a7SKris Kennaway err(1, "%s", tracefile); 17499afdfe5SDag-Erling Smørgrav execvp(*argv, argv); 17599afdfe5SDag-Erling Smørgrav err(1, "exec of '%s' failed", *argv); 1769b50d902SRodney W. Grimes } 17799afdfe5SDag-Erling Smørgrav if (ktrace(tracefile, ops, trpoints, pid) < 0) 1780c4d24a7SKris Kennaway err(1, "%s", tracefile); 1799b50d902SRodney W. Grimes exit(0); 1809b50d902SRodney W. Grimes } 1819b50d902SRodney W. Grimes 18299afdfe5SDag-Erling Smørgrav static void 18399afdfe5SDag-Erling Smørgrav set_pid_clear(const char *p, enum clear cl) 1849b50d902SRodney W. Grimes { 18599afdfe5SDag-Erling Smørgrav intmax_t n; 18699afdfe5SDag-Erling Smørgrav char *e; 1879b50d902SRodney W. Grimes 18899afdfe5SDag-Erling Smørgrav if (clear != NOTSET && cl != NOTSET) { 18999afdfe5SDag-Erling Smørgrav /* either -c and -C or either of them twice */ 19099afdfe5SDag-Erling Smørgrav warnx("only one -c or -C flag is permitted"); 19199afdfe5SDag-Erling Smørgrav usage(); 19299afdfe5SDag-Erling Smørgrav } 19399afdfe5SDag-Erling Smørgrav if ((clear == CLEARALL && p != NULL) || (cl == CLEARALL && pid != 0)) { 19499afdfe5SDag-Erling Smørgrav /* both -C and a pid or pgid */ 19599afdfe5SDag-Erling Smørgrav warnx("the -C flag may not be combined with -g or -p"); 19699afdfe5SDag-Erling Smørgrav usage(); 19799afdfe5SDag-Erling Smørgrav } 19899afdfe5SDag-Erling Smørgrav if (p != NULL && pid != 0) { 19999afdfe5SDag-Erling Smørgrav /* either -p and -g or either of them twice */ 20065b386f1SPhilippe Charnier warnx("only one -g or -p flag is permitted"); 2019b50d902SRodney W. Grimes usage(); 2029b50d902SRodney W. Grimes } 20399afdfe5SDag-Erling Smørgrav if (p != NULL) { 20499afdfe5SDag-Erling Smørgrav errno = 0; 20599afdfe5SDag-Erling Smørgrav n = strtoimax(p, &e, 10); 20699afdfe5SDag-Erling Smørgrav /* 20799afdfe5SDag-Erling Smørgrav * 1) not a number, or outside the range of an intmax_t 20899afdfe5SDag-Erling Smørgrav * 2) inside the range of intmax_t but outside the range 20999afdfe5SDag-Erling Smørgrav * of an int, keeping in mind that the pid may be 21099afdfe5SDag-Erling Smørgrav * negated if it's actually a pgid. 21199afdfe5SDag-Erling Smørgrav */ 21299afdfe5SDag-Erling Smørgrav if (*e != '\0' || n < 1 || errno == ERANGE || 21399afdfe5SDag-Erling Smørgrav n > (intmax_t)INT_MAX || n > -(intmax_t)INT_MIN) { 21499afdfe5SDag-Erling Smørgrav warnx("invalid process or group id"); 2159b50d902SRodney W. Grimes usage(); 2169b50d902SRodney W. Grimes } 21799afdfe5SDag-Erling Smørgrav pid = n; 21899afdfe5SDag-Erling Smørgrav } 21999afdfe5SDag-Erling Smørgrav if (cl != NOTSET) 22099afdfe5SDag-Erling Smørgrav if ((clear = cl) == CLEARALL) 22199afdfe5SDag-Erling Smørgrav pid = 1; 2229b50d902SRodney W. Grimes } 2239b50d902SRodney W. Grimes 224ebdb213bSDavid Malone static void 22501588bbdSMark Murray usage(void) 2269b50d902SRodney W. Grimes { 22799afdfe5SDag-Erling Smørgrav 22899afdfe5SDag-Erling Smørgrav fprintf(stderr, "%s\n%s\n", 229da647ae9SRuslan Ermilov "usage: ktrace [-aCcdi] [-f trfile] [-g pgrp | -p pid] [-t trstr]", 230da647ae9SRuslan Ermilov " ktrace [-adi] [-f trfile] [-t trstr] command"); 2319b50d902SRodney W. Grimes exit(1); 2329b50d902SRodney W. Grimes } 2330bff6132SJames Raynard 234ebdb213bSDavid Malone static void 23501588bbdSMark Murray no_ktrace(int sig __unused) 2360bff6132SJames Raynard { 23799afdfe5SDag-Erling Smørgrav 23899afdfe5SDag-Erling Smørgrav fprintf(stderr, "error:\t%s\n\t%s\n", 23999afdfe5SDag-Erling Smørgrav "ktrace() system call not supported in the running kernel", 24099afdfe5SDag-Erling Smørgrav "re-compile kernel with 'options KTRACE'"); 2410bff6132SJames Raynard exit(1); 2420bff6132SJames Raynard } 243