strace.c revision eb9e2e8904ce85a6c7390be25bb873c6db88c4d3
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;
86b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinint dtime = 0, cflag = 0, xflag = 0, qflag = 0;
87b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
88ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
89ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
90ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
105a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
106a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
107eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
108b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
114b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
116ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
117ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname;
119eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathextern char **environ;
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1210a463880341945df08b6dc79134dc78cc38dc283Roland McGrathstatic int detach P((struct tcb *tcp, int sig));
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void));
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void));
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig));
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted;
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
137bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd));
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig));
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void));
142ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void));
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd));
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
160ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
165bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
174de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
175de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
176ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko   or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
177de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
193ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
197de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
198de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
199de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
20017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
201de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
202de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
21610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
21710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
21810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     flags, newflags;
21910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
22010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
22110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
22210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return 0;
23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fcntl(fd, F_SETFD, newflags) < 0)
23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
23910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
24010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
24110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
24210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
24310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
24410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
25110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (euid != uid && setreuid(euid, uid) < 0)
25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: setreuid: %s\n",
25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		exit(1);
25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
25910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
2604bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
2614bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
2624bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
2634bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
2644bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
2654bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
26610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
26710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode)
26810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
26910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
27010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
27110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
2724bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath	if ((fp = fopen_for_output(path, mode)) == NULL)
27310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: can't fopen '%s': %s\n",
27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, path, strerror(errno));
27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
27610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fp && set_cloexec_flag(fileno(fp)) < 0)
27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
27810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fclose(fp);
27910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fp = NULL;
28010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1;
28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     fds[2];
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: pipe: %s\n",
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(fds[1]) < 0)
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((popen_pid = fork()) == -1)
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fork: %s\n",
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (popen_pid)
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* parent */
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return fdopen(fds[1], "w");
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	} else
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		{
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			fprintf(stderr, "%s: dup2: %s\n",
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				progname, strerror(errno));
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			_exit(1);
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: execl: %s: %s\n",
34510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, _PATH_BSHELL, strerror(errno));
34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		_exit(1);
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
35110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
3547a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		FILE *fp;
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3577a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if ((fp = strace_fopen(name, "w")) == NULL)
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			return -1;
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		tcp->outf = fp;
36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
36602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
36702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
36802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
36902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
37002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
37102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
37202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * We rely on cleanup () from this point on.
37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
37902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
380ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
381ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
382ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
383ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(1);
384ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
385ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
386ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
387ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for child to attach to straced process
388ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * (our parent). Child SIGKILLs us after it attached.
389ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Parent's wait() is unblocked by our death,
390ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
391ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
392ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
393ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
394ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
395ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
396ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
39702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
39802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
39902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
40002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
40102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
40202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (newoutf(tcp) < 0)
40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
418ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
4197a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
42202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
42402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
42502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
42602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
42702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
4297a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
435aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0)
43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
437aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					else if (tid != tcbtab[tcbi]->pid) {
438418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko						tcp = alloctcb(tid);
439eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nchildren++;
44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_threads++;
44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_detached++;
44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->parent = tcbtab[tcbi];
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
445aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					if (interactive) {
446aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_SETMASK, &empty_set, NULL);
447aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						if (interrupted)
448aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko							return;
449aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
450aab52cae4cf597a556911fec3ef4cb5803a95b12Denys Vlasenko					}
45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
4537a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
4547a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
45602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
45702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
4607a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
4617a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
4627a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
4637a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko						tcbtab[tcbi]->pid, ntid);
46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
4667a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
4677a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
46802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif
46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
47302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* INTERRUPTED is going to be checked at the top of TRACE.  */
475ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
476ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
477ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
478ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
479ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
480ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
481ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
482ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
483ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
484ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
485ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
486ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
487ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
488ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
48902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
49002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
49102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
49202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
49302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
49402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
49502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_child (char **argv)
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("strace: exec");
51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
52102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		char *path;
52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		fprintf(stderr, "%s: %s: command not found\n",
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			progname, filename);
56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
566a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
567ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: fork");
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		cleanup();
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
571ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
572ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* parent: to become a traced process */
573ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* child: to become a traced process */
574ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
575ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf != stderr) close (fileno (outf));
57802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
588ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		kill(pid, SIGSTOP); /* stop HERE */
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf!=stderr)
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			close(fileno (outf));
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
594ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
595ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
596ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				perror("strace: ptrace(PTRACE_TRACEME, ...)");
597ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				exit(1);
598ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
599ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
600ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("initgroups");
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setregid");
62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setreuid");
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
634ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
635ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
636ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Induce an immediate stop so that the parent
637ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
638ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * this execve call normally.
639ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
640ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getpid(), SIGSTOP);
641ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
642ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
643ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
644ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
645ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
646ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
647ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
649ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
650ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
651ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
652ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
653ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
654ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
655ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
656ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
657ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
65802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
66002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
66102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: exec");
66202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		_exit(1);
66302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
664ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
665ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	/* We are the tracer.  */
666ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	tcp = alloctcb(daemonized_tracer ? getppid() : pid);
667ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
668ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* We want subsequent startup_attach() to attach to it.  */
669ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
670ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
67102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
672ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
673ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		fprintf(stderr, "trouble opening proc file\n");
674ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		cleanup();
675ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		exit(1);
67602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
677ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif /* USE_PROCFS */
67802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
67902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
68108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
68506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
69008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
69108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
692ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
693ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
694418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
69508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
69608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
69708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
698418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if ((tcbtab[0] = calloc(tcbtabsize, sizeof tcbtab[0][0])) == NULL) {
69908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		fprintf(stderr, "%s: out of memory\n", progname);
70008b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin		exit(1);
70108b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	}
702ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
703ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
704ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
707138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
708138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
70976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
71076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
71176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
71376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
714ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"+cdfFhiqrtTvVxz"
715ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
716ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
717ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
718ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"a:e:o:O:p:s:S:u:E:")) != EOF) {
71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cflag++;
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
727ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
728ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		/* Experimental, not documented in manpage yet. */
729ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
730ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
731ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
732ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
73341c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
73406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
73506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
7659c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
76817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
76917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
77017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
784de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pid == getpid()) {
79054a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
793418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
79476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
79576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
79676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
79876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
799dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
800dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				fprintf(stderr,
801dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					"%s: invalid -s argument: %s\n",
802dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					progname, optarg);
803dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				exit(1);
804dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
80576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
80976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
81076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
81176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
812de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
813de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
814de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
815de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
816de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
817de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
818de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
82476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
825d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
826ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
827ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
82806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
82906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
83006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
831cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
832cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		fprintf(stderr,
833cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			"%s: -c and -ff are mutually exclusive options\n",
834cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			progname);
835cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		exit(1);
836cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
837cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
84076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
84376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
84476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
84576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
85009553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath				progname, username);
85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
85476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
86337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
86437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
86537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
86637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
86737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
86837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
86937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
87037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
87137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
87237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
87337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
87437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
87537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
87610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if ((outf = strace_popen(outfname + 1)) == NULL)
87737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
87854b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
87910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		else if (followfork <= 1 &&
88010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			 (outf = strace_fopen(outfname, "w")) == NULL)
88154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
88437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
88576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
88637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
889369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
89054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
89154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
89254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
89354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
89454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
89554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
89654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
89754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
89854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
89954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
90054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
90154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
90254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
90354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
90576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
90676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
91676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
92176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
92576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
929bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
932553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
933553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
934553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
935553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
936553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
937553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
938553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
939553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
940bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
942ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
94302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
94402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
948a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
949a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
950a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
951a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
952a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
953a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
954a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
955a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
956a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
957a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
958a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
961418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkovoid
962418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
9637b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
9647b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
9657b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
9667b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
9677b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
9687b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
9697b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb **newtab = (struct tcb **)
9707b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
9717b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
9727b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    sizeof *newtcbs);
9737b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	int i;
9747b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	if (newtab == NULL || newtcbs == NULL) {
97576860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
97676860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin			progname);
977418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		cleanup();
978418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		exit(1);
9797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
9807b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
9817b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
9827b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
9837b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
9847b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
9857b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
98710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
992418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
993418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
994418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
995ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
996ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
999eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->parent = NULL;
1000eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nchildren = 0;
1001eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nzombies = 0;
1002eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef TCB_CLONE_THREAD
1003eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nclone_threads = tcp->nclone_detached = 0;
1004eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->nclone_waiting = 0;
1005eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
1008eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->stime.tv_sec = 0;
1009eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp->stime.tv_usec = 0;
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
101210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
101310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1017418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	fprintf(stderr, "%s: bug in alloc_tcb\n", progname);
1018418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	cleanup();
1019418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	exit(1);
102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1022bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1024418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1028bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
102919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
103019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1033bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1038ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
10399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
10409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
10419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
10429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
104510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
10469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
10499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
10509ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
105310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_stat) < 0) {
10549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
10579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
10589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
10599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
106110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_as) < 0) {
10629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
1066bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
106776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
106876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
1069bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1070bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1071bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
1072bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
107610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
10779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
10789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
10799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1080bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1081bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
1082bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
1083bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1084bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1085bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1086bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1087bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
1088bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
1089bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1090bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1091bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1092bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1093bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1094bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
11029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
11069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1107bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1110bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
111216a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1116553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
11209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
11269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
112876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1131553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1140bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1141bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1142bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1143bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
11445ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1145bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1146bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
11485ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
11495ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1150bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1151bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1153bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
115419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
115519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
115619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
115719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
115819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
115919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
116019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
116119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
116219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
116319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
116419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
116519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1166553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
116719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
116819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
116919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
117019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
117119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
117219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
117319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
117419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
117519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
117619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
118019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
118119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
118519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
118619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
118719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
118819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
118919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
119019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
11919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
119519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
119619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
119719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
119819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
119919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
120019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
12019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1205bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1206bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1207bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
1208bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1209bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1210bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1211bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1212bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1221553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
12239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
12249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1228553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1229bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1230bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1231bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1232bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1233553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
12369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
12409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1241bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1242bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
124376989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1247bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
12489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
12499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1250bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1251bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1252553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1256bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1257bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1258bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1259bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1260bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1261bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1262553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1264bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
126576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1266bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1267bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1268553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
12692e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
12702e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
12712e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
12722e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
12732e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
12742e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
12752e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1276553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
12772e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
12782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
12792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
12802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
12812e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
12822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
12832e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
12842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
12852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
12862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
12872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
12882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
12892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
12902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
12912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
12922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1293bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1294bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1308bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1310e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid)
131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1317ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1318ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid && tcp->pid != pid)
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1327bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1335ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1336ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
134076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1345bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
134976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1353e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1354e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1355e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1356e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1357e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1358e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1359e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1360e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1361e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1362e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1365eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1366e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1367e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1368e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1369e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_DETACHED)
1370e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_detached--;
1371e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1372e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1373e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
13740962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED
13750962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath		if (!(tcp->flags & TCB_CLONE_DETACHED))
13760962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif
13770962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->parent->nzombies++;
1378276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#ifdef LINUX
1379276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		/* Update `tcp->parent->parent->nchildren' and the other fields
1380276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   like NCLONE_DETACHED, only for zombie group leader that has
1381276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   already reported and been short-circuited at the top of this
1382276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		   function.  The same condition as at the top of DETACH.  */
1383276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		if ((tcp->flags & TCB_CLONE_THREAD) &&
1384276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    tcp->parent->nclone_threads == 0 &&
1385276ceb33f20fc41403e46684e441230296f6a433Roland McGrath		    (tcp->parent->flags & TCB_EXITING))
1386276ceb33f20fc41403e46684e441230296f6a433Roland McGrath			droptcb(tcp->parent);
1387276ceb33f20fc41403e46684e441230296f6a433Roland McGrath#endif
1388e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1389e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1390e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1391e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1395bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1396bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1397bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1398bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1399bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1400bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1401bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1402bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1403bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1404553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1405bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1406e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1409eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1410822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1412eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1416bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1430e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1431e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1432e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1433e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1435732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0)
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14431bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathstatic int
14441bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrathresume_from_tcp (struct tcb *tcp)
14451bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath{
14461bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int error = 0;
14471bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int resumed = 0;
14481bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14491bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	/* XXX This won't always be quite right (but it never was).
14501bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
14511bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   a particular pgrp, which this child might or might not be
14521bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
14531bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
14541bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   difference to wake up a waiter when there might be more
14551bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   traced children, because it could get a false ECHILD
14561bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
14571bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
14581bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	   search the system for all pid's in the pgrp to be sure.
14591bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14601bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	     && (t->waitpid == -1 ||
14611bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
14621bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
14631bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	*/
14641bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14651bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent &&
14661bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
14671bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
14685ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		error = resume(tcp->parent);
14691bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		++resumed;
14701bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
14711bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifdef TCB_CLONE_THREAD
14721bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
14731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Some other threads of our parent are waiting too.  */
14741bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		unsigned int i;
14751bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
14761bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
14771bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
14781bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			struct tcb *t = tcbtab[i];
14791bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			if (t->parent == tcp->parent && t != tcp
14801bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
14811bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
14821bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && t->waitpid == tcp->pid) {
14831bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				error |= resume (t);
14841bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				++resumed;
14851bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
14861bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		}
14871bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath		if (resumed == 0)
14881bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			/* Noone was waiting for this PID in particular,
14891bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			   so now we might need to resume some wildcarders.  */
14901bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
14911bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				struct tcb *t = tcbtab[i];
14921bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				if (t->parent == tcp->parent && t != tcp
14931bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && ((t->flags
14941bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
14951bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
14961bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				    && t->waitpid <= 0
14971bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					) {
14981bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					error |= resume (t);
14991bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath					break;
15001bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				}
15011bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			}
15021bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	}
15033bb7cd6660032e97f76e8f62efd3540dbba97656Denys Vlasenko#endif
15041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
15051bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	return error;
15061bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath}
15071bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath
1508bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15100a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
15110a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
15120a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
15130a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1521ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
15221bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1523a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1524a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1525a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1526a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1527a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1528a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1529a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1530a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1531ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sig = SIGKILL;
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
15397bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
15407bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
15427bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
15437bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
15447bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
15457bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
154602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
154702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
154802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
154902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
155002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
155102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
15547bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
15557bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
15567bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
15577bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
15587bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1559134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1560134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1561134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
15627bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
15637bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
15647bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
156502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
156602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
156702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
15687bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
15697bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
15707bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
157102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
157202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1573ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
15757508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
15767508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
15777508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
15787508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
15797508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
15817508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
15827508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
15837508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
15847508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
15857508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
15867508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
15877508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
15887508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
15897508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
15907508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
15917508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
15927508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
15937508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
15947508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
15957508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
15967508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
15977508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
15987508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
15997508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
16007508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
16027508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1608732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1611732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
1612eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					WSTOPSIG(status) == SIGTRAP ? 0
1613732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1614732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1617ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
16187bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1625732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1628bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
16291bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	error |= resume_from_tcp (tcp);
1630e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1631e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1636a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1637a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX
16380a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	if (zombie != NULL) {
16390a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		/* TCP no longer exists therefore you must not detach () it.  */
16400a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(zombie);
16410a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	}
1642a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif
1643a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1647bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig)
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct tcb *tcp;
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pid2tcb(pid);
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp)
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1667bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1675ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1676ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
1684ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			tprintf(" <unfinished ...>");
1685ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17076d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
17106d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17298f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
17306d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
17328f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
17338f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
17348f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1755bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1762ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1763ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1764c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1765ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
176646100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "%s: out of memory\n", progname);
1767ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1768ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1769ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1770ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1771ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
17759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
179610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1844bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1845bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1846bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
1851a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
1875a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		_exit(1);
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1886bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
18875ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
18885ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
18895ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
18905ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
18919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
19249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
19599dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
1960d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
19619dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
19669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp = pid2tcb(0);
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
19939dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
19949dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
19959dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
19969dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
1997553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
19989dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
19999dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
20009dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
20019dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
20029dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
20039dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
20049dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
20059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
20069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
20079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
20089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
20109dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
20119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
20129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
20139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
20149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2038b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
20399dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2040b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2043bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
20449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
2045bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2046bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2047bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2048bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2049bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2050bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
2051bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
20525ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko				ioctl_result = IOCTL_WSTOP (tcp);
2053553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2076bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2077bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2078553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
20892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
20902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
20912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
20922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
20932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2094553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2095553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2104bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2105bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2106bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2107bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2108bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2109bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2110bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2111bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2112bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2113bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2114bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2115553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2118bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
21239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2124bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
21269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
21279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2134bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
21369dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
21379dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
21389dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2149ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2150ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
21515826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
21525826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
21535826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
21545826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
21555826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2156ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
21575826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
21585826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2165ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2168bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2169bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
21705ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2171553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
21739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2178553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
21799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
2180553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2181bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
2182553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2190bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2192e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2193e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2194e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2195e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2196e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2197e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2198e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2199e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2200e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2201e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2202e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2203e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
22047a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	struct tcb *leader = NULL;
22057a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko
22067a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	if (tcp->flags & TCB_CLONE_THREAD)
22077a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp->parent;
22087a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko	else if (tcp->nclone_detached > 0)
22097a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		leader = tcp;
2210e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2211e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
22127a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		if (leader != NULL && leader != tcp
22137a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(leader->flags & TCB_GROUP_EXITING)
22147a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		 && !(tcp->flags & TCB_STARTUP)
22157a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		) {
2216e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2217e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2218e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
22197a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		}
22207a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		/* TCP no longer exists therefore you must not detach() it.  */
22211bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#ifndef USE_PROCFS
22227a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		resume_from_tcp(tcp);
22231bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath#endif
22240a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2225e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2226e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2227a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2228a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2229e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
2230d6a32f176c7a07c72c69000c39a5a964e4168874Roland McGrath			detach(tcp, sig);
22315ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			if (leader != NULL && leader != tcp)
22321bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2233732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else {
2234732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_CONT, tcp, sig) < 0) {
2235732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				cleanup();
2236732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				return -1;
2237732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2238732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (leader != NULL) {
22390569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2240732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (leader != tcp)
2241732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					droptcb(tcp);
2242732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2243e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2244e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2245e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2246e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2247e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2248e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2249e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2250e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2251e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2252e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2253eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
2254eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace()
225576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
22622f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2263eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
22642f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2267eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2268222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2269eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2270eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2271eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
22732f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
2274eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
22755bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
22762f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
22772f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
22782f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
2279eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, wait4_options,
2280eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
22812f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
22825bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
22832f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
2284eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			pid = wait4(-1, &status, __WCLONE,
2285eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					cflag ? &ru : NULL);
2286eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			if (pid == -1) {
2287eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				fprintf(stderr, "strace: clone wait4 "
22882f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
22892f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
22902f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
2291eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#else
2292eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
2293eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* __WALL */
229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
229676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
229776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2299eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2300eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
230176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
230276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
2303eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2304eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2306eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
230776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
2314eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (nprocs == 0)
2315eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					return 0;
2316eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				fprintf(stderr, "strace: proc miscount\n");
2317eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				exit(1);
231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
2319eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2320eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2321eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2322eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2323eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
232476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
232610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
232710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
232810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				popen_pid = -1;
232910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
233010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
233176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
233276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
233376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
233476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
233576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2336e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
233741c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2338e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2339e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2340e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2341e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2342e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2343e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2344e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2345e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2346e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2347418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2348e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2349e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2350e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2351e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2352e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
23538b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2354e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2355e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2356e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2357eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2358e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2359e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2360e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2361e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2362e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2363e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
236476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2365eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2366eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
236784e20af5a6f3d6e02c24579b60a282053ef01e0eDenys Vlasenko		if (cflag) {
2368eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
236976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
237076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
2371eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif /* !LINUX */
237276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2373eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
2374f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		if (tcp->flags & TCB_SUSPENDED) {
2375f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			/*
2376f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Apparently, doing any ptrace() call on a stopped
2377f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process, provokes the kernel to report the process
2378f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * status again on a subsequent wait(), even if the
2379f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * process has not been actually restarted.
2380f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * Since we have inspected the arguments of suspended
2381f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 * processes we end up here testing for this case.
2382f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			 */
2383f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko			continue;
2384f9a7e63a1ad57a87c1e6be10b7a6b49282ed1203Denys Vlasenko		}
238576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2386a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2387a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
238876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
238976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
239076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
23912efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
23922efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
23932efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
23942efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
23952efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
23962efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
2397ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
239876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2399e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2400e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2401e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
240276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2403e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
240476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
240576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
240676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2407a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2408a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
240976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
24107a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status));
24117a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED
24120569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
24137a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			    && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING))
24141bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath			    && !(tcp->flags & TCB_GROUP_EXITING)
24150569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
24167a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			) {
241776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
24187a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					"PANIC: attached pid %u exited with %d\n",
24197a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					pid, WEXITSTATUS(status));
24207a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			}
24210a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
24227a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
24230a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
24240a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
24250a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
24260a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2427e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2428e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2429e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
243076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2431e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
243276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
243376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
243476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
243576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
243676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
243776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
243876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
243976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
244076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2441ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
244276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
244302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
244402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
244502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
2446eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		 * than SIGSTOP if we happend to attach
244702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
244802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
244902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
245076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
245176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
245476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
245576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
245602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
245776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
245802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
245902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
246076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
246176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
246276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
246376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
246476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
246576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
246676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
246776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
246876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
246976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2470eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (WSTOPSIG(status) != SIGTRAP) {
247176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
247276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
247476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
247576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
2478732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
248476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
248576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
24861f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				unsigned long addr = 0;
24871f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				long pc = 0;
24889633942c07427ed51caea0e73f139e964d1a19ccDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
24897b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#				define PSR_RI	41
24907b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				struct siginfo si;
24911f942710a57860eeabfa03e62b8ac151022d1be3Jan Kratochvil				long psr;
24927b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2493932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2494932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
24957b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
24967b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
24977b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
24987b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				addr = (unsigned long) si.si_addr;
24993a055d7d64222223da2550ca540043de7e3e232bRoland McGrath#elif defined PTRACE_GETSIGINFO
25003a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				if (WSTOPSIG(status) == SIGSEGV ||
25013a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				    WSTOPSIG(status) == SIGBUS) {
25023a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					siginfo_t si;
25033a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					if (ptrace(PTRACE_GETSIGINFO, pid,
25043a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						   0, &si) == 0)
25053a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						addr = (unsigned long)
25063a055d7d64222223da2550ca540043de7e3e232bRoland McGrath							si.si_addr;
25073a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				}
25087b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
25107b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tprintf("--- %s (%s) @ %lx (%lx) ---",
2511ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WSTOPSIG(status)),
25127b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					strsignal(WSTOPSIG(status)), pc, addr);
2513ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
251476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
25150569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
25160569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
251776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2518e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2519e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2520e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
252176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2522e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
252376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
252476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2525732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (ptrace_restart(PTRACE_SYSCALL, tcp, WSTOPSIG(status)) < 0) {
252676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
252776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
252876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
252976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
253076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
253176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
253202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
253302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
253402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
2535eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2536eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2537eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2538eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2539eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * all processes in thread group. In this case, threads
2540eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * "disappear" in an unpredictable moment without any
2541eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * notification to strace via wait().
2542ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2543ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2544eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (tcp_last) {
2545eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2546eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 * Finish the line then. We cannot
2547eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2548eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp_last->flags |= TCB_REPRINT;
2549eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tprintf(" <unfinished ...>");
2550eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					printtrailer();
2551eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
255276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2553ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2554eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				ptrace(PTRACE_KILL,
2555eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp->pid, (char *) 1, SIGTERM);
255676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
255776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
255876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
255976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
256076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2561e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2562e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2563e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2564e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2565e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2566e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2567e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
256876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
256976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2570732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			else if (ptrace_restart(PTRACE_CONT, tcp, 0) < 0) {
257176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
257276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
257376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
257576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
257676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
257776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
257876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
257976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
258076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
258176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
2582732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, 0) < 0) {
258376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
258476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
258576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
258676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
258776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
258876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
258976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2590bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
259176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
259276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol;
259376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
259476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
259576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
259676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b)
259776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
259876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h>
259976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a)
260076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
260176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
260276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
260376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
260476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
260576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
260676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist)
260776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
260876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl
260976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
261076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
261176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
261376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	VA_START(args, fmt);
2614b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2615b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2616b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		if (n < 0 && outf != stderr)
2617b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			perror(outfname == NULL
2618b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			       ? "<writing to pipe>" : outfname);
2619b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		else
2620b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2621b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
262276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
262376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
262476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
262576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
262676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2627eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathprintleader(tcp)
2628eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstruct tcb *tcp;
262976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2630732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2631eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tcp_last->ptrace_errno) {
2632732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
2633eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tprintf(" <unavailable>)");
2634eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				tabto(acolumn);
2635732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
2636eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf("= ? <unavailable>\n");
2637eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp_last->ptrace_errno = 0;
2638732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
26397e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
2640eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tprintf(" <unfinished ...>\n");
2641732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
264276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
264376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
264476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
264576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
264676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
264776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
264876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
264976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
265076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
265176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
265276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
265376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
265476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
265576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
265776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
265876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
265976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
266076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
266176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
266276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
266376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
266476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
266576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
266676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
266776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
266876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
266976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
267076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
267176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
267276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
267376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
267476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
267576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
267676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
267776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
267876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
267976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
268076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
268176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
268276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
268376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
268476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
268576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
268676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
268776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2688ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
268976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
269076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
269176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
269276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
26939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2694ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
26959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2696ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2697ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2698ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
26999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
27009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2701553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
27029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
27039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
27049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
27059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
27069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
27079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
27089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2709553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2710ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
27119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
27129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
27139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2714