strace.c revision 418d66a847bda4867c59e604c0d07c64ed53e320
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;
86b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinint dtime = 0, cflag = 0, xflag = 0, qflag = 0;
87b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
88ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
89ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
90ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
105a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
106a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
10796d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkostatic int ptrace_stop_sig = SIGTRAP;
10896d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkostatic bool ptrace_opts_set;
109a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin
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;
118ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
119ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname;
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1220a463880341945df08b6dc79134dc78cc38dc283Roland McGrathstatic int detach P((struct tcb *tcp, int sig));
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void));
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void));
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig));
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted;
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
138bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd));
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig));
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void));
143ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void));
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd));
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
161ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
166bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
175de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
176de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
177ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko   or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
178de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
194ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
198de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
199de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
200de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
20117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
202de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
203de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
21710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
21810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
21910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     flags, newflags;
22010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
22110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
22210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return 0;
23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fcntl(fd, F_SETFD, newflags) < 0)
23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
24010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
24110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
24210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
24310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
24410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
25110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (euid != uid && setreuid(euid, uid) < 0)
25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: setreuid: %s\n",
25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		exit(1);
25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
25910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
26010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
2614bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
2624bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
2634bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
2644bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
2654bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
2664bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
26710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
26810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode)
26910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
27010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
27110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
27210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
2734bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath	if ((fp = fopen_for_output(path, mode)) == NULL)
27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: can't fopen '%s': %s\n",
27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, path, strerror(errno));
27610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fp && set_cloexec_flag(fileno(fp)) < 0)
27810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
27910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fclose(fp);
28010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fp = NULL;
28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1;
28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     fds[2];
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: pipe: %s\n",
30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(fds[1]) < 0)
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((popen_pid = fork()) == -1)
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fork: %s\n",
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (popen_pid)
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* parent */
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return fdopen(fds[1], "w");
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	} else
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		{
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			fprintf(stderr, "%s: dup2: %s\n",
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				progname, strerror(errno));
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			_exit(1);
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: execl: %s: %s\n",
34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, _PATH_BSHELL, strerror(errno));
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		_exit(1);
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		char name[MAXPATHLEN];
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		FILE *fp;
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		sprintf(name, "%s.%u", outfname, tcp->pid);
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if ((fp = strace_fopen(name, "w")) == NULL)
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			return -1;
36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		tcp->outf = fp;
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
36510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
36702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
36802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
36902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
37002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
37102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
37202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * We rely on cleanup () from this point on.
37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
37902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
38002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
381ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
382ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
383ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
384ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(1);
385ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
386ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
387ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
388ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for child to attach to straced process
389ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * (our parent). Child SIGKILLs us after it attached.
390ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Parent's wait() is unblocked by our death,
391ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
392ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
393ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
394ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
395ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
396ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
397ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
39802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
39902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
40002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
40102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
40202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (newoutf(tcp) < 0)
40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
41802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
419ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			char procdir[MAXPATHLEN];
42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
42202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
42402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
42502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
42602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
42702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (de->d_fileno == 0 ||
43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					    de->d_name[0] == '.')
43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
43702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (ptrace(PTRACE_ATTACH, tid,
43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						   (char *) 1, 0) < 0)
43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					else if (tid != tcbtab[tcbi]->pid) {
441418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko						tcp = alloctcb(tid);
44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nchildren++;
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_threads++;
44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_detached++;
44602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->parent = tcbtab[tcbi];
44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (interactive) {
44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						sigprocmask(SIG_SETMASK, &empty_set, NULL);
45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						if (interrupted)
45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							return;
45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
45602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (nerr == ntid) {
45702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
46002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					ntid -= nerr;
46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (ntid > 1)
46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						fprintf(stderr, "\
46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathProcess %u attached with %u threads - interrupt to quit\n",
46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							tcp->pid, ntid);
46702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					else
46802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						fprintf(stderr, "\
46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathProcess %u attached - interrupt to quit\n",
47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							tcp->pid);
47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
47302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
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 {
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		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.
646ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
647ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getpid(), SIGSTOP);
648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
649ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
650ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
651ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
652ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
653ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
654ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
655ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
656ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
657ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
658ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
659ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
660ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
661ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
662ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
663ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
664ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
66502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
66602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
66702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: exec");
66902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		_exit(1);
67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
671ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
672ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
673ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
674ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
675ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
67802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		fprintf(stderr, "trouble opening proc file\n");
681ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		cleanup();
682ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		exit(1);
68302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
684ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
68502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
68602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
68808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
69206350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
69708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
69808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
699ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
700ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
701418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
70208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
70308b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
70408b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
705418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
70608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
70708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
70808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
709ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
710ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
711ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
71376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
714138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
715138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
71776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
721ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"+cdfFhiqrtTvVxz"
722ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
723ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
724ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
725ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"a:e:o:O:p:s:S:u:E:")) != EOF) {
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cflag++;
72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
734ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
735ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* Experimental, not documented in manpage yet. */
736ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
737ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
738ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
739ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
74041c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
74106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
74206350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
7729c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
77617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
77717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
791de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
79676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pid == getpid()) {
79754a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
79876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
79976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
800418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
80176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
80276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
80576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
806dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
807dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				fprintf(stderr,
808dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					"%s: invalid -s argument: %s\n",
809dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					progname, optarg);
810dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				exit(1);
811dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
81476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
81676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
819de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
820de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
821de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
822de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
823de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
824de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
825de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
832d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
833ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
834ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
83506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
83606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
83706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
838cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
839cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		fprintf(stderr,
840cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			"%s: -c and -ff are mutually exclusive options\n",
841cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			progname);
842cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		exit(1);
843cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
844cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
85709553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath				progname, username);
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
87037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
87137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
87237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
87337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
87437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
87537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
87637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
87737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
87837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
87937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
88037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
88137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
88237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
88310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if ((outf = strace_popen(outfname + 1)) == NULL)
88437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
88554b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
88610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		else if (followfork <= 1 &&
88710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			 (outf = strace_fopen(outfname, "w")) == NULL)
88854b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
89137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
89276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
89337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
89476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
89576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
896369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
89754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
89854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
89954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
90054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
90154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
90254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
90354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
90454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
90554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
90654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
90754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
90854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
90954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
91054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
936bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
939553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
940553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
941553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
942553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
943553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
944553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
945553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
946553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
947bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
949ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
95002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
95102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
955a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
956a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
957a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
958a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
959a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
960a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
961a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
962a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
963a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
964a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
965a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
968418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkovoid
969418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
9707b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
9717b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
9727b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
9737b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
9747b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
9757b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
9767b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb **newtab = (struct tcb **)
9777b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
9787b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
9797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    sizeof *newtcbs);
9807b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	int i;
9817b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	if (newtab == NULL || newtcbs == NULL) {
98276860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
98376860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin			progname);
984418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		cleanup();
985418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		exit(1);
9867b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
9877b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
9887b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
9897b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
9907b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
9917b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
9927b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
99410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
999418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1000418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1001418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1002ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1003ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->parent = NULL;
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->nchildren = 0;
10080962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->nzombies = 0;
1009e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1010e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_threads = tcp->nclone_detached = 0;
1011e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_waiting = 0;
1012e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_sec = 0;
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_usec = 0;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
101910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
102010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1024418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1025418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	cleanup();
1026418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	exit(1);
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1029bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1031418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1035bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
103619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
103719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1040bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1045ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
10469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
10479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
10489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
10499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
105210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
10539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
10569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
10579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
106010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_stat) < 0) {
10619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
10649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
10659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
106810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_as) < 0) {
10699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1073bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
1076bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1077bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1078bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1079bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
108076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
108310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
10849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1087bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1088bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1089bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1090bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1091bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1092bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1093bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1094bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1095bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1096bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1097bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1098bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1099bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1100bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1101bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
110676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
11099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
11139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1114bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
111916a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1123553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
11279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
11339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1138553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
114276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1148bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1149bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1150bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
1151bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
1152bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1153bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1154bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1155bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCSFL");
1156bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
1157bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1158bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1160bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
116119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
116219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
116319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
116419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
116519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
116619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
116719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
116819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
116919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
117019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
117119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
117219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1173553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
117419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
117519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
117619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
117719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
117819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
117919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
118019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
118119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
118219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
118319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
118719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
118819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
119219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
119319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
119419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
119519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
119619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
119719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
11989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
120219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
120319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
120419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
120519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
120619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
120719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
12089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1212bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1213bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1214bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
1215bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1216bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1217bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1218bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1219bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1228553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
12309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
12319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
123276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1235553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1236bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1237bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1238bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1239bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1240553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
12439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
12479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1248bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1249bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
125076989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1254bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
12559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
12569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1257bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1258bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1259553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1263bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1264bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1265bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1266bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1267bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1268bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1269553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1271bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1273bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1274bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1275553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
12762e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
12772e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
12782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
12792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
12802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
12812e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
12822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1283553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
12842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
12852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
12862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
12872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
12882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
12892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
12902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
12912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
12922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
12932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
12942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
12952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
12962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
12972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
12982e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
12992e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1300bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1301bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1315bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1317e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid)
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1324ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1325ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid && tcp->pid != pid)
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1334bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
134076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1342ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1343ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
134576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
134976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1352bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1360e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1361e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1362e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1363e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1364e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1365e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1366e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1367e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1368e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1369e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1372eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1373e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1374e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1375e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1376e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_DETACHED)
1377e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_detached--;
1378e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1379e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1380e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
13810962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED
13820962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath		if (!(tcp->flags & TCB_CLONE_DETACHED))
13830962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif
13840962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->parent->nzombies++;
1385276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX
1386276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		/* Update `tcp->parent->parent->nchildren' and the other fields
1387276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   like NCLONE_DETACHED, only for zombie group leader that has
1388276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   already reported and been short-circuited at the top of this
1389276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   function.  The same condition as at the top of DETACH.  */
1390276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		if ((tcp->flags & TCB_CLONE_THREAD) &&
1391276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    tcp->parent->nclone_threads == 0 &&
1392276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    (tcp->parent->flags & TCB_EXITING))
1393276ceb33f20fc41403e46684e441230296f6a433Roland McGrath			droptcb(tcp->parent);
1394276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif
1395e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1396e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1397e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1398e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1402bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1403bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1404bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1405bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1406bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1407bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1408bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1409bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1410bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1411553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1412bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1413e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1416eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1417822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1419eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1423bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1437e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1438e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1439e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1440e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1442732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14501bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int
14511bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathresume_from_tcp (struct tcb *tcp)
14521bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{
14531bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int error = 0;
14541bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int resumed = 0;
14551bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14561bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	/* XXX This won't always be quite right (but it never was).
14571bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
14581bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   a particular pgrp, which this child might or might not be
14591bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
14601bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
14611bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   difference to wake up a waiter when there might be more
14621bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   traced children, because it could get a false ECHILD
14631bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
14641bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
14651bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   search the system for all pid's in the pgrp to be sure.
14661bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14671bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	     && (t->waitpid == -1 ||
14681bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
14691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
14701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	*/
14711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent &&
14731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
14741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
14751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 		error = resume(tcp->parent);
14761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		++resumed;
14771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
14781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD
14791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
14801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Some other threads of our parent are waiting too.  */
14811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		unsigned int i;
14821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
14841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
14851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			struct tcb *t = tcbtab[i];
14861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			if (t->parent == tcp->parent && t != tcp
14871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
14881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
14891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && t->waitpid == tcp->pid) {
14901bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				error |= resume (t);
14911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				++resumed;
14921bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
14931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		}
14941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		if (resumed == 0)
14951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			/* Noone was waiting for this PID in particular,
14961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			   so now we might need to resume some wildcarders.  */
14971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
14981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				struct tcb *t = tcbtab[i];
14991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				if (t->parent == tcp->parent && t != tcp
15001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && ((t->flags
15011bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
15021bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
15031bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && t->waitpid <= 0
15041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					) {
15051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					error |= resume (t);
15061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					break;
15071bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				}
15081bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
15091bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
15101bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
15111bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	return error;
15121bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath}
15131bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif
15141bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
1515bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15170a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
15180a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
15190a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
15200a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1528ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
15291bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1530a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1531a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1532a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1533a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1534a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1535a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1536a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1537a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1538ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sig = SIGKILL;
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
15467bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
15477bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
15497bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
15507bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
15517bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
15527bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
155302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
155402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
155502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
155602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
155702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
155802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
15617bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
15627bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
15637bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
15647bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
15657bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1566134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1567134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1568134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
15697bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
15707bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
15717bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
157202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
157302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
157402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
15757bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
15767bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
15777bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
157802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
157902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1580ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
15827508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
15837508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
15847508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
15857508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
15867508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
15887508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
15897508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
15907508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
15917508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
15927508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
15937508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
15947508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
15957508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
15967508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
15977508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
15987508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
15997508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
16007508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
16017508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
16027508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
16037508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16047508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16057508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
16067508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16077508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
16097508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1615732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1618732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
161996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					WSTOPSIG(status) == ptrace_stop_sig ? 0
1620732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1621732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1624ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
16257bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1632732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1635bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
16361bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	error |= resume_from_tcp (tcp);
1637e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1638e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1643a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1644a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX
16450a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	if (zombie != NULL) {
16460a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		/* TCP no longer exists therefore you must not detach () it.  */
16470a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(zombie);
16480a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	}
1649a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif
1650a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1654bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig)
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct tcb *tcp;
166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pid2tcb(pid);
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp)
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1674bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1682ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1683ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1691ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			tprintf(" <unfinished ...>");
1692ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17146d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
17176d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17368f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
17376d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
17398f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
17408f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
17418f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1762bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1769ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1770ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1771c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1772ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
177346100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "%s: out of memory\n", progname);
1774ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1775ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1776ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1777ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1778ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
17829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
180310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1851bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1852bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1853bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
1858a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
1882a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1893bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
1894bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1895bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1896bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1897bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
18989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
19319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
19669dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
1967d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
19689dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
19739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp = pid2tcb(0);
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
20009dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
20019dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
20029dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
20039dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2004553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
20059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
20069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
20079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
20089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
20099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
20109dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
20119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
20129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
20139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
20149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
20159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
20179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
20189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
20209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
20219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2045b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
20469dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2047b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2050bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
20519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
2052bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2053bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2054bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2055bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2056bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2057bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
2058bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
2059bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			  	ioctl_result = IOCTL_WSTOP (tcp);
2060553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2083bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2084bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2085553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
20962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
20972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
20982e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
20992e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
21002e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2101553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2102553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2111bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2112bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2113bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2114bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2115bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2118bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2119bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2120bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2121bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2122553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2125bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
21309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2131bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
21339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
21349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2141bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
21439dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
21449dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
21459dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2156ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2157ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
21585826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
21595826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
21605826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
21615826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
21625826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2163ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
21645826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
21655826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2172ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2175bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2176bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
2177bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		  	continue;
2178553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
21809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2185553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
21869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
2187553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2188bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
2189553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2197bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2199e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2200e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2201e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2202e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2203e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2204e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2205e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2206e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2207e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2208e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2209e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2210e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
2211e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2212e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp->parent
2213e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      : tcp->nclone_detached > 0
2214e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp : NULL);
2215e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2216e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
22170569095472c93c8513edefcf31013503ce4c0589Roland McGrath		if (leader != NULL && leader != tcp &&
22180569095472c93c8513edefcf31013503ce4c0589Roland McGrath		    !(leader->flags & TCB_GROUP_EXITING))
2219e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2220e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2221e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
22220a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		/* TCP no longer exists therefore you must not detach () it.  */
22231bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS
22241bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		resume_from_tcp (tcp);
22251bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif
22260a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2227e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2228e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2229a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2230a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2231e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
2232d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath			detach(tcp, sig);
22331bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		  	if (leader != NULL && leader != tcp)
22341bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2235732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else {
2236732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2237732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				cleanup();
2238732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				return -1;
2239732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2240732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (leader != NULL) {
22410569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2242732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (leader != tcp)
2243732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					droptcb(tcp);
2244732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2245e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2246e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2247e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2248e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2249e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2250e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2251e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2252e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2253e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2254e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2255215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkostatic struct tcb *
2256215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkocollect_stopped_tcbs(void)
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
2264215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	struct rusage* ru_ptr = cflag ? &ru : NULL;
2265215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	int wnohang = 0;
2266f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko	struct tcb *found_tcps;
2267f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko	struct tcb **nextp = &found_tcps;
22682f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2269215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	int wait4_options = __WALL;
22702f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2273215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	while (1) {
227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
22752f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2276215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
22775bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
22782f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
22792f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
22802f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
2281215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
22822f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
22835bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
22842f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
2285215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			pid = wait4(-1, &status, __WCLONE | wnohang, ru_ptr);
2286215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			if (pid < 0 && errno != ECHILD) {
2287215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko				fprintf(stderr, "strace: wait4(WCLONE) "
22882f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
22892f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
22902f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
2291215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#else /* !__WALL */
2292215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		pid = wait4(-1, &status, wnohang, ru_ptr);
2293215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif
229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
229676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
229776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
229976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
230076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
230176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2302215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		if (pid == 0 && wnohang) {
2303215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			/* We had at least one successful
2304215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			 * wait() before. We waited
2305215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			 * with WNOHANG second time.
2306215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			 * Stop collecting more tracees,
2307215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			 * process what we already have.
2308215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			 */
2309215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			break;
2310215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		}
231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (wait_errno) {
231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ECHILD:
231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
232076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
232176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
232276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (nprocs == 0)
2324215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko					return NULL;
232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: proc miscount\n");
232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
232776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
2328215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko				return NULL;
232976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
233076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				errno = wait_errno;
233176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: wait");
2332215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko				exit(1);
233376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
233476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
233510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
233610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
233710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				popen_pid = -1;
233810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
233910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
234076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
234176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
234276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
234476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2345e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
234641c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2347e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2348e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2349e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2350e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2351e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2352e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2353e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2354e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2355e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2356418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2357e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2358e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2359e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2360e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2361e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
23628b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2363e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2364e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2365e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2366215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif /* LINUX */
2367e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2368e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2369e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2370e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2371e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2372e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
237376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2374215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
237576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
237876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
2379215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif
238076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2381f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		if (tcp->flags & TCB_SUSPENDED) {
2382f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			/*
2383f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Apparently, doing any ptrace() call on a stopped
2384f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process, provokes the kernel to report the process
2385f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * status again on a subsequent wait(), even if the
2386f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process has not been actually restarted.
2387f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Since we have inspected the arguments of suspended
2388f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * processes we end up here testing for this case.
2389f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 */
2390f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			continue;
2391f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		}
2392f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko
2393215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		tcp->wait_status = status;
2394215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#ifdef LINUX
2395f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		/* It is important to not invert the order of tasks
2396f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		 * to process. For one, alloc_tcb() above picks newly forked
2397f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		 * threads in some order, processing of them and their parent
2398f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		 * should be in the same order, otherwise bad things happen
2399f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		 * (misinterpreted SIGSTOPs and such).
2400f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		 */
2401f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		*nextp = tcp;
2402f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		nextp = &tcp->next_need_service;
2403215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		wnohang = WNOHANG;
2404215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif
2405215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#ifdef SUNOS4
2406215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		/* Probably need to replace wait with waitpid
2407215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * and loop on Sun too, but I can't test it. Volunteers?
2408215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 */
2409215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		break;
2410215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif
2411f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko	}
2412215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2413f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko	*nextp = NULL;
2414f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko	return found_tcps;
2415215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko}
2416215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2417215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkostatic int
2418215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkohandle_stopped_tcbs(struct tcb *tcp)
2419215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko{
2420215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	for (; tcp; tcp = tcp->next_need_service) {
2421215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		int pid;
2422215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		int status;
242376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2424215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		outf = tcp->outf;
2425215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		status = tcp->wait_status;
2426215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		pid = tcp->pid;
2427215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
242876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2429a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2430a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
243176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
243276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
243376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
24342efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
24352efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
24362efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
24372efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
24382efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
24392efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
2440ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
244176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2442e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2443e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2444e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
244576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2446e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
244776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
244876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2450a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2451a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "pid %u exited\n", pid);
24540569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if ((tcp->flags & TCB_ATTACHED)
24550569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
24560569095472c93c8513edefcf31013503ce4c0589Roland McGrath			    && !(tcp->parent && (tcp->parent->flags &
24570569095472c93c8513edefcf31013503ce4c0589Roland McGrath						 TCB_GROUP_EXITING))
24581bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && !(tcp->flags & TCB_GROUP_EXITING)
24590569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
24600569095472c93c8513edefcf31013503ce4c0589Roland McGrath				)
246176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
246276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					"PANIC: attached pid %u exited\n",
246376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pid);
24640a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
24650a396906981a03f93c07cb912585d0679dd50899Roland McGrath				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
24660a396906981a03f93c07cb912585d0679dd50899Roland McGrath				    == TCB_INSYSCALL)
24670a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
24680a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
24690a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
24700a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2471e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2472e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2473e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
247476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2475e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
247876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
248476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2485ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
248676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
248702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
248802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
248902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
249002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * than SIGSTOP if we happend to attach
249102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
249202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
249302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
249476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
249676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
249776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
249876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
249976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
250002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
250176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
250202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
250302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
250476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
250576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
250676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
250776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
250876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
251076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2511b1efe53531c2f0f3fd2a4fc8a56220737539c44eDenys Vlasenko/* Add more OSes after you verified it works for them. */
2512f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko/* PTRACE_SETOPTIONS may be an enum, not a #define.
2513f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko * But sometimes we can test for it by checking PT_SETOPTIONS.
2514f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko */
2515f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
25160861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# ifndef PTRACE_O_TRACESYSGOOD
25170861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko#  define PTRACE_O_TRACESYSGOOD 0x00000001
25180861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# endif
25190861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# ifndef PTRACE_O_TRACEEXEC
25200861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko#  define PTRACE_O_TRACEEXEC    0x00000010
25210861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# endif
25220861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# ifndef PTRACE_EVENT_EXEC
25230861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko#  define PTRACE_EVENT_EXEC     4
25240861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# endif
25251e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			/*
25261e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * Ask kernel to set signo to SIGTRAP | 0x80
25271e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * on ptrace-generated SIGTRAPs, and mark
25281e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
25291e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 */
253096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko			if (!ptrace_opts_set) {
253196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				ptrace_opts_set = 1;
253296d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				/*
253396d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * NB: even if this "succeeds", we can
253496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * revert back to SIGTRAP if we later see
253596d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * that it didnt really work.
253696d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * Old kernels are known to lie here.
253796d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 */
253896d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
253996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					(void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0)
254096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					ptrace_stop_sig = SIGTRAP | 0x80;
25411e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			}
25421e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko#endif
254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2546f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
254796d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko		if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
25481e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			/*
25491e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * We told ptrace to report SIGTRAP | 0x80 on this process
25501e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * but got bare SIGTRAP. This can be a genuine SIGTRAP:
25511e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * kill(pid, SIGTRAP), trap insn, etc;
25521e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * but be paranoid about it.
25531e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 */
25541e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
25551d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				/* It's post-exec ptrace stop. Ignore it,
25561d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				 * we will get syscall exit ptrace stop later.
25571d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				 */
25581d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko#ifdef TCB_WAITEXECVE
25591d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				tcp->flags &= ~TCB_WAITEXECVE;
25601d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko#endif
25611d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				goto tracing;
25621e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			} else {
25631e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				/* Take a better look...  */
25641e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				siginfo_t si;
25651d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				si.si_signo = 0;
25661e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
25671e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				/*
25681e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Check some fields to make sure we see
25691e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * real SIGTRAP.
25701e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Otherwise interpret it as ptrace stop.
25711e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Real SIGTRAPs (int3 insn on x86, kill() etc)
25721e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * have these values:
25731e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * int3:                   kill -TRAP $pid:
25741e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_signo:5 (SIGTRAP)    si_signo:5 (SIGTRAP)
25751e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_errno:0              si_errno:(?)
25761e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
25771e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_pid:0                si_pid:(>0?)
25781e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_band:0               si_band:(?)
25791e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Ptrace stops have garbage there instead.
25801e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 */
25811e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				if (si.si_signo != SIGTRAP
25821e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
25831e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				) {
258496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code);
258596d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					ptrace_stop_sig = SIGTRAP;
25861e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				}
25871e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			}
25881e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko		}
25891e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko#endif
25901e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko
259196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko		if (WSTOPSIG(status) != ptrace_stop_sig) {
25921e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			/* This isn't a ptrace stop.  */
25931e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko
259476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
259576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
259676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
259776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
259876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
259976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
260076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2601732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
260276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
260376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
260476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
260576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
260676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
260776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
260876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
26091f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				unsigned long addr = 0;
26101f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				long pc = 0;
26119633942c07427ed51caea0e73f139e964d1a19ccDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
26127b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#				define PSR_RI	41
26137b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				struct siginfo si;
26141f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				long psr;
26157b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2616932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2617932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
26187b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
26197b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
26207b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
26217b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				addr = (unsigned long) si.si_addr;
26223a055d7d64222223da2550ca540043de7e3e232bRoland McGrath#elif defined PTRACE_GETSIGINFO
26233a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				if (WSTOPSIG(status) == SIGSEGV ||
26243a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				    WSTOPSIG(status) == SIGBUS) {
26253a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					siginfo_t si;
26263a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					if (ptrace(PTRACE_GETSIGINFO, pid,
26273a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						   0, &si) == 0)
26283a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						addr = (unsigned long)
26293a055d7d64222223da2550ca540043de7e3e232bRoland McGrath							si.si_addr;
26303a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				}
26317b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
263276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
26337b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tprintf("--- %s (%s) @ %lx (%lx) ---",
2634ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WSTOPSIG(status)),
26357b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					strsignal(WSTOPSIG(status)), pc, addr);
2636ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
263776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
26380569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
26390569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
264076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2641e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2642e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2643e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
264476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2645e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
264676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
264776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2648732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
264976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
265076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
265176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
265276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
265376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
265476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
265502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
265602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
265702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2658732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2659ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			/* ptrace() failed in trace_syscall() with ESRCH.
2660ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 * Likely a result of process disappearing mid-flight.
2661ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 * Observed case: exit_group() terminating
2662ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 * all processes in thread group. In this case, threads
2663ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 * "disappear" in an unpredictable moment without any
2664ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 * notification to strace via wait().
2665ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2666ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2667ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				if (tcp_last) {
2668ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					/* Do we have dangling line "syscall(param, param"?
2669ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					 * Finish the line then. We cannot
2670ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					 */
2671ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					tcp_last->flags |= TCB_REPRINT;
2672ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					tprintf(" <unfinished ...>");
2673ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
2674ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				}
267576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2676ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
267776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				ptrace(PTRACE_KILL,
267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					tcp->pid, (char *) 1, SIGTERM);
267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
268076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
268176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
268276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
268376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2684e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2685e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2686e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2687e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2688e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2689e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2690e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
269176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
269276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2693732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
269476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
269576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
269676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
269776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
269876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
269976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
270076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
270176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
270276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
270376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
270476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2705732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
270676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
270776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
270876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2709215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	} /* for each tcp */
2710215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2711215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	return 0;
2712215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko}
2713215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2714215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkostatic int
2715215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkotrace()
2716215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko{
2717215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	int rc;
2718215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	struct tcb *tcbs;
2719215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2720215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	while (nprocs != 0) {
2721215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		if (interrupted)
2722215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			return 0;
2723215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		if (interactive)
2724215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			sigprocmask(SIG_SETMASK, &empty_set, NULL);
2725215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2726215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		/* The loop of "wait for one tracee, serve it, repeat"
2727215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * may leave some tracees never served.
2728215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * Kernel provides no guarantees of fairness when you have
2729215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * many waitable tasks.
2730215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * Try strace -f with test/many_looping_threads.c example.
2731215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * To fix it, we collect *all* waitable tasks, then handle
2732215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * them all, then repeat.
2733215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 */
2734215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		tcbs = collect_stopped_tcbs();
2735215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		if (!tcbs)
2736215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			break;
2737215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		rc = handle_stopped_tcbs(tcbs);
2738215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		if (rc)
2739215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			return rc;
274076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
274176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
274276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
274376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2744bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
274576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
274676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol;
274776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
274876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
274976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
275076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b)
275176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
275276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h>
275376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a)
275476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
275576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
275676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
275776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
275876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
275976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
276076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist)
276176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
276276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl
276376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
276476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
276576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
276676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
276776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	VA_START(args, fmt);
2768b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2769b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2770b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		if (n < 0 && outf != stderr)
2771b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			perror(outfname == NULL
2772b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			       ? "<writing to pipe>" : outfname);
2773b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		else
2774b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2775b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
277676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
277776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
277876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
277976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
278076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
278176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp)
278276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
278376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2784732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2785732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (tcp_last->ptrace_errno) {
2786732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
2787732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				tprintf(" <unavailable>)");
2788732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				tabto(acolumn);
2789732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2790732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			tprintf("= ? <unavailable>\n");
2791732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			tcp_last->ptrace_errno = 0;
2792732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
2793732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2794732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			tprintf(" <unfinished ...>\n");
2795732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
279676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
279776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
279876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
279976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
280076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
280176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
280276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
280376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
280476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
280576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
280676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
280776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
280876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
280976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
281076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
281176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
281276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
281376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
281476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
281576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
281676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
281776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
281876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
281976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
282076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
282176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
282276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
282376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
282476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
282576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
282676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
282776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
282876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
282976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
283076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
283176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
283276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
283376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
283476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
283576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
283676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
283776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
283876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
283976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
284076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
284176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2842ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
284376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
284476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
284576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
284676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
28479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2848ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
28499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2850ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2851ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2852ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
28539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
28549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2855553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
28569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
28579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
28589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
28599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
28609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
28619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
28629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2863553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2864ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
28659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
28669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
28679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2868