strace.c revision 84e20af5a6f3d6e02c24579b60a282053ef01e0e
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>
3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
437e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko#include <sys/utsname.h>
4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h>
4719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h>
4870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
4976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX
51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h>
52134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# if defined __NR_tgkill
53134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# elif defined __NR_tkill
55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else
57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath   /* kill() may choose arbitrarily the target task of the process group
58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      while we later wait on a that specific TID.  PID process waits become
59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      TID task specific waits for a process under ptrace(2).  */
60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) kill ((tid), (sig))
62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif
63134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif
64134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath
657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
687b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
71bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
72bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
7476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
75ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
761d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
7976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
801d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
8196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
82418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
83418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
8496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
8576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8641c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0;
87b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinint dtime = 0, cflag = 0, xflag = 0, qflag = 0;
88b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
89ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
90ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1037e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenkostatic struct utsname utsname_buf;
1047e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko
10517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
108a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
109a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
11096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkostatic int ptrace_stop_sig = SIGTRAP;
11196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkostatic bool ptrace_opts_set;
112a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin
113b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
119b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
121ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
122ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname;
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1250a463880341945df08b6dc79134dc78cc38dc283Roland McGrathstatic int detach P((struct tcb *tcp, int sig));
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void));
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void));
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig));
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted;
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
141bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd));
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig));
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void));
146ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void));
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd));
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
169bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
178de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
179de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
180ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko   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\
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
197ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
201de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
202de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
203de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
20417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
205de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
206de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
22010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
22110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
22210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     flags, newflags;
22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return 0;
23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fcntl(fd, F_SETFD, newflags) < 0)
23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
23910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
24010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
24110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
24210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
24310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
24410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
25110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (euid != uid && setreuid(euid, uid) < 0)
25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: setreuid: %s\n",
25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
25910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		exit(1);
26010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
26110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
26210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
26310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
2644bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
2654bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
2664bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
2674bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
2684bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
2694bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
27010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
27110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode)
27210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
27310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
2764bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath	if ((fp = fopen_for_output(path, mode)) == NULL)
27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: can't fopen '%s': %s\n",
27810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, path, strerror(errno));
27910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
28010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fp && set_cloexec_flag(fileno(fp)) < 0)
28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fclose(fp);
28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fp = NULL;
28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1;
28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     fds[2];
30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: pipe: %s\n",
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(fds[1]) < 0)
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((popen_pid = fork()) == -1)
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fork: %s\n",
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (popen_pid)
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* parent */
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return fdopen(fds[1], "w");
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	} else
33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		{
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			fprintf(stderr, "%s: dup2: %s\n",
34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				progname, strerror(errno));
34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			_exit(1);
34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: execl: %s: %s\n",
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, _PATH_BSHELL, strerror(errno));
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		_exit(1);
35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
3587a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		FILE *fp;
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3617a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if ((fp = strace_fopen(name, "w")) == NULL)
36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			return -1;
36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		tcp->outf = fp;
36510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
36610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
36710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
37002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
37102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
37202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
37902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * We rely on cleanup () from this point on.
38002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
38102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
38202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
38302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
384ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
385ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
386ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
387ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(1);
388ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
389ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
390ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
391ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for child to attach to straced process
392ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * (our parent). Child SIGKILLs us after it attached.
393ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Parent's wait() is unblocked by our death,
394ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
395ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
396ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
397ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
398ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
399ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
400ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
40102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
40202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (newoutf(tcp) < 0)
41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
41802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
41902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
422ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
4237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
42402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
42502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
42602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
42702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
4337a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
43702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
4397a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					else if (tid != tcbtab[tcbi]->pid) {
442418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko						tcp = alloctcb(tid);
44384e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED;
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nchildren++;
44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_threads++;
44602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_detached++;
44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->parent = tcbtab[tcbi];
44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (interactive) {
45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						sigprocmask(SIG_SETMASK, &empty_set, NULL);
45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						if (interrupted)
45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							return;
45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
45602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
4577a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
4587a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
46002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
4647a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
4657a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
4667a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
4677a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko						tcbtab[tcbi]->pid, ntid);
46802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
4707a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
4717a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif
47302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* INTERRUPTED is going to be checked at the top of TRACE.  */
479ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
480ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
481ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
482ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
483ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
484ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
485ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
486ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
487ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
488ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
489ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
490ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
491ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
492ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
49302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
49402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
49502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_child (char **argv)
50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("strace: exec");
51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
52102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		char *path;
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		fprintf(stderr, "%s: %s: command not found\n",
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			progname, filename);
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
570a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
571ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: fork");
57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		cleanup();
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
575ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
576ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
577ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
578ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
579ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf != stderr) close (fileno (outf));
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
592ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		kill(pid, SIGSTOP); /* stop HERE */
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf!=stderr)
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			close(fileno (outf));
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
598ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
599ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
600ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				perror("strace: ptrace(PTRACE_TRACEME, ...)");
601ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				exit(1);
602ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
603ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
604ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("initgroups");
62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setregid");
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setreuid");
63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
638ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
639ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
640ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Induce an immediate stop so that the parent
641ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
642ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * this execve call normally.
643ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
644ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getpid(), SIGSTOP);
645ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
646ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
647ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
649ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
650ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
651ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
652ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
653ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
654ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
655ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
656ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
657ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
658ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
659ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
660ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
661ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
66202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
66302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
66402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
66502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: exec");
66602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		_exit(1);
66702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
668ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
669ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
670ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
671ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
672ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
673ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
674ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
67502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		fprintf(stderr, "trouble opening proc file\n");
678ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		cleanup();
679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		exit(1);
68002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
681ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
68202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
68302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
68508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
68906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
69408b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
69508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
6967e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko	uname(&utsname_buf);
6977e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko
698ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
699ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
700418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
70108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
70208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
70308b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
704418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
70508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
70608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
70708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
708ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
709ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
710ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
71176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
713138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
714138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
71776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
720ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"+cdfFhiqrtTvVxz"
721ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
722ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
723ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
724ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"a:e:o:O:p:s:S:u:E:")) != EOF) {
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cflag++;
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
733ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
734ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* Experimental, not documented in manpage yet. */
735ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
736ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
737ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
738ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
73941c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
74006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
74106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
7719c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
77517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
77617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
790de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pid == getpid()) {
79654a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
79876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
799418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
80176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
80276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
805dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
806dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				fprintf(stderr,
807dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					"%s: invalid -s argument: %s\n",
808dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					progname, optarg);
809dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				exit(1);
810dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
81176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
81476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
81676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
818de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
819de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
820de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
821de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
822de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
823de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
824de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
82576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
831d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
832ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
833ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
83406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
83506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
83606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
837cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
838cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		fprintf(stderr,
839cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			"%s: -c and -ff are mutually exclusive options\n",
840cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			progname);
841cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		exit(1);
842cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
843cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
85609553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath				progname, username);
85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
86937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
87037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
87137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
87237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
87337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
87437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
87537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
87637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
87737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
87837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
87937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
88037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
88137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
88210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if ((outf = strace_popen(outfname + 1)) == NULL)
88337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
88454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
88510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		else if (followfork <= 1 &&
88610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			 (outf = strace_fopen(outfname, "w")) == NULL)
88754b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
89037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
89237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
89376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
89476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
895369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
89654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
89754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
89854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
89954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
90054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
90154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
90254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
90354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
90454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
90554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
90654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
90754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
90854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
90954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
935bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
938553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
939553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
940553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
941553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
942553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
943553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
944553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
945553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
946bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
948ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
94902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
95002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
954a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
955a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
956a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
957a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
958a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
959a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
960a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
961a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
962a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
963a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
964a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
967418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkovoid
968418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
9697b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
9707b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
9717b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
9727b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
9737b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
9747b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
9757b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb **newtab = (struct tcb **)
9767b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
9777b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
9787b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    sizeof *newtcbs);
9797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	int i;
9807b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	if (newtab == NULL || newtcbs == NULL) {
98176860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
98276860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin			progname);
983418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		cleanup();
984418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		exit(1);
9857b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
9867b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
9877b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
9887b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
9897b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
9907b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
9917b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
99310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
998418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
999418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1000418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1001ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1002ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
10047e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			memset(tcp, 0, sizeof(*tcp));
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
101010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
101110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1015418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1016418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	cleanup();
1017418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	exit(1);
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1020bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1022418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1026bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
102719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
102819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1031bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1036ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
10379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
10389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
10399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
10409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
104310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
10449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
10479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
10489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
105110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_stat) < 0) {
10529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
10559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
10569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
105910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_as) < 0) {
10609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
106376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1064bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
1067bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1068bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1069bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1070bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
107410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
10759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1078bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1079bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1080bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1081bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1082bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1083bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1084bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1085bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1086bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1087bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1088bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1089bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1090bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1091bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1092bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
11009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
11049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1105bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
110676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1108bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
111016a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1114553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
11189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
11249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1129553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1138bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1139bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1140bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1141bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
1142bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
1143bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1144bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1145bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1146bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCSFL");
1147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
1148bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1149bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1151bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
115219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
115319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
115419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
115519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
115619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
115719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
115819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
115919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
116019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
116119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
116219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
116319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1164553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
116519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
116619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
116719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
116819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
116919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
117019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
117119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
117219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
117319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
117419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
117819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
117919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
118319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
118419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
118519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
118619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
118719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
118819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
11899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
119319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
119419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
119519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
119619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
119719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
119819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
11999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1203bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1204bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1205bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
1206bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1207bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1208bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1209bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1210bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1219553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
12219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
12229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1226553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1227bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1228bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1229bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1230bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1231553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
123276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
12349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
12389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1239bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1240bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
124176989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1245bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
12469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
12479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1248bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1249bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1250553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1254bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1255bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1256bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1257bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1258bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1259bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1260553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1262bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1264bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1265bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1266553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
12672e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
12682e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
12692e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
12702e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
12712e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
12722e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
12732e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1274553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
12752e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
12762e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
12772e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
12782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
12792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
12802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
12812e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
12822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
12832e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
12842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
12852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
12862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
12872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
12882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
12892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
12902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1291bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1292bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1306bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1308e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid)
131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1315ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1316ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid && tcp->pid != pid)
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1325bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1333ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1334ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
134076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1343bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
134576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
134976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1351e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1352e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1353e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1354e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1355e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1356e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1357e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1358e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1359e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1360e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1363eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1364e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1365e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1366e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1367e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_DETACHED)
1368e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_detached--;
1369e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1370e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1371e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
13720962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED
13730962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath		if (!(tcp->flags & TCB_CLONE_DETACHED))
13740962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif
13750962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->parent->nzombies++;
1376276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX
1377276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		/* Update `tcp->parent->parent->nchildren' and the other fields
1378276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   like NCLONE_DETACHED, only for zombie group leader that has
1379276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   already reported and been short-circuited at the top of this
1380276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   function.  The same condition as at the top of DETACH.  */
1381276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		if ((tcp->flags & TCB_CLONE_THREAD) &&
1382276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    tcp->parent->nclone_threads == 0 &&
1383276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    (tcp->parent->flags & TCB_EXITING))
1384276ceb33f20fc41403e46684e441230296f6a433Roland McGrath			droptcb(tcp->parent);
1385276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif
1386e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1387e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1388e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1389e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
139076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1393bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1394bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1395bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1396bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1397bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1398bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1399bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1400bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1401bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1402553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1403bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1404e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1407eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1408822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1410eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1414bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1428e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1429e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1430e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1431e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1433732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14411bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int
14421bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathresume_from_tcp (struct tcb *tcp)
14431bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{
14441bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int error = 0;
14451bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int resumed = 0;
14461bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14471bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	/* XXX This won't always be quite right (but it never was).
14481bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
14491bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   a particular pgrp, which this child might or might not be
14501bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
14511bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
14521bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   difference to wake up a waiter when there might be more
14531bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   traced children, because it could get a false ECHILD
14541bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
14551bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
14561bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   search the system for all pid's in the pgrp to be sure.
14571bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14581bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	     && (t->waitpid == -1 ||
14591bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
14601bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
14611bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	*/
14621bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14631bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent &&
14641bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
14651bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
14661bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 		error = resume(tcp->parent);
14671bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		++resumed;
14681bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
14691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD
14701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
14711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Some other threads of our parent are waiting too.  */
14721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		unsigned int i;
14731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
14751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
14761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			struct tcb *t = tcbtab[i];
14771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			if (t->parent == tcp->parent && t != tcp
14781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
14791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
14801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && t->waitpid == tcp->pid) {
14811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				error |= resume (t);
14821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				++resumed;
14831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
14841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		}
14851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		if (resumed == 0)
14861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			/* Noone was waiting for this PID in particular,
14871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			   so now we might need to resume some wildcarders.  */
14881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
14891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				struct tcb *t = tcbtab[i];
14901bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				if (t->parent == tcp->parent && t != tcp
14911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && ((t->flags
14921bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
14931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
14941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && t->waitpid <= 0
14951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					) {
14961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					error |= resume (t);
14971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					break;
14981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				}
14991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
15001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
15013bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#endif
15021bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
15031bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	return error;
15041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath}
15051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
1506bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15080a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
15090a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
15100a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
15110a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1519ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
15201bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1521a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1522a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1523a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1524a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1525a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1526a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1527a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1528a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1529ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sig = SIGKILL;
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
15377bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
15387bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
15407bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
15417bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
15427bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
15437bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
154402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
154502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
154602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
154702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
154802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
154902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
15527bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
15537bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
15547bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
15557bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
15567bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1557134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1558134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1559134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
15607bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
15617bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
15627bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
156302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
156402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
156502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
15667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
15677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
15687bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
156902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
157002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1571ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
15737508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
15747508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
15757508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
15767508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
15777508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
15797508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
15807508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
15817508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
15827508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
15837508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
15847508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
15857508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
15867508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
15877508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
15887508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
15897508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
15907508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
15917508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
15927508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
15937508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
15947508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
15957508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
15967508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
15977508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
15987508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
16007508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1606732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1609732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
161096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					WSTOPSIG(status) == ptrace_stop_sig ? 0
1611732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1612732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1615ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
16167bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1623732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1626bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
16271bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	error |= resume_from_tcp (tcp);
1628e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1629e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1634a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1635a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX
16360a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	if (zombie != NULL) {
16370a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		/* TCP no longer exists therefore you must not detach () it.  */
16380a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(zombie);
16390a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	}
1640a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif
1641a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1645bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig)
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct tcb *tcp;
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pid2tcb(pid);
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp)
166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1665bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1673ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1674ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1682ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			tprintf(" <unfinished ...>");
1683ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17056d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
17086d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17278f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
17286d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
17308f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
17318f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
17328f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1753bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1760ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1761ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1762c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1763ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
176446100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "%s: out of memory\n", progname);
1765ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1766ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1767ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1768ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1769ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
17739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
179410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1842bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1843bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1844bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
1849a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
1873a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1884bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
1885bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1886bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1887bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1888bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
18899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
19229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
19579dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
1958d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
19599dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
19649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp = pid2tcb(0);
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
19919dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
19929dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
19939dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
19949dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
1995553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
19969dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
19979dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
19989dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
19999dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
20009dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
20019dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
20029dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
20039dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
20049dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
20059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
20069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
20089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
20099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20109dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
20119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
20129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2036b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
20379dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2038b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2041bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
20429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
2043bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2044bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2045bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2046bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2047bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2048bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
2049bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
2050bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			  	ioctl_result = IOCTL_WSTOP (tcp);
2051553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2074bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2075bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2076553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
20872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
20882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
20892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
20902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
20912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2092553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2093553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2102bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2103bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2104bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2105bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2106bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2107bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2108bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2109bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2110bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2111bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2112bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2113553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
21219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2122bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
21249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
21259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2132bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
21349dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
21359dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
21369dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2147ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2148ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
21495826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
21505826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
21515826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
21525826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
21535826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2154ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
21555826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
21565826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2163ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2166bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2167bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
2168bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		  	continue;
2169553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
21719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2176553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
21779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
2178553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2179bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
2180553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2188bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2190e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2191e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2192e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2193e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2194e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2195e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2196e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2197e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2198e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2199e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2200e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2201e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
22027a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	struct tcb *leader = NULL;
22037a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko
22047a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	if (tcp->flags & TCB_CLONE_THREAD)
22057a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp->parent;
22067a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	else if (tcp->nclone_detached > 0)
22077a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp;
2208e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2209e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
22107a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		if (leader != NULL && leader != tcp
22117a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(leader->flags & TCB_GROUP_EXITING)
22127a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(tcp->flags & TCB_STARTUP)
22137a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		) {
2214e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2215e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2216e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
22177a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		}
22187a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
22191bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS
22207a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		resume_from_tcp(tcp);
22211bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif
22220a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2223e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2224e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2225a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2226a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2227e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
2228d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath			detach(tcp, sig);
22291bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		  	if (leader != NULL && leader != tcp)
22301bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2231732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else {
2232732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2233732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				cleanup();
2234732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				return -1;
2235732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2236732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (leader != NULL) {
22370569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2238732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (leader != tcp)
2239732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					droptcb(tcp);
2240732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2241e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2242e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2243e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2244e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2245e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2246e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2247e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2248e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2249e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2250e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2251215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkostatic struct tcb *
2252215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkocollect_stopped_tcbs(void)
225376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
225447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko#ifdef LINUX
225547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko	static int remembered_pid;
225647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko	static int remembered_status;
225747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko#endif
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
226247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko	struct tcb *found_tcps;
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
226447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko	struct tcb **nextp;
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
2266215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	struct rusage* ru_ptr = cflag ? &ru : NULL;
2267215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	int wnohang = 0;
22682f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2269215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	int wait4_options = __WALL;
22702f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
227147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko
227247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko	if (remembered_pid > 0) {
227347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		pid = remembered_pid;
227447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		remembered_pid = 0;
227547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		if (debug)
227647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko			fprintf(stderr, " [remembered wait(%#x) = %u]\n",
227747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko						remembered_status, pid);
227847ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		tcp = pid2tcb(pid); /* can't be NULL */
227947ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		tcp->wait_status = remembered_status;
228047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		tcp->next_need_service = NULL;
228147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		return tcp;
228247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko	}
228347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko	nextp = &found_tcps;
228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
228647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko	found_tcps = NULL;
2287215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	while (1) {
228876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
22892f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2290215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
22915bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
22922f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
22932f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
22942f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
2295215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			pid = wait4(-1, &status, wait4_options | wnohang, ru_ptr);
22962f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
22975bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
22982f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
2299215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			pid = wait4(-1, &status, __WCLONE | wnohang, ru_ptr);
2300215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			if (pid < 0 && errno != ECHILD) {
2301215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko				fprintf(stderr, "strace: wait4(WCLONE) "
23022f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
23032f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
23042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
2305215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#else /* !__WALL */
2306215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		pid = wait4(-1, &status, wnohang, ru_ptr);
2307215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif
230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2316215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		if (pid == 0 && wnohang) {
2317215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			/* We had at least one successful
2318215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			 * wait() before. We waited
2319215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			 * with WNOHANG second time.
2320215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			 * Stop collecting more tracees,
2321215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			 * process what we already have.
2322215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			 */
2323215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			break;
2324215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		}
232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
23262c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko			if (wait_errno == EINTR)
232776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
23282c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko			if (wait_errno == ECHILD) {
232976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
233076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
233176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
233276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
233376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
233476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
233576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
23362c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko				if (nprocs != 0) {
23372c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko					fprintf(stderr, "strace: proc miscount\n");
23382c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko					exit(1);
23392c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko				}
234076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
23412c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko				break;
234276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
23432c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko			errno = wait_errno;
23442c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko			perror("strace: wait");
23452c8a2583612f4df2a93cb8d180aadda4e93ec1ddDenys Vlasenko			exit(1);
234676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
234710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
234810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
234910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				popen_pid = -1;
235010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
235110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
235376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
235476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
235547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		/* RHEL5 bug workaround.
235647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 * It can re-report stopped tasks. Happens on SIGSTOPs here.
235747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 * Second (bogus) report has signal# set to 0.
235847ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 * Stop collecting and process what we have.
235947ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 */
236047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		if (WIFSTOPPED(status) && WSTOPSIG(status) == 0)
236147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko			break;
236247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko
236376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
236476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2365e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
236641c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2367e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2368e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2369e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2370e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2371e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2372e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2373e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2374e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2375e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2376418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2377e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2378e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2379e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2380e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2381e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
23828b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2383e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2384e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2385e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2386215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif /* LINUX */
2387e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2388e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2389e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2390e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2391e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2392e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
239376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2394215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
239576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
239684e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko		if (cflag) {
239776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
239876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
239976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
240084e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko#endif
2401f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		if (tcp->flags & TCB_SUSPENDED) {
2402f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			/*
2403f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Apparently, doing any ptrace() call on a stopped
2404f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process, provokes the kernel to report the process
2405f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * status again on a subsequent wait(), even if the
2406f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process has not been actually restarted.
2407f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Since we have inspected the arguments of suspended
2408f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * processes we end up here testing for this case.
240947ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko			 *
241047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko			 * We also end up here when we catch new pid of
241147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko			 * CLONE_PTRACEd process. Do not process/restart it
241247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko			 * until we see corresponding clone() syscall exit
241347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko			 * in its parent.
2414f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 */
2415f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			continue;
2416f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		}
2417f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko
2418215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#ifdef LINUX
241947ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		/* So far observed only on RHEL5 ia64, but I imagine this
242047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 * can legitimately happen elsewhere.
242147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 * If we waited and got a stopped task notification,
242247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 * subsequent wait may return the same pid again, for example,
242347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 * with SIGKILL notification. SIGKILL kills even stopped tasks.
242447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 * We must not add it to the list
242547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 * (one task can't be inserted twice in the list).
242647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		 */
242747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		{
242847ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko			struct tcb *f = found_tcps;
242947ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko			while (f) {
243047ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko				if (f == tcp) {
243147ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko					remembered_pid = pid;
243247ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko					remembered_status = status;
243347ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko					return found_tcps;
243447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko				}
243547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko				f = f->next_need_service;
243647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko			}
243747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		}
2438f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		/* It is important to not invert the order of tasks
2439f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		 * to process. For one, alloc_tcb() above picks newly forked
2440f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		 * threads in some order, processing of them and their parent
2441f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		 * should be in the same order, otherwise bad things happen
2442f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		 * (misinterpreted SIGSTOPs and such).
2443f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		 */
244447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		tcp->wait_status = status;
2445f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		*nextp = tcp;
2446f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		nextp = &tcp->next_need_service;
244747ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		*nextp = NULL;
2448215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		wnohang = WNOHANG;
2449215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif
2450215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#ifdef SUNOS4
2451215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		/* Probably need to replace wait with waitpid
2452215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * and loop on Sun too, but I can't test it. Volunteers?
2453215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 */
245447ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		tcp->wait_status = status;
245547ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		tcp->next_need_service = NULL;
245647ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko		found_tcps = tcp;
2457215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		break;
2458215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko#endif
245947ce6dfc9f54fe8809179fd4e200e4e2f5bb7d02Denys Vlasenko	} /* while (1) - collecting all stopped/exited tracees */
2460215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2461f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko	return found_tcps;
2462215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko}
2463215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2464215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkostatic int
2465215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkohandle_stopped_tcbs(struct tcb *tcp)
2466215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko{
2467215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	for (; tcp; tcp = tcp->next_need_service) {
2468215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		int pid;
2469215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		int status;
247076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2471215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		outf = tcp->outf;
2472215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		status = tcp->wait_status;
2473215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		pid = tcp->pid;
2474215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
247576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2476a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2477a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
247876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
24812efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
24822efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
24832efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
24842efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
24852efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
24862efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
2487ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
248876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2489e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2490e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2491e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
249276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2493e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
249476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
249676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2497a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2498a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
249976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
25007a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
25017a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
25020569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
25037a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			    && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
25041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && !(tcp->flags & TCB_GROUP_EXITING)
25050569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
25067a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			) {
250776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
25087a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					"PANIC: attached pid %u exited with %d\n",
25097a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					pid, WEXITSTATUS(status));
25107a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			}
25110a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
25127a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
25130a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
25140a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
25150a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
25160a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2517e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2518e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2519e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
252076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2521e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
252276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
252376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
252476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
252576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
252676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
252776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
252876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
252976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
253076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2531ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
253276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
253302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
253402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
253502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
253684e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko		 * than SIGSTOP if we happen to attach
253702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
253802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
253902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
254076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
254176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
254276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
254602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
254776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
254802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
254902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
255076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
255176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
255276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
255376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
255476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
255576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
255676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2557b1efe53531c2f0f3fd2a4fc8a56220737539c44eDenys Vlasenko/* Add more OSes after you verified it works for them. */
2558f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko/* PTRACE_SETOPTIONS may be an enum, not a #define.
2559f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko * But sometimes we can test for it by checking PT_SETOPTIONS.
2560f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko */
2561f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
25620861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# ifndef PTRACE_O_TRACESYSGOOD
25630861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko#  define PTRACE_O_TRACESYSGOOD 0x00000001
25640861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# endif
25650861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# ifndef PTRACE_O_TRACEEXEC
25660861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko#  define PTRACE_O_TRACEEXEC    0x00000010
25670861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# endif
25680861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# ifndef PTRACE_EVENT_EXEC
25690861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko#  define PTRACE_EVENT_EXEC     4
25700861ecbb44c1a7756e776af4a6fd7731e2a82a68Denys Vlasenko# endif
25711e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			/*
25721e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * Ask kernel to set signo to SIGTRAP | 0x80
25731e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * on ptrace-generated SIGTRAPs, and mark
25741e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
25751e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 */
257696d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko			if (!ptrace_opts_set) {
25777e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko				char *p;
257896d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				ptrace_opts_set = 1;
25797e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko
25807e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko				/* RHEL 2.6.18 definitely has crippling bugs */
25817e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko				/* Vanilla and Fedora 2.6.29 seems to work */
25827e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko				p = utsname_buf.release;
25837e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko				if (strtoul(p, &p, 10) < 2 || *p != '.')
25847e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko					goto tracing;
25857e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko				if (strtoul(++p, &p, 10) < 6 || *p != '.')
25867e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko					goto tracing;
25877e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko				if (strtoul(++p, &p, 10) < 29)
25887e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko					goto tracing;
258996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				/*
259096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * NB: even if this "succeeds", we can
259196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * revert back to SIGTRAP if we later see
259296d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * that it didnt really work.
259396d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * Old kernels are known to lie here.
259496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 */
259596d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
259696d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					(void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0)
259796d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					ptrace_stop_sig = SIGTRAP | 0x80;
25981e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			}
25991e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko#endif
260076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
260176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
260276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2603f535b54bc40373c81b13df0975aef4212dacbbdeDenys Vlasenko#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
260496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko		if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
26051e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			/*
26061e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * We told ptrace to report SIGTRAP | 0x80 on this process
26071e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * but got bare SIGTRAP. This can be a genuine SIGTRAP:
26081e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * kill(pid, SIGTRAP), trap insn, etc;
26091e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * but be paranoid about it.
26101e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 */
26111e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
26121d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				/* It's post-exec ptrace stop. Ignore it,
26131d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				 * we will get syscall exit ptrace stop later.
26141d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				 */
26151d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko#ifdef TCB_WAITEXECVE
26161d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				tcp->flags &= ~TCB_WAITEXECVE;
26171d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko#endif
26181d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				goto tracing;
26191e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			} else {
26201e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				/* Take a better look...  */
26211e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				siginfo_t si;
26221d5b113f8c013b11afa10de8393e770b29c648fdDenys Vlasenko				si.si_signo = 0;
26231e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
26241e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				/*
26251e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Check some fields to make sure we see
26261e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * real SIGTRAP.
26271e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Otherwise interpret it as ptrace stop.
26281e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Real SIGTRAPs (int3 insn on x86, kill() etc)
26291e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * have these values:
26301e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * int3:                   kill -TRAP $pid:
26311e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_signo:5 (SIGTRAP)    si_signo:5 (SIGTRAP)
26321e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_errno:0              si_errno:(?)
26331e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
26341e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_pid:0                si_pid:(>0?)
26351e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_band:0               si_band:(?)
26361e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Ptrace stops have garbage there instead.
26371e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 */
26381e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				if (si.si_signo != SIGTRAP
26391e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
26401e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				) {
264196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code);
264296d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					ptrace_stop_sig = SIGTRAP;
26431e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				}
26441e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			}
26451e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko		}
26461e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko#endif
26471e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko
264896d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko		if (WSTOPSIG(status) != ptrace_stop_sig) {
26491e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			/* This isn't a ptrace stop.  */
26501e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko
265176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
265276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
265376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
265476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
265576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
265776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2658732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
265976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
266076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
266176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
266276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
266376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
266476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
266576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
26661f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				unsigned long addr = 0;
26671f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				long pc = 0;
26689633942c07427ed51caea0e73f139e964d1a19ccDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
26697b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#				define PSR_RI	41
26707b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				struct siginfo si;
26711f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				long psr;
26727b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2673932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2674932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
26757b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
26767b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
26777b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
26787b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				addr = (unsigned long) si.si_addr;
26793a055d7d64222223da2550ca540043de7e3e232bRoland McGrath#elif defined PTRACE_GETSIGINFO
26803a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				if (WSTOPSIG(status) == SIGSEGV ||
26813a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				    WSTOPSIG(status) == SIGBUS) {
26823a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					siginfo_t si;
26833a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					if (ptrace(PTRACE_GETSIGINFO, pid,
26843a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						   0, &si) == 0)
26853a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						addr = (unsigned long)
26863a055d7d64222223da2550ca540043de7e3e232bRoland McGrath							si.si_addr;
26873a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				}
26887b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
268976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
26907b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tprintf("--- %s (%s) @ %lx (%lx) ---",
2691ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WSTOPSIG(status)),
26927b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					strsignal(WSTOPSIG(status)), pc, addr);
2693ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
269476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
26950569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
26960569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
269776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2698e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2699e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2700e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
270176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2702e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
270376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
270476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2705732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
270676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
270776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
270876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
270976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
271076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
271176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
271202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
271302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
271402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2715732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2716ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			/* ptrace() failed in trace_syscall() with ESRCH.
2717ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 * Likely a result of process disappearing mid-flight.
2718ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 * Observed case: exit_group() terminating
2719ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 * all processes in thread group. In this case, threads
2720ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 * "disappear" in an unpredictable moment without any
2721ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 * notification to strace via wait().
2722ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2723ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2724ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				if (tcp_last) {
2725ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					/* Do we have dangling line "syscall(param, param"?
2726ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					 * Finish the line then. We cannot
2727ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					 */
2728ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					tcp_last->flags |= TCB_REPRINT;
2729ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					tprintf(" <unfinished ...>");
2730ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
2731ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				}
273276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2733ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
273476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				ptrace(PTRACE_KILL,
273576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					tcp->pid, (char *) 1, SIGTERM);
273676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
273776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
273876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
273976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
274076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2741e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2742e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2743e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2744e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2745e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2746e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2747e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
274876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
274976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2750732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
275176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
275276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
275376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
275476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
275576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
275676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
275776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
275876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
275976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
276076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
276176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2762732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
276376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
276476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
276576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2766215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	} /* for each tcp */
2767215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2768215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	return 0;
2769215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko}
2770215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2771215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkostatic int
2772215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenkotrace()
2773215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko{
2774215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	int rc;
2775215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	struct tcb *tcbs;
2776215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2777215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko	while (nprocs != 0) {
2778215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		if (interrupted)
2779215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			return 0;
2780215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		if (interactive)
2781215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			sigprocmask(SIG_SETMASK, &empty_set, NULL);
2782215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko
2783215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		/* The loop of "wait for one tracee, serve it, repeat"
2784215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * may leave some tracees never served.
2785215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * Kernel provides no guarantees of fairness when you have
2786215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * many waitable tasks.
2787215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * Try strace -f with test/many_looping_threads.c example.
2788215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * To fix it, we collect *all* waitable tasks, then handle
2789215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 * them all, then repeat.
2790215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		 */
2791215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		tcbs = collect_stopped_tcbs();
2792215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		if (!tcbs)
2793215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			break;
2794215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		rc = handle_stopped_tcbs(tcbs);
2795215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko		if (rc)
2796215cc2703763894faea05899642ea5dfd5fc5c95Denys Vlasenko			return rc;
279776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
279876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
279976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
280076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2801bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
280276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
280376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol;
280476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
280576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
280676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
280776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b)
280876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
280976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h>
281076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a)
281176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
281276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
281376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
281476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
281576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
281676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
281776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist)
281876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
281976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl
282076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
282176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
282276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
282376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
282476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	VA_START(args, fmt);
2825b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2826b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2827b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		if (n < 0 && outf != stderr)
2828b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			perror(outfname == NULL
2829b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			       ? "<writing to pipe>" : outfname);
2830b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		else
2831b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2832b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
283376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
283476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
283576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
283676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
283776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
28387e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenkoprintleader(struct tcb *tcp)
283976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2840732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2841732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (tcp_last->ptrace_errno) {
28427e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->ptrace_errno = 0;
2843732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
28447e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko				tprintf(" <unavailable ...>\n");
28457e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko				tcp_last->flags |= TCB_REPRINT;
28467e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			} else {
28477e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko				tprintf("= ? <unavailable>\n");
2848732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2849732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
2850732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			tprintf(" <unfinished ...>\n");
28517e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2852732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
285376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
285476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
285576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
285676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
285776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
285876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
285976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
286076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
286176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
286276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
286376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
286476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
286576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
286676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
286776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
286876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
286976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
287076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
287176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
287276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
287376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
287476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
287576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
287676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
287776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
287876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
287976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
288076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
288176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
288276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
288376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
288476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
288576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
288676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
288776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
288876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
288976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
289076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
289176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
289276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
289376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
289476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
289576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
289676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
289776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
289876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2899ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
290076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
290176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
290276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
290376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
29049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2905ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
29069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2907ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2908ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2909ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
29109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
29119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2912553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
29139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
29149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
29159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
29169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
29179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
29189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
29199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2920553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2921ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
29229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
29239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
29249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2925