strace.c revision 19e49984acc8f12dfaf0b7835ad17ca24f854c47
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* 276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved. 776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without 976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions 1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met: 1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright 1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * notice, this list of conditions and the following disclaimer. 1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright 1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * notice, this list of conditions and the following disclaimer in the 1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * documentation and/or other materials provided with the distribution. 1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products 1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * derived from this software without specific prior written permission. 1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * $Id$ 3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 332ee6e45f36566e8735b35ffad40bfcc626a25a98Wichert Akkerman#include <sys/types.h> 3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h" 3576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h> 3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h> 3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h> 3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h> 4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h> 4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h> 4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h> 4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h> 4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h> 4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h> 4619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h> 4776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 487b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX) 497b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h> 507b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 517b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 52bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 53bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h> 54bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 55bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 5676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 5776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h> 58ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 591d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H 609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h> 619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 6276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 631d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif 6476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 6576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint debug = 0, followfork = 0, followvfork = 0, interactive = 0; 6676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint rflag = 0, tflag = 0, dtime = 0, cflag = 0; 6776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint iflag = 0, xflag = 0, qflag = 0; 6876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pflag_seen = 0; 6976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 7076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *username = NULL; 7176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid; 7276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid; 7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 7476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN; 7576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN; 7676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *outfname = NULL; 7776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf; 7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb tcbtab[MAX_PROCS]; 7976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nprocs; 8076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname; 8176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char version[]; 8276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char **environ; 8376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pid2tcb P((int pid)); 8576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void)); 8676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void)); 8776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig)); 8876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set; 8976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 9076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T 9176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted; 9276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */ 9376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 9476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted; 9576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */ 9676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted; 9776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */ 9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */ 9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 100bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd)); 10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig)); 10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void)); 105e68d61c7d6dcf986d32c462e533ea46f85183db8Wichert Akkermanstruct pollfd pollv[MAX_PROCS]; 10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void)); 11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd)); 11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd { 11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int fd; 11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int revents; 11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}; 11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid; 11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 }; 12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 123ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 1249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLWRNORM 1259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 1269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLPRI 1279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 128bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval) 13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp; 13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval; 13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(ofp, "\ 13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\ 13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman [-p pid] ... [-s strsize] [-u username] [command [arg ...]]\n\ 13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman or: strace -c [-e expr] ... [-O overhead] [-S sortby] [command [arg ...]]\n\ 13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\ 14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\ 14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\ 14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\ 14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\ 14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\ 14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\ 14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman options: trace, abbrev, verbose, raw, signal, read, or write\n\ 15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\ 15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\ 15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\ 15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman", DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(exitval); 15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar() 16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanmain(argc, argv) 17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint argc; 17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *argv[]; 17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern int optind; 17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern char *optarg; 17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int c, pid = 0; 17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[BUFSIZ]; 18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname = argv[0]; 18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = stderr; 18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 1; 18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("trace=all"); 18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=all"); 18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("verbose=all"); 18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("signal=all"); 19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(DEFAULT_SORTBY); 19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_personality(DEFAULT_PERSONALITY); 19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((c = getopt(argc, argv, 19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "+cdfFhiqrtTvVxa:e:o:O:p:s:S:u:")) != EOF) { 19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (c) { 19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'c': 19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cflag++; 19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'd': 20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman debug++; 20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'f': 20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followfork++; 20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'F': 20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followvfork++; 20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'h': 20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stdout, 0); 21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'i': 21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman iflag++; 21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'q': 21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag++; 21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'r': 21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rflag++; 21976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 22076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 22176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 't': 22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 22376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'T': 22576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 22676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 22776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'x': 22876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman xflag++; 22976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 23076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'v': 23176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=none"); 23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'V': 23476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printf("%s\n", version); 23576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 23676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 23776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'a': 23876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman acolumn = atoi(optarg); 23976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 24076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'e': 24176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify(optarg); 24276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 24376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'o': 24476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = strdup(optarg); 24576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 24676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'O': 24776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_overhead(atoi(optarg)); 24876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 24976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'p': 25076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((pid = atoi(optarg)) == 0) { 25176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: Invalid process id: %s\n", 25276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, optarg); 25376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 25476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 25576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == getpid()) { 25654a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname); 25776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 25876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 25976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = alloctcb(pid)) == NULL) { 26076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: tcb table full, please recompile strace\n", 26176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 26276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 26376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 26476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags |= TCB_ATTACHED; 26576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pflag_seen++; 26676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 26776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 's': 26876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman max_strlen = atoi(optarg); 26976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 27076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'S': 27176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(optarg); 27276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'u': 27476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman username = strdup(optarg); 27576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 27676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 27976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to run as another user. */ 28376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL) { 28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct passwd *pent; 28576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 28676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getuid() != 0 || geteuid() != 0) { 28776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 28876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "%s: you must be root to use the -u option\n", 28976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 29076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 29176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 29276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((pent = getpwnam(username)) == NULL) { 29376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: cannot find user `%s'\n", 29476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, optarg); 29576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 29676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 29776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = pent->pw_uid; 29876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = pent->pw_gid; 29976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 30076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 30176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = getuid(); 30276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = getgid(); 30376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 30476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 30576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 30676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 30776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 30876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 30976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to pipe the output. */ 31076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname && (outfname[0] == '|' || outfname[0] == '!')) { 31176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((outf = popen(outfname + 1, "w")) == NULL) { 31276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: can't popen '%s': %s\n", 31376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, outfname + 1, strerror(errno)); 31476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 31576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 31676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman free(outfname); 31776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = NULL; 31876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 31976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 32076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Check if they want to redirect the output. */ 32176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname) { 32254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman long f; 32354b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman 32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((outf = fopen(outfname, "w")) == NULL) { 32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: can't fopen '%s': %s\n", 32676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, outfname, strerror(errno)); 32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 32954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman 33054b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman if ((f=fcntl(fileno(outf), F_GETFD)) < 0 ) { 33154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman perror("failed to get flags for outputfile"); 33254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman exit(1); 33354b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman } 33454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman 33554b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman if (fcntl(fileno(outf), F_SETFD, f|FD_CLOEXEC) < 0 ) { 33654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman perror("failed to set flags for outputfile"); 33754b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman exit(1); 33854b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman } 33976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 34076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 34176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 34276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 34376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 34476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 34576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!outfname) { 34676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 34776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setvbuf(outf, buf, _IOLBF, BUFSIZ); 34876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 34976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (optind < argc) 35076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 0; 35176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 35276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 35376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 35476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (c = 0, tcp = tcbtab; c < MAX_PROCS; c++, tcp++) { 35576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Reinitialize the output since it may have changed. */ 35676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; 35776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED)) 35876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 359bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 36076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_open(tcp, 1) < 0) { 36176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "trouble opening proc file\n"); 36276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 36376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 36476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 365bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 36676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) { 36776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("attach: ptrace(PTRACE_ATTACH, ...)"); 36876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 36976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 37076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 371bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 37276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 37376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 37476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "Process %u attached - interrupt to quit\n", 37576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid); 37676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (optind < argc) { 37976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct stat statbuf; 38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char *filename; 38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char pathname[MAXPATHLEN]; 38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman filename = argv[optind]; 38476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (strchr(filename, '/')) 38576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strcpy(pathname, filename); 38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef USE_DEBUGGING_EXEC 38776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 38876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Debuggers customarily check the current directory 38976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * first regardless of the path but doing that gives 39076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * security geeks a panic attack. 39176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 39276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (stat(filename, &statbuf) == 0) 39376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strcpy(pathname, filename); 39476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* USE_DEBUGGING_EXEC */ 39576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 39676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char *path; 39776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int m, n, len; 39876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 39976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (path = getenv("PATH"); path && *path; path += m) { 40076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (strchr(path, ':')) { 40176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = strchr(path, ':') - path; 40276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman m = n + 1; 40376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 40476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 40576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman m = n = strlen(path); 40676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n == 0) { 40776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman getcwd(pathname, MAXPATHLEN); 40876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman len = strlen(pathname); 40976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 41076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 41176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strncpy(pathname, path, n); 41276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman len = n; 41376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 41476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (len && pathname[len - 1] != '/') 41576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pathname[len++] = '/'; 41676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strcpy(pathname + len, filename); 41776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (stat(pathname, &statbuf) == 0) 41876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 41976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 42076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 42176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (stat(pathname, &statbuf) < 0) { 42276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: %s: command not found\n", 42376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, filename); 42476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 42576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 42676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (pid = fork()) { 42776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 42876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: fork"); 42976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 43076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 43176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 43276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: { 433bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 434bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (outf != stderr) close (fileno (outf)); 43576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 43676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Kludge for SGI, see proc_open for details. */ 43776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = foobar; 43876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 43976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 44076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 44176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 442bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 44376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pause(); 444bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 445bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(getpid(), SIGSTOP); /* stop HERE */ 446bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 447bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 448bd4125c6bcd20e8f014b682b31d6fc5d0fef3ed0Wichert Akkerman if (outf!=stderr) 4497987cdf192632516d6ba493b0a9943f5a3a7c362Wichert Akkerman close(fileno (outf)); 450bd4125c6bcd20e8f014b682b31d6fc5d0fef3ed0Wichert Akkerman 45176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) { 45276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: ptrace(PTRACE_TRACEME, ...)"); 45376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 45476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 45576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 45676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(getpid(), SIGSTOP); 45776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 45876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL || geteuid() == 0) { 45976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman uid_t run_euid = run_uid; 46076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gid_t run_egid = run_gid; 46176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 46276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (statbuf.st_mode & S_ISUID) 46376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_euid = statbuf.st_uid; 46476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (statbuf.st_mode & S_ISGID) 46576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_egid = statbuf.st_gid; 46676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 46776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 46876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * It is important to set groups before we 46976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * lose privileges on setuid. 47076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 4715ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (username != NULL) { 4725ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (initgroups(username, run_gid) < 0) { 4735ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman perror("initgroups"); 4745ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman exit(1); 4755ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman } 4765ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (setregid(run_gid, run_egid) < 0) { 4775ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman perror("setregid"); 4785ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman exit(1); 4795ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman } 4805ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (setreuid(run_uid, run_euid) < 0) { 4815ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman perror("setreuid"); 4825ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman exit(1); 4835ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman } 48476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 48576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 48676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 48776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(run_uid, run_uid); 488bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 48976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 49076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman execv(pathname, &argv[optind]); 49176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: exec"); 49276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(1); 49376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 49476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 49576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 49676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = alloctcb(pid)) == NULL) { 49776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "tcb table full\n"); 49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 49976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 50076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 501bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 50276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_open(tcp, 0) < 0) { 50376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "trouble opening proc file\n"); 50476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 50576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 50676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 507bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 508bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 50976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fake_execve(tcp, pathname, &argv[optind], environ); 510bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 51176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 51276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 51376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 51476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (pflag_seen == 0) 51576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 51676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 51776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 51876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 51976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = SIG_IGN; 52076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 52176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 52276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTOU, &sa, NULL); 52376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTIN, &sa, NULL); 52476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) { 52576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGHUP); 52676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGINT); 52776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGQUIT); 52876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGPIPE); 52976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGTERM); 53076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interrupt; 53176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 53276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* POSIX signals on sunos4.1 are a little broken. */ 53376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = SA_INTERRUPT; 53476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 53576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 53676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 53776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 53876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 53976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 54076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 541bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 54276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = reaper; 54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGCHLD, &sa, NULL); 544bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 54576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 54676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace() < 0) 54776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 54876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 54976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 55076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 55176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 55276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 55376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermannewoutf(tcp) 55476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 55576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 55676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char name[MAXPATHLEN]; 55776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman FILE *fp; 55876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 55976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname && followfork > 1) { 56076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(name, "%s.%u", outfname, tcp->pid); 56176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 56276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 56376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 56476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fp = fopen(name, "w"); 56576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 56676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 56776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 56876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (fp == NULL) { 56976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("fopen"); 57076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 57176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 57276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = fp; 57376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 57476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 57576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 57676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 57776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb * 57876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanalloctcb(pid) 57976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid; 58076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 58176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 58276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 58376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 58476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) { 58576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_INUSE) == 0) { 58676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = pid; 58776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->parent = NULL; 58876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->nchildren = 0; 58976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags = TCB_INUSE | TCB_STARTUP; 59076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; /* Initialise to current out file */ 59176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime.tv_sec = 0; 59276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime.tv_usec = 0; 59376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 59476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs++; 59576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 59676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 59776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 59876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 59976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 60076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 601bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 60276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 60376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_open(tcp, attaching) 60476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 60576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint attaching; 60676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 60776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char proc[32]; 60876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman long arg; 609bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4 61019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes int i; 61119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes sysset_t syscalls; 61276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t signals; 61376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fltset_t faults; 614bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 61576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 61676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last_pfd; 61776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 619ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 6209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman /* Open the process pseudo-files in /proc. */ 6219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/ctl", tcp->pid); 6229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) { 6239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 6249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) { 6279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 6289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) { 6319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 6329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 6359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) { 6369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 6379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) { 6409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 6419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) { 6449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 6459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/as", tcp->pid); 6489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) { 6499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 6509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) { 6539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 6549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) { 6579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 6589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 66176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Open the process pseudo-file in /proc. */ 662bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 66376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(proc, "/proc/%d", tcp->pid); 66476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) { 665bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 666bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/mem", tcp->pid); 667bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR)) < 0) { 668bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 6729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) { 6739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 6749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) { 6779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 6789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 681bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 682bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/regs", tcp->pid); 683bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) { 684bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../regs\", ...)"); 685bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 686bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 687bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (cflag) { 688bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 689bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) { 690bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("strace: open(\"/proc/.../status\", ...)"); 691bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 692bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 693bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 694bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 695bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rebuild_pollv(); 69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Wait for the child to pause. Because of a race 70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * condition we have to poll for the event. 70176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 7039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_STATUS (tcp) < 0) { 70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTATUS"); 70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 7079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) 708bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman break; 70976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 71076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 711bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Stop the process so that we own the stop. */ 71316a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) { 71476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTOP"); 71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 717bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET 71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set Run-on-Last-Close. */ 72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_RLC; 7219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) { 72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSET PR_RLC"); 72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set or Reset Inherit-on-Fork. */ 72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_FORK; 7279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) { 72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{SET,RESET} PR_FORK"); 72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !PIOCSET */ 732bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, PIOCSRLC) < 0) { 73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSRLC"); 73576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) { 73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{S,R}FORK"); 73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 741bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 742bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* just unset the PF_LINGER flag for the Run-on-Last-Close. */ 743bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) { 744bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCGFL"); 745bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 746bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 747bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg &= ~PF_LINGER; 748bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) { 749bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCSFL"); 750bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 751bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 752bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */ 754bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 75519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable all syscall entries we care about. */ 75619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&syscalls); 75719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 75819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof syscalls) * CHAR_BIT) break; 75919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i); 76019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 76119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_execve); 76219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (followfork) { 76319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork); 76419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall 76519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_forkall); 76619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 76719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_fork1 76819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_fork1); 76919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 77019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1 77119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rfork1); 77219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 77319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall 77419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes praddset (&syscalls, SYS_rforkall); 77519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif 77619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 77719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) { 77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSENTRY"); 77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 78119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable the syscall exits. */ 78219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) { 78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOSEXIT"); 78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 78619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable signals we care about. */ 78719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&signals); 78819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 78919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof signals) * CHAR_BIT) break; 79019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i); 79119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 7929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) { 79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSTRACE"); 79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 79619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes /* Enable faults we care about */ 79719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes premptyset(&faults); 79819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes for (i = 1; i < MAX_QUALS; ++i) { 79919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (i > (sizeof faults) * CHAR_BIT) break; 80019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i); 80119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes } 8029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) { 80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSFAULT"); 80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 80576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 806bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 807bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* set events flags. */ 808bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman arg = S_SIG | S_SCE | S_SCX ; 809bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) { 810bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman perror("PIOCBIS"); 811bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman return -1; 812bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 813bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 81476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 81676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The SGI PRSABORT doesn't work for pause() so 81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * we send it a caught signal to wake it up. 81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGINT); 82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */ 822bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef PRSABORT 82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* The child is in a pause(), abort it. */ 8249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = PRSABORT; 8259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 829bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 830bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/ 831bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 832bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* wake up the child if it received the SIGSTOP */ 833bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 834bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 83676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Wait for the child to do something. */ 8379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_WSTOP (tcp) < 0) { 83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 8419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_WHY == PR_SYSENTRY) { 842bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->flags &= ~TCB_INSYSCALL; 843bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman get_scno(tcp); 844bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->scno == SYS_execve) 84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set it running: maybe execve will be next. */ 848bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 8499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 8509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 851bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 852bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) { 853bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 857bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 858bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* handle the case where we "opened" the child before 859bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman it did the kill -STOP */ 860bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->status.PR_WHY == PR_SIGNALLED && 861bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->status.PR_WHAT == SIGSTOP) 862bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman kill(tcp->pid, SIGCONT); 863bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 865bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 867bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 868bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else { 8692e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (attaching < 2) { 8702e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* We are attaching to an already running process. 8712e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * Try to figure out the state of the process in syscalls, 8722e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * to handle the first event well. 8732e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * This is done by having a look at the "wchan" property of the 8742e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman * process, which tells where it is stopped (if it is). */ 8752e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman FILE * status; 8762e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman char wchan[20]; /* should be enough */ 8772e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman 8782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 8792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman status = fopen(proc, "r"); 8802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status && 8812e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d" 8822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman "%*d,%*d %*d,%*d %19s", wchan) == 1) && 8832e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "nochan") && strcmp(wchan, "spread") && 8842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman strcmp(wchan, "stopevent")) { 8852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* The process is asleep in the middle of a syscall. 8862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman Fake the syscall entry event */ 8872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP); 8882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 8892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman trace_syscall(tcp); 8902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 8912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if (status) 8922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman fclose(status); 8932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } /* otherwise it's a fork being followed */ 894bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 895bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 89676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 89776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) 89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1) { 90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poll_open(); 90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(last_pfd); 90276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last_pfd = tcp->pfd; 90576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 909bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb * 91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid) 91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid; 91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) { 91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid && tcp->pid != pid) 92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 927bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb * 93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd) 93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) { 93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != pfd) 93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 945bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp) 94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pid == 0) 95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs--; 95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = 0; 95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags = 0; 95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != -1) { 95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(tcp->pfd); 95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 959bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 960bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_reg != -1) { 961bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_reg); 962bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_reg = -1; 963bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 964bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (tcp->pfd_status != -1) { 965bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman close(tcp->pfd_status); 966bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman tcp->pfd_status = -1; 967bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } 968bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 969bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rebuild_pollv(); 97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->parent != NULL) { 97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->parent->nchildren--; 97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->parent = NULL; 97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->outf != stderr) 97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fclose(tcp->outf); 98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = 0; 98276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 984bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp) 98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp == NULL) 99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_SUSPENDED)) { 99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid); 99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) { 100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("resume: ptrace(PTRACE_SYSCALL, ...)"); 100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u resumed\n", tcp->pid); 100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1009bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* detach traced process; continue with sig */ 101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig) 101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int error = 0; 101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) 102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = SIGKILL; 102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Linux wrongly insists the child be stopped 102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * before detaching. Arghh. We go through hoops 103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * to make a clean break of things. 103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 1032dacfb6ebd630641d851b6df94c3b4587969a6cfbWichert Akkerman#if defined(SPARC) 1033dacfb6ebd630641d851b6df94c3b4587969a6cfbWichert Akkerman#undef PTRACE_DETACH 1034dacfb6ebd630641d851b6df94c3b4587969a6cfbWichert Akkerman#define PTRACE_DETACH PTRACE_SUNDETACH 1035dacfb6ebd630641d851b6df94c3b4587969a6cfbWichert Akkerman#endif 103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) { 103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* On a clear day, you can see forever. */ 103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (errno != ESRCH) { 104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Shouldn't happen. */ 104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_DETACH, ...)"); 104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (kill(tcp->pid, 0) < 0) { 104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: checking sanity"); 104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (kill(tcp->pid, SIGSTOP) < 0) { 104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: stopping child"); 105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (waitpid(tcp->pid, &status, 0) < 0) { 105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ECHILD) 105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: waiting"); 105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Au revoir, mon ami. */ 106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 106276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP) { 106376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, 106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid, (char *) 1, sig)) < 0) { 106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_DETACH, ...)"); 106776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* I died trying. */ 106876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1, 107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman WSTOPSIG(status) == SIGTRAP ? 107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 0 : WSTOPSIG(status))) < 0) { 107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_CONT, ...)"); 107676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 108076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4) 108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */ 108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig && kill(tcp->pid, sig) < 0) 108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: kill"); 108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = 0; 108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0) 108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_DETACH, ...)"); 108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1091bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS 109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (waiting_parent(tcp)) 109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman error = resume(tcp->parent); 1094bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u detached\n", tcp->pid); 109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return error; 110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1103bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 110676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig) 110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(pid); 111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp) 111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1123bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */ 112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup() 112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) { 113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "cleanup: looking at pid %u\n", tcp->pid); 113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && 113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (!outfname || followfork < 2 || tcp_last == tcp)) { 113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf(" <unfinished ...>\n"); 114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 114276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGCONT); 114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGTERM); 114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 114876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) 115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman call_summary(outf); 115176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 115376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 115476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig) 115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interrupted = 1; 115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR 116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 116276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SYS_ERRLIST_DECLARED 116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr; 116476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[]; 116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SYS_ERRLIST_DECLARED */ 116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 116776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno) 116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno; 117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 117276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno < 1 || errno >= sys_nerr) { 117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown error %d", errno); 117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_errlist[errno]; 117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */ 118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL 118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SYS_SIGLIST_DECLARED 118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST 118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern char *_sys_siglist[]; 118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern char *sys_siglist[]; 118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SYS_SIGLIST_DECLARED */ 119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig) 119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 119776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig < 1 || sig >= NSIG) { 119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown signal %d", sig); 120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST 120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return _sys_siglist[sig]; 120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_siglist[sig]; 120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */ 121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1211bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS 121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv() 121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = j = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) { 122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[j].fd = tcp->pfd; 12239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollv[j].events = POLLWANT; 122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j++; 122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (j != nprocs) { 122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 122876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 123276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open() 123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int arg; 123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pipe(proc_poll_pipe) < 0) { 124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("pipe"); 124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < 2; i++) { 124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) { 124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("F_GETFD"); 124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) { 125076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("F_SETFD"); 125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout) 125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv; 125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds; 126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout; 126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 126476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 126576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0) 126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return n; 126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n != sizeof(struct proc_pollfd)) { 126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "panic: short read: %d\n", n); 127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 127376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[i].fd == pollinfo.fd) 127476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = pollinfo.revents; 127576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = 0; 127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman poller_pid = pollinfo.pid; 127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 1; 128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 128176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig) 128476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd) 129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t blocked_set, empty_set; 129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rlimit rl; 1298bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1299bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman struct procfs_status pfs; 1300bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (fork()) { 130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("fork"); 130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: 130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interactive ? SIG_DFL : SIG_IGN; 131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = wakeup_handler; 132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGUSR1, &sa, NULL); 132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGUSR1); 132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("getrlimit(RLIMIT_NOFILE, ...)"); 132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = rl.rlim_cur; 133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < n; i++) { 133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (i != pfd && i != proc_poll_pipe[1]) 133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(i); 133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.fd = pfd; 133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.pid = getpid(); 133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 1340bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 1341bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(pfd, PIOCWSTOP, NULL) < 0) 1342bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1343bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (ioctl(pfd, PIOCWSTOP, &pfs) < 0) 1344bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 13459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman { 134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (errno) { 134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 134976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLERR; 135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLHUP; 135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("proc_poller: PIOCWSTOP"); 135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 13619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollinfo.revents = POLLWANT; 136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigsuspend(&empty_set); 136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd() 137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last; 137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 137776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (followfork < 2 && 13789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman last < nprocs && (pollv[last].revents & POLLWANT)) { 137976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 138076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The previous process is ready to run again. We'll 138176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * let it do so if it is currently in a syscall. This 138276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * heuristic improves the readability of the trace. 138376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[last].fd); 138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp && (tcp->flags & TCB_INSYSCALL)) 138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[last].fd; 138776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 138876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 138976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 139076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Let competing children run round robin. */ 139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j = (i + last + 1) % nprocs; 139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[j].revents & (POLLHUP | POLLERR)) { 139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[j].fd); 139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) { 139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: lost proc\n"); 139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 14019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (pollv[j].revents & POLLWANT) { 140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last = j; 140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[j].fd; 140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: nothing ready\n"); 140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 14139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 14149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman struct tcb *in_syscall; 14159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pfd; 141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int what; 141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int ioctl_result = 0, ioctl_errno = 0; 14209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman long arg; 142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (nprocs) { 143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 1: 143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] == -1) { 143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(0); 143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) 143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = tcp->pfd; 143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* fall through ... */ 144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS 14479dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 14489dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman /* On some systems (e.g. UnixWare) we get too much ugly 14499dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman "unfinished..." stuff when multiple proceses are in 14509dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman syscalls. Here's a nasty hack */ 14519dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman 14529dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (in_syscall) { 14539dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman struct pollfd pv; 14549dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman tcp = in_syscall; 14559dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = NULL; 14569dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.fd = tcp->pfd; 14579dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.events = POLLWANT; 14589dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if ((what = poll (&pv, 1, 1)) < 0) { 14599dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (interrupted) 14609dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman return 0; 14619dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman continue; 14629dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 14639dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman else if (what == 1 && pv.revents & POLLWANT) { 14649dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman goto FOUND; 14659dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 14669dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 14679dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 14689dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman 146976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (poll(pollv, nprocs, INFTIM) < 0) { 147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */ 147576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll(pollv, nprocs, INFTIM) < 0) { 147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 147976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 148076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 148176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = choose_pfd(); 148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 148676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pfd' in our table. */ 148876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pfd2tcb(pfd)) == NULL) { 148976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "unknown pfd: %u\n", pfd); 149076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 14929dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman FOUND: 149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Get the status of the process. */ 149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!interrupted) { 1495bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 14969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 1497bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */ 1498bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman /* Thanks to some scheduling mystery, the first poller 1499bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sometimes waits for the already processed end of fork 1500bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman event. Doing a non blocking poll here solves the problem. */ 1501bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (proc_poll_pipe[0] != -1) 1502bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman ioctl_result = IOCTL_STATUS (tcp); 1503bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman else 1504bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 1505bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */ 150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ioctl_errno = errno; 150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) { 150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) 151076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGKILL); 151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGUSR1); 151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) { 152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Find out what happened if it failed. */ 152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (ioctl_errno) { 152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 1528bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1529bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case ENOTTY: 1530bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15402e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD 15412e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) { 15422e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman /* discard first event for a syscall we never entered */ 15432e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman IOCTL (tcp->pfd, PIOCRUN, 0); 15442e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman continue; 15452e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman } 15462e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#endif 15472e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman 154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* clear the just started flag */ 154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval stime; 1556bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1557bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman char buf[1024]; 1558bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman int len; 1559bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman 1560bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) { 1561bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman buf[len] = '\0'; 1562bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman sscanf(buf, 1563bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld", 1564bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman &stime.tv_sec, &stime.tv_usec); 1565bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman } else 1566bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman stime.tv_sec = stime.tv_usec = 0; 1567bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !FREEBSD */ 156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_sec = tcp->status.pr_stime.tv_sec; 156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000; 1570bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &stime, &tcp->stime); 157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = stime; 157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 15749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman what = tcp->status.PR_WHAT; 15759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman switch (tcp->status.PR_WHY) { 1576bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_REQUESTED: 15789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) { 15799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 1586bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */ 158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSENTRY: 15889dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 15899dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = tcp; 15909dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSEXIT: 159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SIGNALLED: 159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) { 159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("--- %s (%s) ---", 1601ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(what), strsignal(what)); 160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 16035826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO 16045826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes if (tcp->status.PR_INFO.si_signo == what) { 16055826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printleader(tcp); 16065826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes tprintf(" siginfo="); 16075826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printsiginfo(&tcp->status.PR_INFO, 1); 16085826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes printtrailer(tcp); 16095826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes } 16105826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif 161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_FAULTED: 161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag && (qual_flags[what] & QUAL_FAULT)) { 161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("=== FAULT %d ===", what); 161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 1620bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD 1621bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman case 0: /* handle case we polled for nothing */ 1622bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman continue; 1623bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 16259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY); 162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 16299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 1630bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD 16319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 1632bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else 1633bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) { 1634bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif 163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1642bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */ 164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int wait_errno; 164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rusage ru; 16532f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 16542f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman static int wait4_options = __WALL; 16552f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif 165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while (nprocs != 0) { 165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 16622f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL 16632f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL); 16642f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman if ((wait4_options & __WALL) && errno == EINVAL) { 16652f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* this kernel does not support __WALL */ 16662f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman wait4_options &= ~__WALL; 16672f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman errno = 0; 16682f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman pid = wait4(-1, &status, wait4_options, 16692f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman cflag ? &ru : NULL); 16702f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 16712f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman if (!(wait4_options & __WALL) && errno == ECHILD) { 16722f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman /* most likely a "cloned" process */ 16732f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman pid = wait4(-1, &status, __WCLONE, 16742f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman cflag ? &ru : NULL); 16752f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman if (pid == -1) { 16762f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman fprintf(stderr, "strace: clone wait4 " 16772f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman "failed: %s\n", strerror(errno)); 16782f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 16792f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman } 16802f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#else 168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait4(-1, &status, 0, cflag ? &ru : NULL); 16822f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif /* __WALL */ 168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait(&status); 168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman wait_errno = errno; 168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == -1) { 169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (wait_errno) { 169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ECHILD: 169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * We would like to verify this case 170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * but sometimes a race in Solbourne's 170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * version of SunOS sometimes reports 170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * ECHILD before sending us SIGCHILD. 170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman errno = wait_errno; 171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: wait"); 171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, " [wait(%#x) = %u]\n", status, pid); 172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pid' in our table. */ 172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pid2tcb(pid)) == NULL) { 1723faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#if 0 /* XXX davidm */ /* WTA: disabled again */ 17248b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman struct tcb *tcpchild; 17258b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman 17268b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman if ((tcpchild = alloctcb(pid)) == NULL) { 17278b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman fprintf(stderr, " [tcb table full]\n"); 17288b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman kill(pid, SIGKILL); /* XXX */ 17298b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman return 0; 17308b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman } 17318b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman tcpchild->flags |= TCB_ATTACHED; 17328b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman newoutf(tcpchild); 17338b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman tcp->nchildren++; 17348b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman if (!qflag) 17358b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman fprintf(stderr, "Process %d attached\n", pid); 17368b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#else 173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "unknown pid: %u\n", pid); 173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSTOPPED(status)) 173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ptrace(PTRACE_CONT, pid, (char *) 1, 0); 174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 17418b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif 174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = ru.ru_stime; 174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !LINUX */ 175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Apparently, doing any ptrace() call on a stopped 175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * process, provokes the kernel to report the process 175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * status again on a subsequent wait(), even if the 175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * process has not been actually restarted. 175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Since we have inspected the arguments of suspended 175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * processes we end up here testing for this case. 176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSIGNALED(status)) { 176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag 176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { 176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("+++ killed by %s +++", 1768ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(WTERMSIG(status))); 176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFEXITED(status)) { 177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u exited\n", pid); 177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "PANIC: attached pid %u exited\n", 178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid); 178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u stopped, [%s]\n", 1791ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons pid, signame(WSTOPSIG(status))); 179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_STARTUP) { 179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * This flag is there to keep us in sync. 179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Next time this process stops it should 179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * really be entering a system call. 179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) { 180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Interestingly, the process may stop 180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * with STOPSIG equal to some other signal 180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * than SIGSTOP if we happend to attach 180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * just before the process takes a signal. 180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "pid %u not stopped\n", pid); 181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, WSTOPSIG(status)); 181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* A child of us stopped at exec */ 181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGTRAP && followvfork) 181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fixvfork(tcp); 181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) { 182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (clearbpt(tcp) < 0) /* Pretty fatal */ { 182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman goto tracing; 182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) != SIGTRAP) { 183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP && 183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (tcp->flags & TCB_SIGTRAPPED)) { 183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Trapped attempt to block SIGTRAP 183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Hope we are back in control now. 183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED); 183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, 184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid, (char *) 1, 0) < 0) { 184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag 184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) { 18497b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman unsigned long addr = 0, pc = 0; 18507b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#ifdef PT_GETSIGINFO 18517b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# define PSR_RI 41 18527b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman struct siginfo si; 18537b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman unsigned long psr; 18547b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 18557b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman upeek(pid, PT_CR_IPSR, &psr); 18567b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman upeek(pid, PT_CR_IIP, &pc); 18577b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman 18587b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman pc += (psr >> PSR_RI) & 0x3; 18597b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman ptrace(PT_GETSIGINFO, pid, 0, (long) &si); 18607b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman addr = (unsigned long) si.si_addr; 18617b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif 186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 18637b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman tprintf("--- %s (%s) @ %lx (%lx) ---", 1864ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(WSTOPSIG(status)), 18657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman strsignal(WSTOPSIG(status)), pc, addr); 186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_ATTACHED) && 186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman !sigishandled(tcp, WSTOPSIG(status))) { 187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, WSTOPSIG(status)); 187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman WSTOPSIG(status)) < 0) { 187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ptrace(PTRACE_KILL, 188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid, (char *) 1, SIGTERM); 188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_EXITING) { 189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) { 189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: ptrace(PTRACE_CONT, ...)"); 189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u suspended\n", pid); 190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tracing: 190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) { 190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 1917bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */ 191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol; 192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h> 192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b) 192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h> 192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a) 192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...) 193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist) 193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt; 193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl 193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_list args; 193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman VA_START(args, fmt); 194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outf) 194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman curcol += vfprintf(outf, fmt, args); 194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_end(args); 194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp) 194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) { 195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last->flags |= TCB_REPRINT; 195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf(" <unfinished ...>\n"); 195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman curcol = 0; 195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((followfork == 1 || pflag_seen > 1) && outfname) 195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%-5d ", tcp->pid); 195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1 && !outfname) 195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("[pid %5u] ", tcp->pid); 196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag) { 196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char str[sizeof("HH:MM:SS")]; 196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval tv, dtv; 196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static struct timeval otv; 196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gettimeofday(&tv, NULL); 196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (rflag) { 196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (otv.tv_sec == 0) 196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&dtv, &tv, &otv); 197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%6ld.%06ld ", 197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) dtv.tv_sec, (long) dtv.tv_usec); 197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (tflag > 2) { 197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%ld.%06ld ", 197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) tv.tv_sec, (long) tv.tv_usec); 197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman time_t local = tv.tv_sec; 198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strftime(str, sizeof(str), "%T", localtime(&local)); 198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag > 1) 198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s.%06ld ", str, (long) tv.tv_usec); 198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s ", str); 198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (iflag) 198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printcall(tcp); 198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col) 199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col; 199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (curcol < col) 199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%*s", col - curcol, ""); 199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprinttrailer(tcp) 200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("\n"); 200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 20069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 2007ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 20089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 20099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkermanint mp_ioctl (int fd, int cmd, void *arg, int size) { 20109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 20119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman struct iovec iov[2]; 20129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman int n = 1; 20139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 20149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_base = &cmd; 20159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_len = sizeof cmd; 20169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (arg) { 20179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ++n; 20189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_base = arg; 20199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_len = size; 20209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 20219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 20229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return writev (fd, iov, n); 20239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman} 20249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 20259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 2026