strace.c revision e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073e
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;
81418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
82418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
8396d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8541c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0;
86e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0;
87e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE;
88b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
89ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
90ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
106a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
107a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
108eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
109b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
115b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
117ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
118ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
119ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname;
121eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathextern char **environ;
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
123e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int detach(struct tcb *tcp, int sig);
124e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
125e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
126e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
137e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd);
138e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig);
139e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void);
140ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void);
145e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd);
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
158ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
163bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
172de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
173de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
174ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko   or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
175de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
191ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
195de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
196de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
197de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
19817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
199de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
200de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
213c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
214c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
215c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
216c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
217c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
218c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
219c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
220c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
22110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
22210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     flags, newflags;
22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return 0;
23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fcntl(fd, F_SETFD, newflags) < 0)
23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
23910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
24010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
24110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
24210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
24310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
24410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
25110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (euid != uid && setreuid(euid, uid) < 0)
25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
25910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: setreuid: %s\n",
26010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
26110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		exit(1);
26210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
26310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
26410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
26510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
2664bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
2674bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
2684bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
2694bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
2704bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
2714bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
27210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
27310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode)
27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
27610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
2784bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath	if ((fp = fopen_for_output(path, mode)) == NULL)
27910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: can't fopen '%s': %s\n",
28010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, path, strerror(errno));
28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fp && set_cloexec_flag(fileno(fp)) < 0)
28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fclose(fp);
28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fp = NULL;
28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1;
29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     fds[2];
30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: pipe: %s\n",
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(fds[1]) < 0)
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((popen_pid = fork()) == -1)
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fork: %s\n",
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (popen_pid)
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* parent */
33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return fdopen(fds[1], "w");
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	} else
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		{
34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			fprintf(stderr, "%s: dup2: %s\n",
34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				progname, strerror(errno));
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			_exit(1);
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: execl: %s: %s\n",
35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, _PATH_BSHELL, strerror(errno));
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		_exit(1);
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
3607a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		FILE *fp;
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3637a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if ((fp = strace_fopen(name, "w")) == NULL)
36510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			return -1;
36610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		tcp->outf = fp;
36710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
36910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
37010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
37102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
37202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
37902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
38002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
38102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * We rely on cleanup () from this point on.
38202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
38302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
38402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
38502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
386ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
387ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
388ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
389ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(1);
390ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
391ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
392ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
393ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for child to attach to straced process
394ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * (our parent). Child SIGKILLs us after it attached.
395ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Parent's wait() is unblocked by our death,
396ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
397ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
398ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
399ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
400ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
401ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
402ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (newoutf(tcp) < 0)
41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
41802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
41902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
42202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
424ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
4257a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
42602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
42702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
4357a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
43702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
441aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
443aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					else if (tid != tcbtab[tcbi]->pid) {
444418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko						tcp = alloctcb(tid);
445eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
44602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nchildren++;
44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_threads++;
44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_detached++;
44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->parent = tcbtab[tcbi];
45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
451aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (interactive) {
452aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_SETMASK, &empty_set, NULL);
453aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						if (interrupted)
454aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko							return;
455aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
456aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					}
45702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
4597a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
4607a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
4667a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
4677a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
4687a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
4697a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko						tcbtab[tcbi]->pid, ntid);
47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
4727a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
4737a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif
47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* INTERRUPTED is going to be checked at the top of TRACE.  */
481ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
482ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
483ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
484ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
485ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
486ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
487ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
488ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
489ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
490ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
491ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
492ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
493ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
494ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
49502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_child (char **argv)
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("strace: exec");
52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
52102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		char *path;
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		fprintf(stderr, "%s: %s: command not found\n",
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			progname, filename);
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
572a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
573ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: fork");
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		cleanup();
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
577ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
578ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
579ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
580ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
581ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf != stderr) close (fileno (outf));
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
594ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		kill(pid, SIGSTOP); /* stop HERE */
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf!=stderr)
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			close(fileno (outf));
59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
600ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
601ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
602ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				perror("strace: ptrace(PTRACE_TRACEME, ...)");
603ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				exit(1);
604ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
605ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
606ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("initgroups");
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setregid");
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setreuid");
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
640ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
641ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
642ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Induce an immediate stop so that the parent
643ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
644ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * this execve call normally.
645c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * Unless of course we're on a no-MMU system where
646c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			 * we vfork()-ed, so we cannot stop the child.
647ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
648c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
649c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger				kill(getpid(), SIGSTOP);
650ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
651ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
652ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
653ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
654ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
655ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
656ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
657ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
658ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
659ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
660ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
661ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
662ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
663ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
664ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
665ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
666ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
66702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
66902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: exec");
67102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		_exit(1);
67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
673ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
674ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
675ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
676ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
678ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
679ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
68002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
681ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
682ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		fprintf(stderr, "trouble opening proc file\n");
683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		cleanup();
684ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		exit(1);
68502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
686ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
68702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
68802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
69008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
69406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
69908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
70008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
701ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
702ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
703418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
70408b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
70508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
70608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
707418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
70808b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
70908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
71008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
711ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
712ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
713ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
71476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
716138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
717138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
71876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
723e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		"+cCdfFhiqrtTvVxz"
724ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
725ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
726ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
727ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"a:e:o:O:p:s:S:u:E:")) != EOF) {
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
72976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
730e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
731e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
732e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin					progname);
733e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				exit(1);
734e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
735e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
736e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
737e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
738e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
739e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				fprintf(stderr, "%s: -c and -C are mutually exclusive options\n",
740e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin					progname);
741e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin				exit(1);
742e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
743e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
748ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
749ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* Experimental, not documented in manpage yet. */
750ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
751ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
752ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
753ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
75441c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
75506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
75606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
7869c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
79017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
79117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
79676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
79876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
79976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
80076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
80176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
80276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
80376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
80476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
805de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
81076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pid == getpid()) {
81154a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
814418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
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,
854e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			"%s: (-c or -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
982418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkovoid
983418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
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) {
99676860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
99776860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin			progname);
998418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		cleanup();
999418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		exit(1);
10007b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
10017b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
10027b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
10037b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
10047b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
10057b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
10067b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
100810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1013418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1014418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1015418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1016ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1017ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
1020eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->parent = NULL;
1021eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nchildren = 0;
1022eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nzombies = 0;
1023eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef TCB_CLONE_THREAD
1024eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nclone_threads = tcp->nclone_detached = 0;
1025eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nclone_waiting = 0;
1026eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
1029ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			tcp->curcol = 0;
1030eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->stime.tv_sec = 0;
1031eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			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	}
1039418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1040418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	cleanup();
1041418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	exit(1);
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1044bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1046418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1050bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
105119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
105219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1055bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1060ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
10619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
10629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
10639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
10649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
106710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
10689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
10719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
10729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
107510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_stat) < 0) {
10769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
10799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
10809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
108310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_as) < 0) {
10849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1088bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
1091bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1092bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1093bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1094bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
109810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
10999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
11009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
11019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1102bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1103bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1104bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1105bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1106bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1107bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1108bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1109bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1110bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1111bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1112bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1113bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1114bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1115bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
11249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
11289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1129bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1132bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
113416a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1138553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
11429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
11489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
115176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1153553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
115476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1162bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1163bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1164bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1165bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
11665ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1167bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1168bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1169bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
11705ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
11715ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1172bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1173bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1175bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
117619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
117719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
117819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
117919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
118019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
118119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
118219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
118319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
118419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
118519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
118619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
118719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1188553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
118919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
119019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
119119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
119219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
119319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
119419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
119519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
119619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
119719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
119819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
120219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
120319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
120719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
120819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
120919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
121019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
121119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
121219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
12139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
121719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
121819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
121919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
122019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
122119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
122219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
12239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1227bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1228bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1229bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
1230bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1231bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1232bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1233bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1234bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1243553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
12459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
12469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1250553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1251bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1252bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1253bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1254bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1255553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
12589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
12629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1263bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1264bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
126576989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1269bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
12709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
12719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1272bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1273bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1274553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
127576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1278bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1279bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1280bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1281bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1282bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1283bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1284553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1286bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1288bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1289bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1290553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
12912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
12922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
12932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
12942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
12952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
12962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
12972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1298553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
12992e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
13002e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
13012e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
13022e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
13032e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
13042e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
13052e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
13062e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
13072e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
13082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
13092e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
13102e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
13112e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
13122e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
13132e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
13142e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1315bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1316bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1330bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1332e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid)
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1339ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1340ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid && tcp->pid != pid)
134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
134576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1349bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1357ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1358ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1367bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1375e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1376e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1377e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1378e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1379e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1380e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1381e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1382e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1383e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1384e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1387eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1388e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1389e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1390e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1391e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_DETACHED)
1392e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_detached--;
1393e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1394e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1395e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
13960962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED
13970962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath		if (!(tcp->flags & TCB_CLONE_DETACHED))
13980962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif
13990962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->parent->nzombies++;
1400276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX
1401276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		/* Update `tcp->parent->parent->nchildren' and the other fields
1402276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   like NCLONE_DETACHED, only for zombie group leader that has
1403276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   already reported and been short-circuited at the top of this
1404276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   function.  The same condition as at the top of DETACH.  */
1405276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		if ((tcp->flags & TCB_CLONE_THREAD) &&
1406276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    tcp->parent->nclone_threads == 0 &&
1407276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    (tcp->parent->flags & TCB_EXITING))
1408276ceb33f20fc41403e46684e441230296f6a433Roland McGrath			droptcb(tcp->parent);
1409276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif
1410e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1411e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1412e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1413e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1417bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1418bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1419bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1420bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1421bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1422bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1423bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1424bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1425bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1426553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1427bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1428e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1431eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1432822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1434eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1438bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1452e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1453e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1454e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1455e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
145676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1457732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
145876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14651bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int
14661bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathresume_from_tcp (struct tcb *tcp)
14671bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{
14681bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int error = 0;
14691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int resumed = 0;
14701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	/* XXX This won't always be quite right (but it never was).
14721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
14731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   a particular pgrp, which this child might or might not be
14741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
14751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
14761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   difference to wake up a waiter when there might be more
14771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   traced children, because it could get a false ECHILD
14781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
14791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
14801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   search the system for all pid's in the pgrp to be sure.
14811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	     && (t->waitpid == -1 ||
14831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
14841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
14851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	*/
14861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent &&
14881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
14891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
14905ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		error = resume(tcp->parent);
14911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		++resumed;
14921bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
14931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD
14941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
14951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Some other threads of our parent are waiting too.  */
14961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		unsigned int i;
14971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
14991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
15001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			struct tcb *t = tcbtab[i];
15011bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			if (t->parent == tcp->parent && t != tcp
15021bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
15031bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
15041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && t->waitpid == tcp->pid) {
15051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				error |= resume (t);
15061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				++resumed;
15071bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
15081bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		}
15091bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		if (resumed == 0)
15101bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			/* Noone was waiting for this PID in particular,
15111bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			   so now we might need to resume some wildcarders.  */
15121bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
15131bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				struct tcb *t = tcbtab[i];
15141bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				if (t->parent == tcp->parent && t != tcp
15151bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && ((t->flags
15161bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
15171bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
15181bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && t->waitpid <= 0
15191bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					) {
15201bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					error |= resume (t);
15211bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					break;
15221bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				}
15231bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
15241bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
15253bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#endif
15261bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
15271bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	return error;
15281bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath}
15291bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
1530bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15320a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
15330a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
15340a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
15350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1543ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
15441bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1545a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1546a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1547a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1548a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1549a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1550a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1551a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1552a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1553ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1556840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
15617bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
15627bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
15647bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
15657bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
15667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
15677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
156802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
156902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
157002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
157102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
157202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
157302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
15767bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
15777bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
15787bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
15797bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
15807bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1581134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1582134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1583134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
15847bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
15857bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
15867bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
158702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
158802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
158902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
15907bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
15917bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
15927bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
159302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
159402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1595ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
15977508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
15987508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
15997508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
16007508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16017508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
16037508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
16047508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16057508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
16067508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
16077508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
16087508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
16097508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
16107508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16117508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16127508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
16137508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
16147508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
16157508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
16167508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
16177508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
16187508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
16197508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
16207508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
16217508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16227508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
16247508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1630732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1633732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
1634eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					WSTOPSIG(status) == SIGTRAP ? 0
1635732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1636732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1639ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
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
1671e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig)
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1680bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1688ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1689ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1697ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			tprintf(" <unfinished ...>");
1698ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17206d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
17236d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17428f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
17436d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
17458f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
17468f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
17478f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1768bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1775ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1776ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1777c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1778ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
177946100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "%s: out of memory\n", progname);
1780ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1781ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1782ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1783ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1784ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
17889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
180910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1857bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1858bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1859bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
1864a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
1888a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1899bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
19005ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
19015ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
19025ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
19035ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
19049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
19379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
19729dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
1973d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
19749dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
19799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp = pid2tcb(0);
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
20069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
20079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
20089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
20099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2010553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
20119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
20129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
20139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
20149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
20159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
20169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
20179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
20189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
20199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
20209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
20219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
20239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
20249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
20269dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
20279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2051b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
20529dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2053b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2056bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
20579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
2058bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2059bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2060bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2061bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2062bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2063bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
2064bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
20655ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko				ioctl_result = IOCTL_WSTOP (tcp);
2066553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2089bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2090bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2091553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21012e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
21022e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
21032e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
21042e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
21052e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
21062e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2107553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2108553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
2114ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2118bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2119bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2120bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2121bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2122bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2123bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2124bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2125bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2126bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2127bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2128bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2129553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2132bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
21379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2138bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
21409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
21419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2148bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
21509dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
21519dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
21529dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
2160e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2161e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_SIGNAL)) {
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2164ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2165ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
21665826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
21675826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
21685826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
21695826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
21705826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2171ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
21725826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
21735826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
2177e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAGS_ONLY_STATS
2178e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_FAULT)) {
217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2181ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2184bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2185bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
21865ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2187553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
21899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2193ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2194ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
21959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2196553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
21979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
2198553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2199bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
2200553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2208bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2210e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2211e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2212e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2213e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2214e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2215e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2216e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2217e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2218e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2219e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2220e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2221e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
22227a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	struct tcb *leader = NULL;
22237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko
22247a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	if (tcp->flags & TCB_CLONE_THREAD)
22257a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp->parent;
22267a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	else if (tcp->nclone_detached > 0)
22277a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp;
2228e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2229e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
22307a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		if (leader != NULL && leader != tcp
22317a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(leader->flags & TCB_GROUP_EXITING)
22327a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(tcp->flags & TCB_STARTUP)
22337a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		) {
2234e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2235e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2236e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
22377a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		}
22387a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
22391bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS
22407a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		resume_from_tcp(tcp);
22411bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif
22420a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2243e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2244e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2245a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2246a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2247e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
2248d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath			detach(tcp, sig);
22495ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			if (leader != NULL && leader != tcp)
22501bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2251732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else {
2252732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2253732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				cleanup();
2254732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				return -1;
2255732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2256732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (leader != NULL) {
22570569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2258732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (leader != tcp)
2259732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					droptcb(tcp);
2260732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2261e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2262e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2263e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2264e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2265e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2266e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2267e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2268e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2269e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2270e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2271eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
2272eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace()
227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
227576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
22802f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2281eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
22822f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2285eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2286222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2287eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2288eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2289eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
22912f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2292eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
22935bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
22942f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
22952f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
22962f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
2297eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, wait4_options,
2298eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
22992f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
23005bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
23012f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
2302eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, __WCLONE,
2303eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
2304eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (pid == -1) {
2305eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				fprintf(stderr, "strace: clone wait4 "
23062f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
23072f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
23082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
2309eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#else
2310eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2311eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* __WALL */
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2317eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2318eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
232076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
2321eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2322eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2324eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
232776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
232876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
232976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
233076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
2331eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2332eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2333eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2334eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2335eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
233676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
233776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
233810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
233910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
234010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				popen_pid = -1;
234110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
234210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
234476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
234576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
234676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2348e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
234941c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2350e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2351e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2352e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2353e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2354e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2355e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2356e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2357e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2358e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2359418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2360e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2361e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2362e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2363e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2364e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
23658b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2366e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2367e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2368e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2369eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2370e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2371e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2372e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2373e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2374e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2375e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2377eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2378eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
2379ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
238084e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko		if (cflag) {
2381eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
238276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
238376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
2384eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* !LINUX */
238576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2386eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
2387f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		if (tcp->flags & TCB_SUSPENDED) {
2388f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			/*
2389f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Apparently, doing any ptrace() call on a stopped
2390f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process, provokes the kernel to report the process
2391f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * status again on a subsequent wait(), even if the
2392f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process has not been actually restarted.
2393f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Since we have inspected the arguments of suspended
2394f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * processes we end up here testing for this case.
2395f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 */
2396f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			continue;
2397f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		}
239876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2399a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2400a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2401e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
240276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
240376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
24042efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
24052efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
24062efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
24072efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
24082efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
24092efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
2410ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
241176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2412e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2413e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2414e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
241576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2416e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
241776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
241876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
241976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2420a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2421a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
242276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
24237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
24247a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
24250569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
24267a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			    && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
24271bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && !(tcp->flags & TCB_GROUP_EXITING)
24280569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
24297a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			) {
243076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
24317a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					"PANIC: attached pid %u exited with %d\n",
24327a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					pid, WEXITSTATUS(status));
24337a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			}
24340a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
24357a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
24360a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
24370a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
24380a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
24390a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2440e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2441e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2442e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
244376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2444e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
244576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
244676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
244776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
244876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
245076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
245176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2454ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
245576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
245602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
245702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
245802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
2459eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		 * than SIGSTOP if we happend to attach
246002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
2461c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * A no-MMU vforked child won't send up a signal,
2462c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		 * so skip the first (lost) execve notification.
246302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
2464c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		if ((tcp->flags & TCB_STARTUP) &&
2465c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger		    (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
246676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
246776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
246876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
246976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
247076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
247176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
247202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
247402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
247502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
247876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
248476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
248576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2486eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (WSTOPSIG(status) != SIGTRAP) {
248776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
248876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
248976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
249076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
249176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
249276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
249376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2494732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
249676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
249776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
249876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
249976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2500e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
250176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
25021f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				unsigned long addr = 0;
25031f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				long pc = 0;
25049633942c07427ed51caea0e73f139e964d1a19ccDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
25057b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#				define PSR_RI	41
25067b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				struct siginfo si;
25071f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				long psr;
25087b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2509932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2510932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
25117b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
25127b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
25137b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
25147b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				addr = (unsigned long) si.si_addr;
25153a055d7d64222223da2550ca540043de7e3e232bRoland McGrath#elif defined PTRACE_GETSIGINFO
25163a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				if (WSTOPSIG(status) == SIGSEGV ||
25173a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				    WSTOPSIG(status) == SIGBUS) {
25183a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					siginfo_t si;
25193a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					if (ptrace(PTRACE_GETSIGINFO, pid,
25203a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						   0, &si) == 0)
25213a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						addr = (unsigned long)
25223a055d7d64222223da2550ca540043de7e3e232bRoland McGrath							si.si_addr;
25233a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				}
25247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
252576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
25267b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tprintf("--- %s (%s) @ %lx (%lx) ---",
2527ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WSTOPSIG(status)),
25287b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					strsignal(WSTOPSIG(status)), pc, addr);
2529ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
253076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
25310569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
25320569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
253376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2534e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2535e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2536e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
253776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2538e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
253976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
254076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2541732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
254276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
254676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
254776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
254802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
254902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
255002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2551eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2552eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2553eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2554eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2555eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * all processes in thread group. In this case, threads
2556eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * "disappear" in an unpredictable moment without any
2557eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * notification to strace via wait().
2558ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2559ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2560eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (tcp_last) {
2561eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2562eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 * Finish the line then. We cannot
2563eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2564eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp_last->flags |= TCB_REPRINT;
2565eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tprintf(" <unfinished ...>");
2566eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					printtrailer();
2567eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
256876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2569ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2570eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				ptrace(PTRACE_KILL,
2571eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp->pid, (char *) 1, SIGTERM);
257276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
257376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
257576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
257676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2577e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2578e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2579e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2580e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2581e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2582e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2583e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
258476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
258576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2586732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
258776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
258876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
258976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
259076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
259176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
259276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
259376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
259476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
259576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
259676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
259776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2598ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2599ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
2600732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
260176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
260276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
260376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
260476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
260576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
260676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
260776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2608bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
260976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
261076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
261176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
261476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
261576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
261676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2617e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab	va_start(args, fmt);
2618b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2619b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2620ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		if (n < 0) {
2621ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			if (outf != stderr)
2622ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				perror(outfname == NULL
2623ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				       ? "<writing to pipe>" : outfname);
2624ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		} else
2625b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2626b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
262776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
262876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
262976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
263076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
263176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2632eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathprintleader(tcp)
2633eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstruct tcb *tcp;
263476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2635732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2636eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tcp_last->ptrace_errno) {
2637732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
2638eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tprintf(" <unavailable>)");
2639eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tabto(acolumn);
2640732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2641eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf("= ? <unavailable>\n");
2642eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp_last->ptrace_errno = 0;
2643732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
26447e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2645eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf(" <unfinished ...>\n");
2646732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
264776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
264876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
264976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
265076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
265176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
265276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
265376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
265476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
265576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
265776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
265876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
265976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
266076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
266176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
266276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
266376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
266476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
266576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
266676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
266776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
266876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
266976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
267076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
267176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
267276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
267376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
267476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
267576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
267676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
267776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
268076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
268176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
268276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
268376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
268476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
268576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
268676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
268776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
268876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
268976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
269076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
269176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
269276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2693ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
269476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
269576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
269676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
269776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
26989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2699ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
27009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2701ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2702ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2703ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
27049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
27059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2706553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
27079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
27089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
27099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
27109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
27119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
27129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
27139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2714553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2715ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
27169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
27179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
27189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2719