strace.c revision 4f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35
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
53b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko#  define my_tgkill(pid, tid, sig) syscall(__NR_tgkill, (pid), (tid), (sig))
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# elif defined __NR_tkill
55b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko#  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!"
61b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko#  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;
87f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0;
883454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */
8975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP;
90e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0;
91e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE;
92b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
104ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
105ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
1118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint show_fd_path = 0;
1128a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1138a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
1148a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint tracing_paths = 0;
1158a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
116a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
117a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
11875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
119eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
120b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
126b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
128ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
129ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
1302b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize;
13130145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinconst char *progname;
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
133e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int detach(struct tcb *tcp, int sig);
134e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
135e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
136e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
147e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd);
148e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig);
149e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void);
150ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void);
155e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd);
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
173bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
176cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval)
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
1798a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsusage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
180de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
1818a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards              [-P path] [command [arg ...]]\n\
182b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab   or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
183de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
185b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
1948a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
201ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
205de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
206de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
2078a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
208de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
20917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
210de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
211de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
21675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
21775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
21875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
21975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
22075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
22175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
22275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
22375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
22475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
22575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
22744d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(NULL);
22844d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fprintf(stderr, "%s: ", progname);
22944d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	vfprintf(stderr, fmt, p);
23044d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	if (err_no)
23144d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin		fprintf(stderr, ": %s\n", strerror(err_no));
23244d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	else
23344d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin		putc('\n', stderr);
23444d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(stderr);
23575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
23675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
23775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
23875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
23975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
24075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
24175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
24375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
24575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
24675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
24775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
24875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
24975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
25075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
25175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
25575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
25675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
25775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
25875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
25975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
26075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
26175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(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	die();
2673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
2683454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
26976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
27076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
27176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
27276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
27476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
27576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
27676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
278c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
279c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
280c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
281c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
282c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
283c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
284c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
285c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
2861f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void
28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
2891f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	int flags, newflags;
2901f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko
2911f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	flags = fcntl(fd, F_GETFD);
2921f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	if (flags < 0) {
2931f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		/* Can happen only if fd is bad.
2941f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * Should never happen: if it does, we have a bug
2951f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * in the caller. Therefore we just abort
2961f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * instead of propagating the error.
2971f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 */
2981f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
3031f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		return;
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3051f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	fcntl(fd, F_SETFD, newflags); /* never fails */
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3187b609d5ba0852e6c56ba311350ebd4412361777bDenys Vlasenko	if (euid != uid && setreuid(euid, uid) < 0) {
319cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("setreuid");
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3244bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
3254bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
3264bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
3274bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
3284bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
3294bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
3313d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostrace_fopen(const char *path)
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
3363d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	fp = fopen_for_output(path, "w");
3373d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	if (!fp)
3383d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		perror_msg_and_die("Can't fopen '%s'", path);
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
3403d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	set_cloexec_flag(fileno(fp));
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3447dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenkostatic int popen_pid = 0;
34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
3587dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	FILE *fp;
3597dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	int fds[2];
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
3637dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("pipe");
36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3657dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	set_cloexec_flag(fds[1]); /* never fails */
36610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3677dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	popen_pid = vfork();
3687dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == -1)
3697dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("vfork");
37010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3717dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == 0) {
37210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
37310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
3747dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		if (fds[0] != 0) {
3757dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (dup2(fds[0], 0))
3767dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				perror_msg_and_die("dup2");
3777dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			close(fds[0]);
37810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
37910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
3807dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
38110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
3827dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko
3837dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	/* parent */
3847dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	close(fds[0]);
3857dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	swap_uid();
3867dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	fp = fdopen(fds[1], "w");
3877dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (!fp)
3887dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		error_msg_and_die("Out of memory");
3897dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	return fp;
39010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
39110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3923d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostatic void
39310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
39410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
39510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
3967a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
3977a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
3983d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		tcp->outf = strace_fopen(name);
39910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
40010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
40110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
40202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
412b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	 * We rely on cleanup() from this point on.
41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
417ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
418ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
419ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
420ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(1);
421ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
422ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
423ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
42475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
42575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
42675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
427ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
428ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
429ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
430ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
431ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
43275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
43375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
43475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
435ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
436ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
43702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
44602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
4473d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		newoutf(tcp);
44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
45602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
457ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
4587a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
46002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
46702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
4687a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
47302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
474aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
476aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					else if (tid != tcbtab[tcbi]->pid) {
477418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko						tcp = alloctcb(tid);
47821b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_threads++;
48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->parent = tcbtab[tcbi];
48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
482aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (interactive) {
483aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_SETMASK, &empty_set, NULL);
484aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						if (interrupted)
485aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko							return;
486aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
487aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					}
48802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
48902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
4907a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
4917a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
49202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
49302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
49402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
49502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
4977a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
4987a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
4997a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
5007a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko						tcbtab[tcbi]->pid, ntid);
50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
5037a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
5047a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif
50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* INTERRUPTED is going to be checked at the top of TRACE.  */
512ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
513ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
514ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
515ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
516ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
517ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
518ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
519ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
520ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
521ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
522ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
523ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
524ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
525ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
5381201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
550cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
56430145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
57802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
598cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
600a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
601ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
602cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
603ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
60475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
60575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
606ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
607ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
609b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (outf != stderr) close(fileno(outf));
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
620ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		kill(pid, SIGSTOP); /* stop HERE */
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
623b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (outf != stderr)
624b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			close(fileno(outf));
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
626ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
627ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
628cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
629ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
630ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
631ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
64102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
64202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
64302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
64402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
64502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
64602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
64702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
64802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
649cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					perror_msg_and_die("initgroups");
65002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
65102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
652cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					perror_msg_and_die("setregid");
65302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
65402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
655cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					perror_msg_and_die("setreuid");
65602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
65702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
65802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
66002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
66102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
662ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
663ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
664ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Induce an immediate stop so that the parent
665ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
666ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * this execve call normally.
667c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * Unless of course we're on a no-MMU system where
668c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * we vfork()-ed, so we cannot stop the child.
669ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
670c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
671c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger				kill(getpid(), SIGSTOP);
672ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
673ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
674ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
675ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
678ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
681ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
682ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
684ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
685ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
686ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
687ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
688ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
68902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
69002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
69102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
692cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("exec");
69302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
694ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
695ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
69675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	/* With -D, we are *child* here, IOW: different pid. Fetch it. */
69775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
69875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
699ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
700ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
701ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
702ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
703ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
70402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
705ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
706cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("trouble opening proc file");
70702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
708ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
70902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
71002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
711b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX
712b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
713b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
714b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
715b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
716b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
717b13c0de058585de7d47778a8923426b89bfffbb5Wang Chaostatic int
7183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
719b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
7202fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
7212fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
7222fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
7232fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
724b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
725b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	if ((pid = fork()) < 0)
726b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		return -1;
727b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	else if (pid == 0) {
728b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
729b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			_exit(1);
730b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		kill(getpid(), SIGSTOP);
731b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		_exit(fork() < 0);
732b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
733b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
734b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
735b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
736b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
737b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
738b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid == -1) {
739b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
740b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
741b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			else if (errno == ECHILD)
742b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
7433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			perror("test_ptrace_setoptions_followfork");
744b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			return -1;
745b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
746b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
7472fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
748b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
749b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			    errno != ESRCH)
750b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				kill(tracee_pid, SIGKILL);
751b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
752b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		else if (WIFSTOPPED(status)) {
7532fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			switch (WSTOPSIG(status)) {
7542fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			case SIGSTOP:
7552fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				if (ptrace(PTRACE_SETOPTIONS, pid,
7562fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					   NULL, test_options) < 0) {
757b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao					kill(pid, SIGKILL);
758b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin					return -1;
759b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				}
7602fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				break;
7612fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			case SIGTRAP:
7622fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				if (status >> 16 == PTRACE_EVENT_FORK) {
7632fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					long msg = 0;
7642fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
7652fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					if (ptrace(PTRACE_GETEVENTMSG, pid,
7662fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin						   NULL, (long) &msg) == 0)
7672fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin						expected_grandchild = msg;
7682fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				}
7692fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				break;
770b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
771b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
772b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			    errno != ESRCH)
773b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				kill(pid, SIGKILL);
774b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
775b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
7762fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild)
777f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
778b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	return 0;
779b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
7803454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
7813454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
7823454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
7833454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
7843454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
7853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
7863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
7873454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
7883454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
7893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
7903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
7913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
7923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
7933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
7943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
7953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
7963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
7973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
7983454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
7993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
8003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
8013454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
8033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
80475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
8053454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
8073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
8083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
80975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
81075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
8113454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
8123454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
8133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
8143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8153454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
8163454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
8173454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
8193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
8203454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
8213454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
8223454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
8233454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
82475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
82575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
82675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
82775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
82875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
82975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* PTRACE_TRACEME failed in child. This is fatal. */
83075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			exit(1);
8313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
8333454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
8343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			error_msg_and_die("%s: unexpected wait status %x", __func__, status);
8353454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
8373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
8383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
8393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
8403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
8413454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
8423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
84375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
84475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				if (errno != EINVAL)
84575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					perror_msg("PTRACE_SETOPTIONS");
8463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
8483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
8493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
8513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
85275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
8533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
8553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
85775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
858f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
8593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
860f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
861f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
8623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
8633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
8643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	fprintf(stderr,
8663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		"Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
8673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
868b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif
869b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
87108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
87506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
87808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
87908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
88075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
88175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
882ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
883ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
8844f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
885cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (tcbtab == NULL)
886cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("Out of memory");
8874f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
8884f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	if (tcp == NULL)
889cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("Out of memory");
8904f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
8914f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
892ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
89376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
89476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
895138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
896138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
89776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
9028a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"+cCdfFhiqrtTvVxyz"
903ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
904ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
905ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
9068a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"a:e:o:O:p:s:S:u:E:P:")) != EOF) {
90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
909e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
910cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
911e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
912e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
913e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
914e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
915e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
916cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
917e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
918e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
923ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
924ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
925ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
926ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
927ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
92841c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
92906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
93006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
9568a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
9578a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
9588a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
9639c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
96617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
96717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
96817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
982de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
983cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("Invalid process id: '%s'", optarg);
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
98675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (pid == strace_tracer_pid) {
987cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("I'm sorry, I can't let you do that, Dave.");
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
990418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
9948a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
9958a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
9968a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
997cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
9988a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
9998a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1002dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1003cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Invalid -s argument: '%s'", optarg);
1004dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1012de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
1013de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
1014cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Out of memory");
1015de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
1016de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1023d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
1024ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1025ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1026d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	if (pflag_seen && daemonized_tracer) {
1027cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive options");
1028d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1029d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
103006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
103106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
103206350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1033cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1034cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
1035cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1036cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1042cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
1045cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10558044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX
10568044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin	if (followfork) {
10573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (test_ptrace_setoptions_followfork() < 0) {
10588044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin			fprintf(stderr,
10598044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				"Test for options supported by PTRACE_SETOPTIONS "
10608044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				"failed, giving up using this feature.\n");
1061f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			ptrace_setoptions = 0;
10628044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		}
10638044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		if (debug)
1064f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
1065f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
10668044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin	}
10673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
10688044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif
10698044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
107237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
107337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
107437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
107537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
107637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
107737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
10787dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (followfork > 1)
10797dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
10807dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			outf = strace_popen(outfname + 1);
108154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
10823d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		else if (followfork <= 1)
10833d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko			outf = strace_fopen(outfname);
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1086cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1087cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		static char buf[BUFSIZ];
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
1089cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
109037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1093369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1094b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
109554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
109654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
109754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
109854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
109954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
110054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
110154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
110254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
110354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
110454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
110554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
110654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
110754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
110854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
1134bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
1137553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1138553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1139553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1140553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1141553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1142553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1143553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1144553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
1145bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1147ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
114802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
114902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
115176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
1153a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
1154a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
1155a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
1156a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
1157a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
1158a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
1159a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
1160a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
1161a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
1162a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
1163a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
116476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11662b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic void
1167418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
11687b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
11697b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
11707b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
11717b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
11727b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
11737b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
117418da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	int i = tcbtabsize;
117518da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
117618da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
117718da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	if (newtab == NULL || newtcbs == NULL)
117818da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		error_msg_and_die("expand_tcbtab: out of memory");
11797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
11807b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
118118da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	while (i < tcbtabsize)
118218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		tcbtab[i++] = newtcbs++;
11837b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
11847b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
118610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1191418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1192418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1193418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1194ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1195ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
119718da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko			memset(tcp, 0, sizeof(*tcp));
119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
120310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
120410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
120818da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	error_msg_and_die("bug in alloc_tcb");
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1211bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1213418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1217bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
121819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
121919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1222bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1227ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
12289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
12299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
12309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
12319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
12329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
12339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
12341f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
12359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
12369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
12379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
12389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
12399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
12401f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_stat);
12419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
12429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
12439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
12449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
12459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
12461f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_as);
12479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1249bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
125076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
1251372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR|O_EXCL);
1252bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1253bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1254372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR);
1255bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
1256372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	if (tcp->pfd < 0) {
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
12601f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
12619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1262bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1263bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1264bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1265bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1266bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1267bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1268bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1269bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1270bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1271bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1272bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1273bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1274bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1275bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1276bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
128176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
1284b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_STATUS(tcp) < 0) {
128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
12889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1289cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				break;
129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1292bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
129416a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1298553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
13029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
13089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1313553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1322bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1323bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1324bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1325bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
13265ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1327bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1328bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1329bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
13305ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
13315ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1332bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1333bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1335bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
133619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
133719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
133819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
133919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
1340b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
134119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
1342b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	praddset(&syscalls, SYS_execve);
134319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
1344b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork);
134519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
1346b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_forkall);
134719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1348553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
1349b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork1);
135019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
135119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
1352b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rfork1);
135319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
135419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
1355b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rforkall);
135619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
135719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
135819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
136219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
136319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
136719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
136819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
136919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
137019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
1371b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
137219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
13739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
137719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
137819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
137919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
138019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
1381b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
138219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
13839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1387bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1388bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1389b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	arg = S_SIG | S_SCE | S_SCX;
1390b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1391bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1392bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1393bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1394bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1403553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
14059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
1406b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1410553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1411bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1412bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1413bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1414bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1415553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
1418b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_WSTOP(tcp) < 0) {
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
14229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1423bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1424bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
142576989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1429bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
14309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
14319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1432bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1433bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1434553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1438bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1439bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1440bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1441bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1442bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1443bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1444553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1446bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1448bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1449bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1450553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
14512e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
14522e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
14532e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
14542e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
14552e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
14562e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
14572e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1458553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
14592e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
14602e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
14612e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
14622e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
14632e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
14642e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
14652e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
14662e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
14672e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
14682e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
14692e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
14702e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
14712e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
14722e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
14732e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
14742e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1475bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1476bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
147976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
148076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
148176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
148676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
148876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
148976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1490bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1492e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
149354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
149576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
149654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
149754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
149854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
149976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1500ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
150154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
150254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
150554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1509bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
151076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
151254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void)
151354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{
151454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	int i;
151554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	struct tcb *tcp;
151654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
151754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		tcp = tcbtab[i];
151854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->flags & TCB_INUSE)
151954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath			return tcp;
152054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	}
152154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	return NULL;
152254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath}
152354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
152454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb *
15251201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkopfd2tcb(int pfd)
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1529ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1530ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1539bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
15421201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1546e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1547e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1548e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1549e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1550e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1551e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1552e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1553e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1554e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1555e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1558eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1559e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1560e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1561e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1562e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1563e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
1564276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX
1565b56d6d3bfeeb8889ea18105033acfba6f3fcbf51Denys Vlasenko		/* Update fields like NCLONE_DETACHED, only
1566b56d6d3bfeeb8889ea18105033acfba6f3fcbf51Denys Vlasenko		   for zombie group leader that has already reported
1567b56d6d3bfeeb8889ea18105033acfba6f3fcbf51Denys Vlasenko		   and been short-circuited at the top of this
1568276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   function.  The same condition as at the top of DETACH.  */
1569276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		if ((tcp->flags & TCB_CLONE_THREAD) &&
1570276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    tcp->parent->nclone_threads == 0 &&
1571276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    (tcp->parent->flags & TCB_EXITING))
1572276ceb33f20fc41403e46684e441230296f6a433Roland McGrath			droptcb(tcp->parent);
1573276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif
1574e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1575e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1576e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1577e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1581bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1582bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1583bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1584bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1585bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1586bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1587bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1588bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1589bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1590553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1591bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1592e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1595eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1596822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1598eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16020a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
16030a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
16040a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
16050a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
16081201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodetach(struct tcb *tcp, int sig)
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1611ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
16121bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1613a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1614a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1615a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1616a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1617a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1618a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1619a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1620a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1621ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1624840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
16297bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
16307bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
16327bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
16337bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
16347bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
16357bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
163602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
163702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
163802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
163902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
164002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
164102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
16447bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
16457bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
16467bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
16477bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
16487bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1649134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1650134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1651134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
16527bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
16537bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
16547bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
165502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
165602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
165702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
16587bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
16597bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
16607bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
166102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
166202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1663ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
16657508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
16667508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
16677508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
16687508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16697508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
16717508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16727508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16737508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
16747508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
16757508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
16767508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
16777508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
16787508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16797508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16807508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
16817508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
16827508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
16837508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
16847508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
16857508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
16867508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16877508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16887508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
16897508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16907508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
16927508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1698732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1701732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
170275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1703732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1704732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1707ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
17087bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1715732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1722a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1723a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX
17240a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	if (zombie != NULL) {
1725b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
17260a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(zombie);
17270a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	}
1728a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif
1729a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1733bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1735e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig)
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1744bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17471201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1752ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1753ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1761ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			tprintf(" <unfinished ...>");
1762ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17761201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17836d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
17866d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
17891201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no)
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179335aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
179435aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
179735aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	return sys_errlist[err_no];
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18048f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
18056d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
18078f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
18088f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
18098f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
18121201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig)
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1829bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18321201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkorebuild_pollv(void)
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1836ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1837b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		free(pollv);
1838c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1839ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
1840cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("Out of memory");
1841ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1842ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1843ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1844ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
18489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
1852cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("proc miscount");
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18591201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll_open(void)
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
1864cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("pipe");
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
18671f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		set_cloexec_flag(proc_poll_pipe[i]);
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
18721201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll(struct pollfd *pollv, int nfds, int timeout)
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
1881cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("panic: short read: %d", n);
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18941201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkowakeup_handler(int sig)
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18991201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poller(int pfd)
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1907bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1908bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1909bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
1913cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1936cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1947bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
19485ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
19495ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
19505ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
19515ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
19529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
19859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
2002cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("lost proc");
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2012cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	error_msg_and_die("nothing ready");
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
20161201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
20189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
2019d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
20209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
20259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
203954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath				tcp = first_used_tcb();
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
20529dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
20539dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
20549dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
20559dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2056553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
20579dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
20589dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
20599dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
20609dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
20619dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
20629dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
2063b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				if ((what = poll(&pv, 1, 1)) < 0) {
20649dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
20659dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
20669dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
20679dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20689dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
20699dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
20709dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20719dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
20729dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
20739dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
2094cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("unknown pfd: %u", pfd);
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2096b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
20979dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2098b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2101bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
2102b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			ioctl_result = IOCTL_WSTOP(tcp);
2103bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2104bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2105bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2106bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2107bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2108b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_STATUS(tcp);
2109bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
2110b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_WSTOP(tcp);
2111553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2134bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2135bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2136553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
2141cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("PIOCWSTOP");
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21452e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
21462e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
21472e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
2148b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			IOCTL(tcp->pfd, PIOCRUN, 0);
21492e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
21502e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2151553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2152553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
2158ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2162bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2163bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2164bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2165bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2166bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2167bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2168bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2169bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2170bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2171bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2172bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2173553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2176bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
21819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2182bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
21849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
21859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
2187cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					error_msg_and_die("syscall trouble");
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2191bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
21939dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
21949dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
21959dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
2198cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("syscall trouble");
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
2202e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2203e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_SIGNAL)) {
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2206ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2207ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
22085826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
22095826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
22105826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
22115826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
22125826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2213ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
22145826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
22155826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
2219e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAGS_ONLY_STATS
2220e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_FAULT)) {
222176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2223ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
222476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
222576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2226bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2227bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
22285ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2229553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
2231cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2234ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2235ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
22369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2237553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
2238b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
2239553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2240b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
2241553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2242372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		{
2243cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("PIOCRUN");
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
224676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
224776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2249bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2251e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2252e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2253e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2254e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2255e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2256e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2257e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2258e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2259e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2260e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2261e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2262e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
22637a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	struct tcb *leader = NULL;
22647a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko
22657a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	if (tcp->flags & TCB_CLONE_THREAD)
22667a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp->parent;
2267e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2268e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
22697a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		if (leader != NULL && leader != tcp
22707a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(leader->flags & TCB_GROUP_EXITING)
22717a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(tcp->flags & TCB_STARTUP)
22727a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		) {
2273e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2274e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2275e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
22767a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		}
22777a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
22780a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2279e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2280e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2281a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2282a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2283e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
2284d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath			detach(tcp, sig);
22855ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			if (leader != NULL && leader != tcp)
22861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2287732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else {
2288732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2289732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				cleanup();
2290732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				return -1;
2291732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2292732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (leader != NULL) {
22930569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2294732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (leader != tcp)
2295732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					droptcb(tcp);
2296732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2297e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2298e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2299e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2300e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2301e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2302e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2303e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2304e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2305e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2306e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2307ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
2308ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaostatic int
2309ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaohandle_ptrace_event(int status, struct tcb *tcp)
2310ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao{
2311ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	if (status >> 16 == PTRACE_EVENT_VFORK ||
2312ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	    status >> 16 == PTRACE_EVENT_CLONE ||
2313ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	    status >> 16 == PTRACE_EVENT_FORK) {
23142fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin		long childpid;
2315ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
2316ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2317ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (errno != ESRCH) {
2318cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Cannot get new child's pid");
2319ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			}
2320ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			return -1;
2321ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2322ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		return handle_new_child(tcp, childpid, 0);
2323ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	}
23243454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (status >> 16 == PTRACE_EVENT_EXEC) {
23253454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
23263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			fprintf(stderr, "PTRACE_EVENT_EXEC on pid %d (ignored)\n", tcp->pid);
23273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return 0;
23283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
232975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	/* Some PTRACE_EVENT_foo we didn't ask for?! */
233075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	error_msg("Unexpected status %x on pid %d", status, tcp->pid);
2331ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	return 1;
2332ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao}
2333ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
2334ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
2335eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
2336eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace()
233776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
233876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
233976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
234076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
234176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
234276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
23442f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2345eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
23462f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
234876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2349eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2350222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2351eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2352eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2353eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
235476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
23552f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2356eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
23575bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
23582f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
23592f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
23602f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
2361eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, wait4_options,
2362eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
23632f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
23645bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
23652f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
2366eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, __WCLONE,
2367eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
2368eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (pid == -1) {
2369cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
23702f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
23712f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
2372eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#else
2373eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2374eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* __WALL */
237576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
237876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
237976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2380eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2381eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
238276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
238376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
2384eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2385eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
238676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2387eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
238876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
238976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
239076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
239176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
239276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
239376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
2394eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2395eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2396eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2397eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2398eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
239976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
240076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
240110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
240210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
24037dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
240410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
240510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
240676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
240776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
240876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
240976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
241076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2411e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
241241c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2413e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2414e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2415e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2416e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2417e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2418e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2419e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2420e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2421e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2422418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2423e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2424e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2425e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2426e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2427e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
24288b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2429e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2430e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2431e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2432eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2433e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2434e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2435e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2436cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
2437e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
243876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2439eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2440eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
2441ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
244284e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko		if (cflag) {
2443eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
244476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
244576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
2446eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* !LINUX */
244776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2448eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
2449f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		if (tcp->flags & TCB_SUSPENDED) {
2450f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			/*
2451f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Apparently, doing any ptrace() call on a stopped
2452f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process, provokes the kernel to report the process
2453f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * status again on a subsequent wait(), even if the
2454f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process has not been actually restarted.
2455f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Since we have inspected the arguments of suspended
2456f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * processes we end up here testing for this case.
2457f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 */
2458f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			continue;
2459f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		}
246076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2461a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2462a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2463e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
246476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
246576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
24662efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
24672efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
24682efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
24692efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
24702efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
24712efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
2472ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2474e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2475e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2476e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2478e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2482a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2483a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
248476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
24857a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
24867a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
24870569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
24887a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			    && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
24891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && !(tcp->flags & TCB_GROUP_EXITING)
24900569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
24917a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			) {
249276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
24937a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					"PANIC: attached pid %u exited with %d\n",
24947a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					pid, WEXITSTATUS(status));
24957a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			}
24960a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
24977a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
24980a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
24990a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
25000a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
25010a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2502e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2503e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2504e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
250576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2506e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
250776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
250876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
251076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
251176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
251276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
251376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
251476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
251576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2516ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
251776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
25183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (status >> 16) {
2519ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (handle_ptrace_event(status, tcp) != 1)
2520ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				goto tracing;
2521ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2522ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
252302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
252402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
252502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
2526eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		 * than SIGSTOP if we happend to attach
252702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
2528c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * A no-MMU vforked child won't send up a signal,
2529c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * so skip the first (lost) execve notification.
253002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
2531c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		if ((tcp->flags & TCB_STARTUP) &&
2532c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		    (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
253376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
253476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
253576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
253676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
253776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
253876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
253902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
254076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
254102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
254202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
254676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
254776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
254876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
254976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2550ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
2551f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			/* If options were not set for this tracee yet */
2552f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			if (tcp->parent == NULL) {
2553f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				if (ptrace_setoptions) {
2554f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko					if (debug)
2555f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko						fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2556f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko					if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2557f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko						if (errno != ESRCH) {
2558f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko							/* Should never happen, really */
2559f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko							perror_msg_and_die("PTRACE_SETOPTIONS");
2560f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko						}
25613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
25623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
25633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2564ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
256576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
256676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
256776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
256875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WSTOPSIG(status) != syscall_trap_sig) {
256976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
257076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
257176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
257276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
257376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
257576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2576732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
257776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
257876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
257976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
258076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
258176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2582e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
258376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
2584c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin				siginfo_t si;
2585c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
25866b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
25876b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
25887b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2589932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2590932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
25917b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
25926b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
25937b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
25946b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
25956b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	pc
25966b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
25976b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	"%s"
25986b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	""
25997b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
260076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
26016b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
26026b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- ");
26036b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
26046b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf(" (%s)" PC_FORMAT_STR " ---",
26056b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
26066b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
26076b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
26086b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- %s by %s" PC_FORMAT_STR " ---",
26096b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
26106b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						signame(WSTOPSIG(status)),
26116b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
2612ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
26140569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
26150569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
261676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2617e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2618e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2619e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
262076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2621e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
262276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
262376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2624732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
262576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
262676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
262776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
262876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
262976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
263076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
263102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
263202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
263302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2634eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2635eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2636eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2637eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2638eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * all processes in thread group. In this case, threads
2639eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * "disappear" in an unpredictable moment without any
2640eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * notification to strace via wait().
2641ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2642ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2643eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (tcp_last) {
2644eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2645eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 * Finish the line then. We cannot
2646eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2647eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp_last->flags |= TCB_REPRINT;
2648eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tprintf(" <unfinished ...>");
2649eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					printtrailer();
2650eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
265176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2652ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2653eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				ptrace(PTRACE_KILL,
2654eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp->pid, (char *) 1, SIGTERM);
265576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
265776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
265876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
265976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2660e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2661e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2662e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2663e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2664e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2665e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2666e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
266776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
266876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2669732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
267076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
267176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
267276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
267376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
267476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
267576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
267676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
267776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
268076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2681ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2682ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
2683732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
268476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
268576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
268676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
268776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
268876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
268976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
269076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2691bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
269276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
269376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
269476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
269576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
269676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
269776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
269876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
269976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2700e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab	va_start(args, fmt);
2701b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2702b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2703ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		if (n < 0) {
2704ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			if (outf != stderr)
2705ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				perror(outfname == NULL
2706ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				       ? "<writing to pipe>" : outfname);
2707ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		} else
2708b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2709b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
271076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
271176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
271276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
271376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
271476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
27151201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintleader(struct tcb *tcp)
271676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2717732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2718eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tcp_last->ptrace_errno) {
2719732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
2720e62df004ce7a649c014fc0b5af058d56bc168920Denys Vlasenko				tprintf(" <unavailable>) ");
2721eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tabto(acolumn);
2722732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2723eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf("= ? <unavailable>\n");
2724eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp_last->ptrace_errno = 0;
2725732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
27267e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2727eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf(" <unfinished ...>\n");
2728732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
272976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
273076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
273176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
273276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
273376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
273476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
273576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
273676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
273776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
273876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
273976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
274076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
274176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
274276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
274376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
274476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
274576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
274676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
274776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
274876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
274976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
275076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
275176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
275276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
275376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
275476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
275576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
275676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
275776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
275876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
275976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
276076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
276176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
276276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
276376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
276476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
276576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
276676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
27671201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotabto(int col)
276876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
276976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
277076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
277176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
277276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
277376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2774ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
277576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
277676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
277776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
277876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
27799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2780ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
27819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2782ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2783ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2784ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
27859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
27869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2787553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
27889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
27899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
27909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
27919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
27929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
27939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
27949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2795553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2796ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
27979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
27989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
27999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2800