1d5303c80SXin LI /*- 20a6c71f8SWarner Losh * Copyright 1997 Sean Eric Fagan 309d64da3SSean Eric Fagan * 409d64da3SSean Eric Fagan * Redistribution and use in source and binary forms, with or without 509d64da3SSean Eric Fagan * modification, are permitted provided that the following conditions 609d64da3SSean Eric Fagan * are met: 709d64da3SSean Eric Fagan * 1. Redistributions of source code must retain the above copyright 809d64da3SSean Eric Fagan * notice, this list of conditions and the following disclaimer. 909d64da3SSean Eric Fagan * 2. Redistributions in binary form must reproduce the above copyright 1009d64da3SSean Eric Fagan * notice, this list of conditions and the following disclaimer in the 1109d64da3SSean Eric Fagan * documentation and/or other materials provided with the distribution. 1209d64da3SSean Eric Fagan * 3. All advertising materials mentioning features or use of this software 1309d64da3SSean Eric Fagan * must display the following acknowledgement: 1409d64da3SSean Eric Fagan * This product includes software developed by Sean Eric Fagan 1509d64da3SSean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote 1609d64da3SSean Eric Fagan * products derived from this software without specific prior written 1709d64da3SSean Eric Fagan * permission. 1809d64da3SSean Eric Fagan * 1909d64da3SSean Eric Fagan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2009d64da3SSean Eric Fagan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2109d64da3SSean Eric Fagan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2209d64da3SSean Eric Fagan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2309d64da3SSean Eric Fagan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2409d64da3SSean Eric Fagan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2509d64da3SSean Eric Fagan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2609d64da3SSean Eric Fagan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2709d64da3SSean Eric Fagan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2809d64da3SSean Eric Fagan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2909d64da3SSean Eric Fagan * SUCH DAMAGE. 3009d64da3SSean Eric Fagan */ 3109d64da3SSean Eric Fagan 32b956c13cSPhilippe Charnier #include <sys/cdefs.h> 33b956c13cSPhilippe Charnier __FBSDID("$FreeBSD$"); 343cf51049SPhilippe Charnier 3509d64da3SSean Eric Fagan /* 36bbeaf6c0SSean Eric Fagan * The main module for truss. Suprisingly simple, but, then, the other 37bbeaf6c0SSean Eric Fagan * files handle the bulk of the work. And, of course, the kernel has to 38bbeaf6c0SSean Eric Fagan * do a lot of the work :). 39bbeaf6c0SSean Eric Fagan */ 40bbeaf6c0SSean Eric Fagan 41580e0a2bSDag-Erling Smørgrav #include <sys/param.h> 425cdf6a13SMartin Cracauer #include <sys/types.h> 431d631f7eSMike Barcroft #include <sys/time.h> 445cdf6a13SMartin Cracauer #include <sys/resource.h> 455d2d083cSXin LI #include <sys/sysctl.h> 46d5303c80SXin LI #include <sys/wait.h> 47580e0a2bSDag-Erling Smørgrav 48d75300bfSAlfred Perlstein #include <ctype.h> 493cf51049SPhilippe Charnier #include <err.h> 50821df508SXin LI #include <errno.h> 51821df508SXin LI #include <fcntl.h> 523cf51049SPhilippe Charnier #include <signal.h> 53bbeaf6c0SSean Eric Fagan #include <stdio.h> 54bbeaf6c0SSean Eric Fagan #include <stdlib.h> 55bbeaf6c0SSean Eric Fagan #include <string.h> 5637169f94SMatthew N. Dodd #include <time.h> 5795c4ef65SPeter Wemm #include <unistd.h> 58bbeaf6c0SSean Eric Fagan 59ec0bed25SMatthew N. Dodd #include "truss.h" 601be5d704SMark Murray #include "extern.h" 61ee3b0f6eSDiomidis Spinellis #include "syscall.h" 62bbeaf6c0SSean Eric Fagan 633e1b6078SMarcel Moolenaar #define MAXARGS 6 64bbeaf6c0SSean Eric Fagan 655321ae86SAlfred Perlstein static void 663cf51049SPhilippe Charnier usage(void) 673cf51049SPhilippe Charnier { 683cf51049SPhilippe Charnier fprintf(stderr, "%s\n%s\n", 69ee3b0f6eSDiomidis Spinellis "usage: truss [-cfaedDS] [-o file] [-s strsize] -p pid", 70ee3b0f6eSDiomidis Spinellis " truss [-cfaedDS] [-o file] [-s strsize] command [args]"); 71bbeaf6c0SSean Eric Fagan exit(1); 72bbeaf6c0SSean Eric Fagan } 73bbeaf6c0SSean Eric Fagan 743625b514SSean Eric Fagan /* 753625b514SSean Eric Fagan * WARNING! "FreeBSD a.out" must be first, or set_etype will not 763625b514SSean Eric Fagan * work correctly. 773625b514SSean Eric Fagan */ 78bbeaf6c0SSean Eric Fagan struct ex_types { 791be5d704SMark Murray const char *type; 80ec0bed25SMatthew N. Dodd void (*enter_syscall)(struct trussinfo *, int); 811bcb5f5aSMarcel Moolenaar long (*exit_syscall)(struct trussinfo *, int); 82bbeaf6c0SSean Eric Fagan } ex_types[] = { 83a5d31d16SDavid Malone #ifdef __amd64__ 84a5d31d16SDavid Malone { "FreeBSD ELF64", amd64_syscall_entry, amd64_syscall_exit }, 859a55503eSJohn Baldwin { "FreeBSD ELF32", amd64_fbsd32_syscall_entry, amd64_fbsd32_syscall_exit }, 869a55503eSJohn Baldwin { "Linux ELF32", amd64_linux32_syscall_entry, amd64_linux32_syscall_exit }, 87a5d31d16SDavid Malone #endif 8850cc4492SSean Eric Fagan #ifdef __i386__ 89bbeaf6c0SSean Eric Fagan { "FreeBSD a.out", i386_syscall_entry, i386_syscall_exit }, 9087893934SPeter Wemm { "FreeBSD ELF", i386_syscall_entry, i386_syscall_exit }, 910629483cSMatthew N. Dodd { "FreeBSD ELF32", i386_syscall_entry, i386_syscall_exit }, 92bbeaf6c0SSean Eric Fagan { "Linux ELF", i386_linux_syscall_entry, i386_linux_syscall_exit }, 9350cc4492SSean Eric Fagan #endif 94a3e32192SMarcel Moolenaar #ifdef __ia64__ 95a3e32192SMarcel Moolenaar { "FreeBSD ELF64", ia64_syscall_entry, ia64_syscall_exit }, 96a3e32192SMarcel Moolenaar #endif 977fa9dc1cSPeter Grehan #ifdef __powerpc__ 987fa9dc1cSPeter Grehan { "FreeBSD ELF", powerpc_syscall_entry, powerpc_syscall_exit }, 997fa9dc1cSPeter Grehan { "FreeBSD ELF32", powerpc_syscall_entry, powerpc_syscall_exit }, 1004e583321SNathan Whitehorn #ifdef __powerpc64__ 1014e583321SNathan Whitehorn { "FreeBSD ELF64", powerpc64_syscall_entry, powerpc64_syscall_exit }, 1024e583321SNathan Whitehorn #endif 1037fa9dc1cSPeter Grehan #endif 104f84c971aSJake Burkholder #ifdef __sparc64__ 105f84c971aSJake Burkholder { "FreeBSD ELF64", sparc64_syscall_entry, sparc64_syscall_exit }, 106f84c971aSJake Burkholder #endif 10789fe547fSWarner Losh #ifdef __mips__ 10889fe547fSWarner Losh { "FreeBSD ELF", mips_syscall_entry, mips_syscall_exit }, 10989fe547fSWarner Losh { "FreeBSD ELF32", mips_syscall_entry, mips_syscall_exit }, 11089fe547fSWarner Losh { "FreeBSD ELF64", mips_syscall_entry, mips_syscall_exit }, // XXX 11189fe547fSWarner Losh #endif 112bbeaf6c0SSean Eric Fagan { 0, 0, 0 }, 113bbeaf6c0SSean Eric Fagan }; 114bbeaf6c0SSean Eric Fagan 115bbeaf6c0SSean Eric Fagan /* 116bbeaf6c0SSean Eric Fagan * Set the execution type. This is called after every exec, and when 1175d2d083cSXin LI * a process is first monitored. 118bbeaf6c0SSean Eric Fagan */ 119bbeaf6c0SSean Eric Fagan 120bbeaf6c0SSean Eric Fagan static struct ex_types * 1215321ae86SAlfred Perlstein set_etype(struct trussinfo *trussinfo) 1225321ae86SAlfred Perlstein { 123bbeaf6c0SSean Eric Fagan struct ex_types *funcs; 1241be5d704SMark Murray char progt[32]; 125bbeaf6c0SSean Eric Fagan 1265d2d083cSXin LI size_t len = sizeof(progt); 1275d2d083cSXin LI int mib[4]; 1285d2d083cSXin LI int error; 1295d2d083cSXin LI 1305d2d083cSXin LI mib[0] = CTL_KERN; 1315d2d083cSXin LI mib[1] = KERN_PROC; 1325d2d083cSXin LI mib[2] = KERN_PROC_SV_NAME; 1335d2d083cSXin LI mib[3] = trussinfo->pid; 1345d2d083cSXin LI error = sysctl(mib, 4, progt, &len, NULL, 0); 1355d2d083cSXin LI if (error != 0) 1365d2d083cSXin LI err(2, "can not get etype"); 137bbeaf6c0SSean Eric Fagan 138bbeaf6c0SSean Eric Fagan for (funcs = ex_types; funcs->type; funcs++) 1391be5d704SMark Murray if (!strcmp(funcs->type, progt)) 140bbeaf6c0SSean Eric Fagan break; 141bbeaf6c0SSean Eric Fagan 1424525f3a8SDag-Erling Smørgrav if (funcs->type == NULL) { 1433625b514SSean Eric Fagan funcs = &ex_types[0]; 144b956c13cSPhilippe Charnier warn("execution type %s is not supported -- using %s", 1454525f3a8SDag-Erling Smørgrav progt, funcs->type); 1463625b514SSean Eric Fagan } 1475321ae86SAlfred Perlstein return (funcs); 148bbeaf6c0SSean Eric Fagan } 149bbeaf6c0SSean Eric Fagan 150d75300bfSAlfred Perlstein char * 151d75300bfSAlfred Perlstein strsig(int sig) 152d75300bfSAlfred Perlstein { 153d75300bfSAlfred Perlstein char *ret; 154d75300bfSAlfred Perlstein 155d75300bfSAlfred Perlstein ret = NULL; 156d75300bfSAlfred Perlstein if (sig > 0 && sig < NSIG) { 157d75300bfSAlfred Perlstein int i; 158d75300bfSAlfred Perlstein asprintf(&ret, "sig%s", sys_signame[sig]); 159d75300bfSAlfred Perlstein if (ret == NULL) 160d75300bfSAlfred Perlstein return (NULL); 161d75300bfSAlfred Perlstein for (i = 0; ret[i] != '\0'; ++i) 162d75300bfSAlfred Perlstein ret[i] = toupper(ret[i]); 163d75300bfSAlfred Perlstein } 164d75300bfSAlfred Perlstein return (ret); 165d75300bfSAlfred Perlstein } 166d75300bfSAlfred Perlstein 1673cf51049SPhilippe Charnier int 1685321ae86SAlfred Perlstein main(int ac, char **av) 1695321ae86SAlfred Perlstein { 170bbeaf6c0SSean Eric Fagan int c; 171bbeaf6c0SSean Eric Fagan int i; 172d5303c80SXin LI pid_t childpid; 173d5303c80SXin LI int status; 174bbeaf6c0SSean Eric Fagan char **command; 175bbeaf6c0SSean Eric Fagan struct ex_types *funcs; 176ef29ac7fSXin LI int initial_open; 17772aa911aSAlfred Perlstein char *fname; 178ec0bed25SMatthew N. Dodd struct trussinfo *trussinfo; 179d75300bfSAlfred Perlstein char *signame; 180bbeaf6c0SSean Eric Fagan 18172aa911aSAlfred Perlstein fname = NULL; 18272aa911aSAlfred Perlstein initial_open = 1; 18372aa911aSAlfred Perlstein 184ec0bed25SMatthew N. Dodd /* Initialize the trussinfo struct */ 185216fa4c6SXin LI trussinfo = (struct trussinfo *)calloc(1, sizeof(struct trussinfo)); 186ec0bed25SMatthew N. Dodd if (trussinfo == NULL) 187216fa4c6SXin LI errx(1, "calloc() failed"); 1885d2d083cSXin LI 189ec0bed25SMatthew N. Dodd trussinfo->outfile = stderr; 1900cf21b4fSBrian Somers trussinfo->strsize = 32; 1915d2d083cSXin LI trussinfo->pr_why = S_NONE; 1925d2d083cSXin LI trussinfo->curthread = NULL; 1935d2d083cSXin LI SLIST_INIT(&trussinfo->threadlist); 194ee3b0f6eSDiomidis Spinellis while ((c = getopt(ac, av, "p:o:facedDs:S")) != -1) { 195bbeaf6c0SSean Eric Fagan switch (c) { 196bbeaf6c0SSean Eric Fagan case 'p': /* specified pid */ 197ec0bed25SMatthew N. Dodd trussinfo->pid = atoi(optarg); 198ef29ac7fSXin LI /* make sure i don't trace me */ 199ef29ac7fSXin LI if(trussinfo->pid == getpid()) { 200ef29ac7fSXin LI fprintf(stderr, "attempt to grab self.\n"); 201ef29ac7fSXin LI exit(2); 202ef29ac7fSXin LI } 203bbeaf6c0SSean Eric Fagan break; 204c03bfcc8SMatthew N. Dodd case 'f': /* Follow fork()'s */ 205c03bfcc8SMatthew N. Dodd trussinfo->flags |= FOLLOWFORKS; 206c03bfcc8SMatthew N. Dodd break; 2079897b203SMatthew N. Dodd case 'a': /* Print execve() argument strings. */ 2089897b203SMatthew N. Dodd trussinfo->flags |= EXECVEARGS; 2099897b203SMatthew N. Dodd break; 210ee3b0f6eSDiomidis Spinellis case 'c': /* Count number of system calls and time. */ 211ee3b0f6eSDiomidis Spinellis trussinfo->flags |= COUNTONLY; 212ee3b0f6eSDiomidis Spinellis break; 2139897b203SMatthew N. Dodd case 'e': /* Print execve() environment strings. */ 2149897b203SMatthew N. Dodd trussinfo->flags |= EXECVEENVS; 2159897b203SMatthew N. Dodd break; 2160d0bd00eSMatthew N. Dodd case 'd': /* Absolute timestamps */ 2170d0bd00eSMatthew N. Dodd trussinfo->flags |= ABSOLUTETIMESTAMPS; 2180d0bd00eSMatthew N. Dodd break; 2190d0bd00eSMatthew N. Dodd case 'D': /* Relative timestamps */ 2200d0bd00eSMatthew N. Dodd trussinfo->flags |= RELATIVETIMESTAMPS; 2210d0bd00eSMatthew N. Dodd break; 222bbeaf6c0SSean Eric Fagan case 'o': /* Specified output file */ 2233cf51049SPhilippe Charnier fname = optarg; 224bbeaf6c0SSean Eric Fagan break; 2250cf21b4fSBrian Somers case 's': /* Specified string size */ 2260cf21b4fSBrian Somers trussinfo->strsize = atoi(optarg); 2270cf21b4fSBrian Somers break; 228bbeaf6c0SSean Eric Fagan case 'S': /* Don't trace signals */ 229ec0bed25SMatthew N. Dodd trussinfo->flags |= NOSIGS; 230bbeaf6c0SSean Eric Fagan break; 231bbeaf6c0SSean Eric Fagan default: 232bbeaf6c0SSean Eric Fagan usage(); 233bbeaf6c0SSean Eric Fagan } 234bbeaf6c0SSean Eric Fagan } 235bbeaf6c0SSean Eric Fagan 236bbeaf6c0SSean Eric Fagan ac -= optind; av += optind; 2375321ae86SAlfred Perlstein if ((trussinfo->pid == 0 && ac == 0) || 2385321ae86SAlfred Perlstein (trussinfo->pid != 0 && ac != 0)) 239bbeaf6c0SSean Eric Fagan usage(); 240bbeaf6c0SSean Eric Fagan 2413cf51049SPhilippe Charnier if (fname != NULL) { /* Use output file */ 242ec0bed25SMatthew N. Dodd if ((trussinfo->outfile = fopen(fname, "w")) == NULL) 2433cf51049SPhilippe Charnier errx(1, "cannot open %s", fname); 244ecbb6d34SJaakko Heinonen /* 245ecbb6d34SJaakko Heinonen * Set FD_CLOEXEC, so that the output file is not shared with 246ecbb6d34SJaakko Heinonen * the traced process. 247ecbb6d34SJaakko Heinonen */ 248*e04c3786SJaakko Heinonen if (fcntl(fileno(trussinfo->outfile), F_SETFD, FD_CLOEXEC) == 249*e04c3786SJaakko Heinonen -1) 250ecbb6d34SJaakko Heinonen warn("fcntl()"); 251*e04c3786SJaakko Heinonen } 2523cf51049SPhilippe Charnier 253bbeaf6c0SSean Eric Fagan /* 254bbeaf6c0SSean Eric Fagan * If truss starts the process itself, it will ignore some signals -- 255bbeaf6c0SSean Eric Fagan * they should be passed off to the process, which may or may not 256bbeaf6c0SSean Eric Fagan * exit. If, however, we are examining an already-running process, 257bbeaf6c0SSean Eric Fagan * then we restore the event mask on these same signals. 258bbeaf6c0SSean Eric Fagan */ 259bbeaf6c0SSean Eric Fagan 260ec0bed25SMatthew N. Dodd if (trussinfo->pid == 0) { /* Start a command ourselves */ 261bbeaf6c0SSean Eric Fagan command = av; 262ec0bed25SMatthew N. Dodd trussinfo->pid = setup_and_wait(command); 263bbeaf6c0SSean Eric Fagan signal(SIGINT, SIG_IGN); 264bbeaf6c0SSean Eric Fagan signal(SIGTERM, SIG_IGN); 265bbeaf6c0SSean Eric Fagan signal(SIGQUIT, SIG_IGN); 266bbeaf6c0SSean Eric Fagan } else { 2675d2d083cSXin LI start_tracing(trussinfo->pid); 268bbeaf6c0SSean Eric Fagan signal(SIGINT, restore_proc); 269bbeaf6c0SSean Eric Fagan signal(SIGTERM, restore_proc); 270bbeaf6c0SSean Eric Fagan signal(SIGQUIT, restore_proc); 271bbeaf6c0SSean Eric Fagan } 272bbeaf6c0SSean Eric Fagan 273bbeaf6c0SSean Eric Fagan 274bbeaf6c0SSean Eric Fagan /* 275bbeaf6c0SSean Eric Fagan * At this point, if we started the process, it is stopped waiting to 276bbeaf6c0SSean Eric Fagan * be woken up, either in exit() or in execve(). 277bbeaf6c0SSean Eric Fagan */ 278bbeaf6c0SSean Eric Fagan 279c03bfcc8SMatthew N. Dodd START_TRACE: 280ec0bed25SMatthew N. Dodd funcs = set_etype(trussinfo); 2815d2d083cSXin LI 2825d2d083cSXin LI initial_open = 0; 283bbeaf6c0SSean Eric Fagan /* 284bbeaf6c0SSean Eric Fagan * At this point, it's a simple loop, waiting for the process to 285bbeaf6c0SSean Eric Fagan * stop, finding out why, printing out why, and then continuing it. 286bbeaf6c0SSean Eric Fagan * All of the grunt work is done in the support routines. 287bbeaf6c0SSean Eric Fagan */ 288bbeaf6c0SSean Eric Fagan 289203098d8SMatthew N. Dodd clock_gettime(CLOCK_REALTIME, &trussinfo->start_time); 2900d0bd00eSMatthew N. Dodd 291bbeaf6c0SSean Eric Fagan do { 292081e5c48SPav Lucistnik struct timespec timediff; 2935d2d083cSXin LI waitevent(trussinfo); 294bbeaf6c0SSean Eric Fagan 2955d2d083cSXin LI switch(i = trussinfo->pr_why) { 296bbeaf6c0SSean Eric Fagan case S_SCE: 2975d2d083cSXin LI funcs->enter_syscall(trussinfo, MAXARGS); 2985321ae86SAlfred Perlstein clock_gettime(CLOCK_REALTIME, 2995321ae86SAlfred Perlstein &trussinfo->before); 300bbeaf6c0SSean Eric Fagan break; 301bbeaf6c0SSean Eric Fagan case S_SCX: 3025321ae86SAlfred Perlstein clock_gettime(CLOCK_REALTIME, 3035321ae86SAlfred Perlstein &trussinfo->after); 304c03bfcc8SMatthew N. Dodd 3055d2d083cSXin LI if (trussinfo->curthread->in_fork && 3065321ae86SAlfred Perlstein (trussinfo->flags & FOLLOWFORKS)) { 3075d2d083cSXin LI trussinfo->curthread->in_fork = 0; 3085321ae86SAlfred Perlstein childpid = 3095321ae86SAlfred Perlstein funcs->exit_syscall(trussinfo, 3105d2d083cSXin LI trussinfo->pr_data); 311c03bfcc8SMatthew N. Dodd 312c03bfcc8SMatthew N. Dodd /* 3135321ae86SAlfred Perlstein * Fork a new copy of ourself to trace 3145321ae86SAlfred Perlstein * the child of the original traced 3155321ae86SAlfred Perlstein * process. 316c03bfcc8SMatthew N. Dodd */ 317c03bfcc8SMatthew N. Dodd if (fork() == 0) { 318c03bfcc8SMatthew N. Dodd trussinfo->pid = childpid; 3195d2d083cSXin LI start_tracing(trussinfo->pid); 320c03bfcc8SMatthew N. Dodd goto START_TRACE; 321c03bfcc8SMatthew N. Dodd } 322c03bfcc8SMatthew N. Dodd break; 323c03bfcc8SMatthew N. Dodd } 3245d2d083cSXin LI funcs->exit_syscall(trussinfo, MAXARGS); 325bbeaf6c0SSean Eric Fagan break; 326bbeaf6c0SSean Eric Fagan case S_SIG: 3275d2d083cSXin LI if (trussinfo->flags & NOSIGS) 3285d2d083cSXin LI break; 329081e5c48SPav Lucistnik if (trussinfo->flags & FOLLOWFORKS) 330081e5c48SPav Lucistnik fprintf(trussinfo->outfile, "%5d: ", 331081e5c48SPav Lucistnik trussinfo->pid); 332081e5c48SPav Lucistnik if (trussinfo->flags & ABSOLUTETIMESTAMPS) { 333081e5c48SPav Lucistnik timespecsubt(&trussinfo->after, 334081e5c48SPav Lucistnik &trussinfo->start_time, &timediff); 335081e5c48SPav Lucistnik fprintf(trussinfo->outfile, "%ld.%09ld ", 336081e5c48SPav Lucistnik (long)timediff.tv_sec, 337081e5c48SPav Lucistnik timediff.tv_nsec); 338081e5c48SPav Lucistnik } 339081e5c48SPav Lucistnik if (trussinfo->flags & RELATIVETIMESTAMPS) { 340081e5c48SPav Lucistnik timespecsubt(&trussinfo->after, 341081e5c48SPav Lucistnik &trussinfo->before, &timediff); 342081e5c48SPav Lucistnik fprintf(trussinfo->outfile, "%ld.%09ld ", 343081e5c48SPav Lucistnik (long)timediff.tv_sec, 344081e5c48SPav Lucistnik timediff.tv_nsec); 345081e5c48SPav Lucistnik } 3465d2d083cSXin LI signame = strsig(trussinfo->pr_data); 3475321ae86SAlfred Perlstein fprintf(trussinfo->outfile, 3485d2d083cSXin LI "SIGNAL %u (%s)\n", trussinfo->pr_data, 349d75300bfSAlfred Perlstein signame == NULL ? "?" : signame); 350d75300bfSAlfred Perlstein free(signame); 351bbeaf6c0SSean Eric Fagan break; 352bbeaf6c0SSean Eric Fagan case S_EXIT: 353ee3b0f6eSDiomidis Spinellis if (trussinfo->flags & COUNTONLY) 354ee3b0f6eSDiomidis Spinellis break; 355081e5c48SPav Lucistnik if (trussinfo->flags & FOLLOWFORKS) 356081e5c48SPav Lucistnik fprintf(trussinfo->outfile, "%5d: ", 357081e5c48SPav Lucistnik trussinfo->pid); 358081e5c48SPav Lucistnik if (trussinfo->flags & ABSOLUTETIMESTAMPS) { 359081e5c48SPav Lucistnik timespecsubt(&trussinfo->after, 360081e5c48SPav Lucistnik &trussinfo->start_time, &timediff); 361081e5c48SPav Lucistnik fprintf(trussinfo->outfile, "%ld.%09ld ", 362081e5c48SPav Lucistnik (long)timediff.tv_sec, 363081e5c48SPav Lucistnik timediff.tv_nsec); 364081e5c48SPav Lucistnik } 365081e5c48SPav Lucistnik if (trussinfo->flags & RELATIVETIMESTAMPS) { 366081e5c48SPav Lucistnik timespecsubt(&trussinfo->after, 367081e5c48SPav Lucistnik &trussinfo->before, &timediff); 368081e5c48SPav Lucistnik fprintf(trussinfo->outfile, "%ld.%09ld ", 369081e5c48SPav Lucistnik (long)timediff.tv_sec, timediff.tv_nsec); 370081e5c48SPav Lucistnik } 3715321ae86SAlfred Perlstein fprintf(trussinfo->outfile, 3725d2d083cSXin LI "process exit, rval = %u\n", trussinfo->pr_data); 373bbeaf6c0SSean Eric Fagan break; 374bbeaf6c0SSean Eric Fagan default: 375bbeaf6c0SSean Eric Fagan break; 376bbeaf6c0SSean Eric Fagan } 3775d2d083cSXin LI } while (trussinfo->pr_why != S_EXIT); 3785d2d083cSXin LI 379d5303c80SXin LI if (trussinfo->flags & FOLLOWFORKS) 380d5303c80SXin LI do { 381d5303c80SXin LI childpid = wait(&status); 382d5303c80SXin LI } while (childpid != -1); 383d5303c80SXin LI 384ee3b0f6eSDiomidis Spinellis if (trussinfo->flags & COUNTONLY) 385ee3b0f6eSDiomidis Spinellis print_summary(trussinfo); 386ee3b0f6eSDiomidis Spinellis 387ee3b0f6eSDiomidis Spinellis fflush(trussinfo->outfile); 388ee3b0f6eSDiomidis Spinellis 3895321ae86SAlfred Perlstein return (0); 390bbeaf6c0SSean Eric Fagan } 391