strace.c revision 04f8b4860f12512186481ca21dbd311d9d612326
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>
5244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# if defined __NR_tkill
5344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#  define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else
55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath   /* kill() may choose arbitrarily the target task of the process group
56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      while we later wait on a that specific TID.  PID process waits become
57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      TID task specific waits for a process under ptrace(2).  */
58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
5944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#  define my_tkill(tid, sig) kill((tid), (sig))
60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif
61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif
62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath
637b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
67bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
68bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
7176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
7276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
73ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
741d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
7776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
781d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
7996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
80418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
81418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
8296d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
8376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8441c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0;
85f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0;
863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */
8775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP;
88e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0;
89e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE;
90b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1088a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
1098a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint show_fd_path = 0;
1108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
1128a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint tracing_paths = 0;
1138a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
114a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
115a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
11675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
117eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
118b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
119ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid;
120ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid;
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
124b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
125ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic FILE *outf;
126ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
127ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab;
1282b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize;
129ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const char *progname;
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
131e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int detach(struct tcb *tcp, int sig);
132e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
133e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
134e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
143bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd);
146e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig);
147e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void);
148ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
152e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void);
153e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd);
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
171bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
174cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval)
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
1778a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsusage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
178de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
1798a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards              [-P path] [command [arg ...]]\n\
180b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab   or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
181de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
183b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
1928a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
199ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
203de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
204de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
2058a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
206de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
20717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
208de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
209de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
21475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
21575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
21675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
21775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
21875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
21975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
22075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
22175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
22275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
22375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2243454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
22544d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(NULL);
22644d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fprintf(stderr, "%s: ", progname);
22744d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	vfprintf(stderr, fmt, p);
22844d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	if (err_no)
22944d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin		fprintf(stderr, ": %s\n", strerror(err_no));
23044d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	else
23144d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin		putc('\n', stderr);
23244d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(stderr);
23375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
23475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
23575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
23675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
23775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
23875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
23975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
24175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
24375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
24475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
24575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
24675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
24775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
24875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
24975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
25175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
25275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
25575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
25675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
25775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
25975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...)
26075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
26175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
26275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
26375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
26475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
2653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
2663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
26776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
26876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
26976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
27076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
27176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
27276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
27476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
27576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
276c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
277c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
278c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
279c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
280c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
281c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
282c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
283c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
2841f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void
28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
2871f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	int flags, newflags;
2881f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko
2891f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	flags = fcntl(fd, F_GETFD);
2901f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	if (flags < 0) {
2911f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		/* Can happen only if fd is bad.
2921f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * Should never happen: if it does, we have a bug
2931f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * in the caller. Therefore we just abort
2941f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * instead of propagating the error.
2951f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 */
2961f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
3011f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		return;
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3031f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	fcntl(fd, F_SETFD, newflags); /* never fails */
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3167b609d5ba0852e6c56ba311350ebd4412361777bDenys Vlasenko	if (euid != uid && setreuid(euid, uid) < 0) {
317cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("setreuid");
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3224bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
3234bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
3244bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
3254bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
3264bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
3274bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
3293d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostrace_fopen(const char *path)
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
3343d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	fp = fopen_for_output(path, "w");
3353d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	if (!fp)
3363d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		perror_msg_and_die("Can't fopen '%s'", path);
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
3383d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	set_cloexec_flag(fileno(fp));
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3427dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenkostatic int popen_pid = 0;
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
3567dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	FILE *fp;
3577dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	int fds[2];
35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
3617dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("pipe");
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3637dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	set_cloexec_flag(fds[1]); /* never fails */
36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3657dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	popen_pid = vfork();
3667dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == -1)
3677dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("vfork");
36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3697dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == 0) {
37010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
37110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
3727dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		if (fds[0] != 0) {
3737dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (dup2(fds[0], 0))
3747dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				perror_msg_and_die("dup2");
3757dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			close(fds[0]);
37610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
37710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
3787dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
37910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
3807dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko
3817dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	/* parent */
3827dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	close(fds[0]);
3837dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	swap_uid();
3847dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	fp = fdopen(fds[1], "w");
3857dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (!fp)
3867dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		error_msg_and_die("Out of memory");
3877dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	return fp;
38810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
38910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3903d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostatic void
39110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
39210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
39310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
3947a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
3957a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
3963d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		tcp->outf = strace_fopen(name);
39710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
39810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
39910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
40002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
40102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
40202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
410b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	 * We rely on cleanup() from this point on.
41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
415ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
416ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
417ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
418ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(1);
419ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
420ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
421ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
42275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
42375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
42475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
425ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
426ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
427ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
428ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
429ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
43075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
43175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
43275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
433ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
434ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
43744f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko
43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
44144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko		if (tcp->flags & TCB_ATTACH_DONE)
44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
4463d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		newoutf(tcp);
44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
456ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
4577a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
46002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
4677a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
46802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
473f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
475f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						if (debug)
476f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d failed\n", tid);
477f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					}
478f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					else {
479f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						if (debug)
480f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d succeeded\n", tid);
48144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						if (tid != tcp->pid) {
48244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko							struct tcb *new_tcp = alloctcb(tid);
48344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko							new_tcp->flags |= TCB_ATTACHED|TCB_ATTACH_DONE;
484f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						}
48502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
486aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (interactive) {
487aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_SETMASK, &empty_set, NULL);
488aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						if (interrupted)
48944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko							goto ret;
490aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
491aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					}
49202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
49302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
4947a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
4957a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
5017a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
5027a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
5037a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
50444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						tcp->pid, ntid);
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
5077a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
5087a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
50944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# endif /* LINUX */
51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
515f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko		if (debug)
516f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko			fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
517ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
518ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
519ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
520ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
521ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
522ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
523ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
524ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
525ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
526ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
527ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
528ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
529ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
530ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
536f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko	} /* for each tcbtab[] */
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
53844f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko ret:
53944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#ifdef LINUX
54044f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	/* TCB_ATTACH_DONE flag is used only in this function */
54144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
54244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko		tcp = tcbtab[tcbi];
54344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko		tcp->flags &= ~TCB_ATTACH_DONE;
54444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	}
54544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#endif
54644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
5521201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
564cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
57830145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
612cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
614a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
615ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
616cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
617ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
61875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
61975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
620ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
621ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
623b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (outf != stderr) close(fileno(outf));
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
634ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		kill(pid, SIGSTOP); /* stop HERE */
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
637b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (outf != stderr)
638b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			close(fileno(outf));
63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
640ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
641ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
642cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
643ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
644ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
645ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
64602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
64702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
64802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
64902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
65002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
65102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
65202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
65302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
65402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
65502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
65602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
65702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
65802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
66002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
66102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
66202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
663cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					perror_msg_and_die("initgroups");
66402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
66502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
666cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					perror_msg_and_die("setregid");
66702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
669cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					perror_msg_and_die("setreuid");
67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
67102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
67402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
67502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
678ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Induce an immediate stop so that the parent
679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * this execve call normally.
681c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * Unless of course we're on a no-MMU system where
682c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * we vfork()-ed, so we cannot stop the child.
683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
684c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
685c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger				kill(getpid(), SIGSTOP);
686ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
687ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
688ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
689ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
690ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
691ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
692ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
693ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
694ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
695ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
696ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
697ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
698ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
699ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
700ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
701ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
702ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
70302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
70402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
70502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
706cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("exec");
70702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
708ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
709ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
71075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	/* With -D, we are *child* here, IOW: different pid. Fetch it. */
71175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
71275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
713ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
714ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
715ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
716ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
717ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
71802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
719ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
720cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("trouble opening proc file");
72102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
722ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
72302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
72402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
725b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX
72604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void kill_save_errno(pid_t pid, int sig)
72704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin{
72804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	int saved_errno = errno;
72904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin
73004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	(void) kill(pid, sig);
73104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	errno = saved_errno;
73204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin}
73304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin
734b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
735b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
736b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
737b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
738b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
73904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void
7403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
741b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
7422fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
7432fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
7442fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
7452fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
746b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
747b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	if ((pid = fork()) < 0)
74804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		perror_msg_and_die("fork");
749b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	else if (pid == 0) {
75004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		pid = getpid();
75104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
75204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
75304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
75404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		kill(pid, SIGSTOP);
75504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (fork() < 0)
75604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("fork");
75704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		_exit(0);
758b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
759b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
760b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
761b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
762b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
76304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		errno = 0;
764b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
76504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (tracee_pid <= 0) {
766b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
767b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
768b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			else if (errno == ECHILD)
769b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
77004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
77104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
77204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
77304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
77404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFEXITED(status)) {
77504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (WEXITSTATUS(status)) {
77604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (tracee_pid != pid)
77704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					kill_save_errno(pid, SIGKILL);
77804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				error_msg_and_die("%s: unexpected exit status %u",
77904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin						  __func__, WEXITSTATUS(status));
78004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
78104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
78204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
78304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
78404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
78504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
78604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
78704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
78804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
78904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (!WIFSTOPPED(status)) {
79004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
79104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
79204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill(pid, SIGKILL);
79304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
79404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
795b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
796b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
7972fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
79804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
79904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
80004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
80104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg_and_die("PTRACE_CONT doesn't work");
80204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
80304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
804b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
80504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		switch (WSTOPSIG(status)) {
80604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGSTOP:
80704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
80804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
80904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
81004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
81104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGTRAP:
81204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (status >> 16 == PTRACE_EVENT_FORK) {
81304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				long msg = 0;
8142fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
81504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (ptrace(PTRACE_GETEVENTMSG, pid,
81604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   NULL, (long) &msg) == 0)
81704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					expected_grandchild = msg;
818b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
81904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
82004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
82104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
82204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
82304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
824b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
825b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
82604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild) {
827f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
82804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (debug)
82904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			fprintf(stderr, "ptrace_setoptions = %#x\n",
83004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				ptrace_setoptions);
83104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		return;
83204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	}
83304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACECLONE failed, "
83404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
835b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
8363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
8383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
8393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
8403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
8413454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
8423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
8433454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
8443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
8453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
8463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
8473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
8483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
8493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
8503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
8513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
8523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
8533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
85404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
85504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  PTRACE_O_TRACEEXEC;
8563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
8573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
8583454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
8603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
86175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
8623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
8643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
8653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
86675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
86704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
86804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
8693454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
8703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
8713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
8723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
8743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
8753454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8763454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
8773454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
8783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
8793454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
8803454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
88104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
88204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
88304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
88475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
88575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
88675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
88775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
88804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected exit status %u",
88904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WEXITSTATUS(status));
89004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
89104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
89204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
89304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
8943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
8953454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
8963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
89704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
89804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
8993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9003454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
9013454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
9023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
9033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
9043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
9053454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
9063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
90704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
90804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
90904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
9103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9113454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
9123454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
9133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
91504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
91675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
9173454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9203454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
92175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
922f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
9233454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
924f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
925f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
9263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
9273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
92904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
93004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
9313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
932b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif
933b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
93508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
93906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
94208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
94308b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
94475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
94575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
946ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
947ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
9484f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
949cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (tcbtab == NULL)
950cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("Out of memory");
9514f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
9524f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	if (tcp == NULL)
953cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("Out of memory");
9544f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
9554f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
956ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
959138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
960138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
9668a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"+cCdfFhiqrtTvVxyz"
967ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
968ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
969ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
9708a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"a:e:o:O:p:s:S:u:E:P:")) != EOF) {
97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
973e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
974cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
975e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
976e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
977e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
978e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
979e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
980cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
981e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
982e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
987ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
988ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
989ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
990ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
991ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
99241c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
99306350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
99406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10208a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
10218a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
10228a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
10279c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
103117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
103217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
1046de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
1047cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("Invalid process id: '%s'", optarg);
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
105075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (pid == strace_tracer_pid) {
1051cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("I'm sorry, I can't let you do that, Dave.");
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1054418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10588a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
10598a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
10608a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1061cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
10628a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
10638a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1066dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1067cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Invalid -s argument: '%s'", optarg);
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) {
1078cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Out of memory");
1079de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
1080de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1087d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
1088ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1089ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1090d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	if (pflag_seen && daemonized_tracer) {
1091cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive options");
1092d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1093d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
109406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
109506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
109606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1097cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1098cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
1099cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1100cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1106cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
1109cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11198044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX
112004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (followfork)
112104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		test_ptrace_setoptions_followfork();
11223454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
11238044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif
11248044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
112737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
112837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
112937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
113037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
113137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
113237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
11337dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (followfork > 1)
11347dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
11357dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			outf = strace_popen(outfname + 1);
113654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
11373d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		else if (followfork <= 1)
11383d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko			outf = strace_fopen(outfname);
113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1141cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1142cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		static char buf[BUFSIZ];
114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
1144cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
114537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1148369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1149b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
115054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
115154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
115254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
115354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
115454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
115554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
115654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
115754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
115854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
115954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
116054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
116154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
116254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
116354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
116476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
116776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
117276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
1189bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
1192553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1193553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1194553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1195553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1196553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1197553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1198553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1199553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
1200bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1202ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
120302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
120402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
1208a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
1209a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
1210a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
1211a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
1212a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
1213a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
1214a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
1215a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
1216a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
1217a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
1218a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12212b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic void
1222418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
12237b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
12247b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
12257b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
12267b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
12277b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
12287b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
122918da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	int i = tcbtabsize;
123018da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
123118da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
123218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	if (newtab == NULL || newtcbs == NULL)
123318da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		error_msg_and_die("expand_tcbtab: out of memory");
12347b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
12357b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
123618da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	while (i < tcbtabsize)
123718da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		tcbtab[i++] = newtcbs++;
12387b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
12397b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
124110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1246418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1247418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1248418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1249ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1250ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
125218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko			memset(tcp, 0, sizeof(*tcp));
125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
12581d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (debug)
12591d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
126010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
126110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
126476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
126518da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	error_msg_and_die("bug in alloc_tcb");
126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1268bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1270418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
127376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1274bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
127519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
127619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1279bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
128176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1284ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
12859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
12869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
12879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
12889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
12899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
12909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
12911f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
12929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
12939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
12949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
12959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
12969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
12971f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_stat);
12989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
12999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
13009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13031f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_as);
13049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1306bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
1308372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR|O_EXCL);
1309bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1310bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1311372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR);
1312bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
1313372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	if (tcp->pfd < 0) {
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
13171f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
13189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1319bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1320bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1321bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1322bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1323bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1324bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1325bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1326bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1327bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1328bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1329bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1330bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1331bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1332bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1333bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
134076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
1341b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_STATUS(tcp) < 0) {
134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
13459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1346cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				break;
134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1349bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
135116a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1355553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
13599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
13659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1370553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
137776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
137876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1379bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1380bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1381bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1382bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
13835ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1384bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1385bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1386bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
13875ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
13885ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1389bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1390bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1392bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
139319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
139419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
139519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
139619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
1397b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
139819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
1399b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	praddset(&syscalls, SYS_execve);
140019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
1401b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork);
140219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
1403b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_forkall);
140419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1405553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
1406b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork1);
140719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
140819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
1409b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rfork1);
141019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
141119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
1412b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rforkall);
141319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
141419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
141519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
141919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
142019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
142419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
142519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
142619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
142719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
1428b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
142919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
14309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
143419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
143519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
143619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
143719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
1438b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
143919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
14409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1444bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1445bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1446b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	arg = S_SIG | S_SCE | S_SCX;
1447b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1448bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1449bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1450bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1451bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
145676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
145876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1460553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
14629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
1463b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1467553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1468bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1469bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1470bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1471bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1472553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
1475b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_WSTOP(tcp) < 0) {
147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
14799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1480bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1481bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
148276989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1486bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
14879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
14889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1489bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1490bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1491553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1495bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1496bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1497bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1498bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1499bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1500bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1501553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
150276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1503bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1505bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1506bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1507553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
15082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
15092e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
15102e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
15112e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
15122e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
15132e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
15142e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1515553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
15162e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
15172e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
15182e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
15192e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
15202e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
15212e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
15222e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
15232e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
15242e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
15252e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
15262e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
15272e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
15282e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
15292e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
15302e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
15312e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1532bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1533bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1547bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1549e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
155054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
155354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
155454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
155554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1557ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
155854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
155954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
156254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1566bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
156954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void)
157054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{
157154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	int i;
157254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	struct tcb *tcp;
157354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
157454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		tcp = tcbtab[i];
157554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->flags & TCB_INUSE)
157654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath			return tcp;
157754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	}
157854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	return NULL;
157954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath}
158054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
158154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb *
15821201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkopfd2tcb(int pfd)
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1586ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1587ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1596bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
15991201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
160319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
16051d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko	if (debug)
16061d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
1607eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1611bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1612bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1613bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1614bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1615bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1616bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1617bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1618bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1619bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1620553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1621bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
162219cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko		tcp->flags = 0; /* rebuild_pollv needs it */
162319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko		rebuild_pollv();
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1626eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1627822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1629eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
163019cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko	memset(tcp, 0, sizeof(*tcp));
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16330a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
16340a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
16350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
16360a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
16391201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodetach(struct tcb *tcp, int sig)
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1642ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
16431bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1644ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1647840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
16527bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
16537bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
16557bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
16567bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
16577bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
16587bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
165902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
166002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
166102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
166202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
166302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
166402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
16677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
16687bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
16697bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
16707bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
16717bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
167244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	else if (my_tkill(tcp->pid, 0) < 0) {
16737bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
16747bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
16757bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
167644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
16777bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
16787bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
16797bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
168002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
168102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1682ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
16847508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
16857508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
16867508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
16877508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16887508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
16907508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16917508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16927508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
16937508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
16947508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
16957508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
16967508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
16977508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16987508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16997508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
17007508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
17017508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
17027508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
17037508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
17047508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
17057508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
17067508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
17077508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
17087508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
17097508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
17117508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1717732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1720732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
172175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1722732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1723732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1726ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
17277bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1734732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1741a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1745bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1747e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig)
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1756bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17591201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1764ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1765ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1773ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			tprintf(" <unfinished ...>");
1774ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17881201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17956d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
17986d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
18011201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no)
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180535aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
180635aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180935aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	return sys_errlist[err_no];
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18168f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
18176d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
18198f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
18208f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
18218f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
18241201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig)
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1841bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18441201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkorebuild_pollv(void)
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1848ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1849b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		free(pollv);
1850c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1851ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
1852cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("Out of memory");
1853ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1854ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1855ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1856ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
18609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
1864cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("proc miscount");
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18711201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll_open(void)
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
1876cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("pipe");
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
18791f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		set_cloexec_flag(proc_poll_pipe[i]);
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
18841201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll(struct pollfd *pollv, int nfds, int timeout)
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
1893cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("panic: short read: %d", n);
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19061201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkowakeup_handler(int sig)
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19111201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poller(int pfd)
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1919bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1920bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1921bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
1925cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1948cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1959bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
19605ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
19615ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
19625ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
19635ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
19649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
19979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
2014cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("lost proc");
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2024cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	error_msg_and_die("nothing ready");
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
20281201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
20309dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
2031d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
20329dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
20379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
205154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath				tcp = first_used_tcb();
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
20649dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
20659dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
20669dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
20679dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2068553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
20699dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
20709dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
20719dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
20729dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
20739dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
20749dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
2075b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				if ((what = poll(&pv, 1, 1)) < 0) {
20769dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
20779dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
20789dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
20799dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20809dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
20819dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
20829dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20839dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
20849dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
20859dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
2106cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("unknown pfd: %u", pfd);
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2108b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
21099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2110b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2113bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
2114b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			ioctl_result = IOCTL_WSTOP(tcp);
2115bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2118bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2119bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2120b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_STATUS(tcp);
2121bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
2122b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_WSTOP(tcp);
2123553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2146bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2148553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
2153cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("PIOCWSTOP");
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21572e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
21582e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
21592e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
2160b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			IOCTL(tcp->pfd, PIOCRUN, 0);
21612e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
21622e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2163553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2164553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
2170ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2174bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2175bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2176bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2177bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2178bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2179bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2180bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2181bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2182bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2183bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2184bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2185553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2188bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
21939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2194bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
21969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
21979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
2199cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					error_msg_and_die("syscall trouble");
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2203bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
22059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
22069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
22079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
2210cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("syscall trouble");
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
2214e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2215e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_SIGNAL)) {
221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2218ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2219ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
22205826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
22215826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
22225826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
22235826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
22245826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2225ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
22265826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
22275826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
2231e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAGS_ONLY_STATS
2232e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_FAULT)) {
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2235ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2238bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2239bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
22405ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2241553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
2243cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2246ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2247ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
22489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2249553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
2250b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
2251553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2252b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
2253553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2254372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		{
2255cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("PIOCRUN");
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2261bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2263eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
2264eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace()
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
226876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
227226d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko	struct rusage *rup = cflag ? &ru : NULL;
227326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
2274eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
227526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif
227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2278eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2279222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2280eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2281eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2282eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
228426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
228526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, wait4_options, rup);
22865bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
22872f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
22882f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
228926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, wait4_options, rup);
22902f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
22915bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
22922f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
229326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, __WCLONE, rup);
229426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			if (pid < 0) {
2295cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
22962f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
22972f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
229826d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# else
229926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, 0, rup);
230026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif /* __WALL */
230176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
230276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
230376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
230426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko#endif
230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2306eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2307eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
230926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		if (pid < 0) {
2310eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2311eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2313eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
2320eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2321eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2322eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2323eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2324eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
232710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
232810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
23297dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
233010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
233110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
23321d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		if (debug) {
23331d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
23341d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef LINUX
23351d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			unsigned ev = (unsigned)status >> 16;
23361d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (ev) {
23371d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				static const char *const event_names[] = {
23381d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_CLONE] = "CLONE",
23391d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_FORK]  = "FORK",
23401d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK] = "VFORK",
23411d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
23421d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXEC]  = "EXEC",
23431d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXIT]  = "EXIT",
23441d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				};
23451d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				const char *e;
23461d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				if (ev < ARRAY_SIZE(event_names))
23471d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					e = event_names[ev];
23481d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				else {
23491d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					sprintf(buf, "?? (%u)", ev);
23501d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					e = buf;
23511d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				}
23521d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, " PTRACE_EVENT_%s", e);
23531d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			}
23541d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
23551d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			strcpy(buf, "???");
23561d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSIGNALED(status))
23571d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP
23581d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,%ssig=%s",
23591d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						WCOREDUMP(status) ? "core," : "",
23601d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
23611d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else
23621d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,sig=%s",
23631d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
23641d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
23651d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFEXITED(status))
23661d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
23671d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSTOPPED(status))
23681d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
23695bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED
23701d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFCONTINUED(status))
23711d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				strcpy(buf, "WIFCONTINUED");
23725bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif
23731d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
23741d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		}
237576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2378e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
237941c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2380e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2381e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2382e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2383e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2384e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2385e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2386e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2387e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2388e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2389418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2390833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko				tcp->flags |= TCB_ATTACHED;
2391e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2392833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko					fprintf(stderr, "Process %d attached\n",
2393e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
23948b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2395e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2396e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2397e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2398eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2399e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2400e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2401e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2402cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
2403e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
240476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2405eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2406eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
2407ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
2408eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
240913d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko		if (cflag) {
241076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
241176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
241276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
241313d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#endif
2414eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
241576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2416a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2417a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2418e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
241976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
242076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
242113d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP
24222efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
24232efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
242413d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					WCOREDUMP(status) ? "(core dumped) " : "");
242513d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else
242613d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko				tprintf("+++ killed by %s +++",
242713d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					signame(WTERMSIG(status)));
24282efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
2429ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
243076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
243176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
243276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
243376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
243476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2435a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2436a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
24370a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
24387a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
24390a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
24400a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
24410a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
24420a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
244319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
244419cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printleader(tcp);
244519cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				tprintf("+++ exited with %d +++", WEXITSTATUS(status));
244619cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printtrailer();
244719cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			}
244876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
245076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
245176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
245476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
245576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
245676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
24573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (status >> 16) {
2458833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko			/* Ptrace event (we ignore all of them for now) */
2459833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko			goto tracing;
2460ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao		}
2461ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao
246202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
246302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
246402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
2465eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		 * than SIGSTOP if we happend to attach
246602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
2467c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * A no-MMU vforked child won't send up a signal,
2468c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * so skip the first (lost) execve notification.
246902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
2470c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		if ((tcp->flags & TCB_STARTUP) &&
2471c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		    (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
247276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
247476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
247576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
247802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
248002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
248102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
248476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
248576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
248676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
248776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
248876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2489ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
249044f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko			if (ptrace_setoptions) {
249144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (debug)
249244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
249344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
249444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					if (errno != ESRCH) {
249544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						/* Should never happen, really */
249644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						perror_msg_and_die("PTRACE_SETOPTIONS");
24973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
24983454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
24993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2500ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
250176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
250276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
250376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
250475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WSTOPSIG(status) != syscall_trap_sig) {
250576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
250676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
250776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
250876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
251076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
251176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2512732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
251376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
251476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
251576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
251676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
251776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2518e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
251976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
2520c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin				siginfo_t si;
2521c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
25226b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
25236b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
25247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2525932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2526932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
25277b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
25286b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
25297b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
25306b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
25316b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	pc
25326b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
25336b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	"%s"
25346b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_ARG	""
25357b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
253676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
25376b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
25386b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- ");
25396b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
25406b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf(" (%s)" PC_FORMAT_STR " ---",
25416b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
25426b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
25436b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
25446b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- %s by %s" PC_FORMAT_STR " ---",
25456b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						strsignal(WSTOPSIG(status)),
25466b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						signame(WSTOPSIG(status)),
25476b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
2548ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
254976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2550732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
255176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
255276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
255376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
255476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
255576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
255602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
255702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
255802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2559eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2560eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2561eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2562eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2563eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * all processes in thread group. In this case, threads
2564eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * "disappear" in an unpredictable moment without any
2565eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * notification to strace via wait().
2566ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2567ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2568eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (tcp_last) {
2569eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2570178de007d14f3ae890117b540def9cf14bcb61feDenys Vlasenko					 * Finish the line then.
2571eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2572eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp_last->flags |= TCB_REPRINT;
2573eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tprintf(" <unfinished ...>");
2574eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					printtrailer();
2575eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
257676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2577ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2578eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				ptrace(PTRACE_KILL,
2579eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp->pid, (char *) 1, SIGTERM);
258076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
258176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
258276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
258376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
258476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2585ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2586ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
2587732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
258876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
258976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
259076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
259176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
259276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
259376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
259476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2595bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
259676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
259776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
259876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
259976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
260076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
260176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2602e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab	va_start(args, fmt);
2603b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2604b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2605ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		if (n < 0) {
2606ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			if (outf != stderr)
2607ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				perror(outfname == NULL
2608ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				       ? "<writing to pipe>" : outfname);
2609ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		} else
2610b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2611b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
261476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
261576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
261676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
26171201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintleader(struct tcb *tcp)
261876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2619732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2620eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tcp_last->ptrace_errno) {
2621732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
2622e62df004ce7a649c014fc0b5af058d56bc168920Denys Vlasenko				tprintf(" <unavailable>) ");
2623eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tabto(acolumn);
2624732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2625eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf("= ? <unavailable>\n");
2626eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp_last->ptrace_errno = 0;
2627732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
26287e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2629eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf(" <unfinished ...>\n");
2630732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
263176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
263276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
263376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
263476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
263576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
263676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
263776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
263876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
263976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
264076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
264176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
264276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
264376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
264476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
264576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
264676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
264776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
264876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
264976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
265076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
265176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
265276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
265376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
265476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
265576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
265776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
265876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
265976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
266076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
266176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
266276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
266376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
266476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
266576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
266676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
266776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
266876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
26691201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotabto(int col)
267076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
267176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
267276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
267376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
267476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
267576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2676ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
267776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
268076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
26819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2682ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
26839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2684ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2685ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2686ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
26879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
26889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2689553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
26909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
26919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
26929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
26939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
26949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
26959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
26969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2697553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2698ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
26999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
27009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
27019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2702