strace.c revision 1201426dd43f5b4e12dfe520e2a9c5027d33dc11
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>
363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko#include <stdarg.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h>
4719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h>
4870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
4976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX
51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h>
52134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# if defined __NR_tgkill
53134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# elif defined __NR_tkill
55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else
57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath   /* kill() may choose arbitrarily the target task of the process group
58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      while we later wait on a that specific TID.  PID process waits become
59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      TID task specific waits for a process under ptrace(2).  */
60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) kill ((tid), (sig))
62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif
63134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif
64134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath
657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
687b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
71bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
72bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
7476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
75ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
761d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
7976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
801d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
8196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
82418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
83418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
8496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
8576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8641c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0;
873454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkounsigned int ptrace_setoptions_followfork = 0;
88f8bc0655a0db6fd3031384a88cdc707285029ca5Denys Vlasenkounsigned int ptrace_setoptions_for_all = 0;
893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */
9075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP;
91e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0;
92e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE;
93b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
104ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
105ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
106ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
11017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
1128a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint show_fd_path = 0;
1138a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1148a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
1158a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint tracing_paths = 0;
1168a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
117a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
118a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
11975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
120eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
121b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
127b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
129ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
130ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
131ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
13230145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinconst char *progname;
133eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathextern char **environ;
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int detach(struct tcb *tcp, int sig);
136e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
137e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
138e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
149e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd);
150e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig);
151e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void);
152ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
156e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void);
157e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd);
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
175bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
1838a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsusage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
184de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
1858a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards              [-P path] [command [arg ...]]\n\
186b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab   or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
187de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
189b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
1988a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
205ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
209de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
210de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
2118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
212de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
21317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
214de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
215de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
22075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
22175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
22275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
22375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
22475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
22575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
22675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
22775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
22875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
22975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2303454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
2313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	char *msg;
2323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
2333454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	msg = NULL;
2343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	vasprintf(&msg, fmt, p);
2353454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (msg) {
23675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		fflush(NULL);
23775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (err_no)
23875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
23975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		else
24075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			fprintf(stderr, "%s: %s\n", progname, msg);
2413454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		free(msg);
2423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
24375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
24475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
24575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
24675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
24775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
24875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
24975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
25175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
25575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
25675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
25775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
25875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
25975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
26075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
26175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
26275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
26375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
26475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
26575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
26675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
26775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
26875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
26975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...)
27075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
27175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
27275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
27375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
27475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
2753454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
2763454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
27976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
28376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
28576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
286c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
287c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
288c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
289c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
290c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
291c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
292c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
293c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     flags, newflags;
29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return 0;
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fcntl(fd, F_SETFD, newflags) < 0)
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (euid != uid && setreuid(euid, uid) < 0)
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: setreuid: %s\n",
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		exit(1);
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3394bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
3404bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
3414bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
3424bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
3434bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
3444bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode)
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
3514bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath	if ((fp = fopen_for_output(path, mode)) == NULL)
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: can't fopen '%s': %s\n",
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, path, strerror(errno));
35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fp && set_cloexec_flag(fileno(fp)) < 0)
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fclose(fp);
35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fp = NULL;
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1;
36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
36610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
36710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
37010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
37110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
37210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
37310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
37410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
37510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
37610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
37710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     fds[2];
37810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
37910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
38010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
38110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
38210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: pipe: %s\n",
38310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
38410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
38510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
38610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
38710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
38810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(fds[1]) < 0)
38910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
39010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
39110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
39210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
39310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
39410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
39510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
39610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((popen_pid = fork()) == -1)
39710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
39810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fork: %s\n",
39910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
40010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
40110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
40210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
40310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
40410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
40510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
40610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (popen_pid)
40710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
40810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* parent */
40910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
41010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
41110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return fdopen(fds[1], "w");
41210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	} else
41310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
41410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
41510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
41610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
41710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		{
41810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			fprintf(stderr, "%s: dup2: %s\n",
41910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				progname, strerror(errno));
42010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			_exit(1);
42110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
42210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
42310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: execl: %s: %s\n",
42410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, _PATH_BSHELL, strerror(errno));
42510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		_exit(1);
42610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
42710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
42810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
42910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
43010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
43110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
43210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
4337a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
43410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		FILE *fp;
43510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4367a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
43710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if ((fp = strace_fopen(name, "w")) == NULL)
43810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			return -1;
43910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		tcp->outf = fp;
44010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
44110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
44210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
44310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
44602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * We rely on cleanup () from this point on.
45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
45602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
45702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
459ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
460ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
461ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
462ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(1);
463ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
464ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
465ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
46675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
46775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
46875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
469ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
470ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
471ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
472ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
473ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
47475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
47575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
47675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
477ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
478ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
48202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
48302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
48402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
48502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
48602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
48702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
48802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
48902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (newoutf(tcp) < 0)
49002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
49102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
49202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
49302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
49402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
49502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
500ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
5017a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
5117a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
517aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
519aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					else if (tid != tcbtab[tcbi]->pid) {
520418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko						tcp = alloctcb(tid);
52121b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nchildren++;
52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_threads++;
52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->parent = tcbtab[tcbi];
52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
526aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (interactive) {
527aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_SETMASK, &empty_set, NULL);
528aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						if (interrupted)
529aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko							return;
530aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
531aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					}
53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
5347a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
5357a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
5417a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
5427a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
5437a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
5447a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko						tcbtab[tcbi]->pid, ntid);
54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
5477a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
5487a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* INTERRUPTED is going to be checked at the top of TRACE.  */
556ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
557ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
558ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
559ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
560ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
561ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
562ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
563ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
564ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
565ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
566ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
567ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
568ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
569ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
57802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
5821201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("strace: exec");
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
60930145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
64102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
64202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
64302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		fprintf(stderr, "%s: %s: command not found\n",
64402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			progname, filename);
64502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
64602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
647a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
64902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: fork");
65002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		cleanup();
65102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
652ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
65375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
65475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
655ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
656ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
65702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
65802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf != stderr) close (fileno (outf));
65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
66002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
66102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
66202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
66302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
66402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
66502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
66602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
66702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
669ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		kill(pid, SIGSTOP); /* stop HERE */
67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
67102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf!=stderr)
67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			close(fileno (outf));
67402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
675ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				perror("strace: ptrace(PTRACE_TRACEME, ...)");
678ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				exit(1);
679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
681ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
68202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
68302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
68402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
68502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
68602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
68702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
68802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
68902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
69002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
69102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
69202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
69302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
69402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
69502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
69602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
69702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
69802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
69902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("initgroups");
70002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
70102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
70202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
70302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setregid");
70402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
70502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
70602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
70702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setreuid");
70802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
70902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
71002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
71102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
71202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
71302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
71402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
715ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
716ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
717ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Induce an immediate stop so that the parent
718ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
719ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * this execve call normally.
720c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * Unless of course we're on a no-MMU system where
721c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * we vfork()-ed, so we cannot stop the child.
722ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
723c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
724c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger				kill(getpid(), SIGSTOP);
725ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
726ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
727ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
728ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
729ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
730ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
731ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
732ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
733ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
734ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
735ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
736ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
737ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
738ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
739ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
740ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
741ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
74202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
74302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
74402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
74502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: exec");
74602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		_exit(1);
74702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
748ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
749ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
75075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	/* With -D, we are *child* here, IOW: different pid. Fetch it. */
75175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
75275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
753ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
754ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
755ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
756ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
757ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
75802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
759ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
760ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		fprintf(stderr, "trouble opening proc file\n");
761ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		cleanup();
762ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		exit(1);
76302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
764ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
76502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
76602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
767b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX
768b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
769b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
770b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
771b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
772b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
773b13c0de058585de7d47778a8923426b89bfffbb5Wang Chaostatic int
7743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
775b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
7762fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
7772fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
7782fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
7792fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
780b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
781b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	if ((pid = fork()) < 0)
782b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		return -1;
783b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	else if (pid == 0) {
784b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
785b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			_exit(1);
786b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		kill(getpid(), SIGSTOP);
787b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		_exit(fork() < 0);
788b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
789b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
790b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
791b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
792b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
793b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
794b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid == -1) {
795b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
796b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
797b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			else if (errno == ECHILD)
798b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
7993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			perror("test_ptrace_setoptions_followfork");
800b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			return -1;
801b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
802b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
8032fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
804b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
805b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			    errno != ESRCH)
806b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				kill(tracee_pid, SIGKILL);
807b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
808b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		else if (WIFSTOPPED(status)) {
8092fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			switch (WSTOPSIG(status)) {
8102fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			case SIGSTOP:
8112fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				if (ptrace(PTRACE_SETOPTIONS, pid,
8122fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					   NULL, test_options) < 0) {
813b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao					kill(pid, SIGKILL);
814b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin					return -1;
815b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				}
8162fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				break;
8172fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			case SIGTRAP:
8182fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				if (status >> 16 == PTRACE_EVENT_FORK) {
8192fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					long msg = 0;
8202fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
8212fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					if (ptrace(PTRACE_GETEVENTMSG, pid,
8222fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin						   NULL, (long) &msg) == 0)
8232fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin						expected_grandchild = msg;
8242fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				}
8252fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				break;
826b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
827b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
828b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			    errno != ESRCH)
829b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				kill(pid, SIGKILL);
830b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
831b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
8322fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild)
8333454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		ptrace_setoptions_followfork |= test_options;
834b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	return 0;
835b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
8363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
8383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
8393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
8403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
8413454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
8423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
8433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
8443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
8453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
8463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
8473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
8483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
8493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
8503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
8513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
8523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
8533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
8543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
8553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
8563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
8573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8583454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
8593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
86075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
8613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
8633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
8643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
86575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
86675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
8673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
8683454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
8693454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
8703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
8723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
8733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
8753454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
8763454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
8773454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
8783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
8793454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
88075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
88175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
88275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
88375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
88475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
88575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* PTRACE_TRACEME failed in child. This is fatal. */
88675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			exit(1);
8873454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8883454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
8893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
8903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			error_msg_and_die("%s: unexpected wait status %x", __func__, status);
8913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
8933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
8943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
8953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
8963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
8973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
8983454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
89975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
90075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				if (errno != EINVAL)
90175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					perror_msg("PTRACE_SETOPTIONS");
9023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
9043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
9053454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
9073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
90875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
9093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9113454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9123454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
91375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
9143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		ptrace_setoptions_for_all = test_options;
9153454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
9163454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			fprintf(stderr, "ptrace_setoptions_for_all = %#x\n",
9173454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				ptrace_setoptions_for_all);
9183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
9193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9203454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9213454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	fprintf(stderr,
9223454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		"Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
9233454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
924b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif
925b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
92708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
93106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
93608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
93708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
93875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
93975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
940ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
941ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
942418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
94308b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
94408b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
94508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
946418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
94708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
94808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
94908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
950ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
951ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
952ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
955138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
956138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
9628a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"+cCdfFhiqrtTvVxyz"
963ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
964ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
965ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
9668a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"a:e:o:O:p:s:S:u:E:P:")) != EOF) {
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
969e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
970e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
971e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin					progname);
972e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				exit(1);
973e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
974e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
975e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
976e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
977e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
978e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
979e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin					progname);
980e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				exit(1);
981e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
982e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
987ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
988ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
989ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
990ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
991ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
99241c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
99306350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
99406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10208a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
10218a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
10228a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
10279c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
103117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
103217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
1046de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
105175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (pid == strace_tracer_pid) {
105254a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1055418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10598a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
10608a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
10618a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
10628a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards				fprintf(stderr,"%s : failed to select path '%s'\n", progname, optarg);
10638a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards				exit(1);
10648a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
10658a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
106776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1068dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1069dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				fprintf(stderr,
1070dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					"%s: invalid -s argument: %s\n",
1071dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					progname, optarg);
1072dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				exit(1);
1073dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
107676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
108076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1081de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
1082de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
1083de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
1084de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
1085de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
1086de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
1087de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1094d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
1095ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1096ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1097d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	if (pflag_seen && daemonized_tracer) {
1098d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao		fprintf(stderr,
1099d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao			"%s: -D and -p are mutually exclusive options\n",
1100d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao			progname);
1101d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao		exit(1);
1102d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1103d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
110406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
110506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
110606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1107cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1108cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		fprintf(stderr,
1109e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			"%s: (-c or -C) and -ff are mutually exclusive options\n",
1110cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			progname);
1111cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		exit(1);
1112cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1113cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
112609553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath				progname, username);
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11378044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX
11388044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin	if (followfork) {
11393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (test_ptrace_setoptions_followfork() < 0) {
11408044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin			fprintf(stderr,
11418044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				"Test for options supported by PTRACE_SETOPTIONS "
11428044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				"failed, giving up using this feature.\n");
11433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			ptrace_setoptions_followfork = 0;
11448044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		}
11458044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		if (debug)
11463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			fprintf(stderr, "ptrace_setoptions_followfork = %#x\n",
11473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				ptrace_setoptions_followfork);
11488044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin	}
11493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
11508044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif
11518044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
115376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
115437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
115537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
115637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
115737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
115837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
115937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
116037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
116137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
116237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
116337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
116437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
116537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
116637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
116710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if ((outf = strace_popen(outfname + 1)) == NULL)
116837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
116954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
117010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		else if (followfork <= 1 &&
117110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			 (outf = strace_fopen(outfname, "w")) == NULL)
117254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
117537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
117737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1180369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1181b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
118254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
118354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
118454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
118554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
118654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
118754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
118854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
118954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
119054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
119154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
119254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
119354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
119454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
119554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
119776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
1221bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
1224553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1225553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1226553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1227553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1228553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1229553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1230553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1231553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
1232bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1234ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
123502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
123602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
1240a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
1241a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
1242a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
1243a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
1244a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
1245a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
1246a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
1247a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
1248a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
1249a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
1250a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1253418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkovoid
1254418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
12557b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
12567b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
12577b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
12587b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
12597b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
12607b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
12617b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb **newtab = (struct tcb **)
12627b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
12637b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
12647b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    sizeof *newtcbs);
12657b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	int i;
12667b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	if (newtab == NULL || newtcbs == NULL) {
126776860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
126876860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin			progname);
1269418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		cleanup();
1270418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		exit(1);
12717b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
12727b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
12737b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
12747b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
12757b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
12767b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
12777b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
127910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
128176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1284418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1285418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1286418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1287ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1288ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
1291eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->parent = NULL;
1292eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nchildren = 0;
1293eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nzombies = 0;
1294eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef TCB_CLONE_THREAD
129521b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao			tcp->nclone_threads = 0;
1296eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nclone_waiting = 0;
1297eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
1300ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			tcp->curcol = 0;
1301eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->stime.tv_sec = 0;
1302eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->stime.tv_usec = 0;
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
130510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
130610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1310418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1311418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	cleanup();
1312418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	exit(1);
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1315bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1317418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1321bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
132219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
132319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1326bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1331ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
13329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
13339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
13349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
13359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
133810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
13399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
13429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
13439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
134610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_stat) < 0) {
13479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
13509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
13519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
135410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_as) < 0) {
13559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1359bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
1361372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR|O_EXCL);
1362bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1363bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1364372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR);
1365bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
1366372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	if (tcp->pfd < 0) {
136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
137010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
13719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1374bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1375bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1376bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1377bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1378bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1379bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1380bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1381bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1382bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1383bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1384bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1385bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1386bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1387bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1388bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
138976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
139076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
13969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
14009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1401bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1404bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
140616a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1410553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
14149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
14209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1425553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1434bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1435bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1436bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1437bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
14385ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1439bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1440bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1441bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
14425ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
14435ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1444bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1445bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1447bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
144819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
144919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
145019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
145119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
145219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
145319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
145419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
145519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
145619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
145719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
145819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
145919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1460553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
146119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
146219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
146319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
146419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
146519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
146619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
146719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
146819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
146919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
147019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
147419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
147519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
147919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
148019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
148119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
148219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
148319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
148419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
14859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
148676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
148876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
148919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
149019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
149119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
149219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
149319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
149419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
14959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
149676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
149776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
149876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1499bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1500bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1501bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
1502bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1503bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1504bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1505bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1506bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
151076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1515553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
15179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
15189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1522553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1523bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1524bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1525bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1526bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1527553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
15309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
15349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1535bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1536bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
153776989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1541bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
15429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
15439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1544bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1545bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1546553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1550bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1551bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1552bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1553bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1554bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1555bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1556553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1558bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1560bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1561bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1562553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
15632e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
15642e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
15652e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
15662e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
15672e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
15682e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
15692e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1570553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
15712e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
15722e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
15732e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
15742e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
15752e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
15762e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
15772e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
15782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
15792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
15802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
15812e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
15822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
15832e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
15842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
15852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
15862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1587bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1588bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1602bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1604e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
160554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
160854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
160954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
161054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1612ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
161354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
161454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
161754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1621bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
162454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void)
162554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{
162654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	int i;
162754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	struct tcb *tcp;
162854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
162954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		tcp = tcbtab[i];
163054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->flags & TCB_INUSE)
163154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath			return tcp;
163254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	}
163354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	return NULL;
163454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath}
163554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
163654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb *
16371201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkopfd2tcb(int pfd)
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1641ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1642ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1651bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
16541201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1658e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1659e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1660e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1661e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1662e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1663e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1664e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1665e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1666e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1667e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1670eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1671e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1672e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1673e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1674e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1675e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1676e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
167721b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao		tcp->parent->nzombies++;
1678276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX
1679276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		/* Update `tcp->parent->parent->nchildren' and the other fields
1680276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   like NCLONE_DETACHED, only for zombie group leader that has
1681276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   already reported and been short-circuited at the top of this
1682276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   function.  The same condition as at the top of DETACH.  */
1683276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		if ((tcp->flags & TCB_CLONE_THREAD) &&
1684276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    tcp->parent->nclone_threads == 0 &&
1685276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    (tcp->parent->flags & TCB_EXITING))
1686276ceb33f20fc41403e46684e441230296f6a433Roland McGrath			droptcb(tcp->parent);
1687276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif
1688e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1689e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1690e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1691e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1695bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1696bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1697bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1698bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1699bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1700bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1701bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1702bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1703bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1704553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1705bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1706e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1709eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1710822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1712eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1716bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
17191201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoresume(struct tcb *tcp)
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1729e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1730e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1731e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1732e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1734732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17421bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int
17431201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoresume_from_tcp(struct tcb *tcp)
17441bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{
17451bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int error = 0;
17461bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int resumed = 0;
17471bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
17481bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	/* XXX This won't always be quite right (but it never was).
17491bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
17501bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   a particular pgrp, which this child might or might not be
17511bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
17521bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
17531bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   difference to wake up a waiter when there might be more
17541bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   traced children, because it could get a false ECHILD
17551bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
17561bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
17571bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   search the system for all pid's in the pgrp to be sure.
17581bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
17591bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	     && (t->waitpid == -1 ||
17601bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
17611bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
17621bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	*/
17631bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
17641bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent &&
17651bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
17661bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
17675ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		error = resume(tcp->parent);
17681bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		++resumed;
17691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
17701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD
17711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
17721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Some other threads of our parent are waiting too.  */
17731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		unsigned int i;
17741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
17751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
17761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
17771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			struct tcb *t = tcbtab[i];
17781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			if (t->parent == tcp->parent && t != tcp
17791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
17801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
17811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && t->waitpid == tcp->pid) {
17821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				error |= resume (t);
17831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				++resumed;
17841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
17851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		}
17861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		if (resumed == 0)
17871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			/* Noone was waiting for this PID in particular,
17881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			   so now we might need to resume some wildcarders.  */
17891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
17901bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				struct tcb *t = tcbtab[i];
17911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				if (t->parent == tcp->parent && t != tcp
17921bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && ((t->flags
17931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
17941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
17951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && t->waitpid <= 0
17961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					) {
17971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					error |= resume (t);
17981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					break;
17991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				}
18001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
18011bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
18023bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#endif
18031bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
18041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	return error;
18051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath}
18061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
1807bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18090a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
18100a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
18110a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
18120a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
18151201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodetach(struct tcb *tcp, int sig)
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1818ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
18191bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1820a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1821a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1822a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1823a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1824a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1825a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1826a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1827a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1828ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1831840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
18367bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
18377bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
18397bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
18407bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
18417bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
18427bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
184302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
184402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
184502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
184602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
184702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
184802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
18517bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
18527bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
18537bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
18547bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
18557bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1856134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1857134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1858134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
18597bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
18607bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
18617bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
186202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
186302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
186402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
18657bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
18667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
18677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
186802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
186902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1870ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
18727508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
18737508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
18747508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
18757508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
18767508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
18787508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
18797508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
18807508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
18817508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
18827508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
18837508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
18847508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
18857508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
18867508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
18877508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
18887508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
18897508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
18907508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
18917508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
18927508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
18937508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
18947508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
18957508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
18967508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
18977508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
18997508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1905732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1908732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
190975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1910732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1911732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1914ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
19157bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1922732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1925bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
19261bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	error |= resume_from_tcp (tcp);
1927e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1928e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1933a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1934a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX
19350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	if (zombie != NULL) {
19360a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		/* TCP no longer exists therefore you must not detach () it.  */
19370a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(zombie);
19380a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	}
1939a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif
1940a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1944bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1946e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig)
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1955bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19581201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1963ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1964ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1972ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			tprintf(" <unfinished ...>");
1973ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19871201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19946d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
19976d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
20001201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no)
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
200435aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
200535aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
200835aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	return sys_errlist[err_no];
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20158f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
20166d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
20188f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
20198f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
20208f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
20231201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig)
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2040bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
20431201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkorebuild_pollv(void)
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2047ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
2048ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
2049c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
2050ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
205146100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "%s: out of memory\n", progname);
2052ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
2053ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
2054ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
2055ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
2056ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
20609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
20721201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll_open(void)
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
208110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
20881201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll(struct pollfd *pollv, int nfds, int timeout)
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
21111201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkowakeup_handler(int sig)
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
21161201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poller(int pfd)
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
2124bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2125bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
2126bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
2131a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
2155a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
2166bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
21675ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
21685ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
21695ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
21705ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
21719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
22049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
222076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
222176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
222376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
222476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
222576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
222676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
22279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
223176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
22371201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
223876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
22399dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
2240d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
22419dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
224376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
22469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
224776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
224976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
225276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
225376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
225476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
225576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
226054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath				tcp = first_used_tcb();
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
226876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
22739dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
22749dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
22759dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
22769dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2277553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
22789dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
22799dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
22809dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
22819dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
22829dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
22839dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
22849dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
22859dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
22869dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
22879dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
22889dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
22899dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
22909dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
22919dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
22929dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
22939dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
22949dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
229676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
229776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
229976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
230076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
230176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
230276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
230376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
230476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
230776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2318b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
23199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2320b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
232176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
232276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2323bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
23249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
2325bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2326bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2327bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2328bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2329bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2330bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
2331bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
23325ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko				ioctl_result = IOCTL_WSTOP (tcp);
2333553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
233476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
233576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
233676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
233776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
233876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
233976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
234076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
234176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
234276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
234476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
234576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
234676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
234876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
234976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
235076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
235176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
235376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
235476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
235576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2356bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2357bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2358553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
235976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
236076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
236176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
236276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
236376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
236476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
236576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
236676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
236776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
23682e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
23692e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
23702e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
23712e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
23722e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
23732e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2374553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2375553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
237876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
237976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
238076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
2381ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
238276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
238376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
238476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2385bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2386bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2387bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2388bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2389bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2390bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2391bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2392bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2393bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2394bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2395bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2396553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
239776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
239876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2399bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
240076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
240176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
240276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
24039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
24049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2405bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
240676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
24079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
24089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
240976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
241076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
241176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
241276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
241376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
241476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2415bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
241676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
24179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
24189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
24199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
242076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
242176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
242276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
242376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
242476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
242576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
242676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
2427e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2428e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_SIGNAL)) {
242976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
243076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2431ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2432ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
24335826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
24345826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
24355826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
24365826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
24375826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2438ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
24395826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
24405826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
244176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
244276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
244376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
2444e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAGS_ONLY_STATS
2445e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_FAULT)) {
244676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
244776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2448ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
245076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2451bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2452bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
24535ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2454553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
245576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
24569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
245776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
245876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
245976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2460ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2461ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
24629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2463553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
2464372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0)
2465553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2466372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0)
2467553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2468372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		{
246976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
247076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
247176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
247276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
247476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
247576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2476bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2478e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2479e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2480e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2481e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2482e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2483e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2484e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2485e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2486e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2487e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2488e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2489e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
24907a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	struct tcb *leader = NULL;
24917a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko
24927a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	if (tcp->flags & TCB_CLONE_THREAD)
24937a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp->parent;
2494e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2495e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
24967a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		if (leader != NULL && leader != tcp
24977a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(leader->flags & TCB_GROUP_EXITING)
24987a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(tcp->flags & TCB_STARTUP)
24997a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		) {
2500e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2501e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2502e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
25037a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		}
25047a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
25051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS
25067a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		resume_from_tcp(tcp);
25071bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif
25080a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2509e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2510e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2511a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2512a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2513e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
2514d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath			detach(tcp, sig);
25155ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			if (leader != NULL && leader != tcp)
25161bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2517732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else {
2518732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2519732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				cleanup();
2520732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				return -1;
2521732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2522732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (leader != NULL) {
25230569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2524732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (leader != tcp)
2525732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					droptcb(tcp);
2526732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2527e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2528e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2529e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2530e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2531e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2532e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2533e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2534e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2535e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2536e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2537ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
2538ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaostatic int
2539ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaohandle_ptrace_event(int status, struct tcb *tcp)
2540ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao{
2541ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	if (status >> 16 == PTRACE_EVENT_VFORK ||
2542ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	    status >> 16 == PTRACE_EVENT_CLONE ||
2543ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	    status >> 16 == PTRACE_EVENT_FORK) {
25442fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin		long childpid;
2545ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
2546ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2547ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (errno != ESRCH) {
2548ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				fprintf(stderr, "\
2549ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao%s: handle_ptrace_event: ptrace cannot get new child's pid\n",
2550ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao					progname);
2551ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				cleanup();
2552ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				exit(1);
2553ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			}
2554ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			return -1;
2555ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2556ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		return handle_new_child(tcp, childpid, 0);
2557ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	}
25583454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (status >> 16 == PTRACE_EVENT_EXEC) {
25593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
25603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			fprintf(stderr, "PTRACE_EVENT_EXEC on pid %d (ignored)\n", tcp->pid);
25613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return 0;
25623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
256375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	/* Some PTRACE_EVENT_foo we didn't ask for?! */
256475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	error_msg("Unexpected status %x on pid %d", status, tcp->pid);
2565ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	return 1;
2566ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao}
2567ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
2568ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
2569eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
2570eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace()
257176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
257276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
257376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
257576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
257676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
257776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
25782f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2579eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
25802f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
258176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
258276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2583eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2584222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2585eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2586eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2587eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
258876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
25892f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2590eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
25915bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
25922f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
25932f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
25942f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
2595eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, wait4_options,
2596eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
25972f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
25985bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
25992f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
2600eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, __WCLONE,
2601eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
2602eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (pid == -1) {
2603eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				fprintf(stderr, "strace: clone wait4 "
26042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
26052f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
26062f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
2607eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#else
2608eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2609eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* __WALL */
261076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
261176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
261476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2615eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2616eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
261776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
261876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
2619eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2620eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
262176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2622eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
262376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
262476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
262576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
262676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
262776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
262876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
2629eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2630eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2631eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2632eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2633eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
263476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
263576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
263610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
263710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
263810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				popen_pid = -1;
263910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
264010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
264176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
264276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
264376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
264476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
264576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2646e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
264741c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2648e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2649e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2650e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2651e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2652e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2653e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2654e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2655e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2656e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2657418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2658e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2659e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2660e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2661e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2662e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
26638b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2664e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2665e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2666e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2667eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2668e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2669e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2670e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2671e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2672e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2673e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
267476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2675eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2676eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
2677ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
267884e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko		if (cflag) {
2679eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
268076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
268176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
2682eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* !LINUX */
268376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2684eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
2685f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		if (tcp->flags & TCB_SUSPENDED) {
2686f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			/*
2687f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Apparently, doing any ptrace() call on a stopped
2688f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process, provokes the kernel to report the process
2689f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * status again on a subsequent wait(), even if the
2690f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process has not been actually restarted.
2691f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Since we have inspected the arguments of suspended
2692f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * processes we end up here testing for this case.
2693f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 */
2694f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			continue;
2695f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		}
269676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2697a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2698a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2699e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
270076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
270176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
27022efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
27032efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
27042efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
27052efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
27062efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
27072efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
2708ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
270976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2710e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2711e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2712e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
271376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2714e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
271576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
271676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
271776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2718a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2719a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
272076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
27217a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
27227a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
27230569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
27247a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			    && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
27251bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && !(tcp->flags & TCB_GROUP_EXITING)
27260569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
27277a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			) {
272876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
27297a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					"PANIC: attached pid %u exited with %d\n",
27307a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					pid, WEXITSTATUS(status));
27317a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			}
27320a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
27337a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
27340a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
27350a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
27360a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
27370a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2738e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2739e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2740e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
274176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2742e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
274376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
274476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
274576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
274676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
274776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
274876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
274976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
275076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
275176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2752ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
275376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
27543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (status >> 16) {
2755ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (handle_ptrace_event(status, tcp) != 1)
2756ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				goto tracing;
2757ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2758ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
275902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
276002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
276102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
2762eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		 * than SIGSTOP if we happend to attach
276302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
2764c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * A no-MMU vforked child won't send up a signal,
2765c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * so skip the first (lost) execve notification.
276602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
2767c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		if ((tcp->flags & TCB_STARTUP) &&
2768c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		    (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
276976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
277076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
277176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
277276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
277376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
277476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
277502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
277676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
277702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
277802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
277976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
278076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
278176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
278276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
278376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
278476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
278576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2786ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
27873454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			int options = ptrace_setoptions_for_all;
27883454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (followfork && (tcp->parent == NULL))
27893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				options |= ptrace_setoptions_followfork;
27903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (options) {
27913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				if (debug)
27923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					fprintf(stderr, "setting opts %x on pid %d\n", options, tcp->pid);
27933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, options) < 0) {
27943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					if (errno != ESRCH) {
27953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko						/* Should never happen, really */
279675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko						perror_msg_and_die("PTRACE_SETOPTIONS");
27973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
27983454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
27993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2800ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
280176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
280276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
280376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
280475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WSTOPSIG(status) != syscall_trap_sig) {
280576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
280676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
280776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
280876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
280976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
281076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
281176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2812732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
281376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
281476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
281576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
281676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
281776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2818e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
281976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
2820c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin				siginfo_t si;
2821c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
28226b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
28236b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
28247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2825932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2826932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
28277b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
28286b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
28297b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
28306b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
28316b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	pc
28326b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
28336b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	"%s"
28346b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	""
28357b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
283676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
28376b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
28386b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- ");
28396b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
28406b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf(" (%s)" PC_FORMAT_STR " ---",
28416b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
28426b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
28436b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
28446b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- %s by %s" PC_FORMAT_STR " ---",
28456b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
28466b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						signame(WSTOPSIG(status)),
28476b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
2848ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
284976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
28500569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
28510569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
285276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2853e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2854e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2855e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
285676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2857e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
285876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
285976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2860732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
286176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
286276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
286376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
286476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
286576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
286676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
286702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
286802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
286902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2870eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2871eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2872eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2873eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2874eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * all processes in thread group. In this case, threads
2875eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * "disappear" in an unpredictable moment without any
2876eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * notification to strace via wait().
2877ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2878ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2879eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (tcp_last) {
2880eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2881eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 * Finish the line then. We cannot
2882eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2883eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp_last->flags |= TCB_REPRINT;
2884eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tprintf(" <unfinished ...>");
2885eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					printtrailer();
2886eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
288776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2888ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2889eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				ptrace(PTRACE_KILL,
2890eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp->pid, (char *) 1, SIGTERM);
289176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
289276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
289376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
289476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
289576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2896e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2897e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2898e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2899e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2900e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2901e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2902e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
290376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
290476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2905732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
290676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
290776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
290876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
290976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
291076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
291176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
291276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
291376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
291476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
291576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
291676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2917ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2918ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
2919732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
292076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
292176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
292276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
292376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
292476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
292576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
292676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2927bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
292876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
292976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
293076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
293176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
293276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
293376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
293476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
293576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2936e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab	va_start(args, fmt);
2937b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2938b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2939ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		if (n < 0) {
2940ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			if (outf != stderr)
2941ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				perror(outfname == NULL
2942ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				       ? "<writing to pipe>" : outfname);
2943ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		} else
2944b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2945b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
294676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
294776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
294876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
294976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
295076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
29511201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintleader(struct tcb *tcp)
295276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2953732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2954eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tcp_last->ptrace_errno) {
2955732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
2956eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tprintf(" <unavailable>)");
2957eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tabto(acolumn);
2958732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2959eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf("= ? <unavailable>\n");
2960eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp_last->ptrace_errno = 0;
2961732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
29627e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2963eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf(" <unfinished ...>\n");
2964732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
296576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
296676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
296776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
296876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
296976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
297076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
297176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
297276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
297376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
297476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
297576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
297676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
297776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
297876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
297976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
298076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
298176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
298276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
298376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
298476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
298576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
298676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
298776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
298876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
298976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
299076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
299176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
299276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
299376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
299476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
299576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
299676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
299776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
299876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
299976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
300076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
300176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
300276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
30031201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotabto(int col)
300476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
300576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
300676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
300776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
300876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
300976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
3010ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
301176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
301276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
301376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
301476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
30159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
3016ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
30179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
3018ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
3019ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
3020ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
30219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
30229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
3023553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
30249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
30259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
30269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
30279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
30289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
30299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
30309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
3031553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
3032ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
30339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
30349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
30359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
3036