strace.c revision eebb04d4ae8bf4b08a041f5ea442ca24c90692c2
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;
89aa6ec415c1a9b8a886bddf0db765b5de365a8360Denys Vlasenkostatic int iflag = 0, pflag_seen = 0, rflag = 0, tflag = 0;
90aa6ec415c1a9b8a886bddf0db765b5de365a8360Denys Vlasenkostatic int interactive = 1;
91ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
92ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
93ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
94ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
95ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
96ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
97ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
98ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
99ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
100ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
101ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
102ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
103ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
10617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
10717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1088a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
1098a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint show_fd_path = 0;
1108a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1118a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
1128a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint tracing_paths = 0;
1138a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
114a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
115a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
11675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
117eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
118b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
119ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid;
120ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid;
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
123102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic int acolumn = DEFAULT_ACOLUMN;
124102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic char *acolumn_spaces;
125b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
126ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic FILE *outf;
127ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
128ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab;
1292b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize;
130ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const char *progname;
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1324c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkostatic int detach(struct tcb *tcp);
133e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
134e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
135e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
14076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
14176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
146e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd);
147e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig);
148e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void);
149ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void);
154e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd);
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
172bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
175cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval)
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
1788a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsusage: strace [-CdDffhiqrtttTvVxxy] [-a column] [-e expr] ... [-o file]\n\
179de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
1808a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards              [-P path] [command [arg ...]]\n\
181b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab   or: strace -c [-D] [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
182de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
184b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
1938a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
19476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
19576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
19676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
19776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
200ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
204de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
205de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
2068a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
207de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
20817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
209de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
210de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
21575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
21675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
21775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
21875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
21975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
22075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
22175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
22275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
22375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
22475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2253454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
22682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	char *msg;
22782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
22844d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(NULL);
22982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
23082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We want to print entire message with single fprintf to ensure
23182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * message integrity if stderr is shared with other programs.
23282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * Thus we use vasprintf + single fprintf.
23382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 */
23482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	msg = NULL;
235cfad543087d98c5313fd7f006c0de69a1d87dc8eDenys Vlasenko	if (vasprintf(&msg, fmt, p) >= 0) {
23682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
23782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
23882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
23982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s\n", progname, msg);
24082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		free(msg);
24182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	} else {
24282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		/* malloc in vasprintf failed, try it without malloc */
24382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		fprintf(stderr, "%s: ", progname);
24482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		vfprintf(stderr, fmt, p);
24582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
24682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, ": %s\n", strerror(err_no));
24782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
24882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			putc('\n', stderr);
24982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	}
25082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We don't switch stderr to buffered, thus fprintf(stderr)
25182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * always flushes its output and this is not necessary: */
25282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* fflush(stderr); */
25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
25575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
25675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
25775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
25875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
25975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
26175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
26375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
26475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
26575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
26675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
26775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
26875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
26975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
27075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
27175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
27275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
27375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
27475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
27575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
27675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
27775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
27875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
27975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...)
28075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
28175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
28275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
28375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
28475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
2853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
2863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
2871d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenkovoid die_out_of_memory(void)
2881d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko{
2891d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	static bool recursed = 0;
2901d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (recursed)
2911d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		exit(1);
2921d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	recursed = 1;
2931d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	error_msg_and_die("Out of memory");
2941d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko}
2951d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko
29676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
29776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
29876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
29976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
30076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
30176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
30276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
30376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
30476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
305c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
306c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
307c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
308c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
309c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
310c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
311c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
312c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
3131f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
3161f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	int flags, newflags;
3171f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko
3181f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	flags = fcntl(fd, F_GETFD);
3191f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	if (flags < 0) {
3201f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		/* Can happen only if fd is bad.
3211f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * Should never happen: if it does, we have a bug
3221f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * in the caller. Therefore we just abort
3231f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * instead of propagating the error.
3241f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 */
3251f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
3301f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		return;
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3321f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	fcntl(fd, F_SETFD, newflags); /* never fails */
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
34410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3457b609d5ba0852e6c56ba311350ebd4412361777bDenys Vlasenko	if (euid != uid && setreuid(euid, uid) < 0) {
346cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("setreuid");
34710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
34810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
34910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
35010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3514bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
3524bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
3534bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
3544bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
3554bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
3564bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
35710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
3583d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostrace_fopen(const char *path)
35910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
36010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
36110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
3633d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	fp = fopen_for_output(path, "w");
3643d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	if (!fp)
3653d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		perror_msg_and_die("Can't fopen '%s'", path);
36610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
3673d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	set_cloexec_flag(fileno(fp));
36810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
36910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
37010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3717dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenkostatic int popen_pid = 0;
37210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
37310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
37410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
37510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
37610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
37710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
37810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
37910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
38010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
38110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
38210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
38310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
38410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
3857dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	FILE *fp;
3867dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	int fds[2];
38710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
38810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
38910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
3907dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("pipe");
39110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3927dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	set_cloexec_flag(fds[1]); /* never fails */
39310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3947dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	popen_pid = vfork();
3957dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == -1)
3967dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("vfork");
39710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3987dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == 0) {
39910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
40010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
4017dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		if (fds[0] != 0) {
4027dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (dup2(fds[0], 0))
4037dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				perror_msg_and_die("dup2");
4047dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			close(fds[0]);
40510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
40610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
4077dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
40810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
4097dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko
4107dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	/* parent */
4117dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	close(fds[0]);
4127dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	swap_uid();
4137dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	fp = fdopen(fds[1], "w");
4147dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (!fp)
4151d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
4167dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	return fp;
41710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
41810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4193d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostatic void
42010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
42110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
42210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
4237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
4247a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
4253d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		tcp->outf = strace_fopen(name);
42610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
42710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
42810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
43702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
4382e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	 * between PTRACE_ATTACH and wait4() on SIGSTOP.
439b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	 * We rely on cleanup() from this point on.
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
444ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
445ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
446ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
447014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko			perror_msg_and_die("fork");
448ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
449ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
450ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
45175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
45275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
45375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
454ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
455ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
456ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
457ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
458ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
45975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
46075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
46175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
462ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
463ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
46644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko
467d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Is this a process we should attach to, but not yet attached? */
468d116a7338645af45090aecc331701e999148d284Denys Vlasenko		if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
469d116a7338645af45090aecc331701e999148d284Denys Vlasenko			continue; /* no */
470d116a7338645af45090aecc331701e999148d284Denys Vlasenko
471d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Reinitialize the output since it may have changed */
47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
4733d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		newoutf(tcp);
47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
48202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
483ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
4847a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
48502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
48602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
48702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
48802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
48902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
49002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
49102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
492381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
49302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
494381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					struct tcb *cur_tcp;
495381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					int tid;
496381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
4977a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
503f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) {
50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
505f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						if (debug)
506f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d failed\n", tid);
507381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						continue;
508f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					}
509381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (debug)
510381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						fprintf(stderr, "attach to pid %d succeeded\n", tid);
511381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					cur_tcp = tcp;
512381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (tid != tcp->pid)
513381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						cur_tcp = alloctcb(tid);
514f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
517381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				if (interactive) {
518381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_SETMASK, &empty_set, NULL);
519381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (interrupted)
520381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						goto ret;
521381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_BLOCK, &blocked_set, NULL);
522381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				}
5237a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
5247a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
5307a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
5317a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
5327a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
53344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						tcp->pid, ntid);
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
535f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				if (!(tcp->flags & TCB_STARTUP)) {
536f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					/* -p PID, we failed to attach to PID itself
537f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * but did attach to some of its sibling threads.
538f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * Drop PID's tcp.
539f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 */
540f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					droptcb(tcp);
541f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				}
54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
5437a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
5447a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
54544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# endif /* LINUX */
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
551f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
552f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko		if (debug)
553f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko			fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
554ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
555ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
556ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
557ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
558ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
559ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
560ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
561ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
562ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
563ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
564ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
565ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
566ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
567ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
573f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko	} /* for each tcbtab[] */
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
57544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko ret:
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
57802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
5811201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
593cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
60730145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
62102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
62302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
62902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
641cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
64202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
643a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
644ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
645cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
646ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
64775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
64875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
649ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
650ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
6512e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		if (outf != stderr)
6522e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			close(fileno(outf));
65302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
6542e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# ifdef MIPS
65502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
65602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
65702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
65802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
6602e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# endif
6612e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# ifndef FREEBSD
66202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
6632e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# else
664014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko		kill(pid, SIGSTOP);
6652e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# endif
66602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
667ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
668ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
669cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
670ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
671ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			if (debug)
672ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko				kill(pid, SIGSTOP);
67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
67402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
675ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		if (username != NULL) {
67602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
67702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
67802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
67902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
68002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
68102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
68202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
68302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
68402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
68502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
68602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
687ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (initgroups(username, run_gid) < 0) {
688ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("initgroups");
689ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
690ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setregid(run_gid, run_egid) < 0) {
691ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setregid");
692ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
693ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setreuid(run_uid, run_euid) < 0) {
694ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setreuid");
69502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
69602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
697ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		else if (geteuid() != 0)
69802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
69902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
700ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
701ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
7022e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Induce a ptrace stop. Tracer (our parent)
703ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
7042e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * the immediately following execve syscall.
7052e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Can't do this on NOMMU systems, we are after
7062e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * vfork: parent is blocked, stopping would deadlock.
707ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
708c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
7092e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko				kill(pid, SIGSTOP);
710ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
711ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
712ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
713ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
714ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
715ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
716ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
717ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
718ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
719ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
720ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
721ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
722ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
723ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
724ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
725ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
726ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
72702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
72802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
72902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
730cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("exec");
73102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
732ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
7332e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	/* We are the tracer */
73475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
7352e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	if (!daemonized_tracer) {
7362e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
737f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (!strace_vforked)
738f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags |= TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
739f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		else
740f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags |= TCB_STARTUP;
7412e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	}
7422e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	else {
7432e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* With -D, *we* are child here, IOW: different pid. Fetch it: */
7442e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		strace_tracer_pid = getpid();
7452e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* The tracee is our parent: */
7462e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		pid = getppid();
7472e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
7482e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* We want subsequent startup_attach() to attach to it: */
749ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
750ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
75102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
752ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
753cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("trouble opening proc file");
75402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
7552e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko#endif
75602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
75702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
758b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX
75904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void kill_save_errno(pid_t pid, int sig)
76004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin{
76104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	int saved_errno = errno;
76204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin
76304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	(void) kill(pid, sig);
76404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	errno = saved_errno;
76504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin}
76604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin
767b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
768b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
769b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
770b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
771b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
77204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void
7733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
774b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
7752fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
7762fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
7772fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
7782fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
779b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
7805d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	pid = fork();
7815d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid < 0)
78204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		perror_msg_and_die("fork");
7835d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid == 0) {
78404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		pid = getpid();
78504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
78604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
78704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
78804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		kill(pid, SIGSTOP);
78904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (fork() < 0)
79004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("fork");
79104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		_exit(0);
792b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
793b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
794b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
795b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
796b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
79704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		errno = 0;
798b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
79904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (tracee_pid <= 0) {
800b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
801b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
802b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			else if (errno == ECHILD)
803b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
80404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
80504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
80604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
80704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
80804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFEXITED(status)) {
80904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (WEXITSTATUS(status)) {
81004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (tracee_pid != pid)
81104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					kill_save_errno(pid, SIGKILL);
81204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				error_msg_and_die("%s: unexpected exit status %u",
81304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin						  __func__, WEXITSTATUS(status));
81404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
81504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
81604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
81704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
81804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
81904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
82004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
82104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
82204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
82304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (!WIFSTOPPED(status)) {
82404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
82504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
82604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill(pid, SIGKILL);
82704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
82804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
829b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
830b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
8312fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
83204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
83304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
83404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
83504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg_and_die("PTRACE_CONT doesn't work");
83604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
83704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
838b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
83904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		switch (WSTOPSIG(status)) {
84004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGSTOP:
84104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
84204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
84304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
84404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
84504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGTRAP:
84604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (status >> 16 == PTRACE_EVENT_FORK) {
84704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				long msg = 0;
8482fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
84904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (ptrace(PTRACE_GETEVENTMSG, pid,
85004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   NULL, (long) &msg) == 0)
85104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					expected_grandchild = msg;
852b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
85304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
85404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
85504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
85604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
85704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
858b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
859b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
86004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild) {
861f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
86204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (debug)
86304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			fprintf(stderr, "ptrace_setoptions = %#x\n",
86404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				ptrace_setoptions);
86504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		return;
86604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	}
86704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACECLONE failed, "
86804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
869b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
8703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
8723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
8733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
8743454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
8753454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
8763454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
8773454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
8783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
8793454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
8803454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
8813454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
8823454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
8833454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
8843454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
8853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
8863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
8873454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
88804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
88904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  PTRACE_O_TRACEEXEC;
8903454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
8913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
8923454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
8943454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
89575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
8963454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
8973454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
8983454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
8993454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
90075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
90104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
90204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
9033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
9043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
9053454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9063454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
9083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
9093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
9113454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
9123454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
9133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
9143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
91504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
91604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
91704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
91875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
91975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
92075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
92175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
92204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected exit status %u",
92304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WEXITSTATUS(status));
92404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
92504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
92604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
92704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
9283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9293454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
9303454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
93104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
93204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
9333454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
9353454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
9363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
9373454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
9383454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
9393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
9403454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
94104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
94204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
94304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
9443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
9463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
9473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
94904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
95075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
9513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
9523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
95575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
956f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
9573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
958f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
959f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
9603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
9613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
96304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
96404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
9653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
966b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif
967b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
96908b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
97306350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
97608b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
97708b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
97875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
97975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
980ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
981ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
9824f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
9831d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcbtab)
9841d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
9854f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
9861d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcp)
9871d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
9884f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
9894f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
990ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
992138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
993138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
9998a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"+cCdfFhiqrtTvVxyz"
1000ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
1001ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
1002ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
10038a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"a:e:o:O:p:s:S:u:E:P:")) != EOF) {
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
1006e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
1007cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
1008e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1009e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
1010e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
1011e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
1012e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
1013cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
1014e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1015e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1020ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
1021ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
1022ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
1023ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
1024ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
102541c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
102606350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
102706350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
104576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10538a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
10548a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
10558a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
10609c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
106276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
106317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
106417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
106517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
106776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
1068102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko			if (acolumn < 0)
1069102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko				error_msg_and_die("Bad column width '%s'", optarg);
107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
107676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
108076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
10815d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			pid = atoi(optarg);
10825d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			if (pid <= 0) {
1083cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("Invalid process id: '%s'", optarg);
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
108675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (pid == strace_tracer_pid) {
1087cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("I'm sorry, I can't let you do that, Dave.");
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1090418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
10948a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
10958a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
10968a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1097cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
10988a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
10998a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1102dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1103cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Invalid -s argument: '%s'", optarg);
1104dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
110676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1112de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
11131d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			if (putenv(optarg) < 0)
11141d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko				die_out_of_memory();
1115de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1121837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	argv += optind;
1122837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* argc -= optind; - no need, argc is not used below */
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1124102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces = malloc(acolumn + 1);
1125102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (!acolumn_spaces)
11261d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
1127102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	memset(acolumn_spaces, ' ', acolumn);
1128102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces[acolumn] = '\0';
1129102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko
1130837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* Must have PROG [ARGS], or -p PID. Not both. */
1131837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (!argv[0] == !pflag_seen)
1132ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1133ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1134d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	if (pflag_seen && daemonized_tracer) {
1135cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive options");
1136d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1137d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
113806350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
113906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
114006350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1141cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1142cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
1143cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1144cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
114776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
114876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1150cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
115176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
11525d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		pent = getpwnam(username);
11535d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (pent == NULL) {
1154cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
116276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11648044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX
116504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (followfork)
116604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		test_ptrace_setoptions_followfork();
11673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
11688044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif
11698044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
117237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
117337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
117437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
117537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
117637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
117737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
11787dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (followfork > 1)
11797dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
11807dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			outf = strace_popen(outfname + 1);
118154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
11823d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		else if (followfork <= 1)
11833d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko			outf = strace_fopen(outfname);
118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1186cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1187a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		char *buf = malloc(BUFSIZ);
1188a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		if (!buf)
1189a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko			die_out_of_memory();
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
1191cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
1192837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (outfname && argv[0]) {
119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1195369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1196b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
119754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* Valid states here:
1198837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	   argv[0]	pflag_seen	outfname	interactive
1199837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	   yes		0		0		1
1200837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	   no		1		0		1
1201837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	   yes		0		1		0
1202837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	   no		1		1		1
120354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
120454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
120554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
120654cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
120754cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
120854cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
1209837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (argv[0])
1210837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko		startup_child(argv);
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
1219837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* In interactive mode (if no -o OUTFILE, or -p PID is used),
1220837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	 * fatal signals are blocked across syscall waits, and acted on
1221837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	 * in between. In non-interactive mode, signals are ignored.
1222837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	 */
122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
122876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
123276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
1240bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
124176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
1243553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1244553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1245553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1246553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1247553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1248553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1249553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1250553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
1251bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1253ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
125402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
125502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
1259a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
1260a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
1261a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
1262a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
1263a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
1264a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
1265a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
1266a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
1267a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
1268a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
1269a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12722b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic void
1273418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
12747b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
12757b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
12767b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
12777b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
12787b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
12797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
128018da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	int i = tcbtabsize;
128118da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
128218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
12831d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!newtab || !newtcbs)
12841d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
12857b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
12867b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
128718da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	while (i < tcbtabsize)
128818da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		tcbtab[i++] = newtcbs++;
12897b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
12907b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
129210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1297418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1298418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1299418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1300ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1301ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
130318da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko			memset(tcp, 0, sizeof(*tcp));
130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
1305381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko			tcp->flags = TCB_INUSE;
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
1307a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin#if SUPPORTED_PERSONALITIES > 1
1308a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin			tcp->currpers = current_personality;
1309a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin#endif
13108dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#ifdef USE_PROCFS
131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
13128dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#endif
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
13141d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (debug)
13151d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
131610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
131710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
132118da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	error_msg_and_die("bug in alloc_tcb");
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1324bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1326418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1330bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
133119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
133219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1335bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1340ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
13419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
13429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
13435d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd = open(proc, O_WRONLY|O_EXCL);
13445d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd < 0) {
13459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13481f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
13499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
13505d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
13515d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd_stat < 0) {
13529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13551f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_stat);
13569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
13575d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
13585d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd_as < 0) {
13599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
13609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
13619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
13621f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_as);
13639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
13650890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko# ifndef FREEBSD
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
1367372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR|O_EXCL);
13680890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko# else
1369bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1370372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR);
13710890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko# endif
1372372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	if (tcp->pfd < 0) {
137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
13761f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
13779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1378bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1379bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
13805d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd_reg = open(proc, O_RDONLY);
13815d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd_reg < 0) {
1382bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1383bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1384bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1385bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1386bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
13875d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp->pfd_status = open(proc, O_RDONLY);
13885d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp->pfd_status < 0) {
1389bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1390bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1391bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1392bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1393bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1394bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
1402b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_STATUS(tcp) < 0) {
140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
14069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1407cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				break;
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1410bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
141216a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1416553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
14209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
14269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1431553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1440bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1441bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1442bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1443bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
14445ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1445bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1446bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1447bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
14485ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
14495ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1450bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1451bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1453bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
145419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
145519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
145619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
145719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
1458b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
145919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
1460b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	praddset(&syscalls, SYS_execve);
146119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
1462b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork);
146319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
1464b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_forkall);
146519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1466553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
1467b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork1);
146819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
146919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
1470b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rfork1);
147119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
147219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
1473b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rforkall);
147419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
147519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
147619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
147976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
148019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
148119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
148519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
148619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
148719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
148819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
1489b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
149019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
14919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
149519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
149619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
149719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
149819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
1499b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
150019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
15019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
150276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1505bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1506bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1507b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	arg = S_SIG | S_SCE | S_SCX;
1508b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1509bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1510bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1511bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1512bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1521553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
15239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
1524b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1528553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1529bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1530bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1531bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1532bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1533553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
1536b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_WSTOP(tcp) < 0) {
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
15409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1541bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
154206602d99b72564e77600fc7c94e9ce8b78ec7085Denys Vlasenko				get_scno(tcp);
154376989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1547bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
15489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
15490890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
15500890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko#else
15510890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
15520890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko#endif
15530890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko			{
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1557bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1558bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1559bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1560bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1561bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1562bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1563553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
15660890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko#ifdef FREEBSD
15670890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko	else {
1568553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
15692e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
15702e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
15712e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
15722e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
15732e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
15742e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
15752e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1576553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
15772e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
15782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
15792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
15802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
15812e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
15822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
15832e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
15842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
15852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
15862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
15872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
15882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
15892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
15902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
15912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
15922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1593bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1594bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1608bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1610eebb04d4ae8bf4b08a041f5ea442ca24c90692c2Denys Vlasenkostatic struct tcb *
161154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
161454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
161554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
161654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1618ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
161954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
162054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
162354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1627bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
163054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void)
163154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{
163254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	int i;
163354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	struct tcb *tcp;
163454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
163554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		tcp = tcbtab[i];
163654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->flags & TCB_INUSE)
163754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath			return tcp;
163854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	}
163954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	return NULL;
164054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath}
164154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
164254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb *
16431201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkopfd2tcb(int pfd)
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1647ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1648ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1657bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
16601201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
166419cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
16661d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko	if (debug)
16671d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
1668eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
16698dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#ifdef USE_PROCFS
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
16738dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko# ifdef FREEBSD
1674bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1675bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1676bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1677bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1678bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1679bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1680bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1681bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
16828dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko# endif
168319cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko		tcp->flags = 0; /* rebuild_pollv needs it */
168419cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko		rebuild_pollv();
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
16868dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#endif
1687eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1688822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1690eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
169119cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko	memset(tcp, 0, sizeof(*tcp));
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16940a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
16950a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
16960a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
16970a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
17004c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkodetach(struct tcb *tcp)
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1703ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
17041bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1705ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1708840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
17137bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
17147bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
17167bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
17177bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
17187bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
17197bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
172002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
1721f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	 * We did PTRACE_ATTACH but possibly didn't see the expected SIGSTOP.
1722f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	 * We must catch exactly one as otherwise the detached process
1723f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	 * would be left stopped (process state T).
172402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
1725f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
17264c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko	error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
17275d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (error == 0) {
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
17297bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
17307bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
17317bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
17327bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
17337bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
173444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	else if (my_tkill(tcp->pid, 0) < 0) {
17357bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
17367bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
17377bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
173844f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
17397bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
17407bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
17417bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
174202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
174302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1744ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
17467508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
17477508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
17487508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
17497508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
17507508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
17527508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
17537508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
17547508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
17557508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
17567508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
17577508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
17587508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
17597508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
17607508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
17617508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
17627508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
17637508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
17647508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
17657508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
17667508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
17677508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
17687508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
17697508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
17707508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
17717508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
17737508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
17794c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, 0);
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1782732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
178375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1784732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1785732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1788ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
17897bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
17934c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, 0);
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1800a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1804bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1806e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig)
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1815bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18181201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1823ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1824ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
183260fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko			tprints(" <unfinished ...>");
1833ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			printtrailer();
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
18364c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko			detach(tcp);
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
184376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
18471201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18546d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
185576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
18576d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
18601201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no)
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186435aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
186535aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
186835aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	return sys_errlist[err_no];
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18758f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
18766d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
18788f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
18798f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
18808f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
18831201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig)
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
189776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
189976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1900bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19031201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkorebuild_pollv(void)
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1907cfd364b011e170377ae002551c4391c01f51acbfDenys Vlasenko	free(pollv);
1908cfd364b011e170377ae002551c4391c01f51acbfDenys Vlasenko	pollv = malloc(nprocs * sizeof(pollv[0]));
19091d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!pollv)
19101d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
1911ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1912ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1913ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
19179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
1921cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("proc miscount");
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19281201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll_open(void)
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
1933cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("pipe");
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
19361f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		set_cloexec_flag(proc_poll_pipe[i]);
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
19411201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll(struct pollfd *pollv, int nfds, int timeout)
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19475d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
19485d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (n < 0)
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
1951cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("panic: short read: %d", n);
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19641201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkowakeup_handler(int sig)
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19691201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poller(int pfd)
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
197376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1977bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1978bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1979bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
1983cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
198476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
198576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
2006cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
2017bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
20185ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
20195ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
20205ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
20215ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
20229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
20559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
2062b88f96129f8ebc064d490c8c161bcbc925d938c8Denys Vlasenko		if (tcp && exiting(tcp))
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
2072cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("lost proc");
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2082cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	error_msg_and_die("nothing ready");
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
20861201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
20889dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
2089d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
20909dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
20959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
210954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath				tcp = first_used_tcb();
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
21229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
21239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
21249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
21259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2126553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
21279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
21289dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
21299dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
21309dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
21319dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
21329dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
21335d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko				what = poll(&pv, 1, 1);
21345d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko				if (what < 0) {
21359dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
21369dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
21379dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
21389dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
21399dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
21409dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
21419dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
21429dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
21439dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
21449dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
21645d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pfd2tcb(pfd);
21655d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp == NULL) {
2166cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("unknown pfd: %u", pfd);
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2168b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
21699dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2170b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2173bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
2174b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			ioctl_result = IOCTL_WSTOP(tcp);
2175bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2176bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2177bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2178bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2179bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2180b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_STATUS(tcp);
2181bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
2182b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_WSTOP(tcp);
2183553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2206bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2207bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2208553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
2213cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("PIOCWSTOP");
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
22172e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
22182e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
22192e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
2220b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			IOCTL(tcp->pfd, PIOCRUN, 0);
22212e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
22222e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2223553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2224553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
222576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
222676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
222776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
2230ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
223176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2234bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2235bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2236bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2237bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
22385d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
22395d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			if (len > 0) {
2240bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2241bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2242bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2243bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2244bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2245bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2246553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
224776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2249bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
225276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
22539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
22549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2255bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
22579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
22589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
2260cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					error_msg_and_die("syscall trouble");
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2264bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
22669dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
22679dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
22689dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
2271cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("syscall trouble");
227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
2275e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2276e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_SIGNAL)) {
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2279ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2280ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
22815826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
22825826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
22835826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
228460fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko					tprints("    siginfo=");
22855826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2286ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko					printtrailer();
22875826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
22885826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
229176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
2292e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAGS_ONLY_STATS
2293e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_FAULT)) {
229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
2296ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
229776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2299bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2300bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
23015ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2302553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
230376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
2304cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2307ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2308ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
23099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2310553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
2311b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
2312553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2313b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
2314553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2315372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		{
2316cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("PIOCRUN");
231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
232076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
232176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2322bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2324eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
2325eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathtrace()
232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
232776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
232876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
23296cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko	int status, sig;
233076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
233176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
233276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
233326d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko	struct rusage *rup = cflag ? &ru : NULL;
233426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
2335eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
233626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif
233776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
233876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2339eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2340222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2341eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2342eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2343eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
234476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
234526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
234626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, wait4_options, rup);
23475bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
23482f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
23492f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
235026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, wait4_options, rup);
23512f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
23525bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
23532f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
235426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, __WCLONE, rup);
235526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			if (pid < 0) {
2356cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
23572f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
23582f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
235926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# else
236026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, 0, rup);
236126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif /* __WALL */
236276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
236376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
236476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
236526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko#endif
236676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2367eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2368eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
236976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
237026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		if (pid < 0) {
2371eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2372eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
237376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2374eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
237576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
237876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
237976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
238076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
2381eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2382eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2383eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2384eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2385eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
238676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
238776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
238810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
238910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
23907dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
239110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
239210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
23931d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		if (debug) {
23941d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
23951d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef LINUX
23961d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			unsigned ev = (unsigned)status >> 16;
23971d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (ev) {
23981d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				static const char *const event_names[] = {
23991d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_CLONE] = "CLONE",
24001d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_FORK]  = "FORK",
24011d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK] = "VFORK",
24021d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
24031d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXEC]  = "EXEC",
24041d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXIT]  = "EXIT",
24051d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				};
24061d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				const char *e;
24071d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				if (ev < ARRAY_SIZE(event_names))
24081d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					e = event_names[ev];
24091d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				else {
24101d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					sprintf(buf, "?? (%u)", ev);
24111d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					e = buf;
24121d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				}
24131d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, " PTRACE_EVENT_%s", e);
24141d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			}
24151d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
24161d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			strcpy(buf, "???");
24171d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSIGNALED(status))
24181d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP
24191d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,%ssig=%s",
24201d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						WCOREDUMP(status) ? "core," : "",
24211d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
24221d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else
24231d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,sig=%s",
24241d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
24251d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
24261d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFEXITED(status))
24271d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
24281d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSTOPPED(status))
24291d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
24305bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED
24311d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFCONTINUED(status))
24321d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				strcpy(buf, "WIFCONTINUED");
24335bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif
24341d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
24351d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		}
243676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
243776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
24385d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pid2tcb(pid);
24395d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp == NULL) {
2440e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
244141c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2442e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2443e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2444e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2445e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2446e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2447e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2448e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2449e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2450e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2451418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
2452f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				tcp->flags |= TCB_ATTACHED | TCB_STARTUP | TCB_IGNORE_ONE_SIGSTOP;
2453e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2454833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko					fprintf(stderr, "Process %d attached\n",
2455e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
24568b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2457e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2458e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2459e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2460eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2461e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2462e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2463e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2464cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
2465e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
246676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2467eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2468eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
2469ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
2470eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
247113d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko		if (cflag) {
247276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
247376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
247476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
247513d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#endif
2476eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2478a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2479a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2480e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
248313d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP
24842efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
24852efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
248613d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					WCOREDUMP(status) ? "(core dumped) " : "");
248713d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else
248813d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko				tprintf("+++ killed by %s +++",
248913d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					signame(WTERMSIG(status)));
24902efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
2491ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
249276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
24935e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko			fflush(tcp->outf);
249476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
249676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
249776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2498a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2499a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
25000a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
25017a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL)
25020a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
25030a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
25040a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
25050a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
250619cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
250719cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printleader(tcp);
250819cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				tprintf("+++ exited with %d +++", WEXITSTATUS(status));
250919cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printtrailer();
251019cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			}
25115e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko			fflush(tcp->outf);
251276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
251376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
251476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
251576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
251676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
251776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
251876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
251976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
252076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2521f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this the very first time we see this tracee stopped? */
2522f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (tcp->flags & TCB_STARTUP) {
2523f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			if (debug)
2524f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
252576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
252602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
252776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
252802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
25292ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko				 * parent through fork().
253076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
25316cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko				if (clearbpt(tcp) < 0) {
25326cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko					/* Pretty fatal */
253376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
253476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
253576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
253676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
253776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2538ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
253944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko			if (ptrace_setoptions) {
254044f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (debug)
254144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
254244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
254344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					if (errno != ESRCH) {
254444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						/* Should never happen, really */
254544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						perror_msg_and_die("PTRACE_SETOPTIONS");
25463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
25473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
25483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2549ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
2550f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2551f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2552f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (((unsigned)status >> 16) != 0) {
2553f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			/* Ptrace event (we ignore all of them for now) */
2554f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			goto restart_tracee_with_sig_0;
2555f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2556f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2557f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		sig = WSTOPSIG(status);
2558f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2559f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this post-attach SIGSTOP?
2560f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * Interestingly, the process may stop
2561f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * with STOPSIG equal to some other signal
2562f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * than SIGSTOP if we happend to attach
2563f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * just before the process takes a signal.
2564f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 */
2565f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2566f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			if (debug)
2567f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2568f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
25696cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee_with_sig_0;
257076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
257176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
25726cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (sig != syscall_trap_sig) {
2573e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
25746cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			    && (qual_flags[sig] & QUAL_SIGNAL)) {
2575c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin				siginfo_t si;
2576c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
25776b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
25786b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
25797b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2580932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2581932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
25827b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
25836b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
25847b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
25856b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
25862ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	, pc
25876b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
25882ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_STR	""
25892ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	/* nothing */
25907b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
259176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
2592436d892212dd56401bacf818a238333d30f85c6aDmitry V. Levin				if (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) == 0) {
259360fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko					tprints("--- ");
25946b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
25956b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf(" (%s)" PC_FORMAT_STR " ---",
25966cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						strsignal(sig)
25976b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
25986b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
25996b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					tprintf("--- %s by %s" PC_FORMAT_STR " ---",
26006cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						strsignal(sig),
26016cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						signame(sig)
26026b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
2603ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko				printtrailer();
26045e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko				fflush(tcp->outf);
260576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
26066cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee;
260776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
26082ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
26092ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* We handled quick cases, we are permitted to interrupt now. */
261002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
261102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
26122ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
26132ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* This should be syscall entry or exit.
26142ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * (Or it still can be that pesky post-execve SIGTRAP!)
26152ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * Handle it.
26162ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 */
2617eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2618eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2619eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2620eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2621f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko			 * all processes in thread group.
2622ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2623ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2624eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				if (tcp_last) {
2625eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2626178de007d14f3ae890117b540def9cf14bcb61feDenys Vlasenko					 * Finish the line then.
2627eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2628eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					tcp_last->flags |= TCB_REPRINT;
262960fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko					tprints(" <unfinished ...>");
2630eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					printtrailer();
26315e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko					fflush(tcp->outf);
2632eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
2633f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				/* We assume that ptrace error was caused by process death.
2634f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 * We used to detach(tcp) here, but since we no longer
2635f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 * implement "detach before death" policy/hack,
2636f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 * we can let this process to report its death to us
2637f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 * normally, via WIFEXITED or WIFSIGNALED wait status.
2638f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 */
2639ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2640f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				/* It's our real child (and we also trace it) */
2641f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				/* my_tkill(pid, SIGKILL); - why? */
2642f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				/* droptcb(tcp); - why? */
264376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
264476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
264576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
26466cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee_with_sig_0:
26476cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		sig = 0;
26486cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee:
2649ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2650ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
26516cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
265276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
265376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
265476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
265576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
265676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
265776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
265876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2659bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
266076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
266176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
266276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
266376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
266476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
266576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2666e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab	va_start(args, fmt);
2667b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2668b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2669ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		if (n < 0) {
2670ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			if (outf != stderr)
2671ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				perror(outfname == NULL
2672ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				       ? "<writing to pipe>" : outfname);
2673ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		} else
2674b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2675b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
267676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
26775940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko}
26785940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko
26795940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenkovoid
26805940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenkotprints(const char *str)
26815940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko{
26825940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko	if (outf) {
26835940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		int n = fputs(str, outf);
26845940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		if (n >= 0) {
26855940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			curcol += strlen(str);
26865940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			return;
26875940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		}
26885940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		if (outf != stderr)
26895940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			perror(outfname == NULL
26905940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			       ? "<writing to pipe>" : outfname);
26915940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko	}
269276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
269376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
269476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
26951201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintleader(struct tcb *tcp)
269676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2697732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko	if (tcp_last) {
2698eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (tcp_last->ptrace_errno) {
2699732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (tcp_last->flags & TCB_INSYSCALL) {
270060fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko				tprints(" <unavailable>) ");
2701102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko				tabto();
2702732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
270360fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko			tprints("= ? <unavailable>\n");
2704eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			tcp_last->ptrace_errno = 0;
2705732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
27067e0615f3aecc023e2756a83bdf113c5ceaac431dDenys Vlasenko			tcp_last->flags |= TCB_REPRINT;
270760fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko			tprints(" <unfinished ...>\n");
2708732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
270976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
271076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
271176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
271276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
271376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
271476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
271576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
271676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
271776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
271876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
271976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
272076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
272176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
272276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
272376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
272476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
272576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
272676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
272776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
272876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
272976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
273076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
273176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
273276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
273376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
273476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
273576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
273676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
273776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
273876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
273976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
274076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
274176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
274276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
274376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
274476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
274576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
274676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2747102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkotabto(void)
274876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2749102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (curcol < acolumn)
27505940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		tprints(acolumn_spaces + curcol);
275176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
275276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
275376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
2754ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoprinttrailer(void)
275576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
275660fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko	tprints("\n");
275776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
275876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
27599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2760ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
27619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2762ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
2763ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
2764ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
27659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
27669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2767553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
27689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
27699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
27709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
27719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
27729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
27739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
27749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2775553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
2776ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
27779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
27789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
27799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2780