strace.c revision 26d1b1eaa861ec33d2c671acc9c0ccb867042cb8
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;
121ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid;
122ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid;
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
126b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
127ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic FILE *outf;
128ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
129ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab;
1302b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize;
131ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const 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;
474f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
476f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						if (debug)
477f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d failed\n", tid);
478f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					}
479f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					else {
480f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						if (debug)
481f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d succeeded\n", tid);
482f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						if (tid != tcbtab[tcbi]->pid) {
483f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							tcp = alloctcb(tid);
484f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD;
485f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							tcbtab[tcbi]->nclone_threads++;
486f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							tcp->parent = tcbtab[tcbi];
487f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						}
48802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
489aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (interactive) {
490aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_SETMASK, &empty_set, NULL);
491aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						if (interrupted)
492aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko							return;
493aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
494aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					}
49502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
4977a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
4987a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
5047a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
5057a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
5067a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
5077a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko						tcbtab[tcbi]->pid, ntid);
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
5107a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
5117a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
518f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko		if (debug)
519f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko			fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
520ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
521ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
522ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
523ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
524ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
525ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
526ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
527ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
528ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
529ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
530ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
531ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
532ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
533ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
539f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko	} /* for each tcbtab[] */
54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
5461201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
558cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
57230145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
57802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
606cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
608a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
609ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
610cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
611ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
61275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
61375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
614ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
615ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
617b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (outf != stderr) close(fileno(outf));
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
628ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		kill(pid, SIGSTOP); /* stop HERE */
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
631b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (outf != stderr)
632b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			close(fileno(outf));
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
634ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
635ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
636cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
637ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
638ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
639ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
64102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
64202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
64302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
64402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
64502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
64602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
64702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
64802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
64902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
65002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
65102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
65202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
65302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
65402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
65502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
65602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
657cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					perror_msg_and_die("initgroups");
65802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
660cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					perror_msg_and_die("setregid");
66102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
66202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
663cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					perror_msg_and_die("setreuid");
66402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
66502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
66602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
66702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
66902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
670ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
671ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
672ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Induce an immediate stop so that the parent
673ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
674ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * this execve call normally.
675c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * Unless of course we're on a no-MMU system where
676c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * we vfork()-ed, so we cannot stop the child.
677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
678c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
679c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger				kill(getpid(), SIGSTOP);
680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
681ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
682ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
684ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
685ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
686ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
687ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
688ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
689ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
690ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
691ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
692ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
693ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
694ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
695ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
696ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
69702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
69802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
69902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
700cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("exec");
70102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
702ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
703ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
70475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	/* With -D, we are *child* here, IOW: different pid. Fetch it. */
70575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
70675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
707ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
708ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
709ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
710ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
711ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
71202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
713ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
714cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("trouble opening proc file");
71502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
716ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
71702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
71802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
719b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX
720b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
721b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
722b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
723b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
724b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
725b13c0de058585de7d47778a8923426b89bfffbb5Wang Chaostatic int
7263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
727b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
7282fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
7292fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
7302fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
7312fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
732b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
733b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	if ((pid = fork()) < 0)
734b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		return -1;
735b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	else if (pid == 0) {
736b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
737b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			_exit(1);
738b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		kill(getpid(), SIGSTOP);
739b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		_exit(fork() < 0);
740b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
741b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
742b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
743b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
744b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
745b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
746b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid == -1) {
747b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
748b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
749b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			else if (errno == ECHILD)
750b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
7513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			perror("test_ptrace_setoptions_followfork");
752b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			return -1;
753b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
754b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
7552fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
756b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
757b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			    errno != ESRCH)
758b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				kill(tracee_pid, SIGKILL);
759b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
760b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		else if (WIFSTOPPED(status)) {
7612fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			switch (WSTOPSIG(status)) {
7622fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			case SIGSTOP:
7632fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				if (ptrace(PTRACE_SETOPTIONS, pid,
7642fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					   NULL, test_options) < 0) {
765b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao					kill(pid, SIGKILL);
766b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin					return -1;
767b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				}
7682fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				break;
7692fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			case SIGTRAP:
7702fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				if (status >> 16 == PTRACE_EVENT_FORK) {
7712fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					long msg = 0;
7722fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
7732fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					if (ptrace(PTRACE_GETEVENTMSG, pid,
7742fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin						   NULL, (long) &msg) == 0)
7752fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin						expected_grandchild = msg;
7762fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				}
7772fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				break;
778b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
779b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
780b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			    errno != ESRCH)
781b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				kill(pid, SIGKILL);
782b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
783b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
7842fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild)
785f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
786b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	return 0;
787b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
7883454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
7893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
7903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
7913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
7923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
7933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
7943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
7953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
7963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
7973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
7983454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
7993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
8003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
8013454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
8023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
8033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
8043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
8053454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
8063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
8073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
8083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
8093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
8113454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
81275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
8133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
8153454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
8163454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
81775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
81875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
8193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
8203454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
8213454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
8223454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8233454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
8243454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
8253454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
8273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
8283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
8293454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
8303454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
8313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
83275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
83375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
83475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
83575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
83675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
83775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* PTRACE_TRACEME failed in child. This is fatal. */
83875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			exit(1);
8393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
8413454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
8423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			error_msg_and_die("%s: unexpected wait status %x", __func__, status);
8433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
8453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
8463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
8473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
8483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
8493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
8503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
85175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
85275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				if (errno != EINVAL)
85375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					perror_msg("PTRACE_SETOPTIONS");
8543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
8563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
8573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8583454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
8593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
86075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
8613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
8633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
86575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
866f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
8673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
868f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
869f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
8703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
8713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
8723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	fprintf(stderr,
8743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		"Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
8753454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
876b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif
877b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
87876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
87908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
88306350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
88476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
88576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
88608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
88708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
88875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
88975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
890ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
891ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
8924f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
893cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (tcbtab == NULL)
894cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("Out of memory");
8954f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
8964f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	if (tcp == NULL)
897cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("Out of memory");
8984f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
8994f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
900ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
90276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
903138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
904138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
90576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
9108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"+cCdfFhiqrtTvVxyz"
911ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
912ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
913ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
9148a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"a:e:o:O:p:s:S:u:E:P:")) != EOF) {
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
917e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
918cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
919e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
920e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
921e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
922e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
923e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
924cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
925e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
926e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
931ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
932ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
933ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
934ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
935ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
93641c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
93706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
93806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
9648a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
9658a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
9668a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
9719c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
97417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
97517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
97617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
98276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
990de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
991cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("Invalid process id: '%s'", optarg);
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
99475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (pid == strace_tracer_pid) {
995cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("I'm sorry, I can't let you do that, Dave.");
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
998418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10028a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
10038a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
10048a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1005cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
10068a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
10078a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1010dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1011cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Invalid -s argument: '%s'", optarg);
1012dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1020de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
1021de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
1022cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Out of memory");
1023de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
1024de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1031d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
1032ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1033ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1034d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	if (pflag_seen && daemonized_tracer) {
1035cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive options");
1036d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1037d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
103806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
103906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
104006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1041cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1042cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
1043cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1044cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1050cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
1053cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
106276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10638044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX
10648044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin	if (followfork) {
10653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (test_ptrace_setoptions_followfork() < 0) {
10668044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin			fprintf(stderr,
10678044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				"Test for options supported by PTRACE_SETOPTIONS "
10688044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				"failed, giving up using this feature.\n");
1069f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			ptrace_setoptions = 0;
10708044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		}
10718044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		if (debug)
1072f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
1073f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
10748044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin	}
10753454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
10768044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif
10778044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
108037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
108137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
108237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
108337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
108437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
108537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
10867dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (followfork > 1)
10877dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
10887dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			outf = strace_popen(outfname + 1);
108954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
10903d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		else if (followfork <= 1)
10913d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko			outf = strace_fopen(outfname);
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1094cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1095cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		static char buf[BUFSIZ];
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
1097cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
109837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1101369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1102b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
110354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
110454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
110554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
110654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
110754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
110854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
110954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
111054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
111154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
111254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
111354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
111454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
111554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
111654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
1142bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
1145553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1146553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1147553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1148553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1149553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1150553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1151553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1152553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
1153bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
115476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1155ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
115602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
115702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
1161a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
1162a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
1163a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
1164a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
1165a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
1166a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
1167a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
1168a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
1169a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
1170a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
1171a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
117276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11742b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic void
1175418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
11767b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
11777b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
11787b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
11797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
11807b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
11817b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
118218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	int i = tcbtabsize;
118318da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
118418da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
118518da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	if (newtab == NULL || newtcbs == NULL)
118618da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		error_msg_and_die("expand_tcbtab: out of memory");
11877b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
11887b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
118918da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	while (i < tcbtabsize)
119018da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		tcbtab[i++] = newtcbs++;
11917b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
11927b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
119410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
119776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1199418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1200418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1201418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1202ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1203ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
120518da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko			memset(tcp, 0, sizeof(*tcp));
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
12111d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (debug)
12121d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
121310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
121410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
121818da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	error_msg_and_die("bug in alloc_tcb");
121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1221bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1223418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1227bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
122819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
122919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1232bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1237ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
12389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
12399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
12409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
12419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
12429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
12439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
12441f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
12459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
12469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
12479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
12489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
12499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
12501f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_stat);
12519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
12529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
12539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
12549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
12559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
12561f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_as);
12579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1259bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
1261372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR|O_EXCL);
1262bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1263bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1264372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR);
1265bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
1266372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	if (tcp->pfd < 0) {
126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
12701f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
12719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1272bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1273bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1274bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1275bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1276bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1277bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1278bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1279bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1280bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1281bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1282bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1283bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1284bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1285bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1286bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
1294b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_STATUS(tcp) < 0) {
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
12989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1299cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				break;
130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1302bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
130416a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1308553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
13129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
13189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1323553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1332bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1333bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1334bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1335bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
13365ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1337bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1338bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1339bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
13405ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
13415ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1342bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1343bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1345bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
134619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
134719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
134819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
134919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
1350b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
135119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
1352b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	praddset(&syscalls, SYS_execve);
135319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
1354b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork);
135519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
1356b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_forkall);
135719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1358553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
1359b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork1);
136019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
136119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
1362b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rfork1);
136319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
136419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
1365b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rforkall);
136619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
136719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
136819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
137219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
137319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
137719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
137819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
137919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
138019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
1381b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
138219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
13839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
138719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
138819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
138919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
139019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
1391b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
139219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
13939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1397bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1398bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1399b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	arg = S_SIG | S_SCE | S_SCX;
1400b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1401bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1402bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1403bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1404bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1413553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
14159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
1416b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1420553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1421bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1422bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1423bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1424bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1425553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
1428b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_WSTOP(tcp) < 0) {
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
14329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1433bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1434bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
143576989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1439bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
14409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
14419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1442bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1443bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1444553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1448bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1449bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1450bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1451bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1452bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1453bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1454553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1456bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1458bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1459bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1460553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
14612e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
14622e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
14632e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
14642e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
14652e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
14662e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
14672e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1468553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
14692e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
14702e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
14712e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
14722e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
14732e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
14742e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
14752e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
14762e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
14772e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
14782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
14792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
14802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
14812e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
14822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
14832e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
14842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1485bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1486bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
148876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
148976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
149076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
149576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
149676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
149776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
149876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
149976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1500bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
150176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1502e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
150354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
150576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
150654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
150754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
150854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1510ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
151154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
151254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
151554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1519bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
152254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void)
152354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{
152454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	int i;
152554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	struct tcb *tcp;
152654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
152754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		tcp = tcbtab[i];
152854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->flags & TCB_INUSE)
152954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath			return tcp;
153054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	}
153154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	return NULL;
153254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath}
153354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
153454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb *
15351201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkopfd2tcb(int pfd)
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1539ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1540ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1549bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
15521201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1556e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1557e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1558e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1559e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1560e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1561e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1562e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1563e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1564e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1565e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
15671d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko	if (debug)
15681d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1570eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1571e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1572e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1573e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1574e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1575e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
1576276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX
1577b56d6d3bfeeb8889ea18105033acfba6f3fcbf51Denys Vlasenko		/* Update fields like NCLONE_DETACHED, only
1578b56d6d3bfeeb8889ea18105033acfba6f3fcbf51Denys Vlasenko		   for zombie group leader that has already reported
1579b56d6d3bfeeb8889ea18105033acfba6f3fcbf51Denys Vlasenko		   and been short-circuited at the top of this
1580276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   function.  The same condition as at the top of DETACH.  */
1581276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		if ((tcp->flags & TCB_CLONE_THREAD) &&
1582276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    tcp->parent->nclone_threads == 0 &&
1583276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    (tcp->parent->flags & TCB_EXITING))
1584276ceb33f20fc41403e46684e441230296f6a433Roland McGrath			droptcb(tcp->parent);
1585276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif
1586e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1587e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1588e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1589e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1593bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1594bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1595bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1596bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1597bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1598bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1599bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1600bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1601bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1602553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1603bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1604e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1607eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1608822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1610eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16140a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
16150a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
16160a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
16170a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
16201201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodetach(struct tcb *tcp, int sig)
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1623ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
16241bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1625a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1626a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1627a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1628a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1629a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1630a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1631a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1632a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1633ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1636840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
16417bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
16427bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
16447bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
16457bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
16467bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
16477bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
164802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
164902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
165002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
165102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
165202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
165302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
16567bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
16577bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
16587bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
16597bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
16607bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1661134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1662134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1663134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
16647bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
16657bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
16667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
166702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
166802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
166902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
16707bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
16717bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
16727bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
167302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
167402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1675ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
16777508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
16787508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
16797508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
16807508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16817508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
16837508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16847508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16857508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
16867508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
16877508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
16887508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
16897508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
16907508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16917508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16927508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
16937508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
16947508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
16957508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
16967508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
16977508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
16987508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16997508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
17007508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
17017508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
17027508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
17047508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1710732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1713732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
171475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1715732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1716732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1719ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
17207bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1727732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1734a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1735a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX
17360a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	if (zombie != NULL) {
1737b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
17380a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(zombie);
17390a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	}
1740a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif
1741a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1745bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1747e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig)
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1756bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17591201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1764ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1765ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1773ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			tprintf(" <unfinished ...>");
1774ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17881201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17956d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
17986d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
18011201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no)
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180535aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
180635aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180935aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	return sys_errlist[err_no];
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18168f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
18176d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
18198f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
18208f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
18218f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
18241201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig)
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1841bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18441201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkorebuild_pollv(void)
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1848ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1849b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		free(pollv);
1850c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1851ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
1852cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("Out of memory");
1853ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1854ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1855ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1856ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
18609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
1864cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("proc miscount");
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18711201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll_open(void)
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
1876cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("pipe");
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
18791f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		set_cloexec_flag(proc_poll_pipe[i]);
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
18841201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll(struct pollfd *pollv, int nfds, int timeout)
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
1893cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("panic: short read: %d", n);
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19061201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkowakeup_handler(int sig)
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19111201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poller(int pfd)
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1919bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1920bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1921bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
1925cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1948cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1959bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
19605ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
19615ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
19625ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
19635ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
19649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
19979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
2014cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("lost proc");
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2024cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	error_msg_and_die("nothing ready");
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
20281201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
20309dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
2031d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
20329dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
20379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
205154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath				tcp = first_used_tcb();
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
20649dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
20659dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
20669dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
20679dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2068553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
20699dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
20709dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
20719dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
20729dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
20739dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
20749dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
2075b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				if ((what = poll(&pv, 1, 1)) < 0) {
20769dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
20779dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
20789dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
20799dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20809dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
20819dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
20829dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20839dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
20849dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
20859dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
2106cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("unknown pfd: %u", pfd);
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2108b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
21099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2110b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2113bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
2114b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			ioctl_result = IOCTL_WSTOP(tcp);
2115bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2118bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2119bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2120b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_STATUS(tcp);
2121bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
2122b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_WSTOP(tcp);
2123553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2146bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2148553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
2153cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("PIOCWSTOP");
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21572e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
21582e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
21592e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
2160b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			IOCTL(tcp->pfd, PIOCRUN, 0);
21612e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
21622e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2163553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2164553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
2170ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2174bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2175bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2176bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2177bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2178bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2179bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2180bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2181bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2182bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2183bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2184bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2185553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2188bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
21939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2194bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
21969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
21979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
2199cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					error_msg_and_die("syscall trouble");
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2203bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
22059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
22069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
22079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
2210cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("syscall trouble");
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
2214e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2215e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_SIGNAL)) {
221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2218ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2219ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
22205826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
22215826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
22225826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
22235826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
22245826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2225ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
22265826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
22275826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
2231e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAGS_ONLY_STATS
2232e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_FAULT)) {
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2235ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2238bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2239bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
22405ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2241553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
2243cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2246ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2247ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
22489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2249553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
2250b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
2251553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2252b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
2253553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2254372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		{
2255cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("PIOCRUN");
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2261bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2263e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2264e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2265e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2266e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2267e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2268e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2269e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2270e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2271e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2272e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2273e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2274e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
22757a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	struct tcb *leader = NULL;
22767a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko
22777a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	if (tcp->flags & TCB_CLONE_THREAD)
22787a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp->parent;
2279e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2280e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
22817a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		if (leader != NULL && leader != tcp
22827a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(leader->flags & TCB_GROUP_EXITING)
22837a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(tcp->flags & TCB_STARTUP)
22847a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		) {
2285e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2286e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2287e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
22887a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		}
22897a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
22900a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2291e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2292e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2293a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2294a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2295e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
2296d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath			detach(tcp, sig);
22975ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			if (leader != NULL && leader != tcp)
22981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2299732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else {
2300732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2301732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				cleanup();
2302732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				return -1;
2303732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2304732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (leader != NULL) {
23050569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2306732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (leader != tcp)
2307732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					droptcb(tcp);
2308732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2309e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2310e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2311e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2312e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2313e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2314e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2315e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2316e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2317e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2318e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2319ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
2320ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaostatic int
2321ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaohandle_ptrace_event(int status, struct tcb *tcp)
2322ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao{
2323ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	if (status >> 16 == PTRACE_EVENT_VFORK ||
2324ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	    status >> 16 == PTRACE_EVENT_CLONE ||
2325ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	    status >> 16 == PTRACE_EVENT_FORK) {
23262fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin		long childpid;
2327ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
2328ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2329ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (errno != ESRCH) {
2330cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Cannot get new child's pid");
2331ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			}
2332ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			return -1;
2333ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2334ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		return handle_new_child(tcp, childpid, 0);
2335ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	}
23363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (status >> 16 == PTRACE_EVENT_EXEC) {
23373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return 0;
23383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
233975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	/* Some PTRACE_EVENT_foo we didn't ask for?! */
234075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	error_msg("Unexpected status %x on pid %d", status, tcp->pid);
2341ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	return 1;
2342ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao}
2343ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
2344ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
2345eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
2346eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace()
234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
234876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
234976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
235076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
235176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
235376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
235426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko	struct rusage *rup = cflag ? &ru : NULL;
235526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
2356eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
235726d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif
235876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
235976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2360eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2361222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2362eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2363eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2364eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
236576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
236626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
236726d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, wait4_options, rup);
23685bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
23692f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
23702f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
237126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, wait4_options, rup);
23722f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
23735bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
23742f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
237526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, __WCLONE, rup);
237626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			if (pid < 0) {
2377cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
23782f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
23792f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
238026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# else
238126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, 0, rup);
238226d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif /* __WALL */
238376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
238476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
238576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
238626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko#endif
238776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2388eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2389eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
239076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
239126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		if (pid < 0) {
2392eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2393eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
239476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2395eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
239676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
239776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
239876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
239976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
240076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
240176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
2402eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2403eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2404eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2405eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2406eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
240776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
240876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
240910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
241010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
24117dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
241210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
241310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
24141d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		if (debug) {
24151d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
24161d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef LINUX
24171d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			unsigned ev = (unsigned)status >> 16;
24181d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (ev) {
24191d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				static const char *const event_names[] = {
24201d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_CLONE] = "CLONE",
24211d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_FORK]  = "FORK",
24221d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK] = "VFORK",
24231d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
24241d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXEC]  = "EXEC",
24251d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXIT]  = "EXIT",
24261d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				};
24271d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				const char *e;
24281d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				if (ev < ARRAY_SIZE(event_names))
24291d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					e = event_names[ev];
24301d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				else {
24311d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					sprintf(buf, "?? (%u)", ev);
24321d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					e = buf;
24331d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				}
24341d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, " PTRACE_EVENT_%s", e);
24351d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			}
24361d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
24371d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			strcpy(buf, "???");
24381d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSIGNALED(status))
24391d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP
24401d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,%ssig=%s",
24411d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						WCOREDUMP(status) ? "core," : "",
24421d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
24431d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else
24441d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,sig=%s",
24451d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
24461d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
24471d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFEXITED(status))
24481d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
24491d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSTOPPED(status))
24501d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
24515bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED
24521d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFCONTINUED(status))
24531d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				strcpy(buf, "WIFCONTINUED");
24545bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif
24551d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
24561d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		}
245776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
245876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
245976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2460e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
246141c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2462e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2463e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2464e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2465e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2466e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2467e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2468e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2469e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2470e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2471418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2472e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2473e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2474e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2475e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2476e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
24778b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2478e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2479e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2480e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2481eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2482e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2483e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2484e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2485cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
2486e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
248776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2488eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2489eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
2490ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
2491eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
249213d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko		if (cflag) {
249376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
249476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
249613d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#endif
2497eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
2498f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		if (tcp->flags & TCB_SUSPENDED) {
2499f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			/*
2500f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Apparently, doing any ptrace() call on a stopped
2501f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process, provokes the kernel to report the process
2502f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * status again on a subsequent wait(), even if the
2503f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process has not been actually restarted.
2504f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Since we have inspected the arguments of suspended
2505f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * processes we end up here testing for this case.
2506f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 */
2507f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			continue;
2508f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		}
250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2510a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2511a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2512e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
251376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
251476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
251513d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP
25162efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
25172efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
251813d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					WCOREDUMP(status) ? "(core dumped) " : "");
251913d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else
252013d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko				tprintf("+++ killed by %s +++",
252113d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					signame(WTERMSIG(status)));
25222efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
2523ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
252476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2525e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2526e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2527e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
252876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2529e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
253076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
253176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
253276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2533a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2534a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
25357a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
25360569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
25377a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			    && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
25381bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && !(tcp->flags & TCB_GROUP_EXITING)
25390569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
25407a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			) {
254176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
25427a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					"PANIC: attached pid %u exited with %d\n",
25437a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					pid, WEXITSTATUS(status));
25447a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			}
25450a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
25467a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
25470a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
25480a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
25490a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
25500a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2551e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2552e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2553e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
255476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2555e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
255676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
255776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
255876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
255976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
256076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
256176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
256276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
256376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
25643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (status >> 16) {
2565ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (handle_ptrace_event(status, tcp) != 1)
2566ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				goto tracing;
2567ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2568ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
256902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
257002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
257102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
2572eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		 * than SIGSTOP if we happend to attach
257302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
2574c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * A no-MMU vforked child won't send up a signal,
2575c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * so skip the first (lost) execve notification.
257602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
2577c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		if ((tcp->flags & TCB_STARTUP) &&
2578c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		    (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
257976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
258076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
258176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
258276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
258376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
258476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
258502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
258676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
258702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
258802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
258976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
259076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
259176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
259276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
259376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
259476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
259576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2596ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
2597f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			/* If options were not set for this tracee yet */
2598f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			if (tcp->parent == NULL) {
2599f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				if (ptrace_setoptions) {
2600f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko					if (debug)
2601f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko						fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2602f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko					if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2603f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko						if (errno != ESRCH) {
2604f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko							/* Should never happen, really */
2605f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko							perror_msg_and_die("PTRACE_SETOPTIONS");
2606f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko						}
26073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
26083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
26093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2610ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
261176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
261475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WSTOPSIG(status) != syscall_trap_sig) {
261576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
261676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
261776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
261876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
261976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
262076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
262176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2622732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
262376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
262476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
262576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
262676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
262776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2628e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
262976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
2630c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin				siginfo_t si;
2631c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
26326b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
26336b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
26347b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2635932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2636932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
26377b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
26386b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
26397b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
26406b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
26416b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	pc
26426b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
26436b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	"%s"
26446b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	""
26457b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
264676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
26476b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
26486b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- ");
26496b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
26506b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf(" (%s)" PC_FORMAT_STR " ---",
26516b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
26526b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
26536b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
26546b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- %s by %s" PC_FORMAT_STR " ---",
26556b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
26566b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						signame(WSTOPSIG(status)),
26576b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
2658ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
265976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
26600569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
26610569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
266276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2663e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2664e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2665e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
266676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2667e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
266876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
266976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2670732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
267176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
267276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
267376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
267476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
267576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
267676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
267702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
267802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
267902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2680eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2681eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2682eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2683eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2684eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * all processes in thread group. In this case, threads
2685eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * "disappear" in an unpredictable moment without any
2686eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * notification to strace via wait().
2687ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2688ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2689eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (tcp_last) {
2690eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2691178de007d14f3ae890117b540def9cf14bcb61feDenys Vlasenko					 * Finish the line then.
2692eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2693eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp_last->flags |= TCB_REPRINT;
2694eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tprintf(" <unfinished ...>");
2695eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					printtrailer();
2696eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
269776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2698ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2699eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				ptrace(PTRACE_KILL,
2700eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp->pid, (char *) 1, SIGTERM);
270176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
270276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
270376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
270476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
270576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2706e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2707e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2708e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2709e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2710e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2711e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2712e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
271376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
271476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2715732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
271676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
271776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
271876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
271976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
272076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
272176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
272276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
272376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
272476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
272576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
272676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2727ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2728ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
2729732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
273076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
273176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
273276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
273376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
273476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
273576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
273676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2737bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
273876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
273976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
274076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
274176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
274276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
274376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2744e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab	va_start(args, fmt);
2745b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2746b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2747ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		if (n < 0) {
2748ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			if (outf != stderr)
2749ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				perror(outfname == NULL
2750ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				       ? "<writing to pipe>" : outfname);
2751ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		} else
2752b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2753b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
275476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
275576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
275676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
275776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
275876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
27591201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintleader(struct tcb *tcp)
276076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2761732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2762eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tcp_last->ptrace_errno) {
2763732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
2764e62df004ce7a649c014fc0b5af058d56bc168920Denys Vlasenko				tprintf(" <unavailable>) ");
2765eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tabto(acolumn);
2766732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2767eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf("= ? <unavailable>\n");
2768eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp_last->ptrace_errno = 0;
2769732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
27707e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2771eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf(" <unfinished ...>\n");
2772732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
277376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
277476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
277576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
277676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
277776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
277876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
277976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
278076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
278176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
278276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
278376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
278476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
278576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
278676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
278776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
278876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
278976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
279076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
279176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
279276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
279376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
279476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
279576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
279676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
279776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
279876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
279976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
280076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
280176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
280276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
280376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
280476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
280576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
280676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
280776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
280876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
280976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
281076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
28111201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotabto(int col)
281276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
281376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
281476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
281576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
281676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
281776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2818ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
281976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
282076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
282176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
282276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
28239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2824ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
28259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2826ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2827ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2828ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
28299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
28309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2831553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
28329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
28339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
28349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
28359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
28369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
28379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
28389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2839553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2840ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
28419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
28429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
28439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2844