strace.c revision ecfe2f19f963b5c2f176c5e70d42654d7429ce3e
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>
4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h>
4619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h>
4770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
4876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
49134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX
50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h>
51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# if defined __NR_tgkill
52134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
53134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# elif defined __NR_tkill
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else
56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath   /* kill() may choose arbitrarily the target task of the process group
57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      while we later wait on a that specific TID.  PID process waits become
58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      TID task specific waits for a process under ptrace(2).  */
59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) kill ((tid), (sig))
61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif
62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif
63134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath
647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
68bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
71bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
7276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
74ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
751d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
791d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
8096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
8196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
8276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8341c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0;
84b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinint dtime = 0, cflag = 0, xflag = 0, qflag = 0;
85b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
86ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
87ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
88ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
89ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
90ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
103a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
104a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
10596d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkostatic int ptrace_stop_sig = SIGTRAP;
10696d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkostatic bool ptrace_opts_set;
107a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin
108b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
114b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
116ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
117ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname;
11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1200a463880341945df08b6dc79134dc78cc38dc283Roland McGrathstatic int detach P((struct tcb *tcp, int sig));
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void));
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void));
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig));
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted;
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd));
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig));
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void));
141ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void));
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd));
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
164bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
173de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
174de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
175ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko   or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
176de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
192ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
196de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
197de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
198de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
19917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
200de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
201de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
21510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
21610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
21710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     flags, newflags;
21810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
21910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
22010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
22110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
22210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return 0;
22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fcntl(fd, F_SETFD, newflags) < 0)
23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
23910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
24010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
24110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
24210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
24310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
24410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (euid != uid && setreuid(euid, uid) < 0)
25110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: setreuid: %s\n",
25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		exit(1);
25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
2594bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
2604bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
2614bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
2624bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
2634bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
2644bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
26510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
26610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode)
26710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
26810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
26910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
27010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
2714bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath	if ((fp = fopen_for_output(path, mode)) == NULL)
27210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: can't fopen '%s': %s\n",
27310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, path, strerror(errno));
27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fp && set_cloexec_flag(fileno(fp)) < 0)
27610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fclose(fp);
27810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fp = NULL;
27910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
28010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1;
28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     fds[2];
29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: pipe: %s\n",
30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(fds[1]) < 0)
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((popen_pid = fork()) == -1)
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fork: %s\n",
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (popen_pid)
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* parent */
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return fdopen(fds[1], "w");
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	} else
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		{
33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			fprintf(stderr, "%s: dup2: %s\n",
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				progname, strerror(errno));
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			_exit(1);
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: execl: %s: %s\n",
34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, _PATH_BSHELL, strerror(errno));
34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		_exit(1);
34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		char name[MAXPATHLEN];
35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		FILE *fp;
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		sprintf(name, "%s.%u", outfname, tcp->pid);
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if ((fp = strace_fopen(name, "w")) == NULL)
35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			return -1;
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		tcp->outf = fp;
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
36502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
36602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
36702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
36802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
36902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
37002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
37102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
37202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * We rely on cleanup () from this point on.
37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
379ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
380ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
381ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
382ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(1);
383ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
384ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
385ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
386ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for child to attach to straced process
387ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * (our parent). Child SIGKILLs us after it attached.
388ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Parent's wait() is unblocked by our death,
389ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
390ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
391ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
392ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
393ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
394ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
395ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
39602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
39702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
39802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
39902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
40002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
40102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
40202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (newoutf(tcp) < 0)
40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
417ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
41802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			char procdir[MAXPATHLEN];
41902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
42202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
42402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
42502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
42602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
42702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (de->d_fileno == 0 ||
42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					    de->d_name[0] == '.')
43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (ptrace(PTRACE_ATTACH, tid,
43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						   (char *) 1, 0) < 0)
43702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					else if (tid != tcbtab[tcbi]->pid) {
43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						if (nprocs == tcbtabsize &&
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						    expand_tcbtab())
44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							tcp = NULL;
44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						else
44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							tcp = alloctcb(tid);
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						if (tcp == NULL)
44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							exit(1);
44602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nchildren++;
44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_threads++;
44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_detached++;
45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->parent = tcbtab[tcbi];
45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (interactive) {
45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						sigprocmask(SIG_SETMASK, &empty_set, NULL);
45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						if (interrupted)
45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							return;
45602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
45702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
46002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (nerr == ntid) {
46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					ntid -= nerr;
46702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (ntid > 1)
46802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						fprintf(stderr, "\
46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathProcess %u attached with %u threads - interrupt to quit\n",
47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							tcp->pid, ntid);
47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					else
47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						fprintf(stderr, "\
47302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathProcess %u attached - interrupt to quit\n",
47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							tcp->pid);
47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif
48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
48202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
48302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
48402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
48502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* INTERRUPTED is going to be checked at the top of TRACE.  */
486ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
487ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
488ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
489ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
490ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
491ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
492ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
493ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
494ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
495ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
496ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
497ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
498ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
499ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_child (char **argv)
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
52102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("strace: exec");
52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		char *path;
54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		fprintf(stderr, "%s: %s: command not found\n",
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			progname, filename);
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
577a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
578ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: fork");
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		cleanup();
58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
582ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
583ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
584ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
585ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
586ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf != stderr) close (fileno (outf));
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
599ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		kill(pid, SIGSTOP); /* stop HERE */
60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf!=stderr)
60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			close(fileno (outf));
60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
605ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
606ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
607ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				perror("strace: ptrace(PTRACE_TRACEME, ...)");
608ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				exit(1);
609ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
610ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
611ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("initgroups");
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setregid");
63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setreuid");
63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
64102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
64202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
64302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
64402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
645ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
646ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
647ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Induce an immediate stop so that the parent
648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
649ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * this execve call normally.
650ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
651ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getpid(), SIGSTOP);
652ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
653ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
654ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
655ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
656ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
657ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
658ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
659ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
660ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
661ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
662ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
663ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
664ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
665ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
666ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
667ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
668ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
66902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
67102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: exec");
67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		_exit(1);
67402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
675ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
678ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (tcp == NULL) {
679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		cleanup();
680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		exit(1);
681ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
682ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
684ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
685ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
68602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
687ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
688ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		fprintf(stderr, "trouble opening proc file\n");
689ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		cleanup();
690ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		exit(1);
69102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
692ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
69302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
69402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
69608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	extern int optind;
69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	extern char *optarg;
70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
70176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
70206350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
70708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
70808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
709ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
710ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
71108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	if ((tcbtab = calloc (tcbtabsize, sizeof tcbtab[0])) == NULL) {
71208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
71308b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
71408b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
71508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	if ((tcbtab[0] = calloc (tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
71608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
71708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
71808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
719ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
720ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
721ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
724138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
725138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
73076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
731ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"+cdfFhiqrtTvVxz"
732ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
733ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
734ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
735ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"a:e:o:O:p:s:S:u:E:")) != EOF) {
73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cflag++;
73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
744ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
745ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* Experimental, not documented in manpage yet. */
746ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
747ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
748ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
749ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
75041c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
75106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
75206350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
7829c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
78617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
78717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
79676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
79876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
79976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
801de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
80276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
80576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pid == getpid()) {
80754a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
81010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if ((tcp = alloc_tcb(pid, 0)) == NULL) {
811de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname);
81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
81476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
81676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
820dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
821dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				fprintf(stderr,
822dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					"%s: invalid -s argument: %s\n",
823dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					progname, optarg);
824dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				exit(1);
825dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
833de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
834de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
835de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
836de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
837de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
838de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
839de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
846d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
847ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
848ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
84906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
85006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
85106350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
852cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
853cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		fprintf(stderr,
854cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			"%s: -c and -ff are mutually exclusive options\n",
855cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			progname);
856cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		exit(1);
857cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
858cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
87109553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath				progname, username);
87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
87876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
88437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
88537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
88637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
88737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
88837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
88937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
89037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
89137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
89237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
89337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
89437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
89537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
89637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
89710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if ((outf = strace_popen(outfname + 1)) == NULL)
89837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
89954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
90010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		else if (followfork <= 1 &&
90110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			 (outf = strace_fopen(outfname, "w")) == NULL)
90254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
90537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
90737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
910369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
91154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
91254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
91354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
91454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
91554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
91654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
91754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
91854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
91954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
92054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
92154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
92254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
92354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
92454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
93376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
93876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
950bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
953553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
954553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
955553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
956553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
957553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
958553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
959553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
960553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
961bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
96276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
963ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
96402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
96502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
969a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
970a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
971a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
972a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
973a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
974a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
975a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
976a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
977a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
978a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
979a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9827b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathint
9837b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathexpand_tcbtab()
9847b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
9857b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
9867b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
9877b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
9887b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
9897b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
9907b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb **newtab = (struct tcb **)
9917b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
9927b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
9937b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    sizeof *newtcbs);
9947b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	int i;
9957b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	if (newtab == NULL || newtcbs == NULL) {
9967b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		if (newtab != NULL)
9977b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath			free(newtab);
99876860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
99976860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin			progname);
10007b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		return 1;
10017b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
10027b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
10037b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
10047b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
10057b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
10067b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
10077b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	return 0;
10087b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
10097b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
10107b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
101210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1017ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1018ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->parent = NULL;
102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->nchildren = 0;
10230962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->nzombies = 0;
1024e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1025e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_threads = tcp->nclone_detached = 0;
1026e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_waiting = 0;
1027e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_sec = 0;
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_usec = 0;
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
103410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
103510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
103910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1043bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_open(tcp, attaching)
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint attaching;
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1051bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
105219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
105319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1056bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1061ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
10629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
10639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
10649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
10659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
106810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
10699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
10729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
10739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
107610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_stat) < 0) {
10779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
10809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
10819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
108410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_as) < 0) {
10859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1089bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
1092bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1093bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1094bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1095bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
109910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
11009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
11019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
11029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1103bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1104bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1105bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1106bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1107bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1108bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1109bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1110bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1111bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1112bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1113bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1114bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1115bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
11259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
11299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1130bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1133bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
113516a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1139553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
114276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
11439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
114876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
11499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
115176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
115376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1154553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
116276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1163bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1164bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1165bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1166bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
1167bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
1168bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1169bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1170bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1171bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCSFL");
1172bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
1173bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1174bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1176bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
117719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
117819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
117919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
118019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
118119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
118219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
118319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
118419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
118519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
118619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
118719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
118819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1189553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
119019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
119119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
119219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
119319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
119419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
119519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
119619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
119719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
119819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
119919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
120319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
120419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
120819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
120919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
121019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
121119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
121219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
121319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
12149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
121819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
121919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
122019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
122119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
122219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
122319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
12249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1228bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1229bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1230bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
1231bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1232bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1233bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1234bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1235bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1244553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
12469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
12479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
125076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1251553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1252bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1253bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1254bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1255bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1256553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
12599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
12639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1264bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1265bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
126676989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1270bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
12719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
12729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1273bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1274bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1275553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1279bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1280bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1281bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1282bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1283bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1284bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1285553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1287bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1289bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1290bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1291553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
12922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
12932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
12942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
12952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
12962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
12972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
12982e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1299553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
13002e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
13012e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
13022e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
13032e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
13042e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
13052e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
13062e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
13072e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
13082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
13092e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
13102e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
13112e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
13122e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
13132e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
13142e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
13152e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1316bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1317bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1331bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1333e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid)
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1340ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1341ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid && tcp->pid != pid)
134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
134576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
134976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1350bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1358ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1359ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1368bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1376e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1377e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1378e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1379e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1380e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1381e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1382e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1383e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1384e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1385e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
138776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1388eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1389e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1390e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1391e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1392e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_DETACHED)
1393e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_detached--;
1394e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1395e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1396e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
13970962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED
13980962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath		if (!(tcp->flags & TCB_CLONE_DETACHED))
13990962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif
14000962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->parent->nzombies++;
1401276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX
1402276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		/* Update `tcp->parent->parent->nchildren' and the other fields
1403276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   like NCLONE_DETACHED, only for zombie group leader that has
1404276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   already reported and been short-circuited at the top of this
1405276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   function.  The same condition as at the top of DETACH.  */
1406276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		if ((tcp->flags & TCB_CLONE_THREAD) &&
1407276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    tcp->parent->nclone_threads == 0 &&
1408276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    (tcp->parent->flags & TCB_EXITING))
1409276ceb33f20fc41403e46684e441230296f6a433Roland McGrath			droptcb(tcp->parent);
1410276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif
1411e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1412e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1413e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1414e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1418bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1419bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1420bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1421bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1422bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1423bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1424bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1425bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1426bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1427553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1428bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1429e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1432eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1433822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1435eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1439bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1453e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1454e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1455e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1456e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1458732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14661bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int
14671bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathresume_from_tcp (struct tcb *tcp)
14681bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{
14691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int error = 0;
14701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int resumed = 0;
14711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	/* XXX This won't always be quite right (but it never was).
14731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
14741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   a particular pgrp, which this child might or might not be
14751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
14761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
14771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   difference to wake up a waiter when there might be more
14781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   traced children, because it could get a false ECHILD
14791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
14801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
14811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   search the system for all pid's in the pgrp to be sure.
14821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	     && (t->waitpid == -1 ||
14841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
14851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
14861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	*/
14871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent &&
14891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
14901bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
14911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath 		error = resume(tcp->parent);
14921bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		++resumed;
14931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
14941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD
14951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
14961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Some other threads of our parent are waiting too.  */
14971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		unsigned int i;
14981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
15001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
15011bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			struct tcb *t = tcbtab[i];
15021bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			if (t->parent == tcp->parent && t != tcp
15031bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
15041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
15051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && t->waitpid == tcp->pid) {
15061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				error |= resume (t);
15071bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				++resumed;
15081bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
15091bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		}
15101bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		if (resumed == 0)
15111bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			/* Noone was waiting for this PID in particular,
15121bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			   so now we might need to resume some wildcarders.  */
15131bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
15141bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				struct tcb *t = tcbtab[i];
15151bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				if (t->parent == tcp->parent && t != tcp
15161bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && ((t->flags
15171bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
15181bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
15191bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && t->waitpid <= 0
15201bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					) {
15211bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					error |= resume (t);
15221bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					break;
15231bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				}
15241bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
15251bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
15261bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
15271bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	return error;
15281bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath}
15291bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif
15301bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
1531bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15330a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
15340a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
15350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
15360a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1544ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
15451bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1546a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1547a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1548a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1549a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1550a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1551a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1552a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1553a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1554ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sig = SIGKILL;
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
15627bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
15637bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
15657bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
15667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
15677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
15687bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
156902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
157002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
157102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
157202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
157302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
157402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
15777bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
15787bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
15797bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
15807bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
15817bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1582134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1583134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1584134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
15857bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
15867bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
15877bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
158802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
158902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
159002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
15917bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
15927bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
15937bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
159402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
159502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
159602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (catch_sigstop)
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
15987508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
15997508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
16007508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
16017508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16027508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
16047508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16057508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16067508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
16077508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
16087508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
16097508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
16107508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
16117508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16127508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16137508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
16147508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
16157508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
16167508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
16177508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
16187508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
16197508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16207508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16217508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
16227508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16237508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
16257508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1631732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1634732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
163596d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					WSTOPSIG(status) == ptrace_stop_sig ? 0
1636732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1637732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
16407bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1647732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1650bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
16511bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	error |= resume_from_tcp (tcp);
1652e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1653e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1658a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1659a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX
16600a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	if (zombie != NULL) {
16610a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		/* TCP no longer exists therefore you must not detach () it.  */
16620a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(zombie);
16630a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	}
1664a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif
1665a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1669bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig)
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct tcb *tcp;
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pid2tcb(pid);
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp)
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1689bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1697ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1698ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf(" <unfinished ...>\n");
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp_last = NULL;
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17296d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
17326d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17518f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
17526d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
17548f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
17558f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
17568f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1777bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1784ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1785ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1786c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1787ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
178846100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "%s: out of memory\n", progname);
1789ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1790ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1791ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1792ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1793ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
17979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
181810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1866bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1867bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1868bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
1873a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
1897a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1908bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
1909bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1910bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1911bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1912bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
19139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
19469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
19819dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
1982d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
19839dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
19889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp = pid2tcb(0);
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
20159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
20169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
20179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
20189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2019553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
20209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
20219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
20229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
20239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
20249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
20259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
20269dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
20279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
20289dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
20299dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
20309dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20319dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
20329dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
20339dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20349dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
20359dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
20369dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2060b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
20619dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2062b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2065bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
20669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
2067bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2068bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2069bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2070bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2071bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2072bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
2073bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
2074bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			  	ioctl_result = IOCTL_WSTOP (tcp);
2075553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2098bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2099bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2100553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21102e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
21112e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
21122e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
21132e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
21142e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
21152e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2116553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2117553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2126bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2127bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2128bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2129bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2130bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2131bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2132bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2133bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2134bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2135bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2136bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2137553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2140bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
21459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2146bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
21489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
21499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2156bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
21589dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
21599dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
21609dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2171ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
21735826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
21745826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
21755826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
21765826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
21775826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
21785826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printtrailer(tcp);
21795826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
21805826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2190bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2191bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
2192bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		  	continue;
2193553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
21959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2200553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
22019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
2202553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2203bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
2204553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2212bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2214e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2215e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2216e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2217e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2218e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2219e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2220e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2221e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2222e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2223e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2224e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2225e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
2226e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2227e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp->parent
2228e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      : tcp->nclone_detached > 0
2229e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp : NULL);
2230e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2231e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
22320569095472c93c8513edefcf31013503ce4c0589Roland McGrath		if (leader != NULL && leader != tcp &&
22330569095472c93c8513edefcf31013503ce4c0589Roland McGrath		    !(leader->flags & TCB_GROUP_EXITING))
2234e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2235e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2236e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
22370a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		/* TCP no longer exists therefore you must not detach () it.  */
22381bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS
22391bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		resume_from_tcp (tcp);
22401bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif
22410a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2242e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2243e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2244a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2245a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2246e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
2247d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath			detach(tcp, sig);
22481bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		  	if (leader != NULL && leader != tcp)
22491bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2250732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else {
2251732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2252732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				cleanup();
2253732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				return -1;
2254732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2255732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (leader != NULL) {
22560569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2257732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (leader != tcp)
2258732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					droptcb(tcp);
2259732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2260e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2261e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2262e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2263e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2264e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2265e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2266e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2267e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2268e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2269e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
227576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
22792f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
22802f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman	static int wait4_options = __WALL;
22812f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (nprocs != 0) {
228502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
228602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
228776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
228876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
22902f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
22912f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
22925bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
22932f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
22942f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
22952f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
22962f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, wait4_options,
22972f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
22982f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
22995bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
23002f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
23012f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, __WCLONE,
23022f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
23032f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			if (pid == -1) {
23042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman				fprintf(stderr, "strace: clone wait4 "
23052f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
23062f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
23072f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
23082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#else
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
23102f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif /* __WALL */
231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
232076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (wait_errno) {
232176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
232276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ECHILD:
232476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
232776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
232876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
232976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
233076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
233176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (nprocs == 0)
233276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
233376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: proc miscount\n");
233476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
233576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
233676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
233776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
233876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				errno = wait_errno;
233976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: wait");
234076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
234176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
234276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
234310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
234410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
234510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				popen_pid = -1;
234610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
234710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
234876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
234976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
235076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
235176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2353e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
235441c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2355e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2356e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2357e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2358e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2359e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2360e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2361e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2362e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2363e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
236476860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin				if (nprocs == tcbtabsize &&
236576860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin				    expand_tcbtab())
236676860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin					tcp = NULL;
236776860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin				else
236876860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin					tcp = alloctcb(pid);
236976860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin				if (tcp == NULL) {
2370e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					kill(pid, SIGKILL); /* XXX */
2371e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return 0;
2372e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
2373e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2374e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2375e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2376e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2377e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
23788b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2379e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2380e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2381e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
23828b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif
2383e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2384e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2385e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2386e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2387e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2388e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
238976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
239076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
239176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
239276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
239376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
239476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
239576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
239676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !LINUX */
239776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
239876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
239976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
240076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
240176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Apparently, doing any ptrace() call on a stopped
240276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process, provokes the kernel to report the process
240376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * status again on a subsequent wait(), even if the
240476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process has not been actually restarted.
240576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Since we have inspected the arguments of suspended
240676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * processes we end up here testing for this case.
240776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
240876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
240976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
241076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2411a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2412a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
241376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
241476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
241576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
24162efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
24172efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
24182efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
24192efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
24202efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
24212efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
242276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
242376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2424e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2425e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2426e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
242776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2428e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
242976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
243076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
243176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2432a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2433a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
243476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
243576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "pid %u exited\n", pid);
24360569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if ((tcp->flags & TCB_ATTACHED)
24370569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
24380569095472c93c8513edefcf31013503ce4c0589Roland McGrath			    && !(tcp->parent && (tcp->parent->flags &
24390569095472c93c8513edefcf31013503ce4c0589Roland McGrath						 TCB_GROUP_EXITING))
24401bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && !(tcp->flags & TCB_GROUP_EXITING)
24410569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
24420569095472c93c8513edefcf31013503ce4c0589Roland McGrath				)
244376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
244476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					"PANIC: attached pid %u exited\n",
244576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pid);
24460a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
24470a396906981a03f93c07cb912585d0679dd50899Roland McGrath				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
24480a396906981a03f93c07cb912585d0679dd50899Roland McGrath				    == TCB_INSYSCALL)
24490a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
24500a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
24510a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
24520a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2453e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2454e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2455e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
245676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2457e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
245876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
245976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
246076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
246176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
246276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
246376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
246476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
246576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
246676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2467ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
246876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
246902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
247002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
247102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
247202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * than SIGSTOP if we happend to attach
247302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
247402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
247502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
247876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
248202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
248402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
248502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
248676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
248776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
248876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
248976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
249076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
249176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
249276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2493b1efe53531c2f0f3fd2a4fc8a56220737539c44eDenys Vlasenko/* PTRACE_SETOPTIONS is not a #define. PT_SETOPTIONS is. */
2494b1efe53531c2f0f3fd2a4fc8a56220737539c44eDenys Vlasenko/* Add more OSes after you verified it works for them. */
2495b1efe53531c2f0f3fd2a4fc8a56220737539c44eDenys Vlasenko#if defined LINUX && defined PT_SETOPTIONS
24961e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			/*
24971e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * Ask kernel to set signo to SIGTRAP | 0x80
24981e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * on ptrace-generated SIGTRAPs, and mark
24991e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
25001e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 */
250196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko			if (!ptrace_opts_set) {
250296d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				ptrace_opts_set = 1;
250396d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				/*
250496d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * NB: even if this "succeeds", we can
250596d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * revert back to SIGTRAP if we later see
250696d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * that it didnt really work.
250796d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 * Old kernels are known to lie here.
250896d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				 */
250996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
251096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					(void *) (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC)) == 0)
251196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					ptrace_stop_sig = SIGTRAP | 0x80;
25121e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			}
25131e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko#endif
251476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
251576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
251676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2517b1efe53531c2f0f3fd2a4fc8a56220737539c44eDenys Vlasenko#if defined LINUX && defined PT_SETOPTIONS
251896d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko		if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
25191e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			/*
25201e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * We told ptrace to report SIGTRAP | 0x80 on this process
25211e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * but got bare SIGTRAP. This can be a genuine SIGTRAP:
25221e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * kill(pid, SIGTRAP), trap insn, etc;
25231e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 * but be paranoid about it.
25241e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			 */
25251e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
25261e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				/* It's post-exec ptrace stop.  */
25271e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				/* Set WSTOPSIG(status) = (SIGTRAP | 0x80).  */
25281e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				status |= 0x8000;
25291e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			} else {
25301e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				/* Take a better look...  */
25311e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				siginfo_t si;
25321e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
25331e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				/*
25341e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Check some fields to make sure we see
25351e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * real SIGTRAP.
25361e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Otherwise interpret it as ptrace stop.
25371e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Real SIGTRAPs (int3 insn on x86, kill() etc)
25381e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * have these values:
25391e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * int3:                   kill -TRAP $pid:
25401e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_signo:5 (SIGTRAP)    si_signo:5 (SIGTRAP)
25411e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_errno:0              si_errno:(?)
25421e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
25431e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_pid:0                si_pid:(>0?)
25441e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * si_band:0               si_band:(?)
25451e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 * Ptrace stops have garbage there instead.
25461e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 */
25471e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				if (si.si_signo != SIGTRAP
25481e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				 || (si.si_code != SI_KERNEL && si.si_code != SI_USER)
25491e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				) {
255096d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					fprintf(stderr, "bogus SIGTRAP (si_code:%x), assuming old kernel\n", si.si_code);
255196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko					ptrace_stop_sig = SIGTRAP;
25521e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko				}
25531e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			}
25541e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko		}
25551e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko#endif
25561e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko
255796d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko		if (WSTOPSIG(status) != ptrace_stop_sig) {
25581e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko			/* This isn't a ptrace stop.  */
25591e3ce32a4fadb58230bca4f16baf8152579dd3d0Denys Vlasenko
256076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
256176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
256276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
256376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
256476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
256576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
256676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2567732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
256876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
256976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
257076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
257176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
257276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
257376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
25751f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				unsigned long addr = 0;
25761f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				long pc = 0;
25779633942c07427ed51caea0e73f139e964d1a19ccDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
25787b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#				define PSR_RI	41
25797b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				struct siginfo si;
25801f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				long psr;
25817b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2582932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2583932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
25847b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
25857b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
25867b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
25877b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				addr = (unsigned long) si.si_addr;
25883a055d7d64222223da2550ca540043de7e3e232bRoland McGrath#elif defined PTRACE_GETSIGINFO
25893a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				if (WSTOPSIG(status) == SIGSEGV ||
25903a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				    WSTOPSIG(status) == SIGBUS) {
25913a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					siginfo_t si;
25923a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					if (ptrace(PTRACE_GETSIGINFO, pid,
25933a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						   0, &si) == 0)
25943a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						addr = (unsigned long)
25953a055d7d64222223da2550ca540043de7e3e232bRoland McGrath							si.si_addr;
25963a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				}
25977b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
259876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
25997b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tprintf("--- %s (%s) @ %lx (%lx) ---",
2600ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WSTOPSIG(status)),
26017b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					strsignal(WSTOPSIG(status)), pc, addr);
260276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
260376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
26040569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
26050569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
260676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2607e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2608e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2609e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
261076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2611e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2614732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
261576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
261676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
261776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
261876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
261976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
262076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
262102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
262202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
262302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2624732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
262576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
262676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
262776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
262876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				ptrace(PTRACE_KILL,
262976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					tcp->pid, (char *) 1, SIGTERM);
263076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
263176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
263276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
263376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
263476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2635e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2636e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2637e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2638e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2639e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2640e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2641e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
264276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
264376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2644732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
264576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
264676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
264776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
264876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
264976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
265076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
265176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
265276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
265376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
265476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
265576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2656732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
265776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
265876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
265976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
266076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
266176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
266276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
266376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2664bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
266576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
266676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol;
266776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
266876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
266976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
267076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b)
267176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
267276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h>
267376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a)
267476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
267576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
267676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
267776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
268076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist)
268176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
268276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl
268376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
268476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
268576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
268676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
268776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	VA_START(args, fmt);
2688b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2689b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2690b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		if (n < 0 && outf != stderr)
2691b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			perror(outfname == NULL
2692b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			       ? "<writing to pipe>" : outfname);
2693b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		else
2694b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2695b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
269676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
269776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
269876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
269976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
270076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
270176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp)
270276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
270376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2704732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2705732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (tcp_last->ptrace_errno) {
2706732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
2707732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				tprintf(" <unavailable>)");
2708732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				tabto(acolumn);
2709732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2710732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			tprintf("= ? <unavailable>\n");
2711732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			tcp_last->ptrace_errno = 0;
2712732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
2713732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2714732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			tprintf(" <unfinished ...>\n");
2715732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
271676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
271776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
271876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
271976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
272076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
272176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
272276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
272376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
272476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
272576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
272676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
272776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
272876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
272976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
273076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
273176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
273276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
273376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
273476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
273576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
273676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
273776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
273876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
273976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
274076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
274176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
274276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
274376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
274476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
274576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
274676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
274776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
274876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
274976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
275076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
275176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
275276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
275376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
275476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
275576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
275676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
275776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
275876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
275976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
276076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
276176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
276276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprinttrailer(tcp)
276376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
276476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
276576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
276676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
276776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
27689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2769ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
27709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
27719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkermanint mp_ioctl (int fd, int cmd, void *arg, int size) {
27729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
27739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
27749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2775553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
27769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
27779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
27789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
27799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
27809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
27819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
27829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2783553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
27849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	return writev (fd, iov, n);
27859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
27869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
27879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2788