strace.c revision 4bfa6266eb6c67fce50907b427dff6bbd9e93794
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved.
776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without
976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions
1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met:
1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright
1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer.
1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright
1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer in the
1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    documentation and/or other materials provided with the distribution.
1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products
1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    derived from this software without specific prior written permission.
1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *	$Id$
3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
35795edb11488dd47c4598e2228e3b5431de7ed46dRoland McGrath#include <sys/types.h>
3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h>
4619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h>
4770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
4876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
49134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#ifdef LINUX
50134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# include <asm/unistd.h>
51134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# if defined __NR_tgkill
52134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
53134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# elif defined __NR_tkill
54134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) syscall (__NR_tkill, (tid), (sig))
55134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# else
56134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath   /* kill() may choose arbitrarily the target task of the process group
57134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      while we later wait on a that specific TID.  PID process waits become
58134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath      TID task specific waits for a process under ptrace(2).  */
59134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  warning "Neither tkill(2) nor tgkill(2) available, risk of strace hangs!"
60134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#  define my_tgkill(pid, tid, sig) kill ((tid), (sig))
61134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath# endif
62134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath#endif
63134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath
647b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
657b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
667b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
677b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
68bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
69bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
70bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
71bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
7276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
74ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
751d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
791d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
8076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
81b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinint debug = 0, followfork = 0, followvfork = 0;
82b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinint dtime = 0, cflag = 0, xflag = 0, qflag = 0;
83b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
8617f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
8717f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
88b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *username = NULL;
8976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
9076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
9176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
9376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
94b9fe011cdfb0a3014e68a6e82007b6c2703a340bDmitry V. Levinstatic char *outfname = NULL;
9576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
96ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
97ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname;
9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char **environ;
10076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1010a463880341945df08b6dc79134dc78cc38dc283Roland McGrathstatic int detach P((struct tcb *tcp, int sig));
10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void));
10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void));
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig));
10576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted;
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */
11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd));
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig));
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void));
122ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
12576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void));
12776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd));
12876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
13976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
140ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
145bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
154de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
155de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
156de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath   or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
157de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
16176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
16276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
16376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
16476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
16576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
176de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
177de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
178de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
17917f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
180de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
181de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
19276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
19376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
19510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinset_cloexec_flag(int fd)
19610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
19710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     flags, newflags;
19810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
19910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((flags = fcntl(fd, F_GETFD, 0)) < 0)
20010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
20110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_GETFD: %s\n",
20210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
20310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
20410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
20510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
20610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	newflags = flags | FD_CLOEXEC;
20710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (flags == newflags)
20810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return 0;
20910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
21010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fcntl(fd, F_SETFD, newflags) < 0)
21110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
21210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fcntl F_SETFD: %s\n",
21310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
21410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return -1;
21510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
21610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
21710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
21810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
21910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
22010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
22110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * When strace is setuid executable, we have to swap uids
22210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * before and after filesystem and process management operations.
22310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
22410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic void
22510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinswap_uid(void)
22610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
22710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef SVR4
22810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int euid = geteuid(), uid = getuid();
22910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
23010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (euid != uid && setreuid(euid, uid) < 0)
23110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
23210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: setreuid: %s\n",
23310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
23410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		exit(1);
23510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
23610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
23710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
23810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
2394bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#if _LFS64_LARGEFILE
2404bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen64
2414bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#else
2424bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath# define fopen_for_output fopen
2434bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath#endif
2444bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath
24510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
24610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_fopen(const char *path, const char *mode)
24710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
24810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	FILE *fp;
24910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
25010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
2514bfa6266eb6c67fce50907b427dff6bbd9e93794Roland McGrath	if ((fp = fopen_for_output(path, mode)) == NULL)
25210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: can't fopen '%s': %s\n",
25310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, path, strerror(errno));
25410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
25510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (fp && set_cloexec_flag(fileno(fp)) < 0)
25610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
25710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fclose(fp);
25810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fp = NULL;
25910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
26010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return fp;
26110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
26210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
26310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int popen_pid = -1;
26410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
26510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#ifndef _PATH_BSHELL
26610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin# define _PATH_BSHELL "/bin/sh"
26710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin#endif
26810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
26910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin/*
27010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * We cannot use standard popen(3) here because we have to distinguish
27110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * popen child process from other processes we trace, and standard popen(3)
27210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin * does not export its child's pid.
27310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin */
27410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic FILE *
27510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstrace_popen(const char *command)
27610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
27710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	int     fds[2];
27810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
27910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	swap_uid();
28010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (pipe(fds) < 0)
28110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
28210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: pipe: %s\n",
28310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
28410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
28510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
28610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
28710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
28810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(fds[1]) < 0)
28910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
29010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
29110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
29210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
29310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
29410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
29510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
29610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if ((popen_pid = fork()) == -1)
29710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
29810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: fork: %s\n",
29910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, strerror(errno));
30010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
30110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
30210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
30310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return NULL;
30410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
30510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
30610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (popen_pid)
30710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
30810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* parent */
30910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[0]);
31010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		swap_uid();
31110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		return fdopen(fds[1], "w");
31210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	} else
31310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	{
31410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		/* child */
31510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		close(fds[1]);
31610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (fds[0] && (dup2(fds[0], 0) || close(fds[0])))
31710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		{
31810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			fprintf(stderr, "%s: dup2: %s\n",
31910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				progname, strerror(errno));
32010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			_exit(1);
32110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
32210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		execl(_PATH_BSHELL, "sh", "-c", command, NULL);
32310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		fprintf(stderr, "%s: execl: %s: %s\n",
32410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			progname, _PATH_BSHELL, strerror(errno));
32510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		_exit(1);
32610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
32710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
32810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
32910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinstatic int
33010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinnewoutf(struct tcb *tcp)
33110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin{
33210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (outfname && followfork > 1) {
33310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		char name[MAXPATHLEN];
33410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		FILE *fp;
33510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
33610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		sprintf(name, "%s.%u", outfname, tcp->pid);
33710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if ((fp = strace_fopen(name, "w")) == NULL)
33810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			return -1;
33910de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		tcp->outf = fp;
34010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	}
34110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	return 0;
34210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin}
34310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin
34402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
34502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_attach(void)
34602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
34702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int tcbi;
34802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
34902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
35002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
35102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Block user interruptions as we would leave the traced
35202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * process stopped (process state T) if we would terminate in
35302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * between PTRACE_ATTACH and wait4 () on SIGSTOP.
35402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * We rely on cleanup () from this point on.
35502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
35602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
35702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_BLOCK, &blocked_set, NULL);
35802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
35902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
36002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp = tcbtab[tcbi];
36102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
36202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
36302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef LINUX
36402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
36502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
36602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif
36702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Reinitialize the output since it may have changed. */
36802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		tcp->outf = outf;
36902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (newoutf(tcp) < 0)
37002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
37102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
37202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
37302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 1) < 0) {
37402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
37502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
37602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
37702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
37802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
37902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# ifdef LINUX
38002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (followfork) {
38102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			char procdir[MAXPATHLEN];
38202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			DIR *dir;
38302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
38402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
38502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			dir = opendir(procdir);
38602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (dir != NULL) {
38702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				unsigned int ntid = 0, nerr = 0;
38802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				struct dirent *de;
38902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				int tid;
39002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				while ((de = readdir(dir)) != NULL) {
39102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (de->d_fileno == 0 ||
39202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					    de->d_name[0] == '.')
39302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
39402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					tid = atoi(de->d_name);
39502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (tid <= 0)
39602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						continue;
39702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					++ntid;
39802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (ptrace(PTRACE_ATTACH, tid,
39902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						   (char *) 1, 0) < 0)
40002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						++nerr;
40102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					else if (tid != tcbtab[tcbi]->pid) {
40202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						if (nprocs == tcbtabsize &&
40302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						    expand_tcbtab())
40402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							tcp = NULL;
40502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						else
40602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							tcp = alloctcb(tid);
40702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						if (tcp == NULL)
40802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							exit(1);
40902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
41002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nchildren++;
41102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_threads++;
41202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcbtab[tcbi]->nclone_detached++;
41302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						tcp->parent = tcbtab[tcbi];
41402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
41502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (interactive) {
41602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						sigprocmask(SIG_SETMASK, &empty_set, NULL);
41702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						if (interrupted)
41802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							return;
41902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						sigprocmask(SIG_BLOCK, &blocked_set, NULL);
42002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					}
42102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
42202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				closedir(dir);
42302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (nerr == ntid) {
42402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
42502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					droptcb(tcp);
42602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
42702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
42802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!qflag) {
42902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					ntid -= nerr;
43002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					if (ntid > 1)
43102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						fprintf(stderr, "\
43202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathProcess %u attached with %u threads - interrupt to quit\n",
43302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							tcp->pid, ntid);
43402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					else
43502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath						fprintf(stderr, "\
43602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathProcess %u attached - interrupt to quit\n",
43702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath							tcp->pid);
43802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
43902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
44002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
44102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
44202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath# endif
44302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
44402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("attach: ptrace(PTRACE_ATTACH, ...)");
44502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			droptcb(tcp);
44602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			continue;
44702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
44802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* INTERRUPTED is going to be checked at the top of TRACE.  */
44902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
45002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (!qflag)
45102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr,
45202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				"Process %u attached - interrupt to quit\n",
45302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				tcp->pid);
45402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
45502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
45602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (interactive)
45702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigprocmask(SIG_SETMASK, &empty_set, NULL);
45802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
45902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
46002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstatic void
46102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrathstartup_child (char **argv)
46202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath{
46302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct stat statbuf;
46402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	const char *filename;
46502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	char pathname[MAXPATHLEN];
46602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int pid = 0;
46702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	struct tcb *tcp;
46802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
46902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	filename = argv[0];
47002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (strchr(filename, '/')) {
47102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (strlen(filename) > sizeof pathname - 1) {
47202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			errno = ENAMETOOLONG;
47302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("strace: exec");
47402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
47502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
47602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
47702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
47802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_DEBUGGING_EXEC
47902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
48002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * Debuggers customarily check the current directory
48102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * first regardless of the path but doing that gives
48202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * security geeks a panic attack.
48302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
48402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (stat(filename, &statbuf) == 0)
48502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		strcpy(pathname, filename);
48602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_DEBUGGING_EXEC */
48702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else {
48802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		char *path;
48902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		int m, n, len;
49002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
49102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		for (path = getenv("PATH"); path && *path; path += m) {
49202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (strchr(path, ':')) {
49302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				n = strchr(path, ':') - path;
49402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n + 1;
49502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
49602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else
49702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				m = n = strlen(path);
49802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (n == 0) {
49902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (!getcwd(pathname, MAXPATHLEN))
50002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					continue;
50102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = strlen(pathname);
50202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
50302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else if (n > sizeof pathname - 1)
50402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				continue;
50502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			else {
50602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				strncpy(pathname, path, n);
50702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				len = n;
50802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
50902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (len && pathname[len - 1] != '/')
51002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				pathname[len++] = '/';
51102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			strcpy(pathname + len, filename);
51202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (stat(pathname, &statbuf) == 0 &&
51302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    /* Accept only regular files
51402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       with some execute bits set.
51502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			       XXX not perfect, might still fail */
51602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    S_ISREG(statbuf.st_mode) &&
51702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			    (statbuf.st_mode & 0111))
51802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				break;
51902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
52002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
52102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (stat(pathname, &statbuf) < 0) {
52202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		fprintf(stderr, "%s: %s: command not found\n",
52302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			progname, filename);
52402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
52502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
52602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	switch (pid = fork()) {
52702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	case -1:
52802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: fork");
52902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		cleanup();
53002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		exit(1);
53102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		break;
53202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	case 0: {
53302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
53402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf != stderr) close (fileno (outf));
53502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef MIPS
53602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* Kludge for SGI, see proc_open for details. */
53702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_handler = foobar;
53802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sa.sa_flags = 0;
53902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigemptyset(&sa.sa_mask);
54002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		sigaction(SIGINT, &sa, NULL);
54102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* MIPS */
54202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifndef FREEBSD
54302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		pause();
54402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* FREEBSD */
54502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		kill(getpid(), SIGSTOP); /* stop HERE */
54602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* FREEBSD */
54702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#else /* !USE_PROCFS */
54802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (outf!=stderr)
54902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			close(fileno (outf));
55002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
55102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
55202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			perror("strace: ptrace(PTRACE_TRACEME, ...)");
55302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
55402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
55502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (debug)
55602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			kill(getpid(), SIGSTOP);
55702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
55802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (username != NULL || geteuid() == 0) {
55902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			uid_t run_euid = run_uid;
56002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			gid_t run_egid = run_gid;
56102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
56202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISUID)
56302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_euid = statbuf.st_uid;
56402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (statbuf.st_mode & S_ISGID)
56502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				run_egid = statbuf.st_gid;
56602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
56702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			/*
56802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * It is important to set groups before we
56902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 * lose privileges on setuid.
57002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			 */
57102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (username != NULL) {
57202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (initgroups(username, run_gid) < 0) {
57302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("initgroups");
57402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
57502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
57602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setregid(run_gid, run_egid) < 0) {
57702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setregid");
57802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
57902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
58002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				if (setreuid(run_uid, run_euid) < 0) {
58102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					perror("setreuid");
58202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					exit(1);
58302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				}
58402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			}
58502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
58602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		else
58702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			setreuid(run_uid, run_uid);
58802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
58902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
59002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Induce an immediate stop so that the parent
59102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * will resume us with PTRACE_SYSCALL and display
59202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * this execve call normally.
59302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
59402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		kill(getpid(), SIGSTOP);
59502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* !USE_PROCFS */
59602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
59702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		execv(pathname, argv);
59802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		perror("strace: exec");
59902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		_exit(1);
60002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		break;
60102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
60202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	default:
60302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if ((tcp = alloctcb(pid)) == NULL) {
60402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			cleanup();
60502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
60602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
60702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#ifdef USE_PROCFS
60802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (proc_open(tcp, 0) < 0) {
60902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			fprintf(stderr, "trouble opening proc file\n");
61002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			cleanup();
61102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			exit(1);
61202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		}
61302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath#endif /* USE_PROCFS */
61402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		break;
61502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	}
61602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath}
61702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
61976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanmain(argc, argv)
62076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint argc;
62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *argv[];
62276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
62376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	extern int optind;
62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	extern char *optarg;
62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
62676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
62876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
631ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
632ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
633ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]);
634ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]);
635ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
636ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
637ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
63876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	progname = argv[0];
63976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
64076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
641138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_sortby(DEFAULT_SORTBY);
642138c6a334fd9949d6147c63ada02cf55472e02c0Roland McGrath	set_personality(DEFAULT_PERSONALITY);
64376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
64476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
64576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
64676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
64776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
648de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		"+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
65176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cflag++;
65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
65376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
65476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
65576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
65676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
65776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
65876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
65976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
66076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'F':
66176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followvfork++;
66276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
66376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
66476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
66576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
66776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
66876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
67276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
67376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
67476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
67576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
67676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
67776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
67876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
67976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
68176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
6899c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
69217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
69317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
69417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
70176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
70676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
70776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
708de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
70976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
71076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
71176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
71276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
71376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pid == getpid()) {
71454a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
71710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if ((tcp = alloc_tcb(pid, 0)) == NULL) {
718de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
71976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname);
72076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
72176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
727dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
728dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				fprintf(stderr,
729dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					"%s: invalid -s argument: %s\n",
730dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					progname, optarg);
731dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				exit(1);
732dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
73576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
73976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
740de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
741de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
742de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
743de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
744de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
745de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
746de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
753d0c4c0cb881facd0ccf16b0c266875a8bf3e56aaRoland McGrath	if ((optind == argc) == !pflag_seen)
754ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
755ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
756cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	if (followfork > 1 && cflag) {
757cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		fprintf(stderr,
758cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			"%s: -c and -ff are mutually exclusive options\n",
759cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath			progname);
760cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath		exit(1);
761cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath	}
762cb9def6975f28933ada9d35f05c6fba9ab3fe1fdRoland McGrath
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
77509553f85cd97c4ad35cdf316c8e65621b9e86712Roland McGrath				progname, username);
77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
78576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
78837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
78937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
79037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
79137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
79237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
79337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
79437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
79537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
79637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
79737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
79837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
79937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
80037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
80110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if ((outf = strace_popen(outfname + 1)) == NULL)
80237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
80354b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
80410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		else if (followfork <= 1 &&
80510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			 (outf = strace_fopen(outfname, "w")) == NULL)
80654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
80776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
80876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
80937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
81076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
81137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
81376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
814369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
81676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
81776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
81876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
81976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
82476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
82576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
82676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
83376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
83476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
83576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
83676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
840bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
84176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
84276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
843553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
844553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
845553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
846553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
847553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
848553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
849553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
850553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
851bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
85302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (pflag_seen)
85402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_attach();
85502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
85602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		startup_child(&argv[optind]);
85702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(0);
86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8647b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathint
8657b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathexpand_tcbtab()
8667b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
8677b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
8687b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
8697b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
8707b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
8717b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
8727b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb **newtab = (struct tcb **)
8737b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
8747b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
8757b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    sizeof *newtcbs);
8767b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	int i;
8777b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	if (newtab == NULL || newtcbs == NULL) {
8787b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		if (newtab != NULL)
8797b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath			free(newtab);
88076860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin		fprintf(stderr, "%s: expand_tcbtab: out of memory\n",
88176860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin			progname);
8827b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		return 1;
8837b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
8847b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
8857b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
8867b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
8877b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
8887b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
8897b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	return 0;
8907b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
8917b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
8927b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
89376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
89410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levinalloc_tcb(int pid, int command_options_parsed)
89576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
89676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
89776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
899ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
900ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
90276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
90376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->parent = NULL;
90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->nchildren = 0;
9050962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->nzombies = 0;
906e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
907e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_threads = tcp->nclone_detached = 0;
908e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_waiting = 0;
909e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
91176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
91276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_sec = 0;
91376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_usec = 0;
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
91576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
91610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (command_options_parsed)
91710de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				newoutf(tcp);
91876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
92076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
92110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	fprintf(stderr, "%s: alloc_tcb: tcb table full\n", progname);
92276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
92376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
92476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
925bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
92676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
92776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_open(tcp, attaching)
92876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint attaching;
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
93276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
933bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
93419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
93519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
93776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
938bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
943ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
9449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
9459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
9469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
9479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
9489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
9499ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
95010de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
9519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
9529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
9539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
9549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
9559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
9569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
9579ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
95810de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_stat) < 0) {
9599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
9609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
9619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
9629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
9639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
9649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
9659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
96610de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd_as) < 0) {
9679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
9689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
9699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
971bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
974bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
975bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
976bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
977bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
98110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin	if (set_cloexec_flag(tcp->pfd) < 0) {
9829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
9839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
9849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
985bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
986bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
987bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
988bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
989bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
990bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
991bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
992bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
993bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
994bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
995bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
996bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
997bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
998bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
999bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
10079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
101076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
10119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
1012bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
101376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
101476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1015bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
101716a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
101976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
102076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1021553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
102276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
102376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
102476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
10259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
102676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
103076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
10319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
103276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
103376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
103476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
103576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
1036553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
103976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
104076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
104176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
104476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1045bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1046bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
1047bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
1048bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
1049bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
1050bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1051bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
1052bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
1053bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCSFL");
1054bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
1055bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1056bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
1058bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
105919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
106019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
106119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
106219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
106319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
106419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
106519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
106619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
106719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
106819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
106919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
107019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
1071553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
107219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
107319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
107419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
107519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
107619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
107719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
107819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
107919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
108019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
108119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
108519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
108619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
109019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
109119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
109219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
109319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
109419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
109519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
10969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
110019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
110119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
110219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
110319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
110419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
110519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
11069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1110bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1111bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
1112bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
1113bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
1114bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
1115bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
1116bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1117bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
111876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
111976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
112076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
112176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
112276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
112476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
1126553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
112776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
11289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
11299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
113076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
113176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1133553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1134bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
1135bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1136bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
1137bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
1138553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
113976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
114076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
11419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
114276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
114376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
11459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1146bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
114876989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
115176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1152bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
11539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
11549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1155bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1156bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1157553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
115876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1161bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1162bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1163bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1164bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1165bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1166bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1167553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1169bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1171bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1172bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1173553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
11742e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
11752e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
11762e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
11772e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
11782e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
11792e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
11802e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1181553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
11822e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
11832e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
11842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
11852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
11862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
11872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
11882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
11892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
11902e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
11912e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
11922e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
11932e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
11942e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
11952e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
11962e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
11972e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1198bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1199bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
120776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
120876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1213bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1215e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid)
121776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
121876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
122076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
122176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1222ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1223ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid && tcp->pid != pid)
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
122676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
122776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
122876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
122976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
123176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1232bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
123376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
123476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
123576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
123776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
123876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
123976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1240ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1241ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
124276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
124376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
124476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1250bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
125376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1258e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1259e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1260e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1261e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1262e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1263e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1264e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1265e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1266e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1267e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1270eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1271e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1272e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1273e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1274e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_DETACHED)
1275e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_detached--;
1276e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1277e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1278e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
12790962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED
12800962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath		if (!(tcp->flags & TCB_CLONE_DETACHED))
12810962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif
12820962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->parent->nzombies++;
1283e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1284e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1285e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1286e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1290bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1291bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1292bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1293bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1294bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1295bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1296bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1297bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1298bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1299553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1300bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1301e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1304eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1305822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1307eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1311bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1325e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1326e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1327e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1328e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("resume: ptrace(PTRACE_SYSCALL, ...)");
133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1340bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13420a463880341945df08b6dc79134dc78cc38dc283Roland McGrath/* detach traced process; continue with sig
13430a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   Never call DETACH twice on the same process as both unattached and
13440a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   attached-unstopped processes give the same ESRCH.  For unattached process we
13450a463880341945df08b6dc79134dc78cc38dc283Roland McGrath   would SIGSTOP it and wait for its SIGSTOP notification forever.  */
134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
134976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1353ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
135402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	int status, resumed, catch_sigstop;
1355a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	struct tcb *zombie = NULL;
1356a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1357a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	/* If the group leader is lingering only because of this other
1358a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	   thread now dying, then detach the leader as well.  */
1359a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	if ((tcp->flags & TCB_CLONE_THREAD) &&
1360a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    tcp->parent->nclone_threads == 1 &&
1361a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath	    (tcp->parent->flags & TCB_EXITING))
1362a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		zombie = tcp->parent;
1363ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sig = SIGKILL;
136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
13717bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
13727bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
13747bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
13757bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
13767bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
13777bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
137802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	/*
137902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * On TCB_STARTUP we did PTRACE_ATTACH but still did not get the
138002203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * expected SIGSTOP.  We must catch exactly one as otherwise the
138102203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 * detached process would be left stopped (process state T).
138202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	 */
138302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	catch_sigstop = (tcp->flags & TCB_STARTUP);
138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
13867bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
13877bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
13887bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
13897bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
13907bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
1391134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath	else if (my_tgkill((tcp->flags & TCB_CLONE_THREAD ? tcp->parent->pid
1392134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath							  : tcp->pid),
1393134813ae1ecf7f214440a5a09d5eff15a71bf8e6Roland McGrath			   tcp->pid, 0) < 0) {
13947bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
13957bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
13967bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
139702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else if (!catch_sigstop && my_tgkill((tcp->flags & TCB_CLONE_THREAD
139802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					      ? tcp->parent->pid : tcp->pid),
139902203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath					     tcp->pid, SIGSTOP) < 0) {
14007bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
14017bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
14027bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
140302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	else
140402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		catch_sigstop = 1;
140502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath	if (catch_sigstop)
140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
14077508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
14087508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
14097508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
14107508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
14117508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
14137508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
14147508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
14157508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
14167508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
14177508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
14187508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
14197508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
14207508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
14217508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
14227508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
14237508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
14247508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
14257508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
14267508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
14277508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
14287508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
14297508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
14307508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
14317508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
14327508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
14347508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if ((error = ptrace(PTRACE_DETACH,
14417bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath				    tcp->pid, (char *) 1, sig)) < 0) {
144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					if (errno != ESRCH)
144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						perror("detach: ptrace(PTRACE_DETACH, ...)");
144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					/* I died trying. */
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
14497bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			    WSTOPSIG(status) == SIGTRAP ?
14507bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			    0 : WSTOPSIG(status))) < 0) {
145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (errno != ESRCH)
145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: ptrace(PTRACE_CONT, ...)");
145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
14567bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: ptrace(PTRACE_DETACH, ...)");
146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1467bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
1468e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	resumed = 0;
1469e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1470e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* XXX This won't always be quite right (but it never was).
1471e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
1472e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   a particular pgrp, which this child might or might not be
1473e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
1474e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
1475e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   difference to wake up a waiter when there might be more
1476e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   traced children, because it could get a false ECHILD
1477e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
1478e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
1479e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   search the system for all pid's in the pgrp to be sure.
1480e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1481e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	     && (t->waitpid == -1 ||
1482e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1483e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1484e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	*/
1485e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1486e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->parent &&
1487e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
1488e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1489e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 		error = resume(tcp->parent);
1490e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		++resumed;
1491e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1492e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1493e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1494e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* Some other threads of our parent are waiting too.  */
1495e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		unsigned int i;
1496e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1497e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
1498e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
1499e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			struct tcb *t = tcbtab[i];
1500e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (t->parent == tcp->parent && t != tcp
1501e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1502e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1503e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && t->waitpid == tcp->pid) {
1504e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				error |= resume (t);
1505e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				++resumed;
1506e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1507e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1508e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (resumed == 0)
1509e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* Noone was waiting for this PID in particular,
1510e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   so now we might need to resume some wildcarders.  */
1511e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
1512e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				struct tcb *t = tcbtab[i];
1513e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (t->parent == tcp->parent && t != tcp
1514e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				    && ((t->flags
1515e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1516e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1517e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				    && t->waitpid <= 0
1518e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					) {
1519e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					error |= resume (t);
1520e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					break;
1521e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
1522e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1523e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1524e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1525e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1526bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
1532a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
1533a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#ifdef LINUX
15340a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	if (zombie != NULL) {
15350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		/* TCP no longer exists therefore you must not detach () it.  */
15360a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(zombie);
15370a463880341945df08b6dc79134dc78cc38dc283Roland McGrath	}
1538a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath#endif
1539a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1543bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig)
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct tcb *tcp;
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pid2tcb(pid);
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp)
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1563bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1571ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1572ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf(" <unfinished ...>\n");
158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp_last = NULL;
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16036d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
16066d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16258f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
16266d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
16288f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
16298f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
16308f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1651bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1658ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1659ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1660c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1661ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
166246100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "%s: out of memory\n", progname);
1663ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1664ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1665ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1666ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1667ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
16719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
169210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (set_cloexec_flag(proc_poll_pipe[i]) < 0) {
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
172576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
172676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
172776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
173076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1740bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1741bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1742bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		_exit(0);
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		_exit(0);
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1782bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
1783bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1784bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1785bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1786bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
17879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
18039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
18209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
182376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
182476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
183376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
183476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
183776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
184176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
184276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
18439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
185376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
18559dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
1856d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
18579dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
18629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp = pid2tcb(0);
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
18899dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
18909dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
18919dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
18929dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
1893553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
18949dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
18959dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
18969dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
18979dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
18989dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
18999dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
19009dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
19019dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
19029dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
19039dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
19049dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
19059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
19069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
19079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
19089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
19099dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
19109dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
191176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1934b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
19359dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
1936b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
1939bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
19409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
1941bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1942bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
1943bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
1944bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
1945bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
1946bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
1947bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
1948bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			  	ioctl_result = IOCTL_WSTOP (tcp);
1949553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
196776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
196876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
196976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
197076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
197176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
1972bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1973bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
1974553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
197576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
197676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
197776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
197876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
197976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
198076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
198176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
198276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
198376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19842e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
19852e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
19862e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
19872e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
19882e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
19892e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
1990553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1991553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
2000bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2001bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
2002bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
2003bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
2004bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
2005bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
2006bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
2007bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
2008bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
2009bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
2010bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
2011553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
2014bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
20199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
2020bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
20229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
20239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2030bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
20329dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
20339dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
20349dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
2045ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
20475826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
20485826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
20495826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
20505826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
20515826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
20525826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printtrailer(tcp);
20535826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
20545826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
2064bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
2065bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
2066bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		  	continue;
2067553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
20699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
20739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
2074553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
20759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
2076553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
2077bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
2078553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2086bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2088e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2089e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
2090e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
2091e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
2092e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
2093e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
2094e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
2095e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
2096e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
2097e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
2098e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
2099e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
2100e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
2101e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp->parent
2102e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      : tcp->nclone_detached > 0
2103e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp : NULL);
2104e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2105e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
21060569095472c93c8513edefcf31013503ce4c0589Roland McGrath		if (leader != NULL && leader != tcp &&
21070569095472c93c8513edefcf31013503ce4c0589Roland McGrath		    !(leader->flags & TCB_GROUP_EXITING))
2108e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
2109e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
2110e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
21110a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		/* TCP no longer exists therefore you must not detach () it.  */
21120a463880341945df08b6dc79134dc78cc38dc283Roland McGrath		droptcb(tcp);	/* Already died.  */
2113e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2114e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
2115a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		/* Mark that we are taking the process down.  */
2116a08a97eff32ba016ec5d71d2e6948dd43b98cf34Roland McGrath		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
2117e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
211800dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath		  	if (leader != NULL && leader != tcp) {
21190a463880341945df08b6dc79134dc78cc38dc283Roland McGrath				if ((leader->flags & TCB_ATTACHED) &&
21200a463880341945df08b6dc79134dc78cc38dc283Roland McGrath				    !(leader->flags & TCB_EXITING)) {
212100dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					/* We need to detach the leader so
212200dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   that the process death will be
212300dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   reported to its real parent.
212400dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   But we kill it first to prevent
212500dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   it doing anything before we kill
212600dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   the whole process in a moment.
212700dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   We can use PTRACE_KILL on a
212800dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   thread that's not already
212900dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   stopped.  Then the value we pass
213000dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   in PTRACE_DETACH just sets the
213100dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   death signal reported to the
21320a463880341945df08b6dc79134dc78cc38dc283Roland McGrath					   real parent.
21330a463880341945df08b6dc79134dc78cc38dc283Roland McGrath					   FIXME: This killing gets caught by
21340a463880341945df08b6dc79134dc78cc38dc283Roland McGrath					   WAITPID of the leader's parent.
21350a463880341945df08b6dc79134dc78cc38dc283Roland McGrath					   Testcase: test/leaderkill.c  */
213600dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					ptrace(PTRACE_KILL, leader->pid, 0, 0);
213700dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					if (debug)
213800dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath						fprintf(stderr,
213900dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath							" [%d exit %d kills %d]\n",
214000dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath							tcp->pid, sig, leader->pid);
214100dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					detach(leader, sig);
214200dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath				}
214300dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath				else
214400dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					leader->flags |= TCB_GROUP_EXITING;
2145e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2146e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			detach(tcp, sig);
2147e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2148e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
2149e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			perror("strace: ptrace(PTRACE_CONT, ...)");
2150e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			cleanup();
2151e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return -1;
2152e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2153e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		else {
21540569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (leader != NULL)
21550569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
2156e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (leader != NULL && leader != tcp)
2157e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				droptcb(tcp);
2158e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
2159e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
2160e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
2161e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
2162e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
2163e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
2164e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
2165e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
2166e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
2167e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
21772f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
21782f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman	static int wait4_options = __WALL;
21792f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (nprocs != 0) {
218302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
218402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
21882f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
21892f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
21905bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
21912f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
21922f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
21932f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
21942f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, wait4_options,
21952f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
21962f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
21975bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
21982f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
21992f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, __WCLONE,
22002f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
22012f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			if (pid == -1) {
22022f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman				fprintf(stderr, "strace: clone wait4 "
22032f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
22042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
22052f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
22062f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#else
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
22082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif /* __WALL */
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (wait_errno) {
221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
222076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
222176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ECHILD:
222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
222376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
222476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
222576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
222676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
222776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (nprocs == 0)
223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
223176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: proc miscount\n");
223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				errno = wait_errno;
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: wait");
223876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
223976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
224076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
224110de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		if (pid == popen_pid) {
224210de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			if (WIFEXITED(status) || WIFSIGNALED(status))
224310de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin				popen_pid = -1;
224410de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin			continue;
224510de62bb052b541af3d0566f05f3f870cce0e028Dmitry V. Levin		}
224676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
224776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
224976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2251e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
2252e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (followfork || followvfork) {
2253e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2254e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2255e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2256e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2257e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2258e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2259e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2260e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2261e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
226276860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin				if (nprocs == tcbtabsize &&
226376860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin				    expand_tcbtab())
226476860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin					tcp = NULL;
226576860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin				else
226676860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin					tcp = alloctcb(pid);
226776860f60d73bbdcc98725b6f8d7997ad0746cac2Dmitry V. Levin				if (tcp == NULL) {
2268e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					kill(pid, SIGKILL); /* XXX */
2269e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return 0;
2270e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
2271e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2272e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2273e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2274e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2275e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
22768b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2277e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2278e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2279e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
22808b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif
2281e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2282e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2283e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2284e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2285e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2286e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
228776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
228876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
229176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
229276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
229376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !LINUX */
229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
229676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
229776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
229976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Apparently, doing any ptrace() call on a stopped
230076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process, provokes the kernel to report the process
230176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * status again on a subsequent wait(), even if the
230276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process has not been actually restarted.
230376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Since we have inspected the arguments of suspended
230476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * processes we end up here testing for this case.
230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
230776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
23122efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
23132efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
23142efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
23152efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
23162efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
23172efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2320e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2321e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2322e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2324e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
232776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
232876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
232976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "pid %u exited\n", pid);
23300569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if ((tcp->flags & TCB_ATTACHED)
23310569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
23320569095472c93c8513edefcf31013503ce4c0589Roland McGrath			    && !(tcp->parent && (tcp->parent->flags &
23330569095472c93c8513edefcf31013503ce4c0589Roland McGrath						 TCB_GROUP_EXITING))
23340569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
23350569095472c93c8513edefcf31013503ce4c0589Roland McGrath				)
233676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
233776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					"PANIC: attached pid %u exited\n",
233876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pid);
23390a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
23400a396906981a03f93c07cb912585d0679dd50899Roland McGrath				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
23410a396906981a03f93c07cb912585d0679dd50899Roland McGrath				    == TCB_INSYSCALL)
23420a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
23430a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
23440a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
23450a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2346e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2347e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2348e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
234976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2350e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
235176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
235376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
235476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
235576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
235676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
235776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
235876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
235976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2360ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
236176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
236202203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/*
236302203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * Interestingly, the process may stop
236402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * with STOPSIG equal to some other signal
236502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * than SIGSTOP if we happend to attach
236602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 * just before the process takes a signal.
236702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		 */
236802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if ((tcp->flags & TCB_STARTUP) && WSTOPSIG(status) == SIGSTOP) {
236976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
237076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
237176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
237276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
237376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
237476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
237502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			if (tcp->flags & TCB_BPTSET) {
237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
237702203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * One example is a breakpoint inherited from
237802203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath				 * parent through fork ().
237976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
238076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
238176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
238276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
238376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
238476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
238576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
238676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
238776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
238876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
238976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WSTOPSIG(status) != SIGTRAP) {
239076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
239176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
239276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
239376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
239476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
239576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
239676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
239776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ptrace(PTRACE_SYSCALL,
239876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						pid, (char *) 1, 0) < 0) {
239976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("trace: ptrace(PTRACE_SYSCALL, ...)");
240076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
240176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
240276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
240376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
240476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
240576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
240676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
24077b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				unsigned long addr = 0, pc = 0;
24089633942c07427ed51caea0e73f139e964d1a19ccDmitry V. Levin#if defined(PT_CR_IPSR) && defined(PT_CR_IIP) && defined(PT_GETSIGINFO)
24097b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#				define PSR_RI	41
24107b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				struct siginfo si;
24117b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				unsigned long psr;
24127b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
24137b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				upeek(pid, PT_CR_IPSR, &psr);
24147b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				upeek(pid, PT_CR_IIP, &pc);
24157b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
24167b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
24177b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
24187b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				addr = (unsigned long) si.si_addr;
24193a055d7d64222223da2550ca540043de7e3e232bRoland McGrath#elif defined PTRACE_GETSIGINFO
24203a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				if (WSTOPSIG(status) == SIGSEGV ||
24213a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				    WSTOPSIG(status) == SIGBUS) {
24223a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					siginfo_t si;
24233a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					if (ptrace(PTRACE_GETSIGINFO, pid,
24243a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						   0, &si) == 0)
24253a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						addr = (unsigned long)
24263a055d7d64222223da2550ca540043de7e3e232bRoland McGrath							si.si_addr;
24273a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				}
24287b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
242976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
24307b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tprintf("--- %s (%s) @ %lx (%lx) ---",
2431ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WSTOPSIG(status)),
24327b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					strsignal(WSTOPSIG(status)), pc, addr);
243376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
243476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
24350569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
24360569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
243776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2438e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2439e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2440e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
244176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2442e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
244376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
244476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
244576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
244676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				   WSTOPSIG(status)) < 0) {
244776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("trace: ptrace(PTRACE_SYSCALL, ...)");
244876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
244976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
245076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
245176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
245276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
245376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
245402203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		/* we handled the STATUS, we are permitted to interrupt now. */
245502203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath		if (interrupted)
245602203311e96a90608c30e6604dc1f7bda0a777f0Roland McGrath			return 0;
245776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (trace_syscall(tcp) < 0) {
245876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
245976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
246076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
246176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				ptrace(PTRACE_KILL,
246276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					tcp->pid, (char *) 1, SIGTERM);
246376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
246476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
246576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
246676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
246776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2468e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2469e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2470e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2471e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2472e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2473e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2474e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
247576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
247676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
247776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
247876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: ptrace(PTRACE_CONT, ...)");
247976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
248076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
248176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
248276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
248376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
248476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
248576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
248676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
248776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
248876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
248976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
249076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
249176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("trace: ptrace(PTRACE_SYSCALL, ...)");
249276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
249376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
249476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
249576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
249676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
249776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
249876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2499bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
250076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
250176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol;
250276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
250376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
250476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
250576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b)
250676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
250776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h>
250876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a)
250976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
251076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
251176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
251276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
251376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
251476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
251576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist)
251676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
251776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl
251876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
251976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
252076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
252176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
252276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	VA_START(args, fmt);
2523b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2524b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2525b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		if (n < 0 && outf != stderr)
2526b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			perror(outfname == NULL
2527b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			       ? "<writing to pipe>" : outfname);
2528b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		else
2529b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2530b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
253176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
253276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
253376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
253476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
253576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
253676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp)
253776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
253876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
253976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
254076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp_last->flags |= TCB_REPRINT;
254176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf(" <unfinished ...>\n");
254276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
254376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
254476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
254576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
254676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
254776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
254876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
254976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
255076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
255176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
255276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
255376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
255476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
255576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
255676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
255776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
255876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
255976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
256076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
256176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
256276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
256376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
256476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
256576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
256676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
256776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
256876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
256976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
257076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
257176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
257276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
257376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
257476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
257576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
257676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
257776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
257876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
257976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
258076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
258176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
258276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
258376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
258476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
258576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
258676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
258776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
258876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprinttrailer(tcp)
258976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
259076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
259176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
259276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
259376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
25949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2595ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
25969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
25979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkermanint mp_ioctl (int fd, int cmd, void *arg, int size) {
25989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
25999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
26009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2601553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
26029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
26039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
26049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
26059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
26069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
26079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
26089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2609553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
26109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	return writev (fd, iov, n);
26119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
26129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
26139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2614