strace.c revision 5ae21ead9f83597452f9a0517e8a51fa4823f921
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> 4676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 4776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 4876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h> 4976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <poll.h> 50ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h> 529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 5376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 5476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 5576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint debug = 0, followfork = 0, followvfork = 0, interactive = 0; 5676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint rflag = 0, tflag = 0, dtime = 0, cflag = 0; 5776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint iflag = 0, xflag = 0, qflag = 0; 5876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pflag_seen = 0; 5976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 6076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *username = NULL; 6176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid; 6276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid; 6376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 6476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN; 6576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN; 6676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *outfname = NULL; 6776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf; 6876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb tcbtab[MAX_PROCS]; 6976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nprocs; 7076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname; 7176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char version[]; 7276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char **environ; 7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 7476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pid2tcb P((int pid)); 7576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void)); 7676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void)); 7776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig)); 7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set; 7976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 8076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T 8176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted; 8276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */ 8376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted; 8576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */ 8676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted; 8776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */ 8876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */ 8976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 9076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 9176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 9276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd)); 9376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig)); 9476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void)); 95e68d61c7d6dcf986d32c462e533ea46f85183db8Wichert Akkermanstruct pollfd pollv[MAX_PROCS]; 9676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 9776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void)); 10076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd)); 10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd { 10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int fd; 10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int revents; 10576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}; 10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid; 10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 }; 11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 113ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 1149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLWRNORM 1159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 1169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT POLLPRI 1179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval) 12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp; 12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval; 12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(ofp, "\ 12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\ 12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman [-p pid] ... [-s strsize] [-u username] [command [arg ...]]\n\ 12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman or: strace -c [-e expr] ... [-O overhead] [-S sortby] [command [arg ...]]\n\ 12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\ 13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\ 13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\ 13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\ 13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\ 13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\ 13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\ 13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\ 13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\ 13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\ 13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\ 14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman options: trace, abbrev, verbose, raw, signal, read, or write\n\ 14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\ 14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\ 14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\ 14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\ 14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\ 14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\ 14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman", DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY); 14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(exitval); 14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar() 15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanmain(argc, argv) 16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint argc; 16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *argv[]; 16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern int optind; 16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern char *optarg; 16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int c, pid = 0; 16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[BUFSIZ]; 17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname = argv[0]; 17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = stderr; 17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 1; 17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("trace=all"); 17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=all"); 17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("verbose=all"); 17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("signal=all"); 18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(DEFAULT_SORTBY); 18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_personality(DEFAULT_PERSONALITY); 18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((c = getopt(argc, argv, 18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "+cdfFhiqrtTvVxa:e:o:O:p:s:S:u:")) != EOF) { 18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (c) { 18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'c': 18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cflag++; 18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'd': 19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman debug++; 19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'f': 19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followfork++; 19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'F': 19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman followvfork++; 19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'h': 19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stdout, 0); 20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'i': 20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman iflag++; 20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'q': 20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag++; 20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'r': 20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rflag++; 20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 't': 21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tflag++; 21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'T': 21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman dtime++; 21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'x': 21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman xflag++; 21976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 22076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'v': 22176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify("abbrev=none"); 22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 22376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'V': 22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printf("%s\n", version); 22576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 22676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 22776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'a': 22876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman acolumn = atoi(optarg); 22976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 23076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'e': 23176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qualify(optarg); 23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'o': 23476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = strdup(optarg); 23576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 23676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'O': 23776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_overhead(atoi(optarg)); 23876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 23976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'p': 24076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((pid = atoi(optarg)) == 0) { 24176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: Invalid process id: %s\n", 24276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, optarg); 24376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 24476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 24576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == getpid()) { 24654a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname); 24776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 24876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 24976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = alloctcb(pid)) == NULL) { 25076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: tcb table full, please recompile strace\n", 25176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 25276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 25376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 25476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags |= TCB_ATTACHED; 25576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pflag_seen++; 25676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 25776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 's': 25876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman max_strlen = atoi(optarg); 25976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 26076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'S': 26176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman set_sortby(optarg); 26276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 26376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 'u': 26476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman username = strdup(optarg); 26576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 26676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 26776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 26876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 26976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 27076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 27176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 27276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to run as another user. */ 27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL) { 27476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct passwd *pent; 27576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 27676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getuid() != 0 || geteuid() != 0) { 27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "%s: you must be root to use the -u option\n", 27976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname); 28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((pent = getpwnam(username)) == NULL) { 28376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: cannot find user `%s'\n", 28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, optarg); 28576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 28676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 28776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = pent->pw_uid; 28876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = pent->pw_gid; 28976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 29076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 29176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_uid = getuid(); 29276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_gid = getgid(); 29376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 29476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 29576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 29676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 29776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 29876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 29976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* See if they want to pipe the output. */ 30076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname && (outfname[0] == '|' || outfname[0] == '!')) { 30176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((outf = popen(outfname + 1, "w")) == NULL) { 30276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: can't popen '%s': %s\n", 30376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, outfname + 1, strerror(errno)); 30476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 30576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 30676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman free(outfname); 30776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outfname = NULL; 30876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 30976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 31076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Check if they want to redirect the output. */ 31176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname) { 31276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((outf = fopen(outfname, "w")) == NULL) { 31376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: can't fopen '%s': %s\n", 31476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, outfname, strerror(errno)); 31576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 31676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 31776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 31876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 31976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 32076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 32176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 32276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 32376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!outfname) { 32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setvbuf(outf, buf, _IOLBF, BUFSIZ); 32676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (optind < argc) 32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interactive = 0; 32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman qflag = 1; 33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (c = 0, tcp = tcbtab; c < MAX_PROCS; c++, tcp++) { 33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Reinitialize the output since it may have changed. */ 33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; 33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED)) 33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 33876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_open(tcp, 1) < 0) { 33976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "trouble opening proc file\n"); 34076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 34176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 34276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 34376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !SVR4 */ 34476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) { 34576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("attach: ptrace(PTRACE_ATTACH, ...)"); 34676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 34776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 34876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 34976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !SVR4 */ 35076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 35176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 35276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "Process %u attached - interrupt to quit\n", 35376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid); 35476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 35576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 35676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (optind < argc) { 35776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct stat statbuf; 35876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char *filename; 35976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char pathname[MAXPATHLEN]; 36076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 36176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman filename = argv[optind]; 36276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (strchr(filename, '/')) 36376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strcpy(pathname, filename); 36476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef USE_DEBUGGING_EXEC 36576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 36676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Debuggers customarily check the current directory 36776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * first regardless of the path but doing that gives 36876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * security geeks a panic attack. 36976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 37076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (stat(filename, &statbuf) == 0) 37176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strcpy(pathname, filename); 37276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* USE_DEBUGGING_EXEC */ 37376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 37476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char *path; 37576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int m, n, len; 37676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (path = getenv("PATH"); path && *path; path += m) { 37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (strchr(path, ':')) { 37976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = strchr(path, ':') - path; 38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman m = n + 1; 38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman m = n = strlen(path); 38476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n == 0) { 38576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman getcwd(pathname, MAXPATHLEN); 38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman len = strlen(pathname); 38776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 38876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 38976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strncpy(pathname, path, n); 39076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman len = n; 39176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 39276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (len && pathname[len - 1] != '/') 39376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pathname[len++] = '/'; 39476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strcpy(pathname + len, filename); 39576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (stat(pathname, &statbuf) == 0) 39676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 39776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 39876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 39976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (stat(pathname, &statbuf) < 0) { 40076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "%s: %s: command not found\n", 40176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman progname, filename); 40276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 40376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 40476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (pid = fork()) { 40576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 40676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: fork"); 40776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 40876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 40976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 41076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: { 41176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 412789ed35db520a552ba5ea0a5cbe5b31efa7adde5Wichert Akkerman if (outf != stderr) close (fileno (outf)); 41376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 41476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Kludge for SGI, see proc_open for details. */ 41576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = foobar; 41676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 41776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 41876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 41976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */ 42076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pause(); 42176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !SVR4 */ 42276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) { 42376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: ptrace(PTRACE_TRACEME, ...)"); 42476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 42576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 42676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 42776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(getpid(), SIGSTOP); 42876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 42976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (username != NULL || geteuid() == 0) { 43076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman uid_t run_euid = run_uid; 43176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gid_t run_egid = run_gid; 43276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 43376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (statbuf.st_mode & S_ISUID) 43476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_euid = statbuf.st_uid; 43576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (statbuf.st_mode & S_ISGID) 43676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman run_egid = statbuf.st_gid; 43776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 43876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 43976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * It is important to set groups before we 44076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * lose privileges on setuid. 44176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 4425ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (username != NULL) { 4435ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (initgroups(username, run_gid) < 0) { 4445ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman perror("initgroups"); 4455ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman exit(1); 4465ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman } 4475ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (setregid(run_gid, run_egid) < 0) { 4485ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman perror("setregid"); 4495ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman exit(1); 4505ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman } 4515ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman if (setreuid(run_uid, run_euid) < 0) { 4525ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman perror("setreuid"); 4535ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman exit(1); 4545ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman } 45576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 45676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 45776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 45876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(run_uid, run_uid); 45976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !SVR4 */ 46076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 46176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman execv(pathname, &argv[optind]); 46276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: exec"); 46376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(1); 46476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 46576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 46676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 46776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = alloctcb(pid)) == NULL) { 46876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "tcb table full\n"); 46976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 47076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 47176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 47276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 47376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_open(tcp, 0) < 0) { 47476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "trouble opening proc file\n"); 47576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 47676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 47776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 47876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 47976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 48076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fake_execve(tcp, pathname, &argv[optind], environ); 48176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 48276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 48376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 48476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 48576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (pflag_seen == 0) 48676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman usage(stderr, 1); 48776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 48876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 48976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 49076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = SIG_IGN; 49176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 49276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 49376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTOU, &sa, NULL); 49476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTTIN, &sa, NULL); 49576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) { 49676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGHUP); 49776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGINT); 49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGQUIT); 49976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGPIPE); 50076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGTERM); 50176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interrupt; 50276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 50376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* POSIX signals on sunos4.1 are a little broken. */ 50476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = SA_INTERRUPT; 50576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 50676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 50776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 50876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 50976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 51076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 51176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 51276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 51376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = reaper; 51476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGCHLD, &sa, NULL); 51576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 51676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 51776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace() < 0) 51876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 51976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 52076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(0); 52176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 52276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 52376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 52476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermannewoutf(tcp) 52576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 52676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 52776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char name[MAXPATHLEN]; 52876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman FILE *fp; 52976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 53076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outfname && followfork > 1) { 53176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(name, "%s.%u", outfname, tcp->pid); 53276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 53376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 53476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 53576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fp = fopen(name, "w"); 53676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 53776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman setreuid(geteuid(), getuid()); 53876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 53976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (fp == NULL) { 54076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("fopen"); 54176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 54276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = fp; 54476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 54576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 54676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 54776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 54876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb * 54976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanalloctcb(pid) 55076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid; 55176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 55276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 55376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 55476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 55576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) { 55676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_INUSE) == 0) { 55776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = pid; 55876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->parent = NULL; 55976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->nchildren = 0; 56076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags = TCB_INUSE | TCB_STARTUP; 56176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = outf; /* Initialise to current out file */ 56276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime.tv_sec = 0; 56376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime.tv_usec = 0; 56476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 56576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs++; 56676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 56776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 56876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 56976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 57076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 57176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 57276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 57376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint 57476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_open(tcp, attaching) 57576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 57676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint attaching; 57776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 57876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char proc[32]; 57976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman long arg; 58076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sysset_t sc_enter, sc_exit; 58176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t signals; 58276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fltset_t faults; 58376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 58476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last_pfd; 58576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 58676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 587ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 5889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman /* Open the process pseudo-files in /proc. */ 5899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/ctl", tcp->pid); 5909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) { 5919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 5929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 5939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 5949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) { 5959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 5969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 5979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 5989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) { 5999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 6009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/status", tcp->pid); 6039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) { 6049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 6059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) { 6089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 6099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) { 6129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 6139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman sprintf(proc, "/proc/%d/as", tcp->pid); 6169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) { 6179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 6189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) { 6219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 6229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) { 6259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 6269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else 62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Open the process pseudo-file in /proc. */ 63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(proc, "/proc/%d", tcp->pid); 63176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) { 63276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: open(\"/proc/...\", ...)"); 63376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 63476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 6359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) { 6369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_GETFD"); 6379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) { 6409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman perror("F_SETFD"); 6419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return -1; 6429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 6439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 64476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rebuild_pollv(); 64576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 64676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 64776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Wait for the child to pause. Because of a race 64876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * condition we have to poll for the event. 64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 6519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_STATUS (tcp) < 0) { 65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTATUS"); 65376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 65476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 6559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) 65676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 65776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 65876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 65976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Stop the process so that we own the stop. */ 6609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTOP, NULL) < 0) { 66176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: PIOCSTOP"); 66276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 66376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 66476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET 66576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set Run-on-Last-Close. */ 66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_RLC; 6679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) { 66876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSET PR_RLC"); 66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set or Reset Inherit-on-Fork. */ 67276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman arg = PR_FORK; 6739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) { 67476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{SET,RESET} PR_FORK"); 67576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 67676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 67776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !PIOCSET */ 67876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, PIOCSRLC) < 0) { 67976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSRLC"); 68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 68176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) { 68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOC{S,R}FORK"); 68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */ 68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Enable all syscall entries. */ 68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman prfillset(&sc_enter); 6899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSENTRY, &sc_enter) < 0) { 69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSENTRY"); 69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Enable all syscall exits. */ 69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman prfillset(&sc_exit); 6959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSEXIT, &sc_exit) < 0) { 69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOSEXIT"); 69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Enable all signals. */ 70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman prfillset(&signals); 7019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) { 70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSTRACE"); 70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Enable all faults. */ 70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman prfillset(&faults); 7079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) { 70876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCSFAULT"); 70976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 71076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 71176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!attaching) { 71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS 71376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 71476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The SGI PRSABORT doesn't work for pause() so 71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * we send it a caught signal to wake it up. 71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 71776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGINT); 71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */ 71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* The child is in a pause(), abort it. */ 7209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = PRSABORT; 7219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !MIPS */ 72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Wait for the child to do something. */ 7289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL_WSTOP (tcp) < 0) { 72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 7329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_WHY == PR_SYSENTRY) { 73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_PR_SYSCALL 73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int scno = tcp->status.pr_syscall; 73576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_PR_SYSCALL */ 7369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman int scno = tcp->status.PR_WHAT; 73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_PR_SYSCALL */ 73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (scno == SYS_execve) 73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Set it running: maybe execve will be next. */ 7429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 7439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) { 74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) 75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1) { 75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poll_open(); 75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(last_pfd); 75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman proc_poller(tcp->pfd); 75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last_pfd = tcp->pfd; 75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb * 76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid) 76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid; 76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) { 77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid && tcp->pid != pid) 77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb * 78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd) 78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) { 79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != pfd) 79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_INUSE) 79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return tcp; 79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return NULL; 79676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 79876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 79976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 80176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp) 80276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pid == 0) 80576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman nprocs--; 80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid = 0; 80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags = 0; 80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->pfd != -1) { 81076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(tcp->pfd); 81176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pfd = -1; 81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman rebuild_pollv(); 81476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 81676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->parent != NULL) { 81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->parent->nchildren--; 81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->parent = NULL; 81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->outf != stderr) 82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fclose(tcp->outf); 82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 82476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->outf = 0; 82576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp) 83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 83376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp == NULL) 83476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 83676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_SUSPENDED)) { 83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid); 83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) { 84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("resume: ptrace(PTRACE_SYSCALL, ...)"); 84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u resumed\n", tcp->pid); 84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !SVR4 */ 85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* detach traced process; continue with sig */ 85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig) 85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int error = 0; 86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) 86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = SIGKILL; 86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Linux wrongly insists the child be stopped 87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * before detaching. Arghh. We go through hoops 87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * to make a clean break of things. 87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 875dacfb6ebd630641d851b6df94c3b4587969a6cfbWichert Akkerman#if defined(SPARC) 876dacfb6ebd630641d851b6df94c3b4587969a6cfbWichert Akkerman#undef PTRACE_DETACH 877dacfb6ebd630641d851b6df94c3b4587969a6cfbWichert Akkerman#define PTRACE_DETACH PTRACE_SUNDETACH 878dacfb6ebd630641d851b6df94c3b4587969a6cfbWichert Akkerman#endif 87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) { 88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* On a clear day, you can see forever. */ 88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (errno != ESRCH) { 88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Shouldn't happen. */ 88476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_DETACH, ...)"); 88576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (kill(tcp->pid, 0) < 0) { 88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: checking sanity"); 88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (kill(tcp->pid, SIGSTOP) < 0) { 89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 89276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: stopping child"); 89376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 89476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 89576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 89676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (waitpid(tcp->pid, &status, 0) < 0) { 89776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ECHILD) 89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: waiting"); 89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 90276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Au revoir, mon ami. */ 90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 90576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP) { 90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, 90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid, (char *) 1, sig)) < 0) { 90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_DETACH, ...)"); 91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* I died trying. */ 91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1, 91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman WSTOPSIG(status) == SIGTRAP ? 91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 0 : WSTOPSIG(status))) < 0) { 91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno != ESRCH) 91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_CONT, ...)"); 91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4) 92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */ 92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig && kill(tcp->pid, sig) < 0) 92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: kill"); 92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sig = 0; 93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0) 93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("detach: ptrace(PTRACE_DETACH, ...)"); 93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4 93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (waiting_parent(tcp)) 93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman error = resume(tcp->parent); 93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !SVR4 */ 93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u detached\n", tcp->pid); 94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return error; 94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig) 95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(pid); 96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp) 96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */ 96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup() 97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) { 97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "cleanup: looking at pid %u\n", tcp->pid); 98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && 98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (!outfname || followfork < 2 || tcp_last == tcp)) { 98276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf(" <unfinished ...>\n"); 98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGCONT); 98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(tcp->pid, SIGTERM); 99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) 99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman call_summary(outf); 99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig) 99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman interrupted = 1; 100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR 100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SYS_ERRLIST_DECLARED 100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr; 100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[]; 100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SYS_ERRLIST_DECLARED */ 100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno) 101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno; 101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (errno < 1 || errno >= sys_nerr) { 101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown error %d", errno); 101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_errlist[errno]; 102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */ 102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL 102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SYS_SIGLIST_DECLARED 102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST 102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern char *_sys_siglist[]; 103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman extern char *sys_siglist[]; 103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SYS_SIGLIST_DECLARED */ 103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char * 103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig) 103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static char buf[64]; 104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (sig < 1 || sig >= NSIG) { 104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sprintf(buf, "Unknown signal %d", sig); 104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return buf; 104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST 104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return _sys_siglist[sig]; 104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return sys_siglist[sig]; 104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */ 105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4 105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv() 105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 106276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = j = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) { 106376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!(tcp->flags & TCB_INUSE)) 106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[j].fd = tcp->pfd; 10669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollv[j].events = POLLWANT; 106776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j++; 106876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (j != nprocs) { 107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 107676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open() 107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 108076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int arg; 108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pipe(proc_poll_pipe) < 0) { 108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("pipe"); 108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < 2; i++) { 108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) { 108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("F_GETFD"); 109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) { 109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("F_SETFD"); 109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout) 110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv; 110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds; 110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout; 110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 110676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0) 111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return n; 111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (n != sizeof(struct proc_pollfd)) { 111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "panic: short read: %d\n", n); 111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[i].fd == pollinfo.fd) 111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = pollinfo.revents; 111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollv[i].revents = 0; 112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman poller_pid = pollinfo.pid; 112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 1; 112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig) 112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig; 112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void 113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd) 113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd; 113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct proc_pollfd pollinfo; 113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct sigaction sa; 113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigset_t blocked_set, empty_set; 113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i; 113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int n; 114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rlimit rl; 114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 114276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (fork()) { 114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case -1: 114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("fork"); 114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 0: 114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 114876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 115176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = interactive ? SIG_DFL : SIG_IGN; 115376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_flags = 0; 115476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&sa.sa_mask); 115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGHUP, &sa, NULL); 115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGINT, &sa, NULL); 115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGQUIT, &sa, NULL); 115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGPIPE, &sa, NULL); 115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGTERM, &sa, NULL); 116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sa.sa_handler = wakeup_handler; 116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaction(SIGUSR1, &sa, NULL); 116276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&blocked_set); 116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigaddset(&blocked_set, SIGUSR1); 116476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigemptyset(&empty_set); 116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 116776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("getrlimit(RLIMIT_NOFILE, ...)"); 116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman n = rl.rlim_cur; 117276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < n; i++) { 117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (i != pfd && i != proc_poll_pipe[1]) 117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman close(i); 117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.fd = pfd; 117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.pid = getpid(); 117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 11809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (ioctl(pfd, PIOCWSTOP, NULL) < 0) 11819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman { 118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (errno) { 118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLERR; 118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pollinfo.revents = POLLHUP; 119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("proc_poller: PIOCWSTOP"); 119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman _exit(0); 119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 11979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman pollinfo.revents = POLLWANT; 119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo)); 119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigsuspend(&empty_set); 120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd() 120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int i, j; 120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static int last; 121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (followfork < 2 && 12149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman last < nprocs && (pollv[last].revents & POLLWANT)) { 121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * The previous process is ready to run again. We'll 121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * let it do so if it is currently in a syscall. This 121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * heuristic improves the readability of the trace. 121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[last].fd); 122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp && (tcp->flags & TCB_INSYSCALL)) 122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[last].fd; 122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (i = 0; i < nprocs; i++) { 122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Let competing children run round robin. */ 122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman j = (i + last + 1) % nprocs; 122876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pollv[j].revents & (POLLHUP | POLLERR)) { 122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pfd2tcb(pollv[j].fd); 123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) { 123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: lost proc\n"); 123276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 12379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (pollv[j].revents & POLLWANT) { 123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman last = j; 123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return pollv[j].fd; 124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: nothing ready\n"); 124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 12499dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 12509dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman struct tcb *in_syscall; 12519dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pfd; 125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int what; 125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int ioctl_result = 0, ioctl_errno = 0; 12569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman long arg; 125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman for (;;) { 125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 126476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 126576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (nprocs) { 126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case 1: 126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] == -1) { 126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp = pid2tcb(0); 127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!tcp) 127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 127376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = tcp->pfd; 127476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 127576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* fall through ... */ 128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 128176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS 12839dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 12849dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman /* On some systems (e.g. UnixWare) we get too much ugly 12859dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman "unfinished..." stuff when multiple proceses are in 12869dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman syscalls. Here's a nasty hack */ 12879dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman 12889dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (in_syscall) { 12899dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman struct pollfd pv; 12909dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman tcp = in_syscall; 12919dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = NULL; 12929dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.fd = tcp->pfd; 12939dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman pv.events = POLLWANT; 12949dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if ((what = poll (&pv, 1, 1)) < 0) { 12959dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman if (interrupted) 12969dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman return 0; 12979dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman continue; 12989dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 12999dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman else if (what == 1 && pv.revents & POLLWANT) { 13009dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman goto FOUND; 13019dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 13029dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman } 13039dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 13049dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman 130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (poll(pollv, nprocs, INFTIM) < 0) { 130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */ 131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll(pollv, nprocs, INFTIM) < 0) { 131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pfd = choose_pfd(); 131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pfd == -1) 131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pfd' in our table. */ 132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pfd2tcb(pfd)) == NULL) { 132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "unknown pfd: %u\n", pfd); 132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 13289dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman FOUND: 132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Get the status of the process. */ 133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!interrupted) { 13319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ioctl_result = IOCTL_WSTOP (tcp); 133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ioctl_errno = errno; 133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS 133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (proc_poll_pipe[0] != -1) { 133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) 133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGKILL); 133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman kill(poller_pid, SIGUSR1); 133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 134076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */ 134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 134576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ioctl_result < 0) { 134976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Find out what happened if it failed. */ 135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (ioctl_errno) { 135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EBADF: 135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ENOENT: 135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCWSTOP"); 135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* clear the just started flag */ 136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval stime; 137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_sec = tcp->status.pr_stime.tv_sec; 137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000; 137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &stime, &tcp->stime); 137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = stime; 137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 137776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 13789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman what = tcp->status.PR_WHAT; 13799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman switch (tcp->status.PR_WHY) { 138076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_REQUESTED: 13819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (tcp->status.PR_FLAGS & PR_ASLEEP) { 13829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman tcp->status.PR_WHY = PR_SYSENTRY; 138376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 138776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 138876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 138976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSENTRY: 13909dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK 13919dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman in_syscall = tcp; 13929dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif 139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SYSEXIT: 139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "syscall trouble\n"); 139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_SIGNALLED: 140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) { 140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("--- %s (%s) ---", 1403ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(what), strsignal(what)); 140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case PR_FAULTED: 140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag && (qual_flags[what] & QUAL_FAULT)) { 140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("=== FAULT %d ===", what); 141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 14159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY); 141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman break; 141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 14199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman arg = 0; 14209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) { 142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("PIOCRUN"); 142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !SVR4 */ 142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int 143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace() 143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int pid; 143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int wait_errno; 143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman int status; 143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct tcb *tcp; 143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct rusage ru; 143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman while (nprocs != 0) { 144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_SETMASK, &empty_set, NULL); 144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait4(-1, &status, 0, cflag ? &ru : NULL); 144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */ 144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid = wait(&status); 144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman wait_errno = errno; 145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interactive) 145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman sigprocmask(SIG_BLOCK, &blocked_set, NULL); 145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (interrupted) 145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 145676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (pid == -1) { 145876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman switch (wait_errno) { 145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case EINTR: 146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman case ECHILD: 146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * We would like to verify this case 146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * but sometimes a race in Solbourne's 146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * version of SunOS sometimes reports 146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * ECHILD before sending us SIGCHILD. 146776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 146876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0 146976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (nprocs == 0) 147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "strace: proc miscount\n"); 147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 147576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman default: 147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman errno = wait_errno; 147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: wait"); 147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 147976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 148076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 148176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, " [wait(%#x) = %u]\n", status, pid); 148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* Look up `pid' in our table. */ 148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp = pid2tcb(pid)) == NULL) { 1486faf722234dc8af97776f94fdda7e100fb60650a2Wichert Akkerman#if 0 /* XXX davidm */ /* WTA: disabled again */ 14878b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman struct tcb *tcpchild; 14888b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman 14898b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman if ((tcpchild = alloctcb(pid)) == NULL) { 14908b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman fprintf(stderr, " [tcb table full]\n"); 14918b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman kill(pid, SIGKILL); /* XXX */ 14928b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman return 0; 14938b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman } 14948b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman tcpchild->flags |= TCB_ATTACHED; 14958b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman newoutf(tcpchild); 14968b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman tcp->nchildren++; 14978b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman if (!qflag) 14988b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman fprintf(stderr, "Process %d attached\n", pid); 14998b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#else 150076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "unknown pid: %u\n", pid); 150176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSTOPPED(status)) 150276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ptrace(PTRACE_CONT, pid, (char *) 1, 0); 150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman exit(1); 15048b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif 150576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* set current output file */ 150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman outf = tcp->outf; 150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (cflag) { 150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX 151076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime); 151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->stime = ru.ru_stime; 151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !LINUX */ 151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Apparently, doing any ptrace() call on a stopped 151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * process, provokes the kernel to report the process 151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * status again on a subsequent wait(), even if the 152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * process has not been actually restarted. 152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Since we have inspected the arguments of suspended 152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * processes we end up here testing for this case. 152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFSIGNALED(status)) { 152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag 152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { 152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("+++ killed by %s +++", 1531ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(WTERMSIG(status))); 153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WIFEXITED(status)) { 153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u exited\n", pid); 154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "PANIC: attached pid %u exited\n", 154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid); 154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "PANIC: pid %u not stopped\n", pid); 154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (debug) 155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "pid %u stopped, [%s]\n", 1554ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons pid, signame(WSTOPSIG(status))); 155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_STARTUP) { 155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * This flag is there to keep us in sync. 155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Next time this process stops it should 156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * really be entering a system call. 156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_STARTUP; 156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) { 156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Interestingly, the process may stop 156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * with STOPSIG equal to some other signal 156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * than SIGSTOP if we happend to attach 156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * just before the process takes a signal. 156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!WIFSTOPPED(status)) { 157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, 157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman "pid %u not stopped\n", pid); 157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, WSTOPSIG(status)); 157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4 157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* A child of us stopped at exec */ 158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGTRAP && followvfork) 158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fixvfork(tcp); 158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */ 158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_BPTSET) { 158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (clearbpt(tcp) < 0) /* Pretty fatal */ { 158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman goto tracing; 159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) != SIGTRAP) { 159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (WSTOPSIG(status) == SIGSTOP && 159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (tcp->flags & TCB_SIGTRAPPED)) { 159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman /* 159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Trapped attempt to block SIGTRAP 159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Hope we are back in control now. 160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */ 160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED); 160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, 160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman pid, (char *) 1, 0) < 0) { 160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!cflag 161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) { 161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printleader(tcp); 161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("--- %s (%s) ---", 1614ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons signame(WSTOPSIG(status)), 161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strsignal(WSTOPSIG(status))); 161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printtrailer(tcp); 161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((tcp->flags & TCB_ATTACHED) && 161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman !sigishandled(tcp, WSTOPSIG(status))) { 162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, WSTOPSIG(status)); 162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman WSTOPSIG(status)) < 0) { 162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->flags &= ~TCB_SUSPENDED; 163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (trace_syscall(tcp) < 0) { 163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman ptrace(PTRACE_KILL, 163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp->pid, (char *) 1, SIGTERM); 163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman droptcb(tcp); 163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_EXITING) { 164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_ATTACHED) 164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman detach(tcp, 0); 164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) { 164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("strace: ptrace(PTRACE_CONT, ...)"); 164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp->flags & TCB_SUSPENDED) { 165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (!qflag) 165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman fprintf(stderr, "Process %u suspended\n", pid); 165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman continue; 165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tracing: 165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) { 165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman perror("trace: ptrace(PTRACE_SYSCALL, ...)"); 166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman cleanup(); 166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return -1; 166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return 0; 166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !SVR4 */ 166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol; 167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h> 167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b) 167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h> 167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a) 167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__ 168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...) 168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else 168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist) 168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt; 168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl 168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif 168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_list args; 168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman VA_START(args, fmt); 169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (outf) 169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman curcol += vfprintf(outf, fmt, args); 169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman va_end(args); 169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman return; 169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp) 169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) { 170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last->flags |= TCB_REPRINT; 170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf(" <unfinished ...>\n"); 170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman curcol = 0; 170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if ((followfork == 1 || pflag_seen > 1) && outfname) 170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%-5d ", tcp->pid); 170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (nprocs > 1 && !outfname) 170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("[pid %5u] ", tcp->pid); 171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag) { 171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman char str[sizeof("HH:MM:SS")]; 171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman struct timeval tv, dtv; 171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman static struct timeval otv; 171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman gettimeofday(&tv, NULL); 171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (rflag) { 171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (otv.tv_sec == 0) 171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tv_sub(&dtv, &tv, &otv); 172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%6ld.%06ld ", 172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) dtv.tv_sec, (long) dtv.tv_usec); 172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman otv = tv; 172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else if (tflag > 2) { 172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%ld.%06ld ", 172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman (long) tv.tv_sec, (long) tv.tv_usec); 172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else { 172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman time_t local = tv.tv_sec; 173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman strftime(str, sizeof(str), "%T", localtime(&local)); 173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (tflag > 1) 173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s.%06ld ", str, (long) tv.tv_usec); 173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman else 173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%s ", str); 173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman } 173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (iflag) 173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman printcall(tcp); 173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col) 174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col; 174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman if (curcol < col) 174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("%*s", col - curcol, ""); 174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman 174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid 175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprinttrailer(tcp) 175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp; 175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{ 175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tprintf("\n"); 175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman tcp_last = NULL; 175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman} 17569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 1757ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS 17589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 17599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkermanint mp_ioctl (int fd, int cmd, void *arg, int size) { 17609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 17619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman struct iovec iov[2]; 17629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman int n = 1; 17639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 17649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_base = &cmd; 17659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[0].iov_len = sizeof cmd; 17669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman if (arg) { 17679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman ++n; 17689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_base = arg; 17699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman iov[1].iov_len = size; 17709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman } 17719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 17729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman return writev (fd, iov, n); 17739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman} 17749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman 17759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif 1776