19b50d902SRodney W. Grimes /*- 29b50d902SRodney W. Grimes * Copyright (c) 1988, 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 69b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 79b50d902SRodney W. Grimes * are met: 89b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 99b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 109b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 129b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 139b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 149b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 159b50d902SRodney W. Grimes * without specific prior written permission. 169b50d902SRodney W. Grimes * 179b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 189b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 199b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 209b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 219b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 229b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 239b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 249b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 259b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 269b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 279b50d902SRodney W. Grimes * SUCH DAMAGE. 289b50d902SRodney W. Grimes */ 299b50d902SRodney W. Grimes 309b50d902SRodney W. Grimes #ifndef lint 31ebdb213bSDavid Malone static const char copyright[] = 329b50d902SRodney W. Grimes "@(#) Copyright (c) 1988, 1993\n\ 339b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 349b50d902SRodney W. Grimes #endif /* not lint */ 359b50d902SRodney W. Grimes 360bff6132SJames Raynard #if 0 3765b386f1SPhilippe Charnier #ifndef lint 389b50d902SRodney W. Grimes static char sccsid[] = "@(#)ktrace.c 8.1 (Berkeley) 6/6/93"; 399b50d902SRodney W. Grimes #endif /* not lint */ 4065b386f1SPhilippe Charnier #endif 4165b386f1SPhilippe Charnier 42ebdb213bSDavid Malone #include <sys/cdefs.h> 43ebdb213bSDavid Malone __FBSDID("$FreeBSD$"); 44ebdb213bSDavid Malone 459b50d902SRodney W. Grimes #include <sys/param.h> 469b50d902SRodney W. Grimes #include <sys/file.h> 47*99afdfe5SDag-Erling Smørgrav #include <sys/stat.h> 489b50d902SRodney W. Grimes #include <sys/time.h> 499b50d902SRodney W. Grimes #include <sys/uio.h> 509b50d902SRodney W. Grimes #include <sys/ktrace.h> 510bff6132SJames Raynard 520bff6132SJames Raynard #include <err.h> 53*99afdfe5SDag-Erling Smørgrav #include <errno.h> 54*99afdfe5SDag-Erling Smørgrav #include <inttypes.h> 559b50d902SRodney W. Grimes #include <stdio.h> 56ebdb213bSDavid Malone #include <stdlib.h> 570bff6132SJames Raynard #include <unistd.h> 580bff6132SJames Raynard 599b50d902SRodney W. Grimes #include "ktrace.h" 609b50d902SRodney W. Grimes 6101588bbdSMark Murray static char def_tracefile[] = DEF_TRACEFILE; 6201588bbdSMark Murray 63*99afdfe5SDag-Erling Smørgrav static enum clear { NOTSET, CLEAR, CLEARALL } clear = NOTSET; 64*99afdfe5SDag-Erling Smørgrav static int pid; 65*99afdfe5SDag-Erling Smørgrav 66ebdb213bSDavid Malone static void no_ktrace(int); 67*99afdfe5SDag-Erling Smørgrav static void set_pid_clear(const char *, enum clear); 68ebdb213bSDavid Malone static void usage(void); 69b0130767SAndreas Schulz 70ebdb213bSDavid Malone int 7101588bbdSMark Murray main(int argc, char *argv[]) 729b50d902SRodney W. Grimes { 73*99afdfe5SDag-Erling Smørgrav int append, ch, fd, inherit, ops, trpoints; 74ebdb213bSDavid Malone const char *tracefile; 754ac5adf0SJoerg Wunsch mode_t omask; 769bedbe6cSJoerg Wunsch struct stat sb; 779b50d902SRodney W. Grimes 78*99afdfe5SDag-Erling Smørgrav append = ops = inherit = 0; 799b50d902SRodney W. Grimes trpoints = DEF_POINTS; 8001588bbdSMark Murray tracefile = def_tracefile; 811c8af878SWarner Losh while ((ch = getopt(argc,argv,"aCcdf:g:ip:t:")) != -1) 829b50d902SRodney W. Grimes switch((char)ch) { 839b50d902SRodney W. Grimes case 'a': 849b50d902SRodney W. Grimes append = 1; 859b50d902SRodney W. Grimes break; 869b50d902SRodney W. Grimes case 'C': 87*99afdfe5SDag-Erling Smørgrav set_pid_clear("1", CLEARALL); 889b50d902SRodney W. Grimes break; 899b50d902SRodney W. Grimes case 'c': 90*99afdfe5SDag-Erling Smørgrav set_pid_clear(NULL, CLEAR); 919b50d902SRodney W. Grimes break; 929b50d902SRodney W. Grimes case 'd': 939b50d902SRodney W. Grimes ops |= KTRFLAG_DESCEND; 949b50d902SRodney W. Grimes break; 959b50d902SRodney W. Grimes case 'f': 969b50d902SRodney W. Grimes tracefile = optarg; 979b50d902SRodney W. Grimes break; 989b50d902SRodney W. Grimes case 'g': 99*99afdfe5SDag-Erling Smørgrav set_pid_clear(optarg, NOTSET); 100*99afdfe5SDag-Erling Smørgrav pid = -pid; 1019b50d902SRodney W. Grimes break; 1029b50d902SRodney W. Grimes case 'i': 1039b50d902SRodney W. Grimes inherit = 1; 1049b50d902SRodney W. Grimes break; 1059b50d902SRodney W. Grimes case 'p': 106*99afdfe5SDag-Erling Smørgrav set_pid_clear(optarg, NOTSET); 1079b50d902SRodney W. Grimes break; 1089b50d902SRodney W. Grimes case 't': 1099b50d902SRodney W. Grimes trpoints = getpoints(optarg); 1109b50d902SRodney W. Grimes if (trpoints < 0) { 1110bff6132SJames Raynard warnx("unknown facility in %s", optarg); 1129b50d902SRodney W. Grimes usage(); 1139b50d902SRodney W. Grimes } 1149b50d902SRodney W. Grimes break; 1159b50d902SRodney W. Grimes default: 1169b50d902SRodney W. Grimes usage(); 1179b50d902SRodney W. Grimes } 118*99afdfe5SDag-Erling Smørgrav 1199b50d902SRodney W. Grimes argv += optind; 1209b50d902SRodney W. Grimes argc -= optind; 1219b50d902SRodney W. Grimes 122*99afdfe5SDag-Erling Smørgrav /* must have either -[Cc], a pid or a command */ 123*99afdfe5SDag-Erling Smørgrav if (clear == NOTSET && pid == 0 && argc == 0) 1249b50d902SRodney W. Grimes usage(); 125*99afdfe5SDag-Erling Smørgrav /* can't have both a pid and a command */ 126*99afdfe5SDag-Erling Smørgrav /* (note that -C sets pid to 1) */ 127*99afdfe5SDag-Erling Smørgrav if (pid != 0 && argc > 0) { 128*99afdfe5SDag-Erling Smørgrav usage(); 129*99afdfe5SDag-Erling Smørgrav } 1309b50d902SRodney W. Grimes 1319b50d902SRodney W. Grimes if (inherit) 1329b50d902SRodney W. Grimes trpoints |= KTRFAC_INHERIT; 1339b50d902SRodney W. Grimes 1340bff6132SJames Raynard (void)signal(SIGSYS, no_ktrace); 1359b50d902SRodney W. Grimes if (clear != NOTSET) { 1369b50d902SRodney W. Grimes if (clear == CLEARALL) { 1379b50d902SRodney W. Grimes ops = KTROP_CLEAR | KTRFLAG_DESCEND; 1389b50d902SRodney W. Grimes trpoints = ALL_POINTS; 139*99afdfe5SDag-Erling Smørgrav } else { 140*99afdfe5SDag-Erling Smørgrav ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE; 141*99afdfe5SDag-Erling Smørgrav } 1429b50d902SRodney W. Grimes if (ktrace(tracefile, ops, trpoints, pid) < 0) 1430c4d24a7SKris Kennaway err(1, "%s", tracefile); 1449b50d902SRodney W. Grimes exit(0); 1459b50d902SRodney W. Grimes } 1469b50d902SRodney W. Grimes 1474ac5adf0SJoerg Wunsch omask = umask(S_IRWXG|S_IRWXO); 1489bedbe6cSJoerg Wunsch if (append) { 1499e92c8d4SRobert Watson if ((fd = open(tracefile, O_CREAT | O_WRONLY | O_NONBLOCK, 1509e92c8d4SRobert Watson DEFFILEMODE)) < 0) 1510c4d24a7SKris Kennaway err(1, "%s", tracefile); 1529bedbe6cSJoerg Wunsch if (fstat(fd, &sb) != 0 || sb.st_uid != getuid()) 15365b386f1SPhilippe Charnier errx(1, "refuse to append to %s not owned by you", 1549bedbe6cSJoerg Wunsch tracefile); 1559e92c8d4SRobert Watson if (!(S_ISREG(sb.st_mode))) 1569e92c8d4SRobert Watson errx(1, "%s not regular file", tracefile); 1579bedbe6cSJoerg Wunsch } else { 1589bedbe6cSJoerg Wunsch if (unlink(tracefile) == -1 && errno != ENOENT) 1599bedbe6cSJoerg Wunsch err(1, "unlink %s", tracefile); 1609bedbe6cSJoerg Wunsch if ((fd = open(tracefile, O_CREAT | O_EXCL | O_WRONLY, 1619b50d902SRodney W. Grimes DEFFILEMODE)) < 0) 1620c4d24a7SKris Kennaway err(1, "%s", tracefile); 1639bedbe6cSJoerg Wunsch } 1644ac5adf0SJoerg Wunsch (void)umask(omask); 1659b50d902SRodney W. Grimes (void)close(fd); 1669b50d902SRodney W. Grimes 1677144d36fSDmitry Chagin trpoints |= PROC_ABI_POINTS; 1687144d36fSDmitry Chagin 169*99afdfe5SDag-Erling Smørgrav if (argc > 0) { 1709b50d902SRodney W. Grimes if (ktrace(tracefile, ops, trpoints, getpid()) < 0) 1710c4d24a7SKris Kennaway err(1, "%s", tracefile); 172*99afdfe5SDag-Erling Smørgrav execvp(*argv, argv); 173*99afdfe5SDag-Erling Smørgrav err(1, "exec of '%s' failed", *argv); 1749b50d902SRodney W. Grimes } 175*99afdfe5SDag-Erling Smørgrav if (ktrace(tracefile, ops, trpoints, pid) < 0) 1760c4d24a7SKris Kennaway err(1, "%s", tracefile); 1779b50d902SRodney W. Grimes exit(0); 1789b50d902SRodney W. Grimes } 1799b50d902SRodney W. Grimes 180*99afdfe5SDag-Erling Smørgrav static void 181*99afdfe5SDag-Erling Smørgrav set_pid_clear(const char *p, enum clear cl) 1829b50d902SRodney W. Grimes { 183*99afdfe5SDag-Erling Smørgrav intmax_t n; 184*99afdfe5SDag-Erling Smørgrav char *e; 1859b50d902SRodney W. Grimes 186*99afdfe5SDag-Erling Smørgrav if (clear != NOTSET && cl != NOTSET) { 187*99afdfe5SDag-Erling Smørgrav /* either -c and -C or either of them twice */ 188*99afdfe5SDag-Erling Smørgrav warnx("only one -c or -C flag is permitted"); 189*99afdfe5SDag-Erling Smørgrav usage(); 190*99afdfe5SDag-Erling Smørgrav } 191*99afdfe5SDag-Erling Smørgrav if ((clear == CLEARALL && p != NULL) || (cl == CLEARALL && pid != 0)) { 192*99afdfe5SDag-Erling Smørgrav /* both -C and a pid or pgid */ 193*99afdfe5SDag-Erling Smørgrav warnx("the -C flag may not be combined with -g or -p"); 194*99afdfe5SDag-Erling Smørgrav usage(); 195*99afdfe5SDag-Erling Smørgrav } 196*99afdfe5SDag-Erling Smørgrav if (p != NULL && pid != 0) { 197*99afdfe5SDag-Erling Smørgrav /* either -p and -g or either of them twice */ 19865b386f1SPhilippe Charnier warnx("only one -g or -p flag is permitted"); 1999b50d902SRodney W. Grimes usage(); 2009b50d902SRodney W. Grimes } 201*99afdfe5SDag-Erling Smørgrav if (p != NULL) { 202*99afdfe5SDag-Erling Smørgrav errno = 0; 203*99afdfe5SDag-Erling Smørgrav n = strtoimax(p, &e, 10); 204*99afdfe5SDag-Erling Smørgrav /* 205*99afdfe5SDag-Erling Smørgrav * 1) not a number, or outside the range of an intmax_t 206*99afdfe5SDag-Erling Smørgrav * 2) inside the range of intmax_t but outside the range 207*99afdfe5SDag-Erling Smørgrav * of an int, keeping in mind that the pid may be 208*99afdfe5SDag-Erling Smørgrav * negated if it's actually a pgid. 209*99afdfe5SDag-Erling Smørgrav */ 210*99afdfe5SDag-Erling Smørgrav if (*e != '\0' || n < 1 || errno == ERANGE || 211*99afdfe5SDag-Erling Smørgrav n > (intmax_t)INT_MAX || n > -(intmax_t)INT_MIN) { 212*99afdfe5SDag-Erling Smørgrav warnx("invalid process or group id"); 2139b50d902SRodney W. Grimes usage(); 2149b50d902SRodney W. Grimes } 215*99afdfe5SDag-Erling Smørgrav pid = n; 216*99afdfe5SDag-Erling Smørgrav } 217*99afdfe5SDag-Erling Smørgrav if (cl != NOTSET) 218*99afdfe5SDag-Erling Smørgrav if ((clear = cl) == CLEARALL) 219*99afdfe5SDag-Erling Smørgrav pid = 1; 2209b50d902SRodney W. Grimes } 2219b50d902SRodney W. Grimes 222ebdb213bSDavid Malone static void 22301588bbdSMark Murray usage(void) 2249b50d902SRodney W. Grimes { 225*99afdfe5SDag-Erling Smørgrav 226*99afdfe5SDag-Erling Smørgrav fprintf(stderr, "%s\n%s\n", 227da647ae9SRuslan Ermilov "usage: ktrace [-aCcdi] [-f trfile] [-g pgrp | -p pid] [-t trstr]", 228da647ae9SRuslan Ermilov " ktrace [-adi] [-f trfile] [-t trstr] command"); 2299b50d902SRodney W. Grimes exit(1); 2309b50d902SRodney W. Grimes } 2310bff6132SJames Raynard 232ebdb213bSDavid Malone static void 23301588bbdSMark Murray no_ktrace(int sig __unused) 2340bff6132SJames Raynard { 235*99afdfe5SDag-Erling Smørgrav 236*99afdfe5SDag-Erling Smørgrav fprintf(stderr, "error:\t%s\n\t%s\n", 237*99afdfe5SDag-Erling Smørgrav "ktrace() system call not supported in the running kernel", 238*99afdfe5SDag-Erling Smørgrav "re-compile kernel with 'options KTRACE'"); 2390bff6132SJames Raynard exit(1); 2400bff6132SJames Raynard } 241