strace.c revision 6b7a261ff81fdbe84769cb59852fa43cabc77e8f
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
3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
35795edb11488dd47c4598e2228e3b5431de7ed46dRoland McGrath#include <sys/types.h>
3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h>
4619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h>
4770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
4876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
49134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX
50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h>
51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# if defined __NR_tgkill
52134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
53134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# elif defined __NR_tkill
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else
56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath   /* kill() may choose arbitrarily the target task of the process group
57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      while we later wait on a that specific TID.  PID process waits become
58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      TID task specific waits for a process under ptrace(2).  */
59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) kill ((tid), (sig))
61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif
62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif
63134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath
647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
68bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
71bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
7276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
74ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
751d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
791d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
8096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
81418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
82418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
8396d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8541c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0;
86b13c0de058585de7d47778a8923426b89bfffbb5Wang Chaounsigned int ptrace_setoptions = 0;
87e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0;
88e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE;
89b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
90ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
107a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
108a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
109eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
110b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
116b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
118ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
119ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
120ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
12130145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinconst char *progname;
122eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathextern char **environ;
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
124e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int detach(struct tcb *tcp, int sig);
125e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
126e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
127e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
138e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd);
139e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig);
140e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void);
141ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void);
146e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd);
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
164bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
172b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwabusage: strace [-CdDffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
173de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
174de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
175b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab   or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
176de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
178b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
193ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
197de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
198de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
199de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
20017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
201de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
202de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
215c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
216c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
217c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
218c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
219c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
220c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
221c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
222c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     flags, newflags;
22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return 0;
23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fcntl(fd, F_SETFD, newflags) < 0)
24010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
24110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
24210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
24310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
24410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
25110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
25910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (euid != uid && setreuid(euid, uid) < 0)
26010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
26110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: setreuid: %s\n",
26210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
26310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		exit(1);
26410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
26510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
26610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
26710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
2684bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
2694bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
2704bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
2714bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
2724bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
2734bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode)
27610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
27810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
27910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
2804bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath	if ((fp = fopen_for_output(path, mode)) == NULL)
28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: can't fopen '%s': %s\n",
28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, path, strerror(errno));
28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fp && set_cloexec_flag(fileno(fp)) < 0)
28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fclose(fp);
28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fp = NULL;
28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1;
29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     fds[2];
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: pipe: %s\n",
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(fds[1]) < 0)
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((popen_pid = fork()) == -1)
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fork: %s\n",
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (popen_pid)
33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* parent */
33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return fdopen(fds[1], "w");
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	} else
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		{
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			fprintf(stderr, "%s: dup2: %s\n",
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				progname, strerror(errno));
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			_exit(1);
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: execl: %s: %s\n",
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, _PATH_BSHELL, strerror(errno));
35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		_exit(1);
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
3627a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		FILE *fp;
36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3657a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
36610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if ((fp = strace_fopen(name, "w")) == NULL)
36710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			return -1;
36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		tcp->outf = fp;
36910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
37010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
37110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
37210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
37902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
38002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
38102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
38202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
38302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * We rely on cleanup () from this point on.
38402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
38502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
38602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
38702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
388ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
389ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
390ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
391ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(1);
392ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
393ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
394ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
395ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for child to attach to straced process
396ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * (our parent). Child SIGKILLs us after it attached.
397ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Parent's wait() is unblocked by our death,
398ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
399ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
400ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
401ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
402ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
403ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
404ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (newoutf(tcp) < 0)
41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
41802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
41902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
42202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
42402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
42502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
426ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
4277a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
4377a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
443aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
445aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					else if (tid != tcbtab[tcbi]->pid) {
446418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko						tcp = alloctcb(tid);
44721b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nchildren++;
44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_threads++;
45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->parent = tcbtab[tcbi];
45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
452aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (interactive) {
453aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_SETMASK, &empty_set, NULL);
454aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						if (interrupted)
455aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko							return;
456aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
457aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					}
45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
4607a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
4617a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
4677a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
4687a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
4697a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
4707a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko						tcbtab[tcbi]->pid, ntid);
47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
4737a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
4747a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif
47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* INTERRUPTED is going to be checked at the top of TRACE.  */
482ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
483ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
484ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
485ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
486ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
487ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
488ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
489ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
490ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
491ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
492ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
493ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
494ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
495ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_child (char **argv)
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("strace: exec");
52102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
53530145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		fprintf(stderr, "%s: %s: command not found\n",
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			progname, filename);
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
573a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
574ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: fork");
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		cleanup();
57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
578ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
579ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
580ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
581ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
582ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf != stderr) close (fileno (outf));
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
595ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		kill(pid, SIGSTOP); /* stop HERE */
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf!=stderr)
59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			close(fileno (outf));
60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
601ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
602ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
603ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				perror("strace: ptrace(PTRACE_TRACEME, ...)");
604ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				exit(1);
605ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
606ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
607ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("initgroups");
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setregid");
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setreuid");
63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
641ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
642ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
643ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Induce an immediate stop so that the parent
644ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
645ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * this execve call normally.
646c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * Unless of course we're on a no-MMU system where
647c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * we vfork()-ed, so we cannot stop the child.
648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
649c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
650c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger				kill(getpid(), SIGSTOP);
651ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
652ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
653ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
654ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
655ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
656ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
657ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
658ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
659ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
660ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
661ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
662ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
663ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
664ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
665ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
666ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
667ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
66902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
67102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: exec");
67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		_exit(1);
67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
674ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
675ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
678ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
68102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
682ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		fprintf(stderr, "trouble opening proc file\n");
684ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		cleanup();
685ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		exit(1);
68602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
687ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
68802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
68902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
690b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX
691b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
692b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
693b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
694b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
695b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
696b13c0de058585de7d47778a8923426b89bfffbb5Wang Chaostatic int
697b13c0de058585de7d47778a8923426b89bfffbb5Wang Chaotest_ptrace_setoptions(void)
698b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
6992fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
7002fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
7012fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
7022fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
703b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
704b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	if ((pid = fork()) < 0)
705b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		return -1;
706b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	else if (pid == 0) {
707b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
708b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			_exit(1);
709b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		kill(getpid(), SIGSTOP);
710b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		_exit(fork() < 0);
711b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
712b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
713b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
714b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
715b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
716b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
717b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid == -1) {
718b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
719b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
720b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			else if (errno == ECHILD)
721b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
722b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			perror("test_ptrace_setoptions");
723b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			return -1;
724b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
725b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
7262fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
727b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
728b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			    errno != ESRCH)
729b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				kill(tracee_pid, SIGKILL);
730b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
731b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		else if (WIFSTOPPED(status)) {
7322fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			switch (WSTOPSIG(status)) {
7332fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			case SIGSTOP:
7342fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				if (ptrace(PTRACE_SETOPTIONS, pid,
7352fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					   NULL, test_options) < 0) {
736b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao					kill(pid, SIGKILL);
737b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin					return -1;
738b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				}
7392fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				break;
7402fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			case SIGTRAP:
7412fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				if (status >> 16 == PTRACE_EVENT_FORK) {
7422fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					long msg = 0;
7432fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
7442fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					if (ptrace(PTRACE_GETEVENTMSG, pid,
7452fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin						   NULL, (long) &msg) == 0)
7462fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin						expected_grandchild = msg;
7472fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				}
7482fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				break;
749b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
750b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
751b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			    errno != ESRCH)
752b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				kill(pid, SIGKILL);
753b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
754b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
7552fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild)
7562fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin		ptrace_setoptions |= test_options;
757b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	return 0;
758b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
759b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif
760b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
76208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
76606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
77108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
77208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
773ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
774ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
775418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
77608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
77708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
77808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
779418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
78008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
78108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
78208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
783ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
784ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
785ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
788138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
789138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
795e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		"+cCdfFhiqrtTvVxz"
796ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
797ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
798ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
799ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"a:e:o:O:p:s:S:u:E:")) != EOF) {
80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
80176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
802e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
803e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
804e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin					progname);
805e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				exit(1);
806e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
807e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
808e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
809e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
810e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
811e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
812e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin					progname);
813e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				exit(1);
814e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
815e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
81676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
820ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
821ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
822ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
823ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
824ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
82541c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
82606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
82706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
83376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
83476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
83676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
8579c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
86017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
86117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
86217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
876de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
87876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pid == getpid()) {
88254a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
88476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
885418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
891dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
892dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				fprintf(stderr,
893dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					"%s: invalid -s argument: %s\n",
894dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					progname, optarg);
895dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				exit(1);
896dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
89776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
90276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
904de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
905de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
906de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
907de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
908de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
909de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
910de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
917d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
918ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
919ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
920d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	if (pflag_seen && daemonized_tracer) {
921d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao		fprintf(stderr,
922d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao			"%s: -D and -p are mutually exclusive options\n",
923d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao			progname);
924d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao		exit(1);
925d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
926d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
92706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
92806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
92906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
930cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
931cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		fprintf(stderr,
932e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			"%s: (-c or -C) and -ff are mutually exclusive options\n",
933cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			progname);
934cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		exit(1);
935cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
936cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
94909553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath				progname, username);
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9608044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX
9618044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin	if (followfork) {
9628044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		if (test_ptrace_setoptions() < 0) {
9638044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin			fprintf(stderr,
9648044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				"Test for options supported by PTRACE_SETOPTIONS "
9658044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				"failed, giving up using this feature.\n");
9668044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin			ptrace_setoptions = 0;
9678044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		}
9688044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		if (debug)
9698044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin			fprintf(stderr, "ptrace_setoptions = %#x\n",
9708044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				ptrace_setoptions);
9718044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin	}
9728044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif
9738044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
97637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
97737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
97837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
97937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
98037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
98137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
98237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
98337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
98437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
98537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
98637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
98737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
98837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
98910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if ((outf = strace_popen(outfname + 1)) == NULL)
99037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
99154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
99210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		else if (followfork <= 1 &&
99310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			 (outf = strace_fopen(outfname, "w")) == NULL)
99454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
99737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
99937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1002369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1003b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
100454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
100554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
100654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
100754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
100854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
100954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
101054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
101154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
101254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
101354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
101454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
101554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
101654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
101754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
1043bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
1046553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1047553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1048553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1049553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1050553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1051553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1052553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1053553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
1054bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1056ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
105702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
105802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
1062a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
1063a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
1064a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
1065a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
1066a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
1067a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
1068a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
1069a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
1070a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
1071a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
1072a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1075418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkovoid
1076418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
10777b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
10787b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
10797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
10807b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
10817b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
10827b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
10837b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb **newtab = (struct tcb **)
10847b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
10857b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
10867b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    sizeof *newtcbs);
10877b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	int i;
10887b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	if (newtab == NULL || newtcbs == NULL) {
108976860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
109076860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin			progname);
1091418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		cleanup();
1092418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		exit(1);
10937b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
10947b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
10957b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
10967b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
10977b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
10987b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
10997b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
110110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1106418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1107418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1108418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1109ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1110ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
1113eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->parent = NULL;
1114eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nchildren = 0;
1115eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nzombies = 0;
1116eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef TCB_CLONE_THREAD
111721b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao			tcp->nclone_threads = 0;
1118eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nclone_waiting = 0;
1119eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
1122ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			tcp->curcol = 0;
1123eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->stime.tv_sec = 0;
1124eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->stime.tv_usec = 0;
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
112710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
112810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1132418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1133418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	cleanup();
1134418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	exit(1);
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1137bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1139418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
114276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1143bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
114419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
114519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1148bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
115176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1153ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
11549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
11559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
11569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
11579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
11589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
11599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
116010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
11619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
11629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
11639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
11649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
11659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
11669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
11679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
116810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_stat) < 0) {
11699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
11709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
11719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
11729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
11739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
11749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
11759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
117610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_as) < 0) {
11779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
11789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
11799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1181bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
1183372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR|O_EXCL);
1184bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1185bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1186372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR);
1187bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
1188372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	if (tcp->pfd < 0) {
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
119210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
11939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
11949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
11959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1196bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1197bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1198bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1199bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1200bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1201bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1202bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1203bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1204bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1205bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1206bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1207bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1208bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1209bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1210bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
12189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
12229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1223bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1226bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
122816a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1232553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
12369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
12429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1247553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
125076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1256bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1257bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1258bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1259bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
12605ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1261bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1262bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1263bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
12645ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
12655ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1266bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1267bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1269bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
127019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
127119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
127219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
127319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
127419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
127519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
127619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
127719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
127819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
127919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
128019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
128119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1282553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
128319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
128419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
128519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
128619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
128719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
128819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
128919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
129019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
129119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
129219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
129619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
129719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
130119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
130219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
130319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
130419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
130519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
130619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
13079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
131119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
131219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
131319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
131419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
131519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
131619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
13179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1321bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1322bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1323bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
1324bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1325bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1326bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1327bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1328bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1337553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
13399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
13409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1344553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1345bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1346bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1347bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1348bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1349553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
13529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
13569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1357bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1358bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
135976989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1363bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
13649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
13659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1366bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1367bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1368553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1372bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1373bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1374bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1375bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1376bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1377bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1378553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
137976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1380bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
138176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1382bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1383bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1384553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
13852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
13862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
13872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
13882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
13892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
13902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
13912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1392553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
13932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
13942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
13952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
13962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
13972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
13982e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
13992e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
14002e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
14012e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
14022e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
14032e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
14042e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
14052e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
14062e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
14072e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
14082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1409bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1410bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1424bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1426e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
142754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
143054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
143154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
143254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1434ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
143554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
143654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
143954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1443bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
144654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void)
144754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{
144854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	int i;
144954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	struct tcb *tcp;
145054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
145154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		tcp = tcbtab[i];
145254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->flags & TCB_INUSE)
145354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath			return tcp;
145454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	}
145554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	return NULL;
145654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath}
145754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
145854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb *
145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1464ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1465ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
146776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
146876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
146976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1474bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
147576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
147976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
148076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
148176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1482e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1483e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1484e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1485e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1486e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1487e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1488e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1489e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1490e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1491e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1494eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1495e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1496e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1497e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1498e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1499e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1500e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
150121b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao		tcp->parent->nzombies++;
1502276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX
1503276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		/* Update `tcp->parent->parent->nchildren' and the other fields
1504276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   like NCLONE_DETACHED, only for zombie group leader that has
1505276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   already reported and been short-circuited at the top of this
1506276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   function.  The same condition as at the top of DETACH.  */
1507276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		if ((tcp->flags & TCB_CLONE_THREAD) &&
1508276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    tcp->parent->nclone_threads == 0 &&
1509276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    (tcp->parent->flags & TCB_EXITING))
1510276ceb33f20fc41403e46684e441230296f6a433Roland McGrath			droptcb(tcp->parent);
1511276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif
1512e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1513e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1514e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1515e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1519bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1520bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1521bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1522bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1523bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1524bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1525bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1526bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1527bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1528553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1529bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1530e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1533eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1534822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1536eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1540bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1554e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1555e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1556e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1557e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1559732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15671bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int
15681bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathresume_from_tcp (struct tcb *tcp)
15691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{
15701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int error = 0;
15711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int resumed = 0;
15721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
15731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	/* XXX This won't always be quite right (but it never was).
15741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
15751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   a particular pgrp, which this child might or might not be
15761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
15771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
15781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   difference to wake up a waiter when there might be more
15791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   traced children, because it could get a false ECHILD
15801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
15811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
15821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   search the system for all pid's in the pgrp to be sure.
15831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
15841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	     && (t->waitpid == -1 ||
15851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
15861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
15871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	*/
15881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
15891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent &&
15901bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
15911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
15925ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		error = resume(tcp->parent);
15931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		++resumed;
15941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
15951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD
15961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
15971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Some other threads of our parent are waiting too.  */
15981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		unsigned int i;
15991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
16001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
16011bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
16021bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			struct tcb *t = tcbtab[i];
16031bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			if (t->parent == tcp->parent && t != tcp
16041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
16051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
16061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && t->waitpid == tcp->pid) {
16071bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				error |= resume (t);
16081bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				++resumed;
16091bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
16101bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		}
16111bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		if (resumed == 0)
16121bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			/* Noone was waiting for this PID in particular,
16131bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			   so now we might need to resume some wildcarders.  */
16141bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
16151bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				struct tcb *t = tcbtab[i];
16161bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				if (t->parent == tcp->parent && t != tcp
16171bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && ((t->flags
16181bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
16191bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
16201bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && t->waitpid <= 0
16211bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					) {
16221bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					error |= resume (t);
16231bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					break;
16241bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				}
16251bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
16261bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
16273bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#endif
16281bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
16291bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	return error;
16301bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath}
16311bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
1632bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16340a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
16350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
16360a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
16370a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1645ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
16461bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1647a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1648a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1649a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1650a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1651a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1652a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1653a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1654a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1655ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1658840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
16637bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
16647bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
16667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
16677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
16687bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
16697bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
167002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
167102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
167202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
167302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
167402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
167502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
16787bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
16797bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
16807bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
16817bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
16827bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1683134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1684134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1685134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
16867bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
16877bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
16887bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
168902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
169002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
169102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
16927bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
16937bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
16947bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
169502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
169602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1697ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
16997508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
17007508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
17017508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
17027508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
17037508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
17057508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
17067508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
17077508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
17087508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
17097508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
17107508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
17117508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
17127508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
17137508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
17147508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
17157508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
17167508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
17177508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
17187508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
17197508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
17207508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
17217508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
17227508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
17237508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
17247508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
17267508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1732732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1735732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
1736eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					WSTOPSIG(status) == SIGTRAP ? 0
1737732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1738732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1741ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
17427bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1749732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1752bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
17531bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	error |= resume_from_tcp (tcp);
1754e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1755e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1760a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1761a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX
17620a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	if (zombie != NULL) {
17630a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		/* TCP no longer exists therefore you must not detach () it.  */
17640a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(zombie);
17650a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	}
1766a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif
1767a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1771bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1773e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig)
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1782bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1790ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1791ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1799ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			tprintf(" <unfinished ...>");
1800ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18226d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
18256d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18448f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
18456d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
18478f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
18488f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
18498f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1870bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1877ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1878ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1879c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1880ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
188146100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "%s: out of memory\n", progname);
1882ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1883ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1884ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1885ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1886ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
18909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
191110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1959bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1960bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1961bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
1966a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
1990a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
2001bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
20025ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
20035ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
20045ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
20055ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
20069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
20399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
20749dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
2075d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
20769dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
20819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
209554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath				tcp = first_used_tcb();
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
21089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
21099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
21109dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
21119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2112553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
21139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
21149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
21159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
21169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
21179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
21189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
21199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
21209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
21219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
21229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
21239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
21249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
21259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
21269dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
21279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
21289dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
21299dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2153b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
21549dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2155b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2158bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
21599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
2160bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2161bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2162bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2163bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2164bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2165bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
2166bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
21675ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko				ioctl_result = IOCTL_WSTOP (tcp);
2168553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2191bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2192bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2193553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
22032e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
22042e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
22052e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
22062e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
22072e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
22082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2209553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2210553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
2216ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2220bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2221bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2222bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2223bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2224bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2225bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2226bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2227bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2228bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2229bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2230bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2231553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2234bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
22389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
22399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2240bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
224176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
22429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
22439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
224676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
224776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
224976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2250bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
22529dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
22539dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
22549dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
225576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
2262e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2263e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_SIGNAL)) {
226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2266ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2267ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
22685826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
22695826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
22705826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
22715826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
22725826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2273ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
22745826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
22755826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
2279e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAGS_ONLY_STATS
2280e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_FAULT)) {
228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2283ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2286bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2287bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
22885ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2289553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
22919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
229276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
229376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2295ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2296ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
22979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2298553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
2299372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0)
2300553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2301372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0)
2302553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2303372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		{
230476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
230776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2311bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2313e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2314e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2315e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2316e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2317e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2318e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2319e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2320e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2321e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2322e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2323e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2324e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
23257a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	struct tcb *leader = NULL;
23267a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko
23277a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	if (tcp->flags & TCB_CLONE_THREAD)
23287a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp->parent;
2329e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2330e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
23317a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		if (leader != NULL && leader != tcp
23327a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(leader->flags & TCB_GROUP_EXITING)
23337a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(tcp->flags & TCB_STARTUP)
23347a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		) {
2335e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2336e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2337e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
23387a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		}
23397a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
23401bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS
23417a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		resume_from_tcp(tcp);
23421bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif
23430a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2344e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2345e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2346a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2347a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2348e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
2349d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath			detach(tcp, sig);
23505ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			if (leader != NULL && leader != tcp)
23511bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2352732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else {
2353732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2354732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				cleanup();
2355732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				return -1;
2356732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2357732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (leader != NULL) {
23580569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2359732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (leader != tcp)
2360732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					droptcb(tcp);
2361732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2362e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2363e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2364e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2365e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2366e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2367e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2368e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2369e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2370e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2371e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2372ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
2373ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaostatic int
2374ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaohandle_ptrace_event(int status, struct tcb *tcp)
2375ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao{
2376ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	if (status >> 16 == PTRACE_EVENT_VFORK ||
2377ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	    status >> 16 == PTRACE_EVENT_CLONE ||
2378ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	    status >> 16 == PTRACE_EVENT_FORK) {
23792fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin		long childpid;
2380ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
2381ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2382ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (errno != ESRCH) {
2383ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				fprintf(stderr, "\
2384ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao%s: handle_ptrace_event: ptrace cannot get new child's pid\n",
2385ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao					progname);
2386ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				cleanup();
2387ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				exit(1);
2388ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			}
2389ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			return -1;
2390ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2391ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		return handle_new_child(tcp, childpid, 0);
2392ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	}
2393ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	return 1;
2394ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao}
2395ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
2396ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
2397eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
2398eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace()
239976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
240076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
240176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
240276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
240376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
240476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
240576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
24062f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2407eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
24082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
240976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
241076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2411eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2412222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2413eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2414eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2415eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
241676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
24172f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2418eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
24195bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
24202f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
24212f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
24222f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
2423eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, wait4_options,
2424eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
24252f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
24265bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
24272f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
2428eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, __WCLONE,
2429eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
2430eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (pid == -1) {
2431eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				fprintf(stderr, "strace: clone wait4 "
24322f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
24332f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
24342f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
2435eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#else
2436eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2437eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* __WALL */
243876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
243976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
244076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
244176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
244276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2443eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2444eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
244576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
244676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
2447eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2448eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2450eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
245176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
245476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
245576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
245676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
2457eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2458eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2459eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2460eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2461eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
246276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
246376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
246410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
246510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
246610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				popen_pid = -1;
246710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
246810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
246976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
247076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
247176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
247276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2474e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
247541c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2476e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2477e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2478e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2479e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2480e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2481e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2482e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2483e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2484e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2485418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2486e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2487e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2488e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2489e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2490e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
24918b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2492e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2493e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2494e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2495eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2496e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2497e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2498e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2499e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2500e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2501e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
250276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2503eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2504eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
2505ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
250684e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko		if (cflag) {
2507eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
250876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
2510eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* !LINUX */
251176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2512eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
2513f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		if (tcp->flags & TCB_SUSPENDED) {
2514f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			/*
2515f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Apparently, doing any ptrace() call on a stopped
2516f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process, provokes the kernel to report the process
2517f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * status again on a subsequent wait(), even if the
2518f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process has not been actually restarted.
2519f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Since we have inspected the arguments of suspended
2520f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * processes we end up here testing for this case.
2521f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 */
2522f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			continue;
2523f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		}
252476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2525a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2526a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2527e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
252876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
252976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
25302efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
25312efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
25322efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
25332efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
25342efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
25352efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
2536ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
253776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2538e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2539e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2540e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
254176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2542e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2546a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2547a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
254876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
25497a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
25507a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
25510569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
25527a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			    && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
25531bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && !(tcp->flags & TCB_GROUP_EXITING)
25540569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
25557a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			) {
255676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
25577a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					"PANIC: attached pid %u exited with %d\n",
25587a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					pid, WEXITSTATUS(status));
25597a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			}
25600a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
25617a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
25620a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
25630a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
25640a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
25650a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2566e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2567e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2568e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
256976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2570e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
257176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
257276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
257376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
257576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
257676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
257776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
257876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
257976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2580ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
258176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2582ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		if (ptrace_setoptions && (status >> 16)) {
2583ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (handle_ptrace_event(status, tcp) != 1)
2584ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				goto tracing;
2585ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2586ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
258702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
258802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
258902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
2590eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		 * than SIGSTOP if we happend to attach
259102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
2592c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * A no-MMU vforked child won't send up a signal,
2593c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * so skip the first (lost) execve notification.
259402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
2595c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		if ((tcp->flags & TCB_STARTUP) &&
2596c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		    (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
259776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
259876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
259976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
260076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
260176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
260276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
260302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
260476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
260502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
260602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
260776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
260876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
260976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
261076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
261176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2614ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
2615ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (followfork && (tcp->parent == NULL) && ptrace_setoptions)
2616ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				if (ptrace(PTRACE_SETOPTIONS, tcp->pid,
2617ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao					   NULL, ptrace_setoptions) < 0 &&
2618ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				    errno != ESRCH)
2619ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao					ptrace_setoptions = 0;
2620ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
262176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
262276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
262376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2624eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (WSTOPSIG(status) != SIGTRAP) {
262576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
262676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
262776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
262876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
262976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
263076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
263176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2632732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
263376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
263476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
263576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
263676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
263776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2638e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
263976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
2640c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin				siginfo_t si;
2641c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
26426b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
26436b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
26447b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2645932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2646932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
26477b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
26486b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
26497b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
26506b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
26516b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	pc
26526b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
26536b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	"%s"
26546b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	""
26557b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
26576b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
26586b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- ");
26596b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
26606b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf(" (%s)" PC_FORMAT_STR " ---",
26616b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
26626b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
26636b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
26646b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- %s by %s" PC_FORMAT_STR " ---",
26656b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
26666b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						signame(WSTOPSIG(status)),
26676b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
2668ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
266976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
26700569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
26710569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
267276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2673e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2674e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2675e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
267676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2677e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2680732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
268176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
268276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
268376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
268476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
268576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
268676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
268702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
268802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
268902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2690eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2691eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2692eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2693eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2694eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * all processes in thread group. In this case, threads
2695eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * "disappear" in an unpredictable moment without any
2696eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * notification to strace via wait().
2697ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2698ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2699eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (tcp_last) {
2700eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2701eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 * Finish the line then. We cannot
2702eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2703eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp_last->flags |= TCB_REPRINT;
2704eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tprintf(" <unfinished ...>");
2705eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					printtrailer();
2706eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
270776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2708ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2709eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				ptrace(PTRACE_KILL,
2710eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp->pid, (char *) 1, SIGTERM);
271176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
271276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
271376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
271476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
271576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2716e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2717e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2718e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2719e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2720e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2721e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2722e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
272376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
272476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2725732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
272676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
272776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
272876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
272976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
273076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
273176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
273276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
273376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
273476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
273576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
273676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2737ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2738ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
2739732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
274076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
274176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
274276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
274376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
274476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
274576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
274676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2747bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
274876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
274976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
275076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
275176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
275276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
275376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
275476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
275576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2756e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab	va_start(args, fmt);
2757b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2758b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2759ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		if (n < 0) {
2760ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			if (outf != stderr)
2761ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				perror(outfname == NULL
2762ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				       ? "<writing to pipe>" : outfname);
2763ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		} else
2764b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2765b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
276676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
276776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
276876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
276976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
277076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2771eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathprintleader(tcp)
2772eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstruct tcb *tcp;
277376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2774732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2775eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tcp_last->ptrace_errno) {
2776732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
2777eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tprintf(" <unavailable>)");
2778eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tabto(acolumn);
2779732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2780eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf("= ? <unavailable>\n");
2781eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp_last->ptrace_errno = 0;
2782732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
27837e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2784eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf(" <unfinished ...>\n");
2785732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
278676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
278776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
278876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
278976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
279076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
279176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
279276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
279376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
279476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
279576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
279676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
279776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
279876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
279976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
280076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
280176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
280276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
280376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
280476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
280576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
280676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
280776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
280876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
280976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
281076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
281176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
281276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
281376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
281476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
281576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
281676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
281776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
281876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
281976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
282076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
282176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
282276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
282376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
282476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
282576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
282676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
282776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
282876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
282976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
283076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
283176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2832ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
283376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
283476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
283576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
283676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
28379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2838ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
28399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2840ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2841ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2842ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
28439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
28449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2845553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
28469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
28479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
28489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
28499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
28509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
28519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
28529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2853553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2854ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
28559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
28569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
28579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2858