strace.c revision f88837a666a716aecd9974f7ef3fcf006e0afce1
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved.
776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without
976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions
1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met:
1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright
1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer.
1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright
1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer in the
1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    documentation and/or other materials provided with the distribution.
1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products
1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    derived from this software without specific prior written permission.
1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *	$Id$
3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
35795edb11488dd47c4598e2228e3b5431de7ed46dRoland McGrath#include <sys/types.h>
363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko#include <stdarg.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h>
4770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
4876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
49134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX
50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h>
5144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# if defined __NR_tkill
5244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#  define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
53134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath   /* kill() may choose arbitrarily the target task of the process group
55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      while we later wait on a that specific TID.  PID process waits become
56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      TID task specific waits for a process under ptrace(2).  */
57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
5844f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#  define my_tkill(tid, sig) kill((tid), (sig))
59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif
60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif
61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath
627b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
637b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
66bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
67bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
68bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
7076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
7176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
72ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
731d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
7676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
771d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
7896d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
79418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
80418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
8196d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
8276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8341c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0;
84f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0;
853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */
8675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP;
87e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0;
88e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE;
89b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
90ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1078a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
1088a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint show_fd_path = 0;
1098a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
1118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint tracing_paths = 0;
1128a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
113a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
114a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
11575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
116eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
117b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
118ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid;
119ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid;
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
122102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic int acolumn = DEFAULT_ACOLUMN;
123102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic char *acolumn_spaces;
124b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
125ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic FILE *outf;
126ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
127ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab;
1282b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize;
129ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const char *progname;
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
131e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int detach(struct tcb *tcp, int sig);
132e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
133e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
134e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
143bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd);
146e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig);
147e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void);
148ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
152e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void);
153e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd);
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
171bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
174cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval)
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
1778a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsusage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
178de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
1798a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards              [-P path] [command [arg ...]]\n\
180b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab   or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
181de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
183b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
1928a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
199ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
203de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
204de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
2058a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
206de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
20717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
208de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
209de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
21475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
21575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
21675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
21775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
21875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
21975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
22075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
22175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
22275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
22375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2243454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
22544d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(NULL);
22644d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fprintf(stderr, "%s: ", progname);
22744d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	vfprintf(stderr, fmt, p);
22844d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	if (err_no)
22944d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin		fprintf(stderr, ": %s\n", strerror(err_no));
23044d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	else
23144d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin		putc('\n', stderr);
23244d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(stderr);
23375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
23475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
23575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
23675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
23775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
23875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
23975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
24175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
24375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
24475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
24575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
24675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
24775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
24875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
24975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
25175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
25275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
25575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
25675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
25775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
25975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...)
26075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
26175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
26275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
26375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
26475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
2653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
2663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
2671d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenkovoid die_out_of_memory(void)
2681d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko{
2691d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	static bool recursed = 0;
2701d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (recursed)
2711d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		exit(1);
2721d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	recursed = 1;
2731d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	error_msg_and_die("Out of memory");
2741d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko}
2751d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko
27676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
27976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
28376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
285c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
286c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
287c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
288c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
289c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
290c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
291c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
292c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
2931f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void
29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
2961f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	int flags, newflags;
2971f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko
2981f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	flags = fcntl(fd, F_GETFD);
2991f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	if (flags < 0) {
3001f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		/* Can happen only if fd is bad.
3011f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * Should never happen: if it does, we have a bug
3021f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * in the caller. Therefore we just abort
3031f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * instead of propagating the error.
3041f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 */
3051f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
3101f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		return;
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3121f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	fcntl(fd, F_SETFD, newflags); /* never fails */
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3257b609d5ba0852e6c56ba311350ebd4412361777bDenys Vlasenko	if (euid != uid && setreuid(euid, uid) < 0) {
326cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("setreuid");
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3314bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
3324bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
3334bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
3344bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
3354bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
3364bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
3383d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostrace_fopen(const char *path)
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
3433d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	fp = fopen_for_output(path, "w");
3443d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	if (!fp)
3453d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		perror_msg_and_die("Can't fopen '%s'", path);
34610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
3473d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	set_cloexec_flag(fileno(fp));
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3517dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenkostatic int popen_pid = 0;
35210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
35410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
35510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
35610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
35810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
36410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
3657dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	FILE *fp;
3667dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	int fds[2];
36710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
36910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
3707dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("pipe");
37110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3727dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	set_cloexec_flag(fds[1]); /* never fails */
37310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3747dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	popen_pid = vfork();
3757dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == -1)
3767dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("vfork");
37710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3787dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == 0) {
37910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
38010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
3817dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		if (fds[0] != 0) {
3827dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (dup2(fds[0], 0))
3837dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				perror_msg_and_die("dup2");
3847dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			close(fds[0]);
38510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
38610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
3877dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
38810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
3897dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko
3907dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	/* parent */
3917dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	close(fds[0]);
3927dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	swap_uid();
3937dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	fp = fdopen(fds[1], "w");
3947dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (!fp)
3951d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
3967dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	return fp;
39710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
39810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3993d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostatic void
40010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
40110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
40210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
4037a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
4047a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
4053d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		tcp->outf = strace_fopen(name);
40610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
40710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
40810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
4182e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	 * between PTRACE_ATTACH and wait4() on SIGSTOP.
419b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	 * We rely on cleanup() from this point on.
42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
42202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
424ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
425ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
426ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
427014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko			perror_msg_and_die("fork");
428ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
429ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
430ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
43175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
43275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
43375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
434ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
435ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
436ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
437ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
438ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
43975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
44075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
44175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
442ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
443ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
44644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko
447d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Is this a process we should attach to, but not yet attached? */
448d116a7338645af45090aecc331701e999148d284Denys Vlasenko		if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
449d116a7338645af45090aecc331701e999148d284Denys Vlasenko			continue; /* no */
450d116a7338645af45090aecc331701e999148d284Denys Vlasenko
451d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Reinitialize the output since it may have changed */
45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
4533d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		newoutf(tcp);
45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
45602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
45702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
46002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
463ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
4647a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
46702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
46802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
472381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
47302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
474381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					struct tcb *cur_tcp;
475381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					int tid;
476381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
4777a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
48202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
483f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
48402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
485f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						if (debug)
486f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d failed\n", tid);
487381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						continue;
488f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					}
489381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (debug)
490381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						fprintf(stderr, "attach to pid %d succeeded\n", tid);
491381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					cur_tcp = tcp;
492381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (tid != tcp->pid)
493381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						cur_tcp = alloctcb(tid);
494f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
49502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
497381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				if (interactive) {
498381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_SETMASK, &empty_set, NULL);
499381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (interrupted)
500381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						goto ret;
501381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_BLOCK, &blocked_set, NULL);
502381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				}
5037a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
5047a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
5107a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
5117a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
5127a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
51344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						tcp->pid, ntid);
51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
515f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				if (!(tcp->flags & TCB_STARTUP)) {
516f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					/* -p PID, we failed to attach to PID itself
517f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * but did attach to some of its sibling threads.
518f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * Drop PID's tcp.
519f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 */
520f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					droptcb(tcp);
521f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				}
52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
5237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
5247a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
52544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# endif /* LINUX */
52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
531f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
532f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko		if (debug)
533f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko			fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
534ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
535ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
536ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
537ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
538ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
539ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
540ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
541ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
542ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
543ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
544ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
545ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
546ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
547ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
553f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko	} /* for each tcbtab[] */
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
55544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko ret:
55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
5611201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
573cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
57802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
58730145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
621cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
623a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
624ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
625cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
626ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
62775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
62875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
629ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
630ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
6312e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		if (outf != stderr)
6322e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			close(fileno(outf));
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
6342e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# ifdef MIPS
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
6402e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# endif
6412e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# ifndef FREEBSD
64202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
6432e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# else
644014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko		kill(pid, SIGSTOP);
6452e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# endif
64602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
647ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
648ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
649cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
650ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
651ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
652ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
65302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
65402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
655ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		if (username != NULL) {
65602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
65702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
65802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
66002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
66102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
66202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
66302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
66402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
66502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
66602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
667ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (initgroups(username, run_gid) < 0) {
668ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("initgroups");
669ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
670ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setregid(run_gid, run_egid) < 0) {
671ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setregid");
672ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
673ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setreuid(run_uid, run_euid) < 0) {
674ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setreuid");
67502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
67602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
677ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		else if (geteuid() != 0)
67802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
67902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
680ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
681ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
6822e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Induce a ptrace stop. Tracer (our parent)
683ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
6842e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * the immediately following execve syscall.
6852e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Can't do this on NOMMU systems, we are after
6862e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * vfork: parent is blocked, stopping would deadlock.
687ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
688c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
6892e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko				kill(pid, SIGSTOP);
690ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
691ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
692ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
693ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
694ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
695ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
696ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
697ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
698ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
699ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
700ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
701ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
702ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
703ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
704ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
705ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
706ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
70702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
70802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
70902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
710cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("exec");
71102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
712ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
7132e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	/* We are the tracer */
71475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
7152e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	if (!daemonized_tracer) {
7162e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
717f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (!strace_vforked)
718f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
719f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		else
720f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags |= TCB_STARTUP;
7212e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	}
7222e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	else {
7232e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* With -D, *we* are child here, IOW: different pid. Fetch it: */
7242e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		strace_tracer_pid = getpid();
7252e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* The tracee is our parent: */
7262e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		pid = getppid();
7272e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
7282e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* We want subsequent startup_attach() to attach to it: */
729ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
730ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
73102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
732ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
733cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("trouble opening proc file");
73402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
7352e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko#endif
73602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
73702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
738b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX
73904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void kill_save_errno(pid_t pid, int sig)
74004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin{
74104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	int saved_errno = errno;
74204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin
74304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	(void) kill(pid, sig);
74404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	errno = saved_errno;
74504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin}
74604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin
747b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
748b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
749b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
750b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
751b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
75204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void
7533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
754b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
7552fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
7562fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
7572fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
7582fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
759b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
7605d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	pid = fork();
7615d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid < 0)
76204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		perror_msg_and_die("fork");
7635d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid == 0) {
76404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		pid = getpid();
76504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
76604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
76704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
76804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		kill(pid, SIGSTOP);
76904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (fork() < 0)
77004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("fork");
77104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		_exit(0);
772b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
773b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
774b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
775b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
776b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
77704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		errno = 0;
778b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
77904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (tracee_pid <= 0) {
780b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
781b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
782b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			else if (errno == ECHILD)
783b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
78404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
78504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
78604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
78704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
78804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFEXITED(status)) {
78904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (WEXITSTATUS(status)) {
79004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (tracee_pid != pid)
79104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					kill_save_errno(pid, SIGKILL);
79204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				error_msg_and_die("%s: unexpected exit status %u",
79304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin						  __func__, WEXITSTATUS(status));
79404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
79504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
79604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
79704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
79804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
79904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
80004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
80104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
80204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
80304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (!WIFSTOPPED(status)) {
80404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
80504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
80604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill(pid, SIGKILL);
80704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
80804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
809b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
810b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
8112fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
81204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
81304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
81404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
81504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg_and_die("PTRACE_CONT doesn't work");
81604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
81704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
818b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
81904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		switch (WSTOPSIG(status)) {
82004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGSTOP:
82104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
82204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
82304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
82404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
82504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGTRAP:
82604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (status >> 16 == PTRACE_EVENT_FORK) {
82704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				long msg = 0;
8282fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
82904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (ptrace(PTRACE_GETEVENTMSG, pid,
83004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   NULL, (long) &msg) == 0)
83104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					expected_grandchild = msg;
832b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
83304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
83404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
83504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
83604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
83704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
838b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
839b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
84004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild) {
841f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
84204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (debug)
84304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			fprintf(stderr, "ptrace_setoptions = %#x\n",
84404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				ptrace_setoptions);
84504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		return;
84604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	}
84704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACECLONE failed, "
84804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
849b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
8503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
8523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
8533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
8543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
8553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
8563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
8573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
8583454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
8593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
8603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
8613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
8623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
8633454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
8643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
8653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
8663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
8673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
86804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
86904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  PTRACE_O_TRACEEXEC;
8703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
8713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
8723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
8743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
87575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
8763454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8773454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
8783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
8793454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
88075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
88104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
88204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
8833454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
8843454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
8853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
8863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8873454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
8883454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
8893454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
8913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
8923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
8933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
8943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
89504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
89604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
89704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
89875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
89975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
90075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
90175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
90204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected exit status %u",
90304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WEXITSTATUS(status));
90404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
90504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
90604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
90704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
9083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
9103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
91104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
91204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
9133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
9153454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
9163454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
9173454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
9183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
9193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
9203454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
92104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
92204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
92304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
9243454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9253454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
9263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
9273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
92904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
93075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
9313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9323454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9333454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
93575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
936f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
9373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
938f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
939f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
9403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
9413454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9423454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
94304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
94404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
9453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
946b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif
947b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
94908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
95306350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
95608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
95708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
95875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
95975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
960ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
961ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
9624f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
9631d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcbtab)
9641d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
9654f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
9661d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcp)
9671d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
9684f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
9694f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
970ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
973138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
974138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
9808a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"+cCdfFhiqrtTvVxyz"
981ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
982ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
983ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
9848a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"a:e:o:O:p:s:S:u:E:P:")) != EOF) {
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
987e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
988cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
989e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
990e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
991e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
992e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
993e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
994cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
995e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
996e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1001ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
1002ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
1003ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
1004ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
1005ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
100641c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
100706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
100806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
101176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
102176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10348a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
10358a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
10368a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
10419c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
104417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
104517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
104617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
1049102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko			if (acolumn < 0)
1050102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko				error_msg_and_die("Bad column width '%s'", optarg);
105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
10625d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			pid = atoi(optarg);
10635d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			if (pid <= 0) {
1064cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("Invalid process id: '%s'", optarg);
106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
106775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (pid == strace_tracer_pid) {
1068cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("I'm sorry, I can't let you do that, Dave.");
106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1071418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10758a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
10768a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
10778a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1078cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
10798a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
10808a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1083dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1084cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Invalid -s argument: '%s'", optarg);
1085dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1093de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
10941d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			if (putenv(optarg) < 0)
10951d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko				die_out_of_memory();
1096de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1103102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces = malloc(acolumn + 1);
1104102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (!acolumn_spaces)
11051d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
1106102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	memset(acolumn_spaces, ' ', acolumn);
1107102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces[acolumn] = '\0';
1108102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko
1109d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
1110ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1111ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1112d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	if (pflag_seen && daemonized_tracer) {
1113cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive options");
1114d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1115d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
111606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
111706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
111806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1119cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1120cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
1121cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1122cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1128cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
11305d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		pent = getpwnam(username);
11315d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (pent == NULL) {
1132cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
113776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
114176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11428044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX
114304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (followfork)
114404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		test_ptrace_setoptions_followfork();
11453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
11468044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif
11478044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
114876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
115037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
115137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
115237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
115337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
115437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
115537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
11567dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (followfork > 1)
11577dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
11587dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			outf = strace_popen(outfname + 1);
115954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
11603d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		else if (followfork <= 1)
11613d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko			outf = strace_fopen(outfname);
116276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1164cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1165cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		static char buf[BUFSIZ];
116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
1167cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
116837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1171369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1172b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
117354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
117454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   optind < argc	pflag_seen	outfname	interactive
117554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		0		1
117654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		0		1
117754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   1			0		1		0
117854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   0			1		1		1
117954cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
118054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
118154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
118254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
118354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
118454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
118554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	if (!pflag_seen)
118654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath		startup_child(&argv[optind]);
118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
119776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
1212bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
1215553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1216553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1217553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1218553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1219553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1220553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1221553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1222553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
1223bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1225ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
122602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
122702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
122876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
1231a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
1232a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
1233a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
1234a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
1235a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
1236a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
1237a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
1238a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
1239a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
1240a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
1241a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12442b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic void
1245418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
12467b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
12477b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
12487b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
12497b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
12507b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
12517b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
125218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	int i = tcbtabsize;
125318da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
125418da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
12551d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!newtab || !newtcbs)
12561d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
12577b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
12587b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
125918da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	while (i < tcbtabsize)
126018da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		tcbtab[i++] = newtcbs++;
12617b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
12627b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
126410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
126576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1269418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1270418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1271418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1272ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1273ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
127476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
127518da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko			memset(tcp, 0, sizeof(*tcp));
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
1277381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko			tcp->flags = TCB_INUSE;
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
12798dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#ifdef USE_PROCFS
128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
12818dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#endif
128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
12831d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (debug)
12841d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
128510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
128610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
129018da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	error_msg_and_die("bug in alloc_tcb");
129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1293bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1295418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1299bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
130019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
130119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1304bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1309ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
13109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
13119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
13125d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd = open(proc, O_WRONLY|O_EXCL);
13135d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd < 0) {
13149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13171f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
13189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
13195d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
13205d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd_stat < 0) {
13219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13241f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_stat);
13259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
13265d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
13275d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd_as < 0) {
13289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13311f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_as);
13329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
13340890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko# ifndef FREEBSD
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
1336372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR|O_EXCL);
13370890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko# else
1338bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1339372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR);
13400890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko# endif
1341372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	if (tcp->pfd < 0) {
134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
13451f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
13469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1347bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1348bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
13495d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd_reg = open(proc, O_RDONLY);
13505d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd_reg < 0) {
1351bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1352bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1353bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1354bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1355bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
13565d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp->pfd_status = open(proc, O_RDONLY);
13575d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp->pfd_status < 0) {
1358bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1359bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1360bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1361bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1362bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1363bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
1371b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_STATUS(tcp) < 0) {
137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
13759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1376cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				break;
137776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
137876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1379bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
138076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
138116a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
138276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
138376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1385553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
138776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
138876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
13899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
139076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
13959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1400553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1409bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1410bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1411bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1412bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
14135ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1414bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1415bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1416bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
14175ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
14185ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1419bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1420bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1422bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
142319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
142419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
142519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
142619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
1427b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
142819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
1429b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	praddset(&syscalls, SYS_execve);
143019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
1431b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork);
143219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
1433b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_forkall);
143419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1435553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
1436b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork1);
143719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
143819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
1439b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rfork1);
144019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
144119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
1442b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rforkall);
144319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
144419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
144519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
144919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
145019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
145419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
145519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
145619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
145719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
1458b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
145919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
14609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
146419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
146519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
146619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
146719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
1468b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
146919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
14709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1474bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1475bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1476b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	arg = S_SIG | S_SCE | S_SCX;
1477b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1478bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1479bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1480bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1481bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
148676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
148876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
148976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1490553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
14929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
1493b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
149576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
149676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1497553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1498bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1499bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1500bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1501bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1502553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
1505b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_WSTOP(tcp) < 0) {
150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
15099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1510bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
151106602d99b72564e77600fc7c94e9ce8b78ec7085Denys Vlasenko				get_scno(tcp);
151276989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1516bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
15179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
15180890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
15190890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko#else
15200890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
15210890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko#endif
15220890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko			{
152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1526bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1527bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1528bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1529bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1530bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1531bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1532553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
15350890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko#ifdef FREEBSD
15360890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko	else {
1537553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
15382e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
15392e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
15402e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
15412e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
15422e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
15432e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
15442e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1545553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
15462e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
15472e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
15482e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
15492e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
15502e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
15512e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
15522e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
15532e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
15542e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
15552e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
15562e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
15572e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
15582e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
15592e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
15602e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
15612e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1562bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1563bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1577bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1579e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
158054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
158354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
158454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
158554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1587ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
158854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
158954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
159254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1596bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
159954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void)
160054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{
160154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	int i;
160254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	struct tcb *tcp;
160354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
160454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		tcp = tcbtab[i];
160554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->flags & TCB_INUSE)
160654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath			return tcp;
160754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	}
160854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	return NULL;
160954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath}
161054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
161154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb *
16121201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkopfd2tcb(int pfd)
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1616ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1617ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1626bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
16291201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
163319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
16351d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko	if (debug)
16361d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
1637eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
16388dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#ifdef USE_PROCFS
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
16428dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko# ifdef FREEBSD
1643bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1644bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1645bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1646bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1647bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1648bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1649bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1650bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
16518dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko# endif
165219cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko		tcp->flags = 0; /* rebuild_pollv needs it */
165319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko		rebuild_pollv();
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
16558dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#endif
1656eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1657822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1659eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
166019cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko	memset(tcp, 0, sizeof(*tcp));
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16630a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
16640a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
16650a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
16660a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
16691201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodetach(struct tcb *tcp, int sig)
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1672ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
16731bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1674ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1677840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
16827bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
16837bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
16857bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
16867bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
16877bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
16887bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
168902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
1690f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	 * We did PTRACE_ATTACH but possibly didn't see the expected SIGSTOP.
1691f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	 * We must catch exactly one as otherwise the detached process
1692f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	 * would be left stopped (process state T).
169302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
1694f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
16955d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig);
16965d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (error == 0) {
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
16987bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
16997bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
17007bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
17017bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
17027bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
170344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	else if (my_tkill(tcp->pid, 0) < 0) {
17047bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
17057bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
17067bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
170744f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
17087bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
17097bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
17107bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
171102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
171202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1713ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
17157508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
17167508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
17177508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
17187508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
17197508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
17217508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
17227508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
17237508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
17247508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
17257508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
17267508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
17277508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
17287508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
17297508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
17307508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
17317508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
17327508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
17337508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
17347508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
17357508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
17367508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
17377508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
17387508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
17397508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
17407508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
17427508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
1748732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, sig);
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1751732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
175275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1753732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1754732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1757ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
17587bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
1765732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, sig);
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1772a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1776bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1778e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig)
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1787bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
17901201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1795ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1796ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
180460fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko			tprints(" <unfinished ...>");
1805ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18191201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18266d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
18296d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
18321201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no)
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183635aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
183735aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
184035aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	return sys_errlist[err_no];
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18478f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
18486d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
18508f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
18518f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
18528f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
18551201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig)
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1872bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18751201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkorebuild_pollv(void)
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1879cfd364b011e170377ae002551c4391c01f51acbfDenys Vlasenko	free(pollv);
1880cfd364b011e170377ae002551c4391c01f51acbfDenys Vlasenko	pollv = malloc(nprocs * sizeof(pollv[0]));
18811d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!pollv)
18821d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
1883ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1884ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1885ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
18899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
1893cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("proc miscount");
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19001201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll_open(void)
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
1905cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("pipe");
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
19081f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		set_cloexec_flag(proc_poll_pipe[i]);
190976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
19131201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll(struct pollfd *pollv, int nfds, int timeout)
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19195d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
19205d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (n < 0)
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
1923cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("panic: short read: %d", n);
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19361201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkowakeup_handler(int sig)
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19411201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poller(int pfd)
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1949bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1950bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1951bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
1955cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1978cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1989bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
19905ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
19915ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
19925ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
19935ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
19949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
20279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
2034b88f96129f8ebc064d490c8c161bcbc925d938c8Denys Vlasenko		if (tcp && exiting(tcp))
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
2044cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("lost proc");
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2054cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	error_msg_and_die("nothing ready");
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
20581201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
20609dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
2061d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
20629dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
20679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
208154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath				tcp = first_used_tcb();
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
20949dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
20959dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
20969dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
20979dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2098553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
20999dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
21009dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
21019dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
21029dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
21039dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
21049dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
21055d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko				what = poll(&pv, 1, 1);
21065d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko				if (what < 0) {
21079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
21089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
21099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
21109dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
21119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
21129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
21139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
21149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
21159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
21169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
21365d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pfd2tcb(pfd);
21375d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp == NULL) {
2138cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("unknown pfd: %u", pfd);
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2140b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
21419dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2142b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2145bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
2146b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			ioctl_result = IOCTL_WSTOP(tcp);
2147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2148bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2149bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2150bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2151bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2152b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_STATUS(tcp);
2153bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
2154b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_WSTOP(tcp);
2155553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2178bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2179bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2180553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
2185cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("PIOCWSTOP");
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
21902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
21912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
2192b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			IOCTL(tcp->pfd, PIOCRUN, 0);
21932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
21942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2195553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2196553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
2202ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2206bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2207bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2208bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2209bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
22105d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
22115d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			if (len > 0) {
2212bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2213bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2214bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2215bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2216bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2217bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2218553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
222076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2221bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
222376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
222476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
22259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
22269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2227bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
22299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
22309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
223176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
2232cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					error_msg_and_die("syscall trouble");
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2236bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
22389dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
22399dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
22409dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
224176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
2243cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("syscall trouble");
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
224676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
2247e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2248e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_SIGNAL)) {
224976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2251ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2252ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
22535826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
22545826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
22555826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
225660fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko					tprints("    siginfo=");
22575826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2258ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
22595826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
22605826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
2264e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAGS_ONLY_STATS
2265e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_FAULT)) {
226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2268ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2271bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2272bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
22735ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2274553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
227576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
2276cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2279ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2280ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
22819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2282553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
2283b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
2284553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2285b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
2286553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2287372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		{
2288cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("PIOCRUN");
228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
229176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
229276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
229376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2294bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2296eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
2297eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace()
229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
229976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
230076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
23016cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko	int status, sig;
230276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
230376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
230476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
230526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko	struct rusage *rup = cflag ? &ru : NULL;
230626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
2307eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
230826d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2311eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2312222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2313eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2314eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2315eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
231726d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
231826d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, wait4_options, rup);
23195bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
23202f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
23212f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
232226d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, wait4_options, rup);
23232f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
23245bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
23252f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
232626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, __WCLONE, rup);
232726d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			if (pid < 0) {
2328cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
23292f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
23302f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
233126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# else
233226d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, 0, rup);
233326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif /* __WALL */
233476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
233576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
233676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
233726d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko#endif
233876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2339eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2340eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
234176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
234226d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		if (pid < 0) {
2343eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2344eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
234576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2346eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
234876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
234976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
235076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
235176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
2353eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2354eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2355eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2356eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2357eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
235876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
235976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
236010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
236110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
23627dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
236310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
236410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
23651d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		if (debug) {
23661d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
23671d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef LINUX
23681d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			unsigned ev = (unsigned)status >> 16;
23691d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (ev) {
23701d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				static const char *const event_names[] = {
23711d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_CLONE] = "CLONE",
23721d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_FORK]  = "FORK",
23731d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK] = "VFORK",
23741d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
23751d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXEC]  = "EXEC",
23761d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXIT]  = "EXIT",
23771d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				};
23781d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				const char *e;
23791d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				if (ev < ARRAY_SIZE(event_names))
23801d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					e = event_names[ev];
23811d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				else {
23821d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					sprintf(buf, "?? (%u)", ev);
23831d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					e = buf;
23841d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				}
23851d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, " PTRACE_EVENT_%s", e);
23861d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			}
23871d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
23881d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			strcpy(buf, "???");
23891d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSIGNALED(status))
23901d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP
23911d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,%ssig=%s",
23921d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						WCOREDUMP(status) ? "core," : "",
23931d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
23941d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else
23951d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,sig=%s",
23961d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
23971d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
23981d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFEXITED(status))
23991d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
24001d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSTOPPED(status))
24011d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
24025bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED
24031d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFCONTINUED(status))
24041d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				strcpy(buf, "WIFCONTINUED");
24055bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif
24061d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
24071d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		}
240876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
240976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
24105d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pid2tcb(pid);
24115d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp == NULL) {
2412e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
241341c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2414e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2415e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2416e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2417e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2418e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2419e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2420e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2421e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2422e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2423418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2424f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
2425e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2426833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko					fprintf(stderr, "Process %d attached\n",
2427e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
24288b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2429e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2430e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2431e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2432eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2433e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2434e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2435e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2436cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
2437e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
243876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2439eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2440eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
2441ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
2442eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
244313d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko		if (cflag) {
244476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
244576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
244676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
244713d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#endif
2448eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2450a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2451a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2452e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
245476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
245513d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP
24562efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
24572efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
245813d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					WCOREDUMP(status) ? "(core dumped) " : "");
245913d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else
246013d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko				tprintf("+++ killed by %s +++",
246113d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					signame(WTERMSIG(status)));
24622efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
2463ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
246476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
246576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
246676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
246776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
246876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2469a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2470a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
24710a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
24727a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
24730a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
24740a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
24750a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
24760a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
247719cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
247819cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printleader(tcp);
247919cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				tprintf("+++ exited with %d +++", WEXITSTATUS(status));
248019cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printtrailer();
248119cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			}
248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
248476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
248576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
248676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
248776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
248876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
248976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
249076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2491f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this the very first time we see this tracee stopped? */
2492f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (tcp->flags & TCB_STARTUP) {
2493f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			if (debug)
2494f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
249602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
249776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
249802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
24992ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko				 * parent through fork().
250076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
25016cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko				if (clearbpt(tcp) < 0) {
25026cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko					/* Pretty fatal */
250376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
250476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
250576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
250676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
250776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2508ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
250944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko			if (ptrace_setoptions) {
251044f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (debug)
251144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
251244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
251344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					if (errno != ESRCH) {
251444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						/* Should never happen, really */
251544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						perror_msg_and_die("PTRACE_SETOPTIONS");
25163454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
25173454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
25183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2519ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
2520f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2521f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2522f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (((unsigned)status >> 16) != 0) {
2523f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			/* Ptrace event (we ignore all of them for now) */
2524f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			goto restart_tracee_with_sig_0;
2525f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2526f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2527f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		sig = WSTOPSIG(status);
2528f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2529f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this post-attach SIGSTOP?
2530f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * Interestingly, the process may stop
2531f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * with STOPSIG equal to some other signal
2532f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * than SIGSTOP if we happend to attach
2533f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * just before the process takes a signal.
2534f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 */
2535f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2536f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			if (debug)
2537f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2538f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
25396cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee_with_sig_0;
254076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
254176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
25426cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (sig != syscall_trap_sig) {
25436cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			if (sig == SIGSTOP &&
254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
254676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
254776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
254876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
254976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
25506cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko				goto restart_tracee_with_sig_0;
255176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2552e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
25536cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			    && (qual_flags[sig] & QUAL_SIGNAL)) {
2554c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin				siginfo_t si;
2555c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
25566b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
25576b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
25587b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2559932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2560932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
25617b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
25626b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
25637b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
25646b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
25652ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	, pc
25666b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
25672ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_STR	""
25682ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	/* nothing */
25697b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
257076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
25716b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
257260fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko					tprints("--- ");
25736b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
25746b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf(" (%s)" PC_FORMAT_STR " ---",
25756cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						strsignal(sig)
25766b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
25776b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
25786b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- %s by %s" PC_FORMAT_STR " ---",
25796cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						strsignal(sig),
25806cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						signame(sig)
25816b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
2582ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
258376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
25846cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee;
258576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
25862ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
25872ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* We handled quick cases, we are permitted to interrupt now. */
258802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
258902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
25902ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
25912ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* This should be syscall entry or exit.
25922ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * (Or it still can be that pesky post-execve SIGTRAP!)
25932ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * Handle it.
25942ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 */
2595eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2596eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2597eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2598eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2599eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * all processes in thread group. In this case, threads
2600eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * "disappear" in an unpredictable moment without any
2601eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * notification to strace via wait().
2602ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2603ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2604eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (tcp_last) {
2605eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2606178de007d14f3ae890117b540def9cf14bcb61feDenys Vlasenko					 * Finish the line then.
2607eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2608eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp_last->flags |= TCB_REPRINT;
260960fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko					tprints(" <unfinished ...>");
2610eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					printtrailer();
2611eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
261276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
2613ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2614eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				ptrace(PTRACE_KILL,
2615eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp->pid, (char *) 1, SIGTERM);
261676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
261776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
261876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
261976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
26206cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee_with_sig_0:
26216cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		sig = 0;
26226cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee:
2623ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2624ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
26256cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
262676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
262776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
262876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
262976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
263076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
263176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
263276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2633bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
263476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
263576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
263676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
263776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
263876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
263976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2640e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab	va_start(args, fmt);
2641b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2642b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2643ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		if (n < 0) {
2644ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			if (outf != stderr)
2645ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				perror(outfname == NULL
2646ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				       ? "<writing to pipe>" : outfname);
2647ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		} else
2648b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2649b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
265076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
26515940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko}
26525940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko
26535940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenkovoid
26545940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenkotprints(const char *str)
26555940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko{
26565940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko	if (outf) {
26575940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		int n = fputs(str, outf);
26585940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		if (n >= 0) {
26595940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			curcol += strlen(str);
26605940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			return;
26615940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		}
26625940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		if (outf != stderr)
26635940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			perror(outfname == NULL
26645940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			       ? "<writing to pipe>" : outfname);
26655940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko	}
266676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
266776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
266876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
26691201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintleader(struct tcb *tcp)
267076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2671732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2672eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tcp_last->ptrace_errno) {
2673732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
267460fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko				tprints(" <unavailable>) ");
2675102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko				tabto();
2676732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
267760fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko			tprints("= ? <unavailable>\n");
2678eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp_last->ptrace_errno = 0;
2679732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
26807e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
268160fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko			tprints(" <unfinished ...>\n");
2682732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
268376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
268476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
268576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
268676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
268776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
268876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
268976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
269076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
269176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
269276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
269376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
269476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
269576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
269676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
269776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
269876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
269976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
270076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
270176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
270276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
270376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
270476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
270576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
270676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
270776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
270876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
270976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
271076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
271176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
271276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
271376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
271476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
271576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
271676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
271776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
271876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
271976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
272076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2721102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkotabto(void)
272276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2723102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (curcol < acolumn)
27245940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		tprints(acolumn_spaces + curcol);
272576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
272676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
272776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2728ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
272976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
273060fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko	tprints("\n");
273176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
273276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
27339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2734ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
27359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2736ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2737ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2738ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
27399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
27409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2741553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
27429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
27439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
27449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
27459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
27469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
27479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
27489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2749553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2750ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
27519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
27529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
27539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2754