strace.c revision f44cce48bbbd573cc5ae801f69f857433160b03a
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved.
776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without
976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions
1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met:
1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright
1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer.
1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright
1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer in the
1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    documentation and/or other materials provided with the distribution.
1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products
1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    derived from this software without specific prior written permission.
1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *	$Id$
3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
35795edb11488dd47c4598e2228e3b5431de7ed46dRoland McGrath#include <sys/types.h>
363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko#include <stdarg.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h>
4719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h>
4870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
4976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX
51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h>
52134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# if defined __NR_tgkill
53b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko#  define my_tgkill(pid, tid, sig) syscall(__NR_tgkill, (pid), (tid), (sig))
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# elif defined __NR_tkill
55b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko#  define my_tgkill(pid, tid, sig) syscall(__NR_tkill, (tid), (sig))
56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else
57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath   /* kill() may choose arbitrarily the target task of the process group
58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      while we later wait on a that specific TID.  PID process waits become
59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      TID task specific waits for a process under ptrace(2).  */
60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
61b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko#  define my_tgkill(pid, tid, sig) kill((tid), (sig))
62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif
63134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif
64134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath
657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
687b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
71bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
72bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
7476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
75ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
761d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
7976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
801d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
8196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
82418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
83418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
8496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
8576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8641c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0;
87f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0;
883454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */
8975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP;
90e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0;
91e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE;
92b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
104ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
105ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
1118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint show_fd_path = 0;
1128a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1138a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
1148a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint tracing_paths = 0;
1158a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
116a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
117a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
11875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
119eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
120b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
126b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
128ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
129ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
130ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
13130145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levinconst char *progname;
132eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathextern char **environ;
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
134e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int detach(struct tcb *tcp, int sig);
135e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
136e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
137e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
146bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
148e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd);
149e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig);
150e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void);
151ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void);
156e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd);
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
174bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
1828a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsusage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
183de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
1848a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards              [-P path] [command [arg ...]]\n\
185b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab   or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
186de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
188b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
1978a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
204ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
208de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
209de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
2108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
211de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
21217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
213de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
214de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
21975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
22075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
22175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
22275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
22375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
22475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
22575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
22675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
22775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
22875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2293454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
23044d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(NULL);
23144d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fprintf(stderr, "%s: ", progname);
23244d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	vfprintf(stderr, fmt, p);
23344d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	if (err_no)
23444d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin		fprintf(stderr, ": %s\n", strerror(err_no));
23544d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	else
23644d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin		putc('\n', stderr);
23744d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(stderr);
23875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
23975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
24075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
24175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
24275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
24375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
24475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
24675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
24875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
24975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
25075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
25175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
25275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
25675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
25775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
25875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
25975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
26075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
26175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
26275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
26375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
26475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...)
26575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
26675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
26775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
26875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
26975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
2703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
2713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
27276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
27476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
27576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
27676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
27976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
281c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
282c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
283c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
284c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
285c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
286c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
287c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
288c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     flags, newflags;
29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return 0;
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fcntl(fd, F_SETFD, newflags) < 0)
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (euid != uid && setreuid(euid, uid) < 0)
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: setreuid: %s\n",
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		exit(1);
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3344bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
3354bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
3364bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
3374bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
3384bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
3394bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode)
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
3464bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath	if ((fp = fopen_for_output(path, mode)) == NULL)
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: can't fopen '%s': %s\n",
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, path, strerror(errno));
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fp && set_cloexec_flag(fileno(fp)) < 0)
35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fclose(fp);
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fp = NULL;
35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1;
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
36510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
36610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
36710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
36910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
37010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
37110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
37210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     fds[2];
37310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
37410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
37510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
37610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
37710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: pipe: %s\n",
37810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
37910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
38010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
38110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
38210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
38310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(fds[1]) < 0)
38410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
38510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
38610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
38710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
38810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
38910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
39010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
39110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((popen_pid = fork()) == -1)
39210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
39310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fork: %s\n",
39410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
39510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
39610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
39710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
39810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
39910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
40010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
40110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (popen_pid)
40210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
40310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* parent */
40410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
40510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
40610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return fdopen(fds[1], "w");
40710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	} else
40810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
40910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
41010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
41110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
41210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		{
41310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			fprintf(stderr, "%s: dup2: %s\n",
41410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				progname, strerror(errno));
41510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			_exit(1);
41610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
41710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
41810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: execl: %s: %s\n",
41910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, _PATH_BSHELL, strerror(errno));
42010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		_exit(1);
42110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
42210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
42310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
42410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
42510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
42610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
42710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
4287a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
42910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		FILE *fp;
43010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4317a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
43210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if ((fp = strace_fopen(name, "w")) == NULL)
43310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			return -1;
43410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		tcp->outf = fp;
43510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
43610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
43710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
43810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
44602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
449b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	 * We rely on cleanup() from this point on.
45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
454ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
455ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
456ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
457ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(1);
458ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
459ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
460ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
46175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
46275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
46375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
464ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
465ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
466ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
467ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
468ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
46975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
47075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
47175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
472ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
473ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
48202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
48302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
48402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (newoutf(tcp) < 0)
48502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
48602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
48702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
48802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
48902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
49002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
49102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
49202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
49302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
49402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
495ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
4967a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
5067a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
512aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
514aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					else if (tid != tcbtab[tcbi]->pid) {
515418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko						tcp = alloctcb(tid);
51621b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_FOLLOWFORK;
51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nchildren++;
51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_threads++;
51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->parent = tcbtab[tcbi];
52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
521aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (interactive) {
522aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_SETMASK, &empty_set, NULL);
523aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						if (interrupted)
524aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko							return;
525aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
526aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					}
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
5297a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
5307a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
5367a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
5377a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
5387a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
5397a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko						tcbtab[tcbi]->pid, ntid);
54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
5427a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
5437a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif
54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* INTERRUPTED is going to be checked at the top of TRACE.  */
551ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
552ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
553ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
554ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
555ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
556ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
557ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
558ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
559ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
560ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
561ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
562ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
563ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
564ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
5771201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
57802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("strace: exec");
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
60430145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		fprintf(stderr, "%s: %s: command not found\n",
63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			progname, filename);
64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
64102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
642a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
643ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
64402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: fork");
64502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		cleanup();
64602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
647ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
64875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
64975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
650ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
651ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
65202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
653b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (outf != stderr) close(fileno(outf));
65402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
65502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
65602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
65702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
65802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
66002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
66102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
66202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
66302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
664ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		kill(pid, SIGSTOP); /* stop HERE */
66502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
66602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
667b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (outf != stderr)
668b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			close(fileno(outf));
66902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
670ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
671ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
672ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				perror("strace: ptrace(PTRACE_TRACEME, ...)");
673ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				exit(1);
674ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
675ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
67702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
67802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
67902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
68002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
68102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
68202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
68302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
68402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
68502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
68602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
68702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
68802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
68902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
69002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
69102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
69202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
69302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
69402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("initgroups");
69502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
69602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
69702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
69802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setregid");
69902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
70002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
70102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
70202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setreuid");
70302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
70402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
70502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
70602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
70702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
70802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
70902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
710ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
711ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
712ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Induce an immediate stop so that the parent
713ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
714ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * this execve call normally.
715c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * Unless of course we're on a no-MMU system where
716c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * we vfork()-ed, so we cannot stop the child.
717ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
718c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
719c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger				kill(getpid(), SIGSTOP);
720ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
721ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
722ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
723ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
724ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
725ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
726ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
727ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
728ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
729ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
730ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
731ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
732ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
733ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
734ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
735ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
736ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
73702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
73802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
73902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
74002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: exec");
74102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		_exit(1);
74202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
743ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
744ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
74575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	/* With -D, we are *child* here, IOW: different pid. Fetch it. */
74675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
74775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
748ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
749ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
750ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
751ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
752ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
75302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
754ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
755ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		fprintf(stderr, "trouble opening proc file\n");
756ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		cleanup();
757ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		exit(1);
75802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
759ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
76002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
76102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
762b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX
763b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
764b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
765b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
766b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
767b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
768b13c0de058585de7d47778a8923426b89bfffbb5Wang Chaostatic int
7693454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
770b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
7712fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
7722fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
7732fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
7742fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
775b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
776b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	if ((pid = fork()) < 0)
777b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		return -1;
778b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	else if (pid == 0) {
779b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (ptrace(PTRACE_TRACEME, 0, (char *)1, 0) < 0)
780b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			_exit(1);
781b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		kill(getpid(), SIGSTOP);
782b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		_exit(fork() < 0);
783b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
784b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
785b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
786b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
787b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
788b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
789b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid == -1) {
790b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
791b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
792b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			else if (errno == ECHILD)
793b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
7943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			perror("test_ptrace_setoptions_followfork");
795b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			return -1;
796b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
797b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
7982fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
799b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0 &&
800b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			    errno != ESRCH)
801b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				kill(tracee_pid, SIGKILL);
802b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
803b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		else if (WIFSTOPPED(status)) {
8042fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			switch (WSTOPSIG(status)) {
8052fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			case SIGSTOP:
8062fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				if (ptrace(PTRACE_SETOPTIONS, pid,
8072fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					   NULL, test_options) < 0) {
808b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao					kill(pid, SIGKILL);
809b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin					return -1;
810b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				}
8112fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				break;
8122fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			case SIGTRAP:
8132fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				if (status >> 16 == PTRACE_EVENT_FORK) {
8142fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					long msg = 0;
8152fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
8162fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					if (ptrace(PTRACE_GETEVENTMSG, pid,
8172fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin						   NULL, (long) &msg) == 0)
8182fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin						expected_grandchild = msg;
8192fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				}
8202fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin				break;
821b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
822b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0 &&
823b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			    errno != ESRCH)
824b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				kill(pid, SIGKILL);
825b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
826b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
8272fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild)
828f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
829b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	return 0;
830b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
8313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
8333454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
8343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
8353454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
8363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
8373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
8383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
8393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
8403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
8413454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
8423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
8433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
8443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
8453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
8463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
8473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
8483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
8493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	const unsigned int test_options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC;
8503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
8513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
8523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
8543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
85575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
8563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
8583454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
8593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
86075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
86175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work", __func__);
8623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
8633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
8643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
8653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
8673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
8683454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8693454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
8703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
8713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
8723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
8733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
8743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
87575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("%s: unexpected wait result %d", __func__, tracee_pid);
87675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
87775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
87875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
87975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
88075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* PTRACE_TRACEME failed in child. This is fatal. */
88175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			exit(1);
8823454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8833454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
8843454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
8853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			error_msg_and_die("%s: unexpected wait status %x", __func__, status);
8863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8873454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
8883454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
8893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
8903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
8913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
8923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
8933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
89475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0)
89575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				if (errno != EINVAL)
89675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					perror_msg("PTRACE_SETOPTIONS");
8973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8983454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
8993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
9003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9013454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
9023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
90375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
9043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9053454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
90875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
909f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
9103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
911f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
912f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
9133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
9143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9153454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9163454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	fprintf(stderr,
9173454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		"Test for PTRACE_O_TRACESYSGOOD failed, giving up using this feature.\n");
9183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
919b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif
920b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
92208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
92606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
93108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
93208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
93375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
93475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
935ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
936ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
937418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
93808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
93908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
94008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
941418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
94208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
94308b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
94408b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
945ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
946ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
947ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
950138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
951138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
9578a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"+cCdfFhiqrtTvVxyz"
958ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
959ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
960ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
9618a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"a:e:o:O:p:s:S:u:E:P:")) != EOF) {
96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
964e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
965e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
966e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin					progname);
967e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				exit(1);
968e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
969e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
970e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
971e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
972e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
973e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
974e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin					progname);
975e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				exit(1);
976e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
977e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
982ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
983ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
984ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
985ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
986ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
98741c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
98806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
98906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10158a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
10168a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
10178a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
10229c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
102517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
102617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
102717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
1041de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
104675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (pid == strace_tracer_pid) {
104754a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1050418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10548a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
10558a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
10568a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1057b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				fprintf(stderr, "%s : failed to select path '%s'\n", progname, optarg);
10588a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards				exit(1);
10598a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
10608a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
106276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1063dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1064dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				fprintf(stderr,
1065dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					"%s: invalid -s argument: %s\n",
1066dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					progname, optarg);
1067dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				exit(1);
1068dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1076de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
1077de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
1078de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
1079de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
1080de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
1081de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
1082de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1089d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
1090ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1091ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1092d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	if (pflag_seen && daemonized_tracer) {
1093d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao		fprintf(stderr,
1094d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao			"%s: -D and -p are mutually exclusive options\n",
1095d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao			progname);
1096d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao		exit(1);
1097d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1098d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
109906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
110006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
110106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1102cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1103cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		fprintf(stderr,
1104e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			"%s: (-c or -C) and -ff are mutually exclusive options\n",
1105cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			progname);
1106cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		exit(1);
1107cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1108cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
112109553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath				progname, username);
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11328044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX
11338044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin	if (followfork) {
11343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (test_ptrace_setoptions_followfork() < 0) {
11358044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin			fprintf(stderr,
11368044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				"Test for options supported by PTRACE_SETOPTIONS "
11378044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin				"failed, giving up using this feature.\n");
1138f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			ptrace_setoptions = 0;
11398044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		}
11408044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin		if (debug)
1141f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
1142f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
11438044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin	}
11443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
11458044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif
11468044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
114876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
114937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
115037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
115137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
115237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
115337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
115437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
115537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
115637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
115737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
115837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
115937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
116037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
116137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
116210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if ((outf = strace_popen(outfname + 1)) == NULL)
116337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
116454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
116510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		else if (followfork <= 1 &&
116610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			 (outf = strace_fopen(outfname, "w")) == NULL)
116754b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
117037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
117237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1175369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1176b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
117754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
117854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
117954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
118054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
118154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
118254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
118354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
118454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
118554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
118654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
118754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
118854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
118954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
119054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
119776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
1216bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
1219553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1220553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1221553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1222553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1223553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1224553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1225553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1226553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
1227bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
122876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1229ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
123002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
123102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
123276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
1235a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
1236a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
1237a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
1238a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
1239a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
1240a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
1241a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
1242a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
1243a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
1244a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
1245a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1248418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkovoid
1249418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
12507b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
12517b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
12527b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
12537b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
12547b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
12557b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
12567b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb **newtab = (struct tcb **)
12577b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
12587b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
12597b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    sizeof *newtcbs);
12607b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	int i;
12617b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	if (newtab == NULL || newtcbs == NULL) {
126276860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
126376860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin			progname);
1264418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		cleanup();
1265418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		exit(1);
12667b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
12677b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
12687b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
12697b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
12707b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
12717b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
12727b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
127376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
127410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
127576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1279418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1280418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1281418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1282ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1283ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
128476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
1286eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->parent = NULL;
1287eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nchildren = 0;
1288eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nzombies = 0;
1289eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef TCB_CLONE_THREAD
129021b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao			tcp->nclone_threads = 0;
1291eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
1294ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			tcp->curcol = 0;
1295eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->stime.tv_sec = 0;
1296eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->stime.tv_usec = 0;
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
129910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
130010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1304418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1305418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	cleanup();
1306418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	exit(1);
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1309bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1311418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1315bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
131619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
131719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1320bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1325ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
13269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
13279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
13289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
13299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
133210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
13339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
13369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
13379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
134010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_stat) < 0) {
13419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
13449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
13459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
134810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_as) < 0) {
13499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1353bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
1355372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR|O_EXCL);
1356bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1357bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1358372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR);
1359bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
1360372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	if (tcp->pfd < 0) {
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
136410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
13659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1368bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1369bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1370bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1371bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1372bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1373bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1374bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1375bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1376bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1377bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1378bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1379bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1380bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1381bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1382bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
138376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
138776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
138876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
138976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
1390b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_STATUS(tcp) < 0) {
139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
13949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1395bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1398bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
140016a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1404553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
14089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
14149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1419553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1428bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1429bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1430bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1431bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
14325ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1433bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1434bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1435bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
14365ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
14375ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1438bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1439bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1441bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
144219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
144319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
144419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
144519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
1446b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
144719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
1448b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	praddset(&syscalls, SYS_execve);
144919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
1450b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork);
145119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
1452b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_forkall);
145319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1454553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
1455b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork1);
145619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
145719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
1458b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rfork1);
145919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
146019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
1461b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rforkall);
146219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
146319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
146419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
146776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
146819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
146919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
147319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
147419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
147519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
147619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
1477b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
147819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
14799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
148076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
148176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
148319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
148419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
148519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
148619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
1487b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
148819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
14899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
149076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1493bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1494bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1495b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	arg = S_SIG | S_SCE | S_SCX;
1496b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1497bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1498bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1499bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1500bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
150176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
150276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
150576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1509553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
151076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
15119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
1512b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1516553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1517bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1518bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1519bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1520bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1521553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
1524b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_WSTOP(tcp) < 0) {
152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
15289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1529bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1530bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
153176989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1535bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
15369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
15379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1538bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1539bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1540553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1544bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1545bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1546bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1547bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1548bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1549bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1550553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1552bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1554bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1555bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1556553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
15572e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
15582e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
15592e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
15602e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
15612e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
15622e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
15632e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1564553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
15652e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
15662e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
15672e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
15682e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
15692e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
15702e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
15712e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
15722e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
15732e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
15742e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
15752e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
15762e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
15772e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
15782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
15792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
15802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1581bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1582bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1596bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1598e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
159954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
160254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
160354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
160454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1606ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
160754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
160854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
161154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1615bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
161854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void)
161954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{
162054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	int i;
162154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	struct tcb *tcp;
162254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
162354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		tcp = tcbtab[i];
162454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->flags & TCB_INUSE)
162554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath			return tcp;
162654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	}
162754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	return NULL;
162854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath}
162954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
163054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb *
16311201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkopfd2tcb(int pfd)
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1635ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1636ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1645bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
16481201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1652e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1653e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1654e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1655e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1656e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1657e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1658e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1659e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1660e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1661e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1664eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1665e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1666e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1667e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1668e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1669e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1670e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
167121b8db4eb966a6098c7cd10bd6cf0ce8ec59cab8Wang Chao		tcp->parent->nzombies++;
1672276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX
1673276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		/* Update `tcp->parent->parent->nchildren' and the other fields
1674276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   like NCLONE_DETACHED, only for zombie group leader that has
1675276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   already reported and been short-circuited at the top of this
1676276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   function.  The same condition as at the top of DETACH.  */
1677276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		if ((tcp->flags & TCB_CLONE_THREAD) &&
1678276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    tcp->parent->nclone_threads == 0 &&
1679276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    (tcp->parent->flags & TCB_EXITING))
1680276ceb33f20fc41403e46684e441230296f6a433Roland McGrath			droptcb(tcp->parent);
1681276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif
1682e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1683e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1684e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1685e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1689bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1690bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1691bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1692bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1693bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1694bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1695bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1696bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1697bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1698553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1699bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1700e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1703eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1704822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1706eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17100a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
17110a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
17120a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
17130a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
17161201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodetach(struct tcb *tcp, int sig)
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1719ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
17201bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1721a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1722a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1723a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1724a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1725a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1726a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1727a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1728a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1729ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1732840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
17377bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
17387bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
17407bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
17417bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
17427bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
17437bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
174402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
174502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
174602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
174702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
174802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
174902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
17527bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
17537bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
17547bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
17557bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
17567bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1757134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1758134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1759134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
17607bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
17617bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
17627bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
176302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
176402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
176502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
17667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
17677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
17687bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
176902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
177002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1771ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
17737508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
17747508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
17757508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
17767508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
17777508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
17797508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
17807508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
17817508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
17827508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
17837508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
17847508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
17857508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
17867508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
17877508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
17887508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
17897508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
17907508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
17917508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
17927508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
17937508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
17947508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
17957508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
17967508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
17977508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
17987508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
18007508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1806732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1809732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
181075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1811732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1812732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1815ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
18167bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1823732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1830a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1831a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX
18320a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	if (zombie != NULL) {
1833b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
18340a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(zombie);
18350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	}
1836a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif
1837a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1841bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1843e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig)
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1852bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18551201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1860ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1861ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1869ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			tprintf(" <unfinished ...>");
1870ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18841201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18916d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
18946d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
18971201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no)
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190135aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
190235aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
190535aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	return sys_errlist[err_no];
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19128f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
19136d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
19158f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
19168f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
19178f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
19201201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig)
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1937bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19401201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkorebuild_pollv(void)
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1944ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1945b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		free(pollv);
1946c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1947ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
194846100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "%s: out of memory\n", progname);
1949ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1950ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1951ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1952ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1953ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
19579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19691201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll_open(void)
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
197810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
19851201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll(struct pollfd *pollv, int nfds, int timeout)
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
20081201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkowakeup_handler(int sig)
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
20131201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poller(int pfd)
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
2021bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2022bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
2023bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
2028a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
2052a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
2063bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
20645ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
20655ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
20665ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
20675ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
20689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
21019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
21341201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
21369dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
2137d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
21389dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
21439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
215754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath				tcp = first_used_tcb();
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
21709dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
21719dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
21729dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
21739dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2174553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
21759dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
21769dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
21779dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
21789dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
21799dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
21809dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
2181b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				if ((what = poll(&pv, 1, 1)) < 0) {
21829dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
21839dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
21849dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
21859dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
21869dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
21879dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
21889dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
21899dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
21909dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
21919dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2215b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
22169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2217b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2220bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
2221b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			ioctl_result = IOCTL_WSTOP(tcp);
2222bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2223bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2224bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2225bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2226bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2227b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_STATUS(tcp);
2228bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
2229b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_WSTOP(tcp);
2230553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
223176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
223876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
223976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
224076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
224176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
224376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
224676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
224776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
224976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
225276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2253bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2254bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2255553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
22652e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
22662e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
22672e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
2268b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			IOCTL(tcp->pfd, PIOCRUN, 0);
22692e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
22702e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2271553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2272553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
227576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
2278ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2282bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2283bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2284bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2285bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2286bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2287bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2288bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2289bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2290bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2291bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2292bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2293553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2296bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
229776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
229976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
23009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
23019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2302bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
230376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
23049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
23059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
230776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2312bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
23149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
23159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
23169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
232076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
232176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
232276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
2324e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2325e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_SIGNAL)) {
232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
232776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2328ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2329ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
23305826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
23315826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
23325826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
23335826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
23345826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2335ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
23365826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
23375826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
233876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
233976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
234076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
2341e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAGS_ONLY_STATS
2342e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_FAULT)) {
234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
234476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2345ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
234676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2348bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2349bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
23505ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2351553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
23539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
235476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
235576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
235676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2357ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2358ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
23599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2360553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
2361b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
2362553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2363b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
2364553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2365372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		{
236676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
236776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
236876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
236976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
237076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
237176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
237276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2373bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
237476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2375e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2376e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2377e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2378e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2379e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2380e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2381e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2382e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2383e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2384e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2385e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2386e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
23877a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	struct tcb *leader = NULL;
23887a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko
23897a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	if (tcp->flags & TCB_CLONE_THREAD)
23907a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp->parent;
2391e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2392e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
23937a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		if (leader != NULL && leader != tcp
23947a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(leader->flags & TCB_GROUP_EXITING)
23957a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(tcp->flags & TCB_STARTUP)
23967a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		) {
2397e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2398e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2399e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
24007a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		}
24017a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
24020a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2403e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2404e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2405a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2406a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2407e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
2408d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath			detach(tcp, sig);
24095ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			if (leader != NULL && leader != tcp)
24101bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2411732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else {
2412732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2413732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				cleanup();
2414732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				return -1;
2415732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2416732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (leader != NULL) {
24170569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2418732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (leader != tcp)
2419732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					droptcb(tcp);
2420732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2421e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2422e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2423e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2424e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2425e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2426e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2427e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2428e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2429e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2430e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2431ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
2432ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaostatic int
2433ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chaohandle_ptrace_event(int status, struct tcb *tcp)
2434ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao{
2435ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	if (status >> 16 == PTRACE_EVENT_VFORK ||
2436ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	    status >> 16 == PTRACE_EVENT_CLONE ||
2437ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	    status >> 16 == PTRACE_EVENT_FORK) {
24382fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin		long childpid;
2439ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
2440ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		if (do_ptrace(PTRACE_GETEVENTMSG, tcp, NULL, &childpid) < 0) {
2441ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (errno != ESRCH) {
2442ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				fprintf(stderr, "\
2443ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao%s: handle_ptrace_event: ptrace cannot get new child's pid\n",
2444ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao					progname);
2445ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				cleanup();
2446ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				exit(1);
2447ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			}
2448ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			return -1;
2449ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2450ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		return handle_new_child(tcp, childpid, 0);
2451ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	}
24523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (status >> 16 == PTRACE_EVENT_EXEC) {
24533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
24543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			fprintf(stderr, "PTRACE_EVENT_EXEC on pid %d (ignored)\n", tcp->pid);
24553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return 0;
24563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
245775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	/* Some PTRACE_EVENT_foo we didn't ask for?! */
245875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	error_msg("Unexpected status %x on pid %d", status, tcp->pid);
2459ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao	return 1;
2460ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao}
2461ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
2462ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
2463eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
2464eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace()
246576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
246676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
246776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
246876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
246976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
247076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
247176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
24722f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2473eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
24742f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
247576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2477eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2478222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2479eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2480eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2481eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
24832f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2484eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
24855bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
24862f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
24872f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
24882f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
2489eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, wait4_options,
2490eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
24912f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
24925bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
24932f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
2494eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, __WCLONE,
2495eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
2496eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (pid == -1) {
2497eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				fprintf(stderr, "strace: clone wait4 "
24982f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
24992f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
25002f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
2501eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#else
2502eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2503eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* __WALL */
250476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
250576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
250676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
250776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
250876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2509eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2510eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
251176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
251276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
2513eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2514eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
251576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2516eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
251776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
251876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
251976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
252076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
252176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
252276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
2523eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2524eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2525eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2526eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2527eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
252876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
252976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
253010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
253110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
253210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				popen_pid = -1;
253310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
253410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
253576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
253676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
253776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
253876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
253976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2540e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
254141c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2542e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2543e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2544e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2545e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2546e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2547e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2548e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2549e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2550e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2551418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2552e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2553e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2554e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2555e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2556e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
25578b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2558e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2559e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2560e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2561eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2562e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2563e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2564e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2565e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2566e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2567e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
256876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2569eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2570eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
2571ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
257284e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko		if (cflag) {
2573eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
257576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
2576eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* !LINUX */
257776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2578eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
2579f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		if (tcp->flags & TCB_SUSPENDED) {
2580f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			/*
2581f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Apparently, doing any ptrace() call on a stopped
2582f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process, provokes the kernel to report the process
2583f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * status again on a subsequent wait(), even if the
2584f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process has not been actually restarted.
2585f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Since we have inspected the arguments of suspended
2586f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * processes we end up here testing for this case.
2587f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 */
2588f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			continue;
2589f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		}
259076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2591a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2592a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2593e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
259476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
259576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
25962efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
25972efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
25982efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
25992efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
26002efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
26012efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
2602ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
260376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2604e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2605e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2606e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
260776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2608e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
260976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
261076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
261176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2612a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2613a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
261476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
26157a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
26167a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
26170569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
26187a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			    && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
26191bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && !(tcp->flags & TCB_GROUP_EXITING)
26200569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
26217a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			) {
262276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
26237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					"PANIC: attached pid %u exited with %d\n",
26247a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					pid, WEXITSTATUS(status));
26257a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			}
26260a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
26277a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
26280a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
26290a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
26300a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
26310a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2632e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2633e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2634e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
263576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2636e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
263776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
263876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
263976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
264076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
264176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
264276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
264376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
264476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
264576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2646ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
264776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
26483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (status >> 16) {
2649ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao			if (handle_ptrace_event(status, tcp) != 1)
2650ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao				goto tracing;
2651ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2652ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
265302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
265402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
265502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
2656eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		 * than SIGSTOP if we happend to attach
265702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
2658c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * A no-MMU vforked child won't send up a signal,
2659c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * so skip the first (lost) execve notification.
266002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
2661c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		if ((tcp->flags & TCB_STARTUP) &&
2662c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		    (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
266376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
266476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
266576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
266676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
266776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
266876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
266902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
267076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
267102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
267202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
267376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
267476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
267576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
267676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
267776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2680ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
2681f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			/* If options were not set for this tracee yet */
2682f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			if (tcp->parent == NULL) {
2683f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				if (ptrace_setoptions) {
2684f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko					if (debug)
2685f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko						fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
2686f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko					if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
2687f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko						if (errno != ESRCH) {
2688f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko							/* Should never happen, really */
2689f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko							perror_msg_and_die("PTRACE_SETOPTIONS");
2690f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko						}
26913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
26923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
26933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2694ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
269576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
269676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
269776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
269875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WSTOPSIG(status) != syscall_trap_sig) {
269976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
270076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
270176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
270276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
270376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
270476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
270576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2706732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
270776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
270876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
270976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
271076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
271176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2712e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
271376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
2714c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin				siginfo_t si;
2715c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
27166b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
27176b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
27187b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2719932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2720932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
27217b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
27226b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
27237b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
27246b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
27256b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	pc
27266b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
27276b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	"%s"
27286b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	""
27297b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
273076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
27316b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
27326b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- ");
27336b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
27346b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf(" (%s)" PC_FORMAT_STR " ---",
27356b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
27366b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
27376b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
27386b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- %s by %s" PC_FORMAT_STR " ---",
27396b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
27406b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						signame(WSTOPSIG(status)),
27416b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
2742ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
274376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
27440569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
27450569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
274676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2747e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2748e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2749e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
275076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2751e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
275276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
275376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2754732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
275576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
275676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
275776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
275876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
275976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
276076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
276102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
276202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
276302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2764eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2765eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2766eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2767eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2768eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * all processes in thread group. In this case, threads
2769eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * "disappear" in an unpredictable moment without any
2770eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * notification to strace via wait().
2771ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2772ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2773eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (tcp_last) {
2774eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2775eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 * Finish the line then. We cannot
2776eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2777eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp_last->flags |= TCB_REPRINT;
2778eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tprintf(" <unfinished ...>");
2779eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					printtrailer();
2780eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
278176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2782ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2783eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				ptrace(PTRACE_KILL,
2784eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp->pid, (char *) 1, SIGTERM);
278576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
278676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
278776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
278876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
278976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2790e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2791e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2792e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2793e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2794e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2795e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2796e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
279776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
279876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2799732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
280076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
280176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
280276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
280376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
280476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
280576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
280676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
280776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
280876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
280976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
281076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2811ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2812ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
2813732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
281476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
281576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
281676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
281776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
281876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
281976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
282076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2821bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
282276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
282376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
282476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
282576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
282676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
282776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
282876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
282976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2830e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab	va_start(args, fmt);
2831b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2832b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2833ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		if (n < 0) {
2834ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			if (outf != stderr)
2835ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				perror(outfname == NULL
2836ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				       ? "<writing to pipe>" : outfname);
2837ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		} else
2838b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2839b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
284076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
284176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
284276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
284376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
284476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
28451201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintleader(struct tcb *tcp)
284676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2847732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2848eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tcp_last->ptrace_errno) {
2849732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
2850e62df004ce7a649c014fc0b5af058d56bc168920Denys Vlasenko				tprintf(" <unavailable>) ");
2851eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tabto(acolumn);
2852732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2853eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf("= ? <unavailable>\n");
2854eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp_last->ptrace_errno = 0;
2855732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
28567e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2857eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf(" <unfinished ...>\n");
2858732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
285976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
286076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
286176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
286276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
286376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
286476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
286576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
286676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
286776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
286876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
286976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
287076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
287176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
287276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
287376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
287476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
287576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
287676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
287776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
287876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
287976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
288076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
288176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
288276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
288376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
288476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
288576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
288676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
288776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
288876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
288976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
289076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
289176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
289276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
289376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
289476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
289576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
289676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
28971201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotabto(int col)
289876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
289976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
290076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
290176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
290276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
290376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2904ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
290576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
290676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
290776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
290876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
29099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2910ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
29119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2912ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2913ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2914ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
29159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
29169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2917553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
29189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
29199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
29209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
29219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
29229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
29239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
29249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2925553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2926ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
29279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
29289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
29299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2930