strace.c revision 3521884c91d0bbd8e796d72619da40bdad95789c
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>
48f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko#include <sys/utsname.h>
4976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX
51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h>
5244f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# if defined __NR_tkill
5344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#  define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else
55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath   /* kill() may choose arbitrarily the target task of the process group
56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      while we later wait on a that specific TID.  PID process waits become
57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      TID task specific waits for a process under ptrace(2).  */
58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
5944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko#  define my_tkill(tid, sig) kill((tid), (sig))
60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif
61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif
62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath
637b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
67bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
68bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
7176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
7276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
73ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
741d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
7776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
781d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
7996d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenkoextern char **environ;
80418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern int optind;
81418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoextern char *optarg;
8296d5a76109b4f1d1f4c9c76641e6ec896108083dDenys Vlasenko
8376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8441c48227a86a176da333f713d5047240885f25ccRoland McGrathint debug = 0, followfork = 0;
85f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenkounsigned int ptrace_setoptions = 0;
863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/* Which WSTOPSIG(status) value marks syscall traps? */
8775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic unsigned int syscall_trap_sig = SIGTRAP;
88e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levinint dtime = 0, xflag = 0, qflag = 0;
89e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levincflag_t cflag = CFLAG_NONE;
90aa6ec415c1a9b8a886bddf0db765b5de365a8360Denys Vlasenkostatic int iflag = 0, pflag_seen = 0, rflag = 0, tflag = 0;
91b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
92b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* -I n */
93b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkoenum {
94b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_NOT_SET        = 0,
95b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_ANYWHERE       = 1, /* don't block/ignore any signals */
96b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_WHILE_WAIT     = 2, /* block fatal signals while decoding syscall. default */
97b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_NEVER          = 3, /* block fatal signals. default if '-o FILE PROG' */
98b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    INTR_BLOCK_TSTP_TOO = 4, /* block fatal signals and SIGTSTP (^Z) */
99b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko    NUM_INTR_OPTS
100b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko};
101b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkostatic int opt_intr;
102b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko/* We play with signal mask only if this mode is active: */
103b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko#define interactive (opt_intr == INTR_WHILE_WAIT)
104b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
105ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko/*
106ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * daemonized_tracer supports -D option.
107ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * With this option, strace forks twice.
108ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * Unlike normal case, with -D *grandparent* process exec's,
109ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * becoming a traced process. Child exits (this prevents traced process
110ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * from having children it doesn't expect to have), and grandchild
111ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * attaches to grandparent similarly to strace -p PID.
112ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * This allows for more transparent interaction in cases
113ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * when process and its parent are communicating via signals,
114ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * wait() etc. Without -D, strace process gets lodged in between,
115ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko * disrupting parent<->child link.
116ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko */
117ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenkostatic bool daemonized_tracer = 0;
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
12031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
12131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize (post_attach_sigstop == 0)
12231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
12331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define post_attach_sigstop TCB_IGNORE_ONE_SIGSTOP
12431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define use_seize 0
12531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
12631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
12717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
12817f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
12917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
1308a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* Show path associated with fd arguments */
1318a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint show_fd_path = 0;
1328a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
1338a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards/* are we filtering traces based on paths? */
1348a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwardsint tracing_paths = 0;
1358a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards
136a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int exit_code = 0;
137a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levinstatic int strace_child = 0;
13875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic int strace_tracer_pid = 0;
139eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
140b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
141ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic uid_t run_uid;
142ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic gid_t run_gid;
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
145102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic int acolumn = DEFAULT_ACOLUMN;
146102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkostatic char *acolumn_spaces;
147b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
148ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic FILE *outf;
149000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenkostruct tcb *printing_tcp = NULL;
150ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwabstatic int curcol;
151ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic struct tcb **tcbtab;
1522b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic unsigned int nprocs, tcbtabsize;
153ead73bd3493c517fde508aecf6bc097aeae1752cDenys Vlasenkostatic const char *progname;
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenkostatic char *os_release; /* from uname() */
156f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1574c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkostatic int detach(struct tcb *tcp);
158e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic int trace(void);
159e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void cleanup(void);
160e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void interrupt(int sig);
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
165a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#else
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
167a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko#endif
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic struct tcb *pfd2tcb(int pfd);
172e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void reaper(int sig);
173e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void rebuild_pollv(void);
174ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poll_open(void);
179e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwabstatic void proc_poller(int pfd);
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
197bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
200cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenkousage(FILE *ofp, int exitval)
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
203b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenkousage: strace [-CdDffhiqrtttTvVxxy] [-I n] [-a column] [-e expr]... [-o file]\n\
204b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko              [-p pid]... [-s strsize] [-u username] [-E var=val]...\n\
205b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko              [-P path] [PROG [ARGS]]]\n\
206b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   or: strace -c [-D] [-I n] [-e expr]... [-O overhead] [-S sortby] [-E var=val]...\n\
207b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko              [PROG [ARGS]]]\n\
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
209b87d30c785679b37a2ec7242881f0d0b819c738dAndreas Schwab-C -- like -c but also print regular output while processes are running\n\
210b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-D -- run tracer process as a detached grandchild, not as parent\n\
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
214b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko-I interruptible\n\
215b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   1: no signals are blocked\n\
216b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   2: fatal signals are blocked while decoding syscall (default)\n\
217b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   3: fatal signals are always blocked (default if '-o FILE PROG')\n\
218b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko   4: fatal signals and SIGTSTP (^Z) are always blocked\n\
219b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko      (useful to make 'strace -o FILE PROG' not stop on ^Z)\n\
22076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
22176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
22376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
2258a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-y -- print paths associated with file descriptor arguments\n\
22676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
22776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
22876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
22976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
23076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
23176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
23476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
235de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
236de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
2378a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards-P path -- trace accesses to path\n\
238de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
23917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
240de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
241de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
24276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
24376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
24476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
24575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void) __attribute__ ((noreturn));
24675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void die(void)
24775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
24875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if (strace_tracer_pid == getpid()) {
24975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cflag = 0;
25075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		cleanup();
25175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	}
25275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	exit(1);
25375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
25475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
25575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkostatic void verror_msg(int err_no, const char *fmt, va_list p)
2563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
25782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	char *msg;
25882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
25944d053218ba658c901c3ab7dd905ab31ba417286Dmitry V. Levin	fflush(NULL);
26082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko
26182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We want to print entire message with single fprintf to ensure
26282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * message integrity if stderr is shared with other programs.
26382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * Thus we use vasprintf + single fprintf.
26482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 */
26582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	msg = NULL;
266cfad543087d98c5313fd7f006c0de69a1d87dc8eDenys Vlasenko	if (vasprintf(&msg, fmt, p) >= 0) {
26782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
26882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(err_no));
26982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
27082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, "%s: %s\n", progname, msg);
27182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		free(msg);
27282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	} else {
27382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		/* malloc in vasprintf failed, try it without malloc */
27482bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		fprintf(stderr, "%s: ", progname);
27582bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		vfprintf(stderr, fmt, p);
27682bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		if (err_no)
27782bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			fprintf(stderr, ": %s\n", strerror(err_no));
27882bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko		else
27982bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko			putc('\n', stderr);
28082bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	}
28182bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* We don't switch stderr to buffered, thus fprintf(stderr)
28282bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	 * always flushes its output and this is not necessary: */
28382bb78c149a1b527f4ae7a764be29a9c85067b29Denys Vlasenko	/* fflush(stderr); */
28475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
28575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
28675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg(const char *fmt, ...)
28775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
28875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
28975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
29075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
2913454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	va_end(p);
29275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
2933454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
29475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid error_msg_and_die(const char *fmt, ...)
29575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
29675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
29775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
29875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(0, fmt, p);
29975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
30075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
30175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
30275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg(const char *fmt, ...)
30375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
30475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
30575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
30675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
30775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_end(p);
30875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko}
30975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
31075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenkovoid perror_msg_and_die(const char *fmt, ...)
31175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko{
31275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_list p;
31375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	va_start(p, fmt);
31475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	verror_msg(errno, fmt, p);
31575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	die();
3163454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
3173454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
3181d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenkovoid die_out_of_memory(void)
3191d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko{
3201d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	static bool recursed = 0;
3211d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (recursed)
3221d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		exit(1);
3231d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	recursed = 1;
3241d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	error_msg_and_die("Out of memory");
3251d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko}
3261d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko
32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
336c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger/* Glue for systems without a MMU that cannot provide fork() */
337c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#ifdef HAVE_FORK
338c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 0
339c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#else
340c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define strace_vforked 1
341c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger# define fork()         vfork()
342c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger#endif
343c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger
34431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
34531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic int
34631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkoptrace_attach_or_seize(int pid)
34731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
34831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int r;
34931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (!use_seize)
35031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return ptrace(PTRACE_ATTACH, pid, 0, 0);
35131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL);
35231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (r)
35331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		return r;
35431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	r = ptrace(PTRACE_INTERRUPT, pid, 0, 0);
35531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	return r;
35631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
35731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#else
35831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# define ptrace_attach_or_seize(pid) ptrace(PTRACE_ATTACH, (pid), 0, 0)
35931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
36031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
3611f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenkostatic void
36210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
36310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
3641f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	int flags, newflags;
3651f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko
3661f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	flags = fcntl(fd, F_GETFD);
3671f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	if (flags < 0) {
3681f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		/* Can happen only if fd is bad.
3691f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * Should never happen: if it does, we have a bug
3701f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * in the caller. Therefore we just abort
3711f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 * instead of propagating the error.
3721f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		 */
3731f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		perror_msg_and_die("fcntl(%d, F_GETFD)", fd);
37410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
37510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
37610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
37710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
3781f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		return;
37910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3801f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	fcntl(fd, F_SETFD, newflags); /* never fails */
38110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
38210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
38310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
38410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
38510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
38610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
38710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
38810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
38910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
39010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
39110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
39210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3937b609d5ba0852e6c56ba311350ebd4412361777bDenys Vlasenko	if (euid != uid && setreuid(euid, uid) < 0) {
394cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("setreuid");
39510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
39610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
39710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
39810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
3994bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
4004bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
4014bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
4024bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
4034bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
4044bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
40510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
4063d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostrace_fopen(const char *path)
40710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
40810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
40910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
41010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
4113d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	fp = fopen_for_output(path, "w");
4123d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	if (!fp)
4133d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		perror_msg_and_die("Can't fopen '%s'", path);
41410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
4153d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko	set_cloexec_flag(fileno(fp));
41610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
41710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
41810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4197dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenkostatic int popen_pid = 0;
42010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
42110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
42210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
42310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
42410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
42510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
42610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
42710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
42810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
42910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
43010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
43110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
43210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
4337dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	FILE *fp;
4347dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	int fds[2];
43510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
43610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
43710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
4387dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("pipe");
43910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4407dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	set_cloexec_flag(fds[1]); /* never fails */
44110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4427dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	popen_pid = vfork();
4437dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == -1)
4447dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("vfork");
44510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4467dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (popen_pid == 0) {
44710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
44810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
4497dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		if (fds[0] != 0) {
4507dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (dup2(fds[0], 0))
4517dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				perror_msg_and_die("dup2");
4527dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			close(fds[0]);
45310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
45410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
4557dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko		perror_msg_and_die("Can't execute '%s'", _PATH_BSHELL);
45610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
4577dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko
4587dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	/* parent */
4597dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	close(fds[0]);
4607dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	swap_uid();
4617dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	fp = fdopen(fds[1], "w");
4627dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	if (!fp)
4631d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
4647dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko	return fp;
46510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
46610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
4673d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenkostatic void
46810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
46910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
47010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
4717a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		char name[520 + sizeof(int) * 3];
4727a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		sprintf(name, "%.512s.%u", outfname, tcp->pid);
4733d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		tcp->outf = strace_fopen(name);
47410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
47510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
47610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
48202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
48302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
48402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
48502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
4862e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	 * between PTRACE_ATTACH and wait4() on SIGSTOP.
487b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	 * We rely on cleanup() from this point on.
48802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
48902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
49002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
49102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
492ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (daemonized_tracer) {
493ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid_t pid = fork();
494ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid < 0) {
495014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko			perror_msg_and_die("fork");
496ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
497ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (pid) { /* parent */
498ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
49975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Wait for grandchild to attach to straced process
50075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * (grandparent). Grandchild SIGKILLs us after it attached.
50175422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			 * Grandparent's wait() is unblocked by our death,
502ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * it proceeds to exec the straced program.
503ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
504ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			pause();
505ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			_exit(0); /* paranoia */
506ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
50775422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* grandchild */
50875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		/* We will be the tracer process. Remember our new pid: */
50975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		strace_tracer_pid = getpid();
510ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
511ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
51444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko
515d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Is this a process we should attach to, but not yet attached? */
516d116a7338645af45090aecc331701e999148d284Denys Vlasenko		if ((tcp->flags & (TCB_ATTACHED | TCB_STARTUP)) != TCB_ATTACHED)
517d116a7338645af45090aecc331701e999148d284Denys Vlasenko			continue; /* no */
518d116a7338645af45090aecc331701e999148d284Denys Vlasenko
519d116a7338645af45090aecc331701e999148d284Denys Vlasenko		/* Reinitialize the output since it may have changed */
52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
5213d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		newoutf(tcp);
52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
531ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (followfork && !daemonized_tracer) {
5327a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
540381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
542381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					struct tcb *cur_tcp;
543381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					int tid;
544381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko
5457a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					if (de->d_fileno == 0)
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
55131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (ptrace_attach_or_seize(tid) < 0) {
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
553f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko						if (debug)
554f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko							fprintf(stderr, "attach to pid %d failed\n", tid);
555381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						continue;
556f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko					}
557381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (debug)
558381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						fprintf(stderr, "attach to pid %d succeeded\n", tid);
559381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					cur_tcp = tcp;
560381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (tid != tcp->pid)
561381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						cur_tcp = alloctcb(tid);
56231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cur_tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
565381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				if (interactive) {
566381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_SETMASK, &empty_set, NULL);
567381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					if (interrupted)
568381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko						goto ret;
569381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko					sigprocmask(SIG_BLOCK, &blocked_set, NULL);
570381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko				}
5717a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				ntid -= nerr;
5727a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko				if (ntid == 0) {
57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
5787a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko					fprintf(stderr, ntid > 1
5797a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko? "Process %u attached with %u threads - interrupt to quit\n"
5807a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko: "Process %u attached - interrupt to quit\n",
58144f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						tcp->pid, ntid);
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
583f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				if (!(tcp->flags & TCB_STARTUP)) {
584f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					/* -p PID, we failed to attach to PID itself
585f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * but did attach to some of its sibling threads.
586f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 * Drop PID's tcp.
587f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					 */
588f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko					droptcb(tcp);
589f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				}
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
5917a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko			} /* if (opendir worked) */
5927a8bf065802f836901ae886317efcb4ed77cae7bDenys Vlasenko		} /* if (-f) */
59344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko# endif /* LINUX */
59431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace_attach_or_seize(tcp->pid) < 0) {
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
59931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		tcp->flags |= TCB_STARTUP | post_attach_sigstop;
600f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko		if (debug)
601f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko			fprintf(stderr, "attach to pid %d (main) succeeded\n", tcp->pid);
602ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
603ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (daemonized_tracer) {
604ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
605ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It is our grandparent we trace, not a -p PID.
606ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Don't want to just detach on exit, so...
607ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
608ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			tcp->flags &= ~TCB_ATTACHED;
609ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
610ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make parent go away.
611ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Also makes grandparent's wait() unblock.
612ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
613ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			kill(getppid(), SIGKILL);
614ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
615ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
61802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
61902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
62002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
621f95397afb8aadf017b2d3d42056c5929dbf16775Denys Vlasenko	} /* for each tcbtab[] */
62202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
62344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko ret:
62402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
62502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
62602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
62702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
62802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
6291201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostartup_child(char **argv)
63002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
63102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
63202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
63302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
63402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
63502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
63602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
63702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
63802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
63902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
64002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
641cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("exec");
64202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
64302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
64402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
64502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
64602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
64702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
64802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
64902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
65002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
65102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
65202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
65302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
65402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
65530145dda9d7ff70df1d5ad750a183572c73e8963Dmitry V. Levin		const char *path;
65602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
65702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
65802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
65902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
66002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
66102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
66202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
66302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
66402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
66502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
66602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
66702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
66802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
66902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
67002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
67102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
67202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
67302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
67402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
67502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
67602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
67702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
67802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
67902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
68002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
68102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
68202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
68302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
68402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
68502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
68602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
68702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
68802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
689cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("Can't stat '%s'", filename);
69002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
691a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	strace_child = pid = fork();
692ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pid < 0) {
693cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
694ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
69575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	if ((pid != 0 && daemonized_tracer) /* -D: parent to become a traced process */
69675422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	 || (pid == 0 && !daemonized_tracer) /* not -D: child to become a traced process */
697ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	) {
698ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		pid = getpid();
6992e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		if (outf != stderr)
7002e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			close(fileno(outf));
70102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
7022e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# ifdef MIPS
70302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
70402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
70502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
70602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
70702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
7082e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# endif
7092e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# ifndef FREEBSD
71002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
7112e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# else
712014ca3a53cb24d8e12e87f43a880efc52940a8beDenys Vlasenko		kill(pid, SIGSTOP);
7132e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko# endif
71402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
71531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!daemonized_tracer && !use_seize) {
71631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0) {
717cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("ptrace(PTRACE_TRACEME, ...)");
718ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			}
71902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
72002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
721ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		if (username != NULL) {
72202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
72302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
72402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
72502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
72602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
72702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
72802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
72902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
73002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
73102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
73202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
733ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (initgroups(username, run_gid) < 0) {
734ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("initgroups");
735ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
736ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setregid(run_gid, run_egid) < 0) {
737ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setregid");
738ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			}
739ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko			if (setreuid(run_uid, run_euid) < 0) {
740ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko				perror_msg_and_die("setreuid");
74102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
74202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
743ab034fbf09460c2fd933ea47c9085d09b8a1ab27Denys Vlasenko		else if (geteuid() != 0)
74402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
74502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
746ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		if (!daemonized_tracer) {
747ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
7482e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Induce a ptrace stop. Tracer (our parent)
749ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will resume us with PTRACE_SYSCALL and display
7502e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * the immediately following execve syscall.
7512e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * Can't do this on NOMMU systems, we are after
7522e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko			 * vfork: parent is blocked, stopping would deadlock.
753ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
754c1a5b7e8c42086635d09ce8adc7f8b3dd018c999Mike Frysinger			if (!strace_vforked)
7552e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko				kill(pid, SIGSTOP);
756ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		} else {
757ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			struct sigaction sv_sigchld;
758ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, NULL, &sv_sigchld);
759ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
760ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Make sure it is not SIG_IGN, otherwise wait
761ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * will not block.
762ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
763ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			signal(SIGCHLD, SIG_DFL);
764ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			/*
765ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * Wait for grandchild to attach to us.
766ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 * It kills child after that, and wait() unblocks.
767ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			 */
768ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(3);
769ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			wait(NULL);
770ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			alarm(0);
771ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			sigaction(SIGCHLD, &sv_sigchld, NULL);
772ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		}
77302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
77402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
77502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
776cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("exec");
77702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
778ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko
7792e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	/* We are the tracer */
78075422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
7812e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	if (!daemonized_tracer) {
78231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (!use_seize) {
78331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* child did PTRACE_TRACEME, nothing to do in parent */
78431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		} else {
78531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!strace_vforked) {
78631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* Wait until child stopped itself */
78731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				int status;
78831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				while (waitpid(pid, &status, WSTOPPED) < 0) {
78931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					if (errno == EINTR)
79031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko						continue;
79131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("waitpid");
79231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
79331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
79431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					kill(pid, SIGKILL);
79531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					perror_msg_and_die("Unexpected wait status %x", status);
79631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
79731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
79831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Else: vforked case, we have no way to sync.
79931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * Just attach to it as soon as possible.
80031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * This means that we may miss a few first syscalls...
80131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
80231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
80331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (ptrace_attach_or_seize(pid)) {
80431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				kill(pid, SIGKILL);
80531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				perror_msg_and_die("Can't attach to %d", pid);
80631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
80731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!strace_vforked)
80831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				kill(pid, SIGCONT);
80931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
8102e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
811f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (!strace_vforked)
81231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			tcp->flags |= TCB_STARTUP | post_attach_sigstop;
813f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		else
814f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags |= TCB_STARTUP;
8152e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	}
8162e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko	else {
8172e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* With -D, *we* are child here, IOW: different pid. Fetch it: */
8182e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		strace_tracer_pid = getpid();
8192e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* The tracee is our parent: */
8202e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		pid = getppid();
8212e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		tcp = alloctcb(pid);
8222e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko		/* We want subsequent startup_attach() to attach to it: */
823ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		tcp->flags |= TCB_ATTACHED;
824ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	}
82502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
826ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (proc_open(tcp, 0) < 0) {
827cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("trouble opening proc file");
82802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
8292e968c0bb7b89aa43df726eb651f0b51572b4194Denys Vlasenko#endif
83002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
83102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
832b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#ifdef LINUX
83304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void kill_save_errno(pid_t pid, int sig)
83404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin{
83504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	int saved_errno = errno;
83604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin
83704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	(void) kill(pid, sig);
83804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	errno = saved_errno;
83904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin}
84004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin
841b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao/*
842b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * Test whether the kernel support PTRACE_O_TRACECLONE et al options.
843b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao * First fork a new child, call ptrace with PTRACE_SETOPTIONS on it,
844b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin * and then see which options are supported by the kernel.
845b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao */
84604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levinstatic void
8473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_followfork(void)
848b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao{
8492fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	int pid, expected_grandchild = 0, found_grandchild = 0;
8502fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACECLONE |
8512fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEFORK |
8522fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin					  PTRACE_O_TRACEVFORK;
853b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
8545d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	pid = fork();
8555d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid < 0)
85604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		perror_msg_and_die("fork");
8575d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (pid == 0) {
85804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		pid = getpid();
85931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
86004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
86104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
86204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		kill(pid, SIGSTOP);
86304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (fork() < 0)
86404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("fork");
86504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		_exit(0);
866b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
867b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
868b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin	while (1) {
869b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		int status, tracee_pid;
870b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin
87104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		errno = 0;
872b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		tracee_pid = wait(&status);
87304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (tracee_pid <= 0) {
874b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			if (errno == EINTR)
875b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin				continue;
876b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin			else if (errno == ECHILD)
877b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao				break;
87804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
87904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
88004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
88104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
88204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFEXITED(status)) {
88304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (WEXITSTATUS(status)) {
88404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (tracee_pid != pid)
88504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					kill_save_errno(pid, SIGKILL);
88604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				error_msg_and_die("%s: unexpected exit status %u",
88704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin						  __func__, WEXITSTATUS(status));
88804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
88904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
89004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
89104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
89204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
89304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
89404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
89504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
89604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
89704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (!WIFSTOPPED(status)) {
89804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (tracee_pid != pid)
89904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
90004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill(pid, SIGKILL);
90104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
90204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
903b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
904b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		if (tracee_pid != pid) {
9052fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin			found_grandchild = tracee_pid;
90604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_CONT, tracee_pid, 0, 0) < 0) {
90704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(tracee_pid, SIGKILL);
90804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				kill_save_errno(pid, SIGKILL);
90904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg_and_die("PTRACE_CONT doesn't work");
91004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			}
91104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			continue;
912b1467440f7c57c4ba9dc17ab9756e45c84d0adbeDmitry V. Levin		}
91304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		switch (WSTOPSIG(status)) {
91404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGSTOP:
91504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0, test_options) < 0
91604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
91704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
91804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
91904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		case SIGTRAP:
92004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (status >> 16 == PTRACE_EVENT_FORK) {
92104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				long msg = 0;
9222fabd0eaf05379bf121c208ee7a1c129ce1f2f18Dmitry V. Levin
92304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				if (ptrace(PTRACE_GETEVENTMSG, pid,
92404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   NULL, (long) &msg) == 0)
92504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					expected_grandchild = msg;
926b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao			}
92704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			break;
92804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
92904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) {
93004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
93104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
932b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao		}
933b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao	}
93404f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (expected_grandchild && expected_grandchild == found_grandchild) {
935f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
93604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (debug)
93704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			fprintf(stderr, "ptrace_setoptions = %#x\n",
93804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				ptrace_setoptions);
93904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		return;
94004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	}
94104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACECLONE failed, "
94204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
943b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao}
9443454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9453454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko/*
9463454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Test whether the kernel support PTRACE_O_TRACESYSGOOD.
9473454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * First fork a new child, call ptrace(PTRACE_SETOPTIONS) on it,
9483454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and then see whether it will stop with (SIGTRAP | 0x80).
9493454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *
9503454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * Use of this option enables correct handling of user-generated SIGTRAPs,
9513454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * and SIGTRAPs generated by special instructions such as int3 on x86:
9523454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * _start:	.globl	_start
9533454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int3
9543454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$42, %ebx
9553454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		movl	$1, %eax
9563454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko *		int	$0x80
9573454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko * (compile with: "gcc -nostartfiles -nostdlib -o int3 int3.S")
9583454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko */
9593454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkostatic void
9603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenkotest_ptrace_setoptions_for_all(void)
9613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko{
96204f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	const unsigned int test_options = PTRACE_O_TRACESYSGOOD |
96304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  PTRACE_O_TRACEEXEC;
9643454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int pid;
9653454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	int it_worked = 0;
9663454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9673454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	pid = fork();
9683454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid < 0)
96975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		perror_msg_and_die("fork");
9703454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9713454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (pid == 0) {
9723454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		pid = getpid();
9733454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) < 0)
97475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			/* Note: exits with exitcode 1 */
97504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: PTRACE_TRACEME doesn't work",
97604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__);
9773454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		kill(pid, SIGSTOP);
9783454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		_exit(0); /* parent should see entry into this syscall */
9793454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
9803454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9813454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	while (1) {
9823454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		int status, tracee_pid;
9833454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
9843454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		errno = 0;
9853454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		tracee_pid = wait(&status);
9863454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (tracee_pid <= 0) {
9873454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			if (errno == EINTR)
9883454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				continue;
98904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
99004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			perror_msg_and_die("%s: unexpected wait result %d",
99104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					   __func__, tracee_pid);
99275422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		}
99375422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		if (WIFEXITED(status)) {
99475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (WEXITSTATUS(status) == 0)
99575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko				break;
99604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected exit status %u",
99704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WEXITSTATUS(status));
99804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		}
99904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		if (WIFSIGNALED(status)) {
100004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected signal %u",
100104f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, WTERMSIG(status));
10023454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10033454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (!WIFSTOPPED(status)) {
10043454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			kill(pid, SIGKILL);
100504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			error_msg_and_die("%s: unexpected wait status %x",
100604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin					  __func__, status);
10073454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10083454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == SIGSTOP) {
10093454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			/*
10103454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * We don't check "options aren't accepted" error.
10113454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * If it happens, we'll never get (SIGTRAP | 0x80),
10123454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * and thus will decide to not use the option.
10133454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 * IOW: the outcome of the test will be correct.
10143454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			 */
101504f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			if (ptrace(PTRACE_SETOPTIONS, pid, 0L, test_options) < 0
101604f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			    && errno != EINVAL && errno != EIO)
101704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin				perror_msg("PTRACE_SETOPTIONS");
10183454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10193454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
10203454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			it_worked = 1;
10213454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10223454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (ptrace(PTRACE_SYSCALL, pid, 0L, 0L) < 0) {
102304f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin			kill_save_errno(pid, SIGKILL);
102475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			perror_msg_and_die("PTRACE_SYSCALL doesn't work");
10253454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		}
10263454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
10273454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
10283454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	if (it_worked) {
102975422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko		syscall_trap_sig = (SIGTRAP | 0x80);
1030f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko		ptrace_setoptions |= test_options;
10313454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		if (debug)
1032f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko			fprintf(stderr, "ptrace_setoptions = %#x\n",
1033f44cce48bbbd573cc5ae801f69f857433160b03aDenys Vlasenko				ptrace_setoptions);
10343454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko		return;
10353454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	}
10363454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko
103704f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	error_msg("Test for PTRACE_O_TRACESYSGOOD failed, "
103804f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		  "giving up using this feature.");
10393454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko}
104031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
104131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# ifdef USE_SEIZE
104231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkostatic void
104331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkotest_ptrace_seize(void)
104431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko{
104531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	int pid;
104631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
104731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	pid = fork();
104831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid < 0)
104931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		perror_msg_and_die("fork");
105031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
105131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (pid == 0) {
105231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		pause();
105331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		_exit(0);
105431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
105531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
105631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	/* PTRACE_SEIZE, unlike ATTACH, doesn't force tracee to trap.  After
105731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * attaching tracee continues to run unless a trap condition occurs.
105831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * PTRACE_SEIZE doesn't affect signal or group stop state.
105931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 */
106031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	if (ptrace(PTRACE_SEIZE, pid, 0, PTRACE_SEIZE_DEVEL) == 0) {
106131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		post_attach_sigstop = 0; /* this sets use_seize to 1 */
106231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	} else if (debug) {
106331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		fprintf(stderr, "PTRACE_SEIZE doesn't work\n");
106431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
106531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
106631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	kill(pid, SIGKILL);
106731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
106831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	while (1) {
106931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int status, tracee_pid;
107031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
107131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		errno = 0;
107231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		tracee_pid = waitpid(pid, &status, 0);
107331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (tracee_pid <= 0) {
107431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (errno == EINTR)
107531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
107631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			perror_msg_and_die("%s: unexpected wait result %d",
107731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					 __func__, tracee_pid);
107831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
107931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		if (WIFSIGNALED(status)) {
108031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			return;
108131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		}
108231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		error_msg_and_die("%s: unexpected wait status %x",
108331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				__func__, status);
108431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	}
108531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko}
108631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# else /* !USE_SEIZE */
108731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#  define test_ptrace_seize() ((void)0)
108831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko# endif
108931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
1090b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao#endif
1091b13c0de058585de7d47778a8923426b89bfffbb5Wang Chao
1092f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko/* Noinline: don't want main to have struct utsname permanently on stack */
1093f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenkostatic void __attribute__ ((noinline))
1094f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenkoget_os_release(void)
1095f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko{
1096f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	struct utsname u;
1097f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	if (uname(&u) < 0)
1098f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		perror_msg_and_die("uname");
1099f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	os_release = strdup(u.release);
1100f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	if (!os_release)
1101f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		die_out_of_memory();
1102f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko}
1103f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
110508b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levinmain(int argc, char *argv[])
110676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
110906350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	int optF = 0;
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
111208b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin	progname = argv[0] ? argv[0] : "strace";
111308b623eb84266d4a2defc619fa78400c4e4f0dc1Dmitry V. Levin
111475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko	strace_tracer_pid = getpid();
111575422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko
1116f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko	get_os_release();
1117f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
1118ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
1119ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
11204f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcbtab = calloc(tcbtabsize, sizeof(tcbtab[0]));
11211d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcbtab)
11221d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
11234f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	tcp = calloc(tcbtabsize, sizeof(*tcp));
11241d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!tcp)
11251d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
11264f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko	for (c = 0; c < tcbtabsize; c++)
11274f12af24e4c1d4e44b84ba6d5e72e6d8b6490e35Denys Vlasenko		tcbtab[c] = tcp++;
1128ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
1130138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
1131138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
113376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
11378a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		"+cCdfFhiqrtTvVxyz"
1138ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
1139ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		"D"
1140ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
1141b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		"a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
114276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
1144e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_BOTH) {
1145cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
1146e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1147e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_ONLY_STATS;
1148e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			break;
1149e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin		case 'C':
1150e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag == CFLAG_ONLY_STATS) {
1151cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("-c and -C are mutually exclusive options");
1152e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			}
1153e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			cflag = CFLAG_BOTH;
115476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1158ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#ifndef USE_PROCFS
1159ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko		case 'D':
1160ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			daemonized_tracer = 1;
1161ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko			break;
1162ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko#endif
116341c48227a86a176da333f713d5047240885f25ccRoland McGrath		case 'F':
116406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			optF = 1;
116506350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin			break;
116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
116776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
117276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
11918a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'y':
11928a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			show_fd_path = 1;
11938a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
119776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
11989c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
120117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
120217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
120317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
1206102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko			if (acolumn < 0)
1207102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko				error_msg_and_die("Bad column width '%s'", optarg);
120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
12195d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			pid = atoi(optarg);
12205d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			if (pid <= 0) {
1221cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("Invalid process id: '%s'", optarg);
122276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
122376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
122475422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko			if (pid == strace_tracer_pid) {
1225cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg("I'm sorry, I can't let you do that, Dave.");
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1228418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko			tcp = alloc_tcb(pid, 0);
122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
12328a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards		case 'P':
12338a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			tracing_paths = 1;
12348a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			if (pathtrace_select(optarg)) {
1235cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Failed to select path '%s'", optarg);
12368a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			}
12378a08277d13d0378c2ff3ce851534c3bf7e31defaGrant Edwards			break;
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
1240dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
1241b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko				error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1242dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1250de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
12511d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko			if (putenv(optarg) < 0)
12521d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko				die_out_of_memory();
1253de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
1254b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		case 'I':
1255b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			opt_intr = atoi(optarg);
1256b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			if (opt_intr <= 0 || opt_intr >= NUM_INTR_OPTS) {
1257b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko				error_msg_and_die("Invalid -%c argument: '%s'", c, optarg);
1258b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			}
1259b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			break;
126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
126476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1265837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	argv += optind;
1266837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* argc -= optind; - no need, argc is not used below */
126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1268102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces = malloc(acolumn + 1);
1269102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (!acolumn_spaces)
12701d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
1271102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	memset(acolumn_spaces, ' ', acolumn);
1272102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	acolumn_spaces[acolumn] = '\0';
1273102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko
1274837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	/* Must have PROG [ARGS], or -p PID. Not both. */
1275837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (!argv[0] == !pflag_seen)
1276ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
1277ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
1278d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	if (pflag_seen && daemonized_tracer) {
1279cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("-D and -p are mutually exclusive options");
1280d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao	}
1281d322a4bbe118642c4c9b170451a601a1e80b72d6Wang Chao
128206350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin	if (!followfork)
128306350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin		followfork = optF;
128406350dba7505eda4b8220cca8a9b112504fafc4dDmitry V. Levin
1285cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
1286cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("(-c or -C) and -ff are mutually exclusive options");
1287cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
1288cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
1294cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("You must be root to use the -u option");
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
12965d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		pent = getpwnam(username);
12975d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (pent == NULL) {
1298cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("Cannot find user '%s'", username);
129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13088044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#ifdef LINUX
130904f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin	if (followfork)
131004f8b4860f12512186481ca21dbd311d9d612326Dmitry V. Levin		test_ptrace_setoptions_followfork();
13113454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko	test_ptrace_setoptions_for_all();
131231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	test_ptrace_seize();
13138044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin#endif
13148044bc1463f62ae5f974cc531576bc18dade0337Dmitry V. Levin
131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
131737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
131837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
131937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
132037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
132137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
132237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
13237dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			if (followfork > 1)
13247dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				error_msg_and_die("Piping the output and -ff are mutually exclusive");
13257dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko			outf = strace_popen(outfname + 1);
132654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
13273d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko		else if (followfork <= 1)
13283d5ed41252ab8c0bb9f410058c61e95ba91caf90Denys Vlasenko			outf = strace_fopen(outfname);
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1331cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	if (!outfname || outfname[0] == '|' || outfname[0] == '!') {
1332a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		char *buf = malloc(BUFSIZ);
1333a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko		if (!buf)
1334a677da5e3f25107d4402c1c917d019f2d0bc9f29Denys Vlasenko			die_out_of_memory();
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
1336cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	}
1337837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (outfname && argv[0]) {
1338b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (!opt_intr)
1339b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			opt_intr = INTR_NEVER;
134076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
1341369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
1342b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (!opt_intr)
1343b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		opt_intr = INTR_WHILE_WAIT;
1344b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
1345b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	/* argv[0]	-pPID	-oFILE	Default interactive setting
1346b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	0	INTR_WHILE_WAIT
1347b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	0	INTR_WHILE_WAIT
1348b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * yes		0	1	INTR_NEVER
1349b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	 * no		1	1	INTR_WHILE_WAIT
135054cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	 */
135154cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath
135254cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	/* STARTUP_CHILD must be called before the signal handlers get
135354cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   installed below as they are inherited into the spawned process.
135454cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   Also we do not need to be protected by them as during interruption
135554cc1c8ae2d097502439a95d43e1f0ed6782d38cRoland McGrath	   in the STARTUP_CHILD mode we kill the spawned process anyway.  */
1356837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko	if (argv[0])
1357837399af4ffefec55f9693022dc6d8608da442cfDenys Vlasenko		startup_child(argv);
135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
1364b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTOU, &sa, NULL); /* SIG_IGN */
1365b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	sigaction(SIGTTIN, &sa, NULL); /* SIG_IGN */
1366b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko	if (opt_intr != INTR_ANYWHERE) {
1367b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_BLOCK_TSTP_TOO)
1368b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaction(SIGTSTP, &sa, NULL); /* SIG_IGN */
1369b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/*
1370b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In interactive mode (if no -o OUTFILE, or -p PID is used),
1371b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * fatal signals are blocked while syscall stop is processed,
1372b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * and acted on in between, when waiting for new syscall stops.
1373b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 * In non-interactive mode, signals are ignored.
1374b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		 */
1375b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		if (opt_intr == INTR_WHILE_WAIT) {
1376b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGHUP);
1377b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGINT);
1378b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGQUIT);
1379b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGPIPE);
1380b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sigaddset(&blocked_set, SIGTERM);
1381b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sa.sa_handler = interrupt;
138276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
1383b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			/* POSIX signals on sunos4.1 are a little broken. */
1384b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko			sa.sa_flags = SA_INTERRUPT;
1385b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko#endif
1386b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		}
1387b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		/* SIG_IGN, or set handler for these */
1388b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGHUP, &sa, NULL);
1389b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGINT, &sa, NULL);
1390b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGQUIT, &sa, NULL);
1391b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGPIPE, &sa, NULL);
1392b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko		sigaction(SIGTERM, &sa, NULL);
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1394bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
1397553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1398553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
1399553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
1400553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
1401553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
1402553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
1403553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
1404553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
1405bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1407ecfe2f19f963b5c2f176c5e70d42654d7429ce3eDenys Vlasenko	if (pflag_seen || daemonized_tracer)
140802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
140902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
1412b51581e8f0b11d8f1cce055cebb287f728a508a3Denys Vlasenko
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
1414a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	fflush(NULL);
1415a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	if (exit_code > 0xff) {
1416a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Child was killed by a signal, mimic that.  */
1417a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code &= 0xff;
1418a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		signal(exit_code, SIG_DFL);
1419a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		raise(exit_code);
1420a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		/* Paranoia - what if this signal is not fatal?
1421a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		   Exit with 128 + signo then.  */
1422a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin		exit_code += 128;
1423a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	}
1424a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin	exit(exit_code);
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14272b60c35b33cf22a88405c60db1e620880d05a7d4Denys Vlasenkostatic void
1428418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoexpand_tcbtab(void)
14297b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
14307b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
14317b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
14327b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
14337b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
14347b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
143518da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	int i = tcbtabsize;
143618da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb *newtcbs = calloc(tcbtabsize, sizeof(newtcbs[0]));
143718da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	struct tcb **newtab = realloc(tcbtab, tcbtabsize * 2 * sizeof(tcbtab[0]));
14381d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!newtab || !newtcbs)
14391d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
14407b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
14417b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
144218da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	while (i < tcbtabsize)
144318da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko		tcbtab[i++] = newtcbs++;
14447b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
14457b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
144710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1452418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko	if (nprocs == tcbtabsize)
1453418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko		expand_tcbtab();
1454418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko
1455ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1456ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
145818da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko			memset(tcp, 0, sizeof(*tcp));
145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
1460381dbc22929428579f50d9b0b39193feba93dcfdDenys Vlasenko			tcp->flags = TCB_INUSE;
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
1462a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin#if SUPPORTED_PERSONALITIES > 1
1463a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin			tcp->currpers = current_personality;
1464a5a839a920da9d54c4174ebc82b29d7718839029Dmitry V. Levin#endif
14658dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#ifdef USE_PROCFS
146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
14678dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#endif
146876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
14691d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (debug)
14701d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, "new tcb for pid %d, active tcbs:%d\n", tcp->pid, nprocs);
147110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
147210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
147576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
147618da27367534217ac52a425413ae3f8b4b9d8ad2Denys Vlasenko	error_msg_and_die("bug in alloc_tcb");
147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1479bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
148076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
1481418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenkoproc_open(struct tcb *tcp, int attaching)
148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
1485bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
148619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
148719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
148876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
148976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
1490bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1495ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
14969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
14979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
14985d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd = open(proc, O_WRONLY|O_EXCL);
14995d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd < 0) {
15009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
15019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
15029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
15031f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
15049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
15055d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL);
15065d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd_stat < 0) {
15079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
15089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
15099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
15101f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_stat);
15119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
15125d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd_as = open(proc, O_RDONLY|O_EXCL);
15135d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd_as < 0) {
15149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
15159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
15169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
15171f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd_as);
15189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
15200890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko# ifndef FREEBSD
152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
1522372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR|O_EXCL);
15230890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko# else
1524bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
1525372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	tcp->pfd = open(proc, O_RDWR);
15260890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko# endif
1527372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab	if (tcp->pfd < 0) {
152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
15311f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko	set_cloexec_flag(tcp->pfd);
15329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
1533bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1534bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
15355d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	tcp->pfd_reg = open(proc, O_RDONLY);
15365d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (tcp->pfd_reg < 0) {
1537bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
1538bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1539bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1540bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
1541bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
15425d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp->pfd_status = open(proc, O_RDONLY);
15435d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp->pfd_status < 0) {
1544bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
1545bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
1546bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1547bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
1548bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
1549bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
1557b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_STATUS(tcp) < 0) {
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
15619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1562cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				break;
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1565bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
156716a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1571553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
15759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
15819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1586553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1595bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1596bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1597bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1598bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
15995ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1600bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1601bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1602bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
16035ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		perror("PIOCSFL");
16045ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		return -1;
1605bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1606bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1608bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
160919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
161019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
161119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
161219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
1613b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_TRACE) praddset(&syscalls, i);
161419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
1615b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	praddset(&syscalls, SYS_execve);
161619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
1617b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork);
161819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
1619b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_forkall);
162019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1621553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
1622b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_fork1);
162319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
162419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
1625b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rfork1);
162619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
162719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
1628b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		praddset(&syscalls, SYS_rforkall);
162919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
163019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
163119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
163519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
163619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
164019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
164119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
164219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
164319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
1644b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_SIGNAL) praddset(&signals, i);
164519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
16469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
165019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
165119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
165219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
165319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
1654b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (qual_flags[i] & QUAL_FAULT) praddset(&faults, i);
165519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
16569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1660bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1661bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1662b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	arg = S_SIG | S_SCE | S_SCX;
1663b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko	if (ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1664bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1665bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1666bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1667bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1676553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
16789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
1679b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1683553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1684bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1685bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1686bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1687bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1688553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
1691b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			if (IOCTL_WSTOP(tcp) < 0) {
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
16959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1696bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
169706602d99b72564e77600fc7c94e9ce8b78ec7085Denys Vlasenko				get_scno(tcp);
169876989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1702bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
17039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
17040890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
17050890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko#else
17060890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
17070890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko#endif
17080890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko			{
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1712bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1713bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1714bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1715bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1716bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1717bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1718553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
17210890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko#ifdef FREEBSD
17220890c8a403f60c2f66f17bf5d6bb16039b47c913Denys Vlasenko	else {
1723553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
17242e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
17252e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
17262e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
17272e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
17282e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
17292e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
17302e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1731553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
17322e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
17332e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
17342e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
17352e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
17362e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
17372e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
17382e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
17392e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
17402e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
17412e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
17422e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
17432e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
17442e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
17452e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
17462e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
17472e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1748bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1749bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1763bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1765eebb04d4ae8bf4b08a041f5ea442ca24c90692c2Denys Vlasenkostatic struct tcb *
176654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathpid2tcb(int pid)
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
176954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
177054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	if (pid <= 0)
177154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		return NULL;
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1773ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
177454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		struct tcb *tcp = tcbtab[i];
177554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->pid == pid && (tcp->flags & TCB_INUSE))
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
177854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1782bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
178554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathfirst_used_tcb(void)
178654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath{
178754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	int i;
178854e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	struct tcb *tcp;
178954e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
179054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		tcp = tcbtab[i];
179154e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath		if (tcp->flags & TCB_INUSE)
179254e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath			return tcp;
179354e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	}
179454e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath	return NULL;
179554e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath}
179654e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath
179754e931fb858410644f61885b4b36fc20320e1fc6Roland McGrathstatic struct tcb *
17981201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkopfd2tcb(int pfd)
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1802ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1803ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1812bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
18151201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkodroptcb(struct tcb *tcp)
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
181919cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
18211d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko	if (debug)
18221d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		fprintf(stderr, "dropped tcb for pid %d, %d remain\n", tcp->pid, nprocs);
1823eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
18248dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#ifdef USE_PROCFS
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
18288dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko# ifdef FREEBSD
1829bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1830bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1831bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1832bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1833bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1834bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1835bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1836bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
18378dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko# endif
183819cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko		tcp->flags = 0; /* rebuild_pollv needs it */
183919cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko		rebuild_pollv();
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
18418dc0c8c5ef66c2b2eb76484b83c750c0712891f9Denys Vlasenko#endif
1842eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1843822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1845eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
184619cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko	memset(tcp, 0, sizeof(*tcp));
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18490a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
18500a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
18510a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
18520a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
18554c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenkodetach(struct tcb *tcp)
185676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1858ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
18591bfd31032538222fa7d6b5d1741f1a4efa0eb739Roland McGrath	int status, catch_sigstop;
1860ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
1863840d85b3e50cea9f28aedd23af94742c2a60265aAndreas Schwab		clearbpt(tcp);
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
18687bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
18697bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
18717bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
18727bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
18737bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
18747bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
187502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
187631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko	 * We attached but possibly didn't see the expected SIGSTOP.
1877f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	 * We must catch exactly one as otherwise the detached process
1878f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	 * would be left stopped (process state T).
187902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
1880f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko	catch_sigstop = (tcp->flags & TCB_IGNORE_ONE_SIGSTOP);
18814c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko	error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, 0);
18825d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (error == 0) {
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
18847bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
18857bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
18867bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
18877bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
18887bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
188944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	else if (my_tkill(tcp->pid, 0) < 0) {
18907bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
18917bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
18927bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
189344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko	else if (!catch_sigstop && my_tkill(tcp->pid, SIGSTOP) < 0) {
18947bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
18957bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
18967bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
189702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
189802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
1899ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	if (catch_sigstop) {
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
19017508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
19027508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
19037508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
19047508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
19057508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
19077508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
19087508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
19097508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
19107508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
19117508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
19127508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
19137508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
19147508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
19157508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
19167508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
19177508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
19187508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
19197508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
19207508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
19217508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
19227508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
19237508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
19247508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
19257508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
19267508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
19287508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
19344c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko				ptrace_restart(PTRACE_DETACH, tcp, 0);
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1937732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			error = ptrace_restart(PTRACE_CONT, tcp,
193875422766d51cf96ea081977c9d0b26b2ba1a8adeDenys Vlasenko					WSTOPSIG(status) == syscall_trap_sig ? 0
1939732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko					: WSTOPSIG(status));
1940732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			if (error < 0)
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1943ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	}
19447bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
19484c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko	error = ptrace_restart(PTRACE_DETACH, tcp, 0);
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1955a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1959bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1961e5e60858063f214fcd7860f50f8bcb46f951f9abDmitry V. Levinstatic void reaper(int sig)
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1970bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
197276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
19731201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkocleanup(void)
197476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
19773521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	int fatal_sig;
19783521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko
19793521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	/* 'interrupted' is a volatile object, fetch it only once */
19803521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	fatal_sig = interrupted;
19813521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko	if (!fatal_sig)
19823521884c91d0bbd8e796d72619da40bdad95789cDenys Vlasenko		fatal_sig = SIGTERM;
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1984ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1985ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
1991000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko		if (printing_tcp &&
1992000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko		    (!outfname || followfork < 2 || printing_tcp == tcp)) {
1993000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko			tprints(" <unfinished ...>\n");
1994000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko			printing_tcp = NULL;
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
19974c1963836fd96909c2d86315d4972b5b0075edf6Denys Vlasenko			detach(tcp);
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
2000a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko			kill(tcp->pid, fatal_sig);
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
20081201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkointerrupt(int sig)
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2010a3559250d48ccc3ef755183ebb3246cbbb442c0dDenys Vlasenko	interrupted = sig;
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20156d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
20186d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
20211201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrerror(int err_no)
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
202535aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	if (err_no < 1 || err_no >= sys_nerr) {
202635aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko		sprintf(buf, "Unknown error %d", err_no);
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
202935aba6a8dd87a8d1fd69110d80f98224d1f5b18dDenys Vlasenko	return sys_errlist[err_no];
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
20368f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
20376d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
20398f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
20408f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
20418f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
20441201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkostrsignal(int sig)
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2061bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
20641201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkorebuild_pollv(void)
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2068cfd364b011e170377ae002551c4391c01f51acbfDenys Vlasenko	free(pollv);
2069cfd364b011e170377ae002551c4391c01f51acbfDenys Vlasenko	pollv = malloc(nprocs * sizeof(pollv[0]));
20701d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko	if (!pollv)
20711d46ba57a8ab16b353b531f2bbefe2ad7f354ca9Denys Vlasenko		die_out_of_memory();
2072ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
2073ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
2074ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
20789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
2082cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("proc miscount");
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
20891201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll_open(void)
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
2094cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("pipe");
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
20971f532ab27db945c33818ba5298fdd78c52d229eaDenys Vlasenko		set_cloexec_flag(proc_poll_pipe[i]);
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
21021201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poll(struct pollfd *pollv, int nfds, int timeout)
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
21085d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo));
21095d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko	if (n < 0)
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
2112cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		error_msg_and_die("panic: short read: %d", n);
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
21251201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkowakeup_handler(int sig)
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
21301201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoproc_poller(int pfd)
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
2138bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2139bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
2140bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
2144cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("fork");
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
2167cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko		perror_msg_and_die("getrlimit(RLIMIT_NOFILE, ...)");
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
2178bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
21795ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
21805ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#else
21815ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko		if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
21825ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko#endif
21839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
21999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
22169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
222076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
222176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
2223b88f96129f8ebc064d490c8c161bcbc925d938c8Denys Vlasenko		if (tcp && exiting(tcp))
222476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
222576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
222676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
222776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
223176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
2233cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("lost proc");
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
22389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
223976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
224076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
224176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2243cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko	error_msg_and_die("nothing ready");
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
224676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
22471201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkotrace(void)
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
22499dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
2250d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
22519dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
225276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
225376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
225476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
225576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
22569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
226876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
227054e931fb858410644f61885b4b36fc20320e1fc6Roland McGrath				tcp = first_used_tcb();
227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
227576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
22839dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
22849dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
22859dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
22869dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
2287553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
22889dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
22899dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
22909dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
22919dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
22929dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
22939dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
22945d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko				what = poll(&pv, 1, 1);
22955d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko				if (what < 0) {
22969dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
22979dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
22989dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
22999dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
23009dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
23019dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
23029dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
23039dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
23049dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
23059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
230776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
232076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
232176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
232276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
232476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
23255d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pfd2tcb(pfd);
23265d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp == NULL) {
2327cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("unknown pfd: %u", pfd);
232876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2329b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
23309dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
2331b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
233276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
233376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
2334bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
2335b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			ioctl_result = IOCTL_WSTOP(tcp);
2336bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
2337bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
2338bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
2339bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
2340bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
2341b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_STATUS(tcp);
2342bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
2343b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko				ioctl_result = IOCTL_WSTOP(tcp);
2344553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
234576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
234676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
234876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
234976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
235076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
235176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
235376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
235476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
235576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
235676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
235776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
235876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
235976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
236076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
236176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
236276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
236376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
236476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
236576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
236676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2367bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2368bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
2369553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
237076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
237176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
237276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
237376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
2374cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg_and_die("PIOCWSTOP");
237576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
23782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
23792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
23802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
2381b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko			IOCTL(tcp->pfd, PIOCRUN, 0);
23822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
23832e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
2384553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2385553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
238676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
238776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
238876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
238976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
239076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
2391ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
239276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
239376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
239476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2395bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2396bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2397bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2398bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
23995d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0);
24005d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko			if (len > 0) {
2401bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2402bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2403bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2404bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2405bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2406bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2407553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
240876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
240976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2410bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
241176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
241276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
241376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
24149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
24159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2416bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
241776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
24189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
24199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
242076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
2421cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko					error_msg_and_die("syscall trouble");
242276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
242376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
242476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2425bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
242676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
24279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
24289dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
24299dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
243076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
243176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
2432cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("syscall trouble");
243376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
243476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
243576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
2436e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
2437e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_SIGNAL)) {
243876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
2439000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("--- %s (%s) ---\n",
2440ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
2441000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				printing_tcp = NULL;
24425826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
24435826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
24445826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
244560fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko					tprints("    siginfo=");
24465826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
2447000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					tprints("\n");
2448000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					printing_tcp = NULL;
24495826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
24505826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
245176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
2454e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAGS_ONLY_STATS
2455e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			    && (qual_flags[what] & QUAL_FAULT)) {
245676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
2457000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("=== FAULT %d ===\n", what);
2458000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				printing_tcp = NULL;
245976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
246076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2461bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2462bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
24635ae2b7c601dadf79a4345e1ee21053947b9e4addDenys Vlasenko			continue;
2464553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
246576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
2466cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			error_msg_and_die("odd stop %d", tcp->status.PR_WHY);
246776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
246876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2469ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2470ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
24719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2472553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
2473b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0)
2474553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2475b63256e69bf3f1a74aadb0e14556490bc8f4ef95Denys Vlasenko		if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0)
2476553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
2477372cc84c972f8e88cc148f343b02f4b5beb83dc7Andreas Schwab		{
2478cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko			perror_msg_and_die("PIOCRUN");
247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2484bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
248576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2486eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrathstatic int
248731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenkotrace(void)
248876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
248976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
249076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
249126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko	struct rusage *rup = cflag ? &ru : NULL;
249226d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
2493eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	static int wait4_options = __WALL;
249426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif
249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
249676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2497eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath	while (nprocs != 0) {
2498f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int pid;
2499f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int wait_errno;
2500f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		int status, sig;
250131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		int stopped;
2502f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		struct tcb *tcp;
2503f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		unsigned event;
2504f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
2505222713aa409c5caa47327a084f1083a7d6fee66fDenys Vlasenko		if (interrupted)
2506eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			return 0;
2507eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2508eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_SETMASK, &empty_set, NULL);
250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
251026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# ifdef __WALL
251126d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, wait4_options, rup);
25125bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
25132f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
25142f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
251526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, wait4_options, rup);
25162f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
25175bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
25182f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
251926d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			pid = wait4(-1, &status, __WCLONE, rup);
252026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko			if (pid < 0) {
2521cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				perror_msg("wait4(__WCLONE) failed");
25222f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
25232f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
252426d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# else
252526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		pid = wait4(-1, &status, 0, rup);
252626d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko# endif /* __WALL */
252776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
252876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
252976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
253026d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko#endif
253176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
2532eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (interactive)
2533eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
253476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
253526d1b1eaa861ec33d2c671acc9c0ccb867042cb8Denys Vlasenko		if (pid < 0) {
2536eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			switch (wait_errno) {
2537eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case EINTR:
253876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
2539eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			case ECHILD:
254076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
254176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
254276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
2546eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return 0;
2547eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			default:
2548eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				errno = wait_errno;
2549eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				perror("strace: wait");
2550eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				return -1;
255176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
255276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
255310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
255410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
25557dd23384f77e9917bd3173c673f318c5d5b485acDenys Vlasenko				popen_pid = 0;
255610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
255710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
2558f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
2559f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		event = ((unsigned)status >> 16);
25601d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		if (debug) {
25611d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			char buf[sizeof("WIFEXITED,exitcode=%u") + sizeof(int)*3 /*paranoia:*/ + 16];
25621d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef LINUX
2563f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			if (event != 0) {
25641d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				static const char *const event_names[] = {
25651d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_CLONE] = "CLONE",
25661d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_FORK]  = "FORK",
25671d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK] = "VFORK",
25681d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_VFORK_DONE] = "VFORK_DONE",
25691d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXEC]  = "EXEC",
25701d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					[PTRACE_EVENT_EXIT]  = "EXIT",
25711d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				};
25721d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				const char *e;
2573f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				if (event < ARRAY_SIZE(event_names))
2574f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					e = event_names[event];
25751d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				else {
2576f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					sprintf(buf, "?? (%u)", event);
25771d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko					e = buf;
25781d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				}
25791d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				fprintf(stderr, " PTRACE_EVENT_%s", e);
25801d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			}
25811d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
25821d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			strcpy(buf, "???");
25831d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSIGNALED(status))
25841d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#ifdef WCOREDUMP
25851d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,%ssig=%s",
25861d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						WCOREDUMP(status) ? "core," : "",
25871d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
25881d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#else
25891d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSIGNALED,sig=%s",
25901d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko						signame(WTERMSIG(status)));
25911d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko#endif
25921d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFEXITED(status))
25931d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFEXITED,exitcode=%u", WEXITSTATUS(status));
25941d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFSTOPPED(status))
25951d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				sprintf(buf, "WIFSTOPPED,sig=%s", signame(WSTOPSIG(status)));
25965bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#ifdef WIFCONTINUED
25971d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			if (WIFCONTINUED(status))
25981d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko				strcpy(buf, "WIFCONTINUED");
25995bd67c86a93c658d258348e8f14af94fd45cbeb6Denys Vlasenko#endif
26001d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko			fprintf(stderr, " [wait(0x%04x) = %u] %s\n", status, pid, buf);
26011d5f12ecb88f0cd7aa889d1d7ebd47449f4691b7Denys Vlasenko		}
260276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2603f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Look up 'pid' in our table. */
26045d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		tcp = pid2tcb(pid);
2605f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
2606f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko#ifdef LINUX
2607f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		/* Under Linux, execve changes pid to thread leader's pid,
2608f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and we see this changed pid on EVENT_EXEC and later,
2609f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * execve sysexit. Leader "disappears" without exit
2610f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * notification. Let user know that, drop leader's tcb,
2611f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * and fix up pid in execve thread's tcb.
2612f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * Effectively, execve thread's tcb replaces leader's tcb.
2613f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
2614f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * BTW, leader is 'stuck undead' (doesn't report WIFEXITED
2615f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * on exit syscall) in multithreaded programs exactly
2616f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * in order to handle this case.
2617f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 *
2618f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
2619f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 * On 2.6 and earlier, it can return garbage.
2620f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		 */
2621f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
2622f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			long old_pid = 0;
2623f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
2624f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			 && old_pid > 0
2625f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			 && old_pid != pid
2626f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			) {
2627f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				struct tcb *execve_thread = pid2tcb(old_pid);
2628f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				if (tcp) {
2629f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					outf = tcp->outf;
2630f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					curcol = tcp->curcol;
2631f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					if (!cflag) {
2632000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko						if (printing_tcp)
2633f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko							tprints(" <unfinished ...>\n");
2634f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						printleader(tcp);
2635000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko						tprintf("+++ superseded by execve in pid %lu +++\n", old_pid);
2636000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko						printing_tcp = NULL;
2637f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						fflush(outf);
2638f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					}
2639f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					if (execve_thread) {
2640f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						/* swap output FILEs (needed for -ff) */
2641f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						tcp->outf = execve_thread->outf;
2642f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko						execve_thread->outf = outf;
2643f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					}
2644f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					droptcb(tcp);
2645f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				}
2646f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				tcp = execve_thread;
2647f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				if (tcp) {
2648f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					tcp->pid = pid;
2649f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko					tcp->flags |= TCB_REPRINT;
2650f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko				}
2651f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko			}
2652f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		}
2653f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko#endif
2654f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko
26555d64581e106f47c474707001f924ee15ef22830bDenys Vlasenko		if (tcp == NULL) {
2656e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
265741c48227a86a176da333f713d5047240885f25ccRoland McGrath			if (followfork) {
2658e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2659e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2660e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2661e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2662e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2663e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2664e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2665e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2666e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2667418d66a847bda4867c59e604c0d07c64ed53e320Denys Vlasenko				tcp = alloctcb(pid);
266831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
2669e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2670833fb13cef3f1f05b71361b5002aa3c2faad9615Denys Vlasenko					fprintf(stderr, "Process %d attached\n",
2671e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
26728b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2673e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2674e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2675e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
2676eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#endif
2677e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2678e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2679e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2680cb2ad00652e746b370703b5470932b7612308b9cDenys Vlasenko				error_msg_and_die("Unknown pid: %u", pid);
2681e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
268276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
2683eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		/* set current output file */
2684eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		outf = tcp->outf;
2685ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		curcol = tcp->curcol;
2686eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath#ifdef LINUX
268713d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko		if (cflag) {
268876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
268976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
269076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
269113d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#endif
2692eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath
269376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
2694a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2695a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = 0x100 | WTERMSIG(status);
2696e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
269776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
269876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
269913d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#ifdef WCOREDUMP
2700000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s %s+++\n",
27012efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
270213d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					WCOREDUMP(status) ? "(core dumped) " : "");
270313d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko#else
2704000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ killed by %s +++\n",
270513d22f1aa3a1beba79a8febb3770f75e646211a8Denys Vlasenko					signame(WTERMSIG(status)));
27062efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
2707000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				printing_tcp = NULL;
270876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
27095e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko			fflush(tcp->outf);
271076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
271176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
271276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
271376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
2714a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin			if (pid == strace_child)
2715a68096576afc07e51d33b49c432d658b27a7f13cDmitry V. Levin				exit_code = WEXITSTATUS(status);
2716000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko			if (tcp == printing_tcp) {
2717000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprints(" <unfinished ...>\n");
2718000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				printing_tcp = NULL;
27190a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
272019cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			if (!cflag /* && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL) */ ) {
272119cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko				printleader(tcp);
2722000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				tprintf("+++ exited with %d +++\n", WEXITSTATUS(status));
2723000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				printing_tcp = NULL;
272419cdada5b499b978ffd9c3367b4ef34ad6f8bf2bDenys Vlasenko			}
27255e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko			fflush(tcp->outf);
272676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
272776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
272876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
272976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
273076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
273176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
273276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
273376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
273476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2735f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this the very first time we see this tracee stopped? */
2736f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (tcp->flags & TCB_STARTUP) {
2737f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			if (debug)
2738f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "pid %d has TCB_STARTUP, initializing it\n", tcp->pid);
273976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
274002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
274176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
274202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
27432ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko				 * parent through fork().
274476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
27456cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko				if (clearbpt(tcp) < 0) {
27466cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko					/* Pretty fatal */
274776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
274876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
274976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
275076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
275176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2752ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#ifdef LINUX
275344f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko			if (ptrace_setoptions) {
275444f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (debug)
275544f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					fprintf(stderr, "setting opts %x on pid %d\n", ptrace_setoptions, tcp->pid);
275644f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko				if (ptrace(PTRACE_SETOPTIONS, tcp->pid, NULL, ptrace_setoptions) < 0) {
275744f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko					if (errno != ESRCH) {
275844f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						/* Should never happen, really */
275944f87efc676467ab47972feec49af4f7f34356bfDenys Vlasenko						perror_msg_and_die("PTRACE_SETOPTIONS");
27603454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko					}
27613454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko				}
27623454e4b463e6c22c7ea8c5461ef5a077f4650a54Denys Vlasenko			}
2763ca8ab8d2958f86297a6574a73cc1b9759d59c9b1Wang Chao#endif
2764f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2765f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
276631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko		sig = WSTOPSIG(status);
276731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
2768f7db5dd876eb41a3f0d5fd223c831734acc8d8d1Denys Vlasenko		if (event != 0) {
276931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Ptrace event */
277031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
277131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (event == PTRACE_EVENT_STOP || event == PTRACE_EVENT_STOP1) {
27726703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				/*
27736703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop or group-stop.
27746703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
27756703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko				 */
277631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (sig == SIGSTOP
277731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTSTP
277831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTIN
277931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 || sig == SIGTTOU
278031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				) {
278131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					stopped = 1;
278231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					goto show_stopsig;
278331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
278431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
278531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
2786f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			goto restart_tracee_with_sig_0;
2787f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		}
2788f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko
2789f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		/* Is this post-attach SIGSTOP?
2790f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * Interestingly, the process may stop
2791f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * with STOPSIG equal to some other signal
2792f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * than SIGSTOP if we happend to attach
2793f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 * just before the process takes a signal.
2794f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		 */
2795f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko		if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
2796f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			if (debug)
2797f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko				fprintf(stderr, "ignored SIGSTOP on pid %d\n", tcp->pid);
2798f88837a666a716aecd9974f7ef3fcf006e0afce1Denys Vlasenko			tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
27996cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee_with_sig_0;
280076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
280176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
28026cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (sig != syscall_trap_sig) {
280331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			siginfo_t si;
280431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
280531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* Nonzero (true) if tracee is stopped by signal
280631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 * (as opposed to "tracee received signal").
280731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			 */
280831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0);
28096703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#ifdef USE_SEIZE
281031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko show_stopsig:
28116703816060c2cf4aaf9c82057ced31c3ba744346Denys Vlasenko#endif
2812e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073eDmitry V. Levin			if (cflag != CFLAG_ONLY_STATS
28136cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			    && (qual_flags[sig] & QUAL_SIGNAL)) {
2814c15dfc796150d09bb74bebfbb85bebf142766b6cDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP)
28156b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long pc = 0;
28166b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				long psr = 0;
28177b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
2818932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IPSR, &psr);
2819932fc7d4fc1a29e8b8bcea5685db3f6c2e212e36Denys Vlasenko				upeek(tcp, PT_CR_IIP, &pc);
28207b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
28216b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PSR_RI	41
28227b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
28236b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin# define PC_FORMAT_STR	" @ %lx"
28242ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	, pc
28256b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin#else
28262ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_STR	""
28272ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko# define PC_FORMAT_ARG	/* nothing */
28287b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
282976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
283031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (!stopped) {
283160fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko					tprints("--- ");
28326b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin					printsiginfo(&si, verbose(tcp));
2833000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					tprintf(" (%s)" PC_FORMAT_STR " ---\n",
28346cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						strsignal(sig)
28356b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
28366b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin				} else
2837000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					tprintf("--- %s by %s" PC_FORMAT_STR " ---\n",
28386cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						strsignal(sig),
28396cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko						signame(sig)
28406b7a261ff81fdbe84769cb59852fa43cabc77e8fDmitry V. Levin						PC_FORMAT_ARG);
2841000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				printing_tcp = NULL;
28425e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko				fflush(tcp->outf);
284376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
284431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
284531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (!stopped)
284631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/* It's signal-delivery-stop. Inject the signal */
284731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				goto restart_tracee;
284831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko
284931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* It's group-stop */
285031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#ifdef USE_SEIZE
285131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			if (use_seize) {
285231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				/*
285331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This ends ptrace-stop, but does *not* end group-stop.
285431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * This makes stopping signals work properly on straced process
285531fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 * (that is, process really stops. It used to continue to run).
285631fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				 */
285731fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				if (ptrace_restart(PTRACE_LISTEN, tcp, 0) < 0) {
285831fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					cleanup();
285931fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko					return -1;
286031fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				}
286131fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko				continue;
286231fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			}
286331fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko			/* We don't have PTRACE_LISTEN support... */
286431fa8a22b17b2f898513b68e04269597147d2478Denys Vlasenko#endif
28656cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko			goto restart_tracee;
286676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
28672ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
28682ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* We handled quick cases, we are permitted to interrupt now. */
286902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
287002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
28712ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko
28722ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		/* This should be syscall entry or exit.
28732ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * (Or it still can be that pesky post-execve SIGTRAP!)
28742ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 * Handle it.
28752ecba32d52db699538bcfc3f69259aaff32a0fa9Denys Vlasenko		 */
2876eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath		if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
2877eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			/* ptrace() failed in trace_syscall() with ESRCH.
2878eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Likely a result of process disappearing mid-flight.
2879eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath			 * Observed case: exit_group() terminating
2880f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko			 * all processes in thread group.
2881ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			 */
2882ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			if (tcp->flags & TCB_ATTACHED) {
2883000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko				if (printing_tcp) {
2884eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					/* Do we have dangling line "syscall(param, param"?
2885178de007d14f3ae890117b540def9cf14bcb61feDenys Vlasenko					 * Finish the line then.
2886eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath					 */
2887000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					printing_tcp->flags |= TCB_REPRINT;
2888000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					tprints(" <unfinished ...>\n");
2889000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko					printing_tcp = NULL;
28905e09d77500a656da343580a16e6d005eb1c560b1Denys Vlasenko					fflush(tcp->outf);
2891eb9e2e8904ce85a6c7390be25bb873c6db88c4d3Roland McGrath				}
2892f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				/* We assume that ptrace error was caused by process death.
2893f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 * We used to detach(tcp) here, but since we no longer
2894f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 * implement "detach before death" policy/hack,
2895f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 * we can let this process to report its death to us
2896f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 * normally, via WIFEXITED or WIFSIGNALED wait status.
2897f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				 */
2898ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko			} else {
2899f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				/* It's our real child (and we also trace it) */
2900f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				/* my_tkill(pid, SIGKILL); - why? */
2901f1e690370359f61f9533134817b52d74460a20fbDenys Vlasenko				/* droptcb(tcp); - why? */
290276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
290376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
290476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
29056cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee_with_sig_0:
29066cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		sig = 0;
29076cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko restart_tracee:
2908ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		/* Remember current print column before continuing. */
2909ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		tcp->curcol = curcol;
29106cda73ff9ca94e2be56d04186fceaca223a9c45bDenys Vlasenko		if (ptrace_restart(PTRACE_SYSCALL, tcp, sig) < 0) {
291176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
291276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
291376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
291476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
291576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
291676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
291776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2918bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
291976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
292076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
292176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
292276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
292376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
292476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2925e5355de95c495dcfc616509f88c4fb5f9996b8e6Andreas Schwab	va_start(args, fmt);
2926b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2927b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2928ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		if (n < 0) {
2929ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab			if (outf != stderr)
2930ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				perror(outfname == NULL
2931ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab				       ? "<writing to pipe>" : outfname);
2932ccdff481c086611488c5df70550fcf8fe907e7afAndreas Schwab		} else
2933b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2934b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
293576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
29365940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko}
29375940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko
29385940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenkovoid
29395940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenkotprints(const char *str)
29405940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko{
29415940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko	if (outf) {
29425940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		int n = fputs(str, outf);
29435940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		if (n >= 0) {
29445940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			curcol += strlen(str);
29455940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			return;
29465940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		}
29475940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		if (outf != stderr)
29485940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			perror(outfname == NULL
29495940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko			       ? "<writing to pipe>" : outfname);
29505940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko	}
295176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
295276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
295376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
29541201426dd43f5b4e12dfe520e2a9c5027d33dc11Denys Vlasenkoprintleader(struct tcb *tcp)
295576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
2956000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko	if (printing_tcp) {
2957000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko		if (printing_tcp->ptrace_errno) {
2958000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko			if (printing_tcp->flags & TCB_INSYSCALL) {
295960fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko				tprints(" <unavailable>) ");
2960102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko				tabto();
2961732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko			}
296260fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko			tprints("= ? <unavailable>\n");
2963000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko			printing_tcp->ptrace_errno = 0;
2964000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko		} else if (!outfname || followfork < 2 || printing_tcp == tcp) {
2965000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko			printing_tcp->flags |= TCB_REPRINT;
296660fe8c139c6f2febefe595781812ddf0864a6ab8Denys Vlasenko			tprints(" <unfinished ...>\n");
2967732d1bf4d4aaff68eff1c41d8900264637a57dfeDenys Vlasenko		}
296876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
2969000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko
2970000b601439d249a4afa2ceb6096850a702612d1eDenys Vlasenko	printing_tcp = tcp;
297176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
297276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
297376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
297476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
297576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
297676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
297776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
297876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
297976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
298076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
298176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
298276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
298376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
298476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
298576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
298676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
298776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
298876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
298976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
299076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
299176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
299276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
299376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
299476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
299576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
299676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
299776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
299876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
299976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
300076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
300176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
300276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
300376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
300476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
300576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
300676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
300776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
3008102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenkotabto(void)
300976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
3010102ec4935440ff52a7fa3566154a84cc2473f16aDenys Vlasenko	if (curcol < acolumn)
30115940e6593911dcace424c668a1c0934c71fccb9eDenys Vlasenko		tprints(acolumn_spaces + curcol);
301276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
301376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3014ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
30159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
3016ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkoint
3017ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenkomp_ioctl(int fd, int cmd, void *arg, int size)
3018ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko{
30199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
30209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
3021553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
30229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
30239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
30249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
30259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
30269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
30279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
30289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
3029553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
3030ef2fbf856cf775981b52278c80ce2a74a44019f4Denys Vlasenko	return writev(fd, iov, n);
30319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
30329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
30339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
3034