strace.c revision 7b54a7ae61d0eda798575f77d898a24dda7a0952
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
332ee6e45f36566e8735b35ffad40bfcc626a25a98Wichert Akkerman#include <sys/types.h>
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
3576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
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
497b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
507b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
517b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
527b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
53bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
54bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
55bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
56bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
5776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
5876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
59ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
601d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
629ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
6376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
641d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
6576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
6676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint debug = 0, followfork = 0, followvfork = 0, interactive = 0;
6776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint rflag = 0, tflag = 0, dtime = 0, cflag = 0;
6876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint iflag = 0, xflag = 0, qflag = 0;
6976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pflag_seen = 0;
7076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
7117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
7217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
7317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
7476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *username = NULL;
7576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
7676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
7776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
7976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
8076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *outfname = NULL;
8176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
82ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
83ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname;
8576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char **environ;
8676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void));
8876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void));
8976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig));
9076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
9176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
9376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
9476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
9576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
9676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
9776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */
9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted;
9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */
10076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
10176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
102bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd));
10576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig));
10676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void));
107ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void));
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd));
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
12476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
125ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
130bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
13876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
139de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
140de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
141de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath   or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
142de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
16076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
161de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
162de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
163de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
16417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
165de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
166de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanmain(argc, argv)
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint argc;
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *argv[];
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	extern int optind;
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	extern char *optarg;
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
19176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
193ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
194ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]);
195ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]);
196ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
197ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
198ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	progname = argv[0];
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	set_sortby(DEFAULT_SORTBY);
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	set_personality(DEFAULT_PERSONALITY);
20876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
209de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		"+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cflag++;
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
21976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
22076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
22176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'F':
22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followvfork++;
22376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
22576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
22676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
22776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
22876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
22976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
23076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
23176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
23476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
23576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
23676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
23776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
23876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
23976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
24076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
24176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
24276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
24376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
24476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
24576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
24676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
24776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
24876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
24976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
2509c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
25176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
25276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
25317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
25417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
25517f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
25676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
25776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
25876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
25976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
26076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
26176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
26276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
26376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
26476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
26576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
26676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
26776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
26876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
269de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
27076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
27176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
27276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
27476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pid == getpid()) {
27554a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
27676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
27876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((tcp = alloctcb(pid)) == NULL) {
279de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname);
28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
28376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
28576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
28676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
28776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
28876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
28976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
29076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
29176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
29276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
29376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
29476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
295de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
296de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
297de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
298de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
299de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
300de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
301de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
30276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
30376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
30476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
30576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
30676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
30776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
308ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath	if (optind == argc && !pflag_seen)
309ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
310ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
31176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
31276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
31376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
31476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
31576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
31676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
31776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
31876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
31976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
32076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
32176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
32276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
32376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, optarg);
32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
32676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	setreuid(geteuid(), getuid());
33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
33976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
34054b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		long f;
34154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
34237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
34337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
34437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
34537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
34637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
34737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
34837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
34937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
35037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
35137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
35237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
35337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
35437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
35537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if ((outf = popen(outfname + 1, "w")) == NULL) {
35637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "%s: can't popen '%s': %s\n",
35737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname, outfname + 1,
35837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					strerror(errno));
35937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
36037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
36137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		}
36237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		else if ((outf = fopen(outfname, "w")) == NULL) {
36376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: can't fopen '%s': %s\n",
36476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, outfname, strerror(errno));
36576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
36676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
36754b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
36854b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		if ((f=fcntl(fileno(outf), F_GETFD)) < 0 ) {
36954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			perror("failed to get flags for outputfile");
37054b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
37154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
37254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
37354b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		if (fcntl(fileno(outf), F_SETFD, f|FD_CLOEXEC) < 0 ) {
37454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			perror("failed to set flags for outputfile");
37554b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
37654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
37976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	setreuid(geteuid(), getuid());
38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
38337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
38476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
38537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
38776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
388369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
38976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
390ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (c = 0; c < tcbtabsize; c++) {
391ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[c];
39276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Reinitialize the output since it may have changed. */
39376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->outf = outf;
39476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
39576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
396bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
39776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (proc_open(tcp, 1) < 0) {
39876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "trouble opening proc file\n");
39976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
40076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
40176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
402bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
40370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath# ifdef LINUX
40470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
40570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			continue;
4067b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		if (followfork) {
40770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			char procdir[MAXPATHLEN];
40870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			DIR *dir;
40970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
41070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			dir = opendir(procdir);
41170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			if (dir != NULL) {
41270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				unsigned int ntid = 0, nerr = 0;
41370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				struct dirent *de;
41470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				int tid;
41570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				while ((de = readdir(dir)) != NULL) {
41670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					if (de->d_fileno == 0 ||
41770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					    de->d_name[0] == '.')
41870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						continue;
41970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					tid = atoi(de->d_name);
42070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					if (tid <= 0)
42170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						continue;
42270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					++ntid;
42370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					if (ptrace(PTRACE_ATTACH, tid,
42470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						   (char *) 1, 0) < 0)
42570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						++nerr;
42670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					else if (tid != tcbtab[c]->pid) {
4277b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						if (nprocs == tcbtabsize &&
4287b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    expand_tcbtab())
4297b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath							tcp = NULL;
4307b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						else
4317b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath							tcp = alloctcb(tid);
43270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						if (tcp == NULL) {
43370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath							fprintf(stderr, "%s: out of memory\n",
43470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath								progname);
43570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath							exit(1);
43670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						}
4377b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
43870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						tcbtab[c]->nchildren++;
43970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						tcbtab[c]->nclone_threads++;
44070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						tcbtab[c]->nclone_detached++;
44170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						tcp->parent = tcbtab[c];
44270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					}
44370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				}
44470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				closedir(dir);
44570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				if (nerr == ntid) {
44670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
44770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					droptcb(tcp);
44870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					continue;
44970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				}
45070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				if (!qflag) {
45170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					ntid -= nerr;
45270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					if (ntid > 1)
45370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						fprintf(stderr, "\
45470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrathProcess %u attached with %u threads - interrupt to quit\n",
45570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath							tcp->pid, ntid);
45670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					else
45770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						fprintf(stderr, "\
45870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrathProcess %u attached - interrupt to quit\n",
45970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath							tcp->pid);
46070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				}
46170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				continue;
46270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			}
46370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath		}
46470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath# endif
46576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
46676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("attach: ptrace(PTRACE_ATTACH, ...)");
46776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
46876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
46976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
470bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
47176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!qflag)
47276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
47376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"Process %u attached - interrupt to quit\n",
474c3266d51f0b4c0af082000a02649e37f992dbc8bRoland McGrath				tcp->pid);
47576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
47676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
477ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath	if (!pflag_seen) {
47876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct stat statbuf;
47976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char *filename;
48076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char pathname[MAXPATHLEN];
48176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
48276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		filename = argv[optind];
483bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath		if (strchr(filename, '/')) {
484bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath			if (strlen(filename) > sizeof pathname - 1) {
485bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath				errno = ENAMETOOLONG;
486bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath				perror("strace: exec");
487bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath				exit(1);
488bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath			}
48976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(pathname, filename);
490bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath		}
49176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef USE_DEBUGGING_EXEC
49276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
49376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Debuggers customarily check the current directory
49476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * first regardless of the path but doing that gives
49576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * security geeks a panic attack.
49676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
49776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (stat(filename, &statbuf) == 0)
49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(pathname, filename);
49976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* USE_DEBUGGING_EXEC */
50076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
50176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			char *path;
50276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			int m, n, len;
50376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
50476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			for (path = getenv("PATH"); path && *path; path += m) {
50576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (strchr(path, ':')) {
50676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					n = strchr(path, ':') - path;
50776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					m = n + 1;
50876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
50976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
51076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					m = n = strlen(path);
51176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (n == 0) {
51276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					getcwd(pathname, MAXPATHLEN);
51376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					len = strlen(pathname);
51476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
515bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath				else if (n > sizeof pathname - 1)
516bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath					continue;
51776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else {
51876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					strncpy(pathname, path, n);
51976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					len = n;
52076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
52176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (len && pathname[len - 1] != '/')
52276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pathname[len++] = '/';
52376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				strcpy(pathname + len, filename);
524ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				if (stat(pathname, &statbuf) == 0 &&
525ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    /* Accept only regular files
526ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				       with some execute bits set.
527ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				       XXX not perfect, might still fail */
528ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    S_ISREG(statbuf.st_mode) &&
529ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    (statbuf.st_mode & 0111))
53076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
53176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
53276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
53376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (stat(pathname, &statbuf) < 0) {
53476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: %s: command not found\n",
53576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, filename);
53676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
53776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
53876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (pid = fork()) {
53976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case -1:
54076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("strace: fork");
54176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
54276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
54476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 0: {
545bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
546bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        if (outf != stderr) close (fileno (outf));
54776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
54876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Kludge for SGI, see proc_open for details. */
54976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sa.sa_handler = foobar;
55076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sa.sa_flags = 0;
55176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigemptyset(&sa.sa_mask);
55276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigaction(SIGINT, &sa, NULL);
55376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
554bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
55576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pause();
556bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
557bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			kill(getpid(), SIGSTOP); /* stop HERE */
558553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
559bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
560553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath			if (outf!=stderr)
5617987cdf192632516d6ba493b0a9943f5a3a7c362Wichert Akkerman				close(fileno (outf));
562bd4125c6bcd20e8f014b682b31d6fc5d0fef3ed0Wichert Akkerman
56376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
56476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: ptrace(PTRACE_TRACEME, ...)");
56576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
56676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
56776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
56876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				kill(getpid(), SIGSTOP);
56976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
57076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (username != NULL || geteuid() == 0) {
57176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				uid_t run_euid = run_uid;
57276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				gid_t run_egid = run_gid;
57376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
57476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (statbuf.st_mode & S_ISUID)
57576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					run_euid = statbuf.st_uid;
57676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (statbuf.st_mode & S_ISGID)
57776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					run_egid = statbuf.st_gid;
57876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
57976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
58076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * It is important to set groups before we
58176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * lose privileges on setuid.
58276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
5835ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman				if (username != NULL) {
5845ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (initgroups(username, run_gid) < 0) {
5855ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("initgroups");
5865ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5875ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
5885ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (setregid(run_gid, run_egid) < 0) {
5895ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("setregid");
5905ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5915ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
5925ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (setreuid(run_uid, run_euid) < 0) {
5935ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("setreuid");
5945ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5955ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
59676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
59776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
59876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
59976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				setreuid(run_uid, run_uid);
600bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
60176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
60276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			execv(pathname, &argv[optind]);
60376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("strace: exec");
60476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(1);
60576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
60676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
60776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
60876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((tcp = alloctcb(pid)) == NULL) {
60976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "tcb table full\n");
61076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
61176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
61276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
613bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
61476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_open(tcp, 0) < 0) {
61576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "trouble opening proc file\n");
61676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
61776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
619bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
620bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fake_execve(tcp, pathname, &argv[optind], environ);
622bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
62376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
62676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
62876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
63176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
63276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
63376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
63476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
63576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
63676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
63776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
63876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
63976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
64076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
64176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
64276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
64376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
64476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
64576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
64676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
64776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
64876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
651bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
65376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
654553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
655553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
656553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
657553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
658553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
659553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
660553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
661553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
662bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
66376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
66476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
66576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
66776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(0);
66876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermannewoutf(tcp)
67276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
67376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
67476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char name[MAXPATHLEN];
67576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	FILE *fp;
67676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
67776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname && followfork > 1) {
67876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(name, "%s.%u", outfname, tcp->pid);
67976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setreuid(geteuid(), getuid());
68176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fp = fopen(name, "w");
68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setreuid(geteuid(), getuid());
68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (fp == NULL) {
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("fopen");
68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->outf = fp;
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
6957b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathint
6967b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathexpand_tcbtab()
6977b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
6987b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
6997b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
7007b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
7017b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
7027b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
7037b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb **newtab = (struct tcb **)
7047b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
7057b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
7067b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    sizeof *newtcbs);
7077b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	int i;
7087b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	if (newtab == NULL || newtcbs == NULL) {
7097b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		if (newtab != NULL)
7107b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath			free(newtab);
7117b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		return 1;
7127b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
7137b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
7147b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
7157b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
7167b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
7177b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
7187b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	return 0;
7197b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
7207b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
7217b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanalloctcb(pid)
72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
72576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
72676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
72776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
72876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
729ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
730ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
73176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->parent = NULL;
73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->nchildren = 0;
7350962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->nzombies = 0;
736e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
737e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_threads = tcp->nclone_detached = 0;
738e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_waiting = 0;
739e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_sec = 0;
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_usec = 0;
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
74776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
752bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_open(tcp, attaching)
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint attaching;
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
760bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
76119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
76219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
765bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
770ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
7719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
7729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
7739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
7749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
7759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
7789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
7799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
7829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
7839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
7869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
7879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
7889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) {
7919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
7929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) {
7959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
7969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
7999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
8009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
8019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) {
8049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
8059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) {
8089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
8099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
81276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
813bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
81476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
81576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
816bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
817bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
818bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
819bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
82076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
82176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
8239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
8249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
8259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
8289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
8299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
832bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
833bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
834bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
835bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
836bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
837bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
838bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
839bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
840bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
841bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
842bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
843bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
844bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
845bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
846bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
85076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
85176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
85276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
85376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
8549ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
85576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
8589ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
859bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
862bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
86416a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
868553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
8729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
8789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
883553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
88476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
88576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
892bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
893bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
894bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
895bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
896bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
897bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
898bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
899bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
900bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCSFL");
901bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
902bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
903bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
90476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
905bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
90619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
90719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
90819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
90919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
91019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
91119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
91219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
91319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
91419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
91519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
91619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
91719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
918553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
91919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
92019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
92119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
92219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
92319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
92419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
92519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
92619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
92719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
92819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
92976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
93076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
93176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
93219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
93319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
93476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
93576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
93676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
93719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
93819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
93919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
94019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
94119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
94219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
9439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
94819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
94919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
95019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
95119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
95219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
9539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
957bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
958bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
959bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
960bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
961bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
962bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
963bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
964bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
97276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
973553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
9759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
9769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
980553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
981bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
982bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
983bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
984bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
985553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
9889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
99076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
9929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
993bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
994bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
995bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				if (tcp->scno == SYS_execve)
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
999bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
10009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
10019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1002bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1003bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1004553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1008bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1009bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1010bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1011bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1012bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1013bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1014553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1016bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1018bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1019bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1020553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
10212e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
10222e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
10232e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
10242e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
10252e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
10262e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
10272e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1028553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
10292e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
10302e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
10312e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
10322e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
10332e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
10342e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
10352e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
10362e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
10372e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
10382e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
10392e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
10402e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
10412e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
10422e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
10432e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
10442e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1045bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1046bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
104776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1060bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1062e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
106376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid)
106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
106776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
106876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1069ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1070ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid && tcp->pid != pid)
107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
107676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1079bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
108076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1087ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1088ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1097bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1105e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1106e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1107e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1108e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1109e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1110e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1111e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1112e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1113e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1114e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
111576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1117eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1118e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1119e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1120e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1121e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_DETACHED)
1122e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_detached--;
1123e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1124e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1125e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
11260962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED
11270962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath		if (!(tcp->flags & TCB_CLONE_DETACHED))
11280962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif
11290962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->parent->nzombies++;
1130e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1131e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1132e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1133e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
113476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
113576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
113676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1137bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1138bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1139bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1140bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1141bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1142bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1143bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1144bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1145bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1146553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1148e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
114976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1151eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1152822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
115376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1154eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1158bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
116276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
116476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
116776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1172e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1173e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1174e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1175e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("resume: ptrace(PTRACE_SYSCALL, ...)");
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1187bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* detach traced process; continue with sig */
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1197ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
1198e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	int status, resumed;
1199ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sig = SIGKILL;
120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
12077bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
12087bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
120976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
12107bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
12117bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
12127bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
12137bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
12167bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
12177bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
12187bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
12197bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
12207bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
12217bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (kill(tcp->pid, 0) < 0) {
12227bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
12237bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
12247bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
12257bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (kill(tcp->pid, SIGSTOP) < 0) {
12267bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
12277bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
12287bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
12297bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else {
123076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
12317508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
12327508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
12337508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
12347508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
12357508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
123676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
12377508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
12387508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
12397508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
12407508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
12417508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
12427508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
12437508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
12447508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
12457508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
12467508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
12477508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
12487508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
12497508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
12507508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
12517508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
12527508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
12537508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
12547508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
12557508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
12567508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
12587508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
126476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if ((error = ptrace(PTRACE_DETACH,
12657bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath				    tcp->pid, (char *) 1, sig)) < 0) {
126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					if (errno != ESRCH)
126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						perror("detach: ptrace(PTRACE_DETACH, ...)");
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					/* I died trying. */
126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
12737bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			    WSTOPSIG(status) == SIGTRAP ?
12747bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			    0 : WSTOPSIG(status))) < 0) {
127576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (errno != ESRCH)
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: ptrace(PTRACE_CONT, ...)");
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
12817bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
128476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: ptrace(PTRACE_DETACH, ...)");
129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1292bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
1293e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	resumed = 0;
1294e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1295e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* XXX This won't always be quite right (but it never was).
1296e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
1297e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   a particular pgrp, which this child might or might not be
1298e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
1299e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
1300e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   difference to wake up a waiter when there might be more
1301e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   traced children, because it could get a false ECHILD
1302e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
1303e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
1304e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   search the system for all pid's in the pgrp to be sure.
1305e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1306e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	     && (t->waitpid == -1 ||
1307e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1308e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1309e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	*/
1310e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1311e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->parent &&
1312e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
1313e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1314e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 		error = resume(tcp->parent);
1315e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		++resumed;
1316e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1317e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1318e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1319e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* Some other threads of our parent are waiting too.  */
1320e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		unsigned int i;
1321e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1322e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
1323e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
1324e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			struct tcb *t = tcbtab[i];
1325e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (t->parent == tcp->parent && t != tcp
1326e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1327e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1328e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && t->waitpid == tcp->pid) {
1329e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				error |= resume (t);
1330e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				++resumed;
1331e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1332e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1333e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (resumed == 0)
1334e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* Noone was waiting for this PID in particular,
1335e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   so now we might need to resume some wildcarders.  */
1336e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
1337e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				struct tcb *t = tcbtab[i];
1338e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (t->parent == tcp->parent && t != tcp
1339e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				    && ((t->flags
1340e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1341e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1342e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				    && t->waitpid <= 0
1343e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					) {
1344e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					error |= resume (t);
1345e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					break;
1346e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
1347e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1348e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1349e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1350e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1351bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1360bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig)
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
137076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct tcb *tcp;
137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pid2tcb(pid);
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp)
137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
137776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
137876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
137976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1380bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
138176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
138276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
138376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
138776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1388ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1389ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
139076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf(" <unfinished ...>\n");
139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp_last = NULL;
139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14206d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
14236d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14428f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
14436d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
14458f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
14468f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
14478f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
145676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
145876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
146776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1468bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
146976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1475ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1476ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1477c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1478ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
1479ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		fprintf(stderr, "strace: out of memory for poll vector\n");
1480ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1481ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1482ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1483ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1484ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
148676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
14889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
148976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
149076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
149576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
149676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
149776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
149876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
149976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
150076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
150176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
150276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int arg;
150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
150576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
151076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) {
151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("F_GETFD");
151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) {
151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("F_SETFD");
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1563bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1564bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1565bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		_exit(0);
157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		_exit(0);
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1605bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
1606bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1607bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1608bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1609bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
16109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
161576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
161676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
161776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
161876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
161976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
162076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
16269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
16439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
16669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
16789dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
1679d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
16809dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
16859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp = pid2tcb(0);
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
17129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
17139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
17149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
17159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
1716553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
17179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
17189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
17199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
17209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
17219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
17229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
17239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
17249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
17259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
17269dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
17279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
17289dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
17299dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
17309dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
17319dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
17329dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
17339dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
173476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
173576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
173676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
173976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1757b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
17589dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
1759b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
1762bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
17639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
1764bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1765bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
1766bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
1767bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
1768bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
1769bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
1770bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
1771bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			  	ioctl_result = IOCTL_WSTOP (tcp);
1772553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
1795bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1796bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
1797553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18072e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
18082e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
18092e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
18102e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
18112e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
18122e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
1813553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1814553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
181776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
181876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
181976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
182076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
182276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
1823bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1824bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
1825bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
1826bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
1827bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1828bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
1829bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
1830bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1831bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
1832bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
1833bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
1834553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
183576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
183676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
1837bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
183876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
183976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
184076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
18419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
18429ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
1843bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
184476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
18459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
18469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
184776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
185176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
185276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1853bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
18559dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
18569dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
18579dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
186376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
186576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
186676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
186776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
1868ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
18705826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
18715826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
18725826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
18735826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
18745826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
18755826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printtrailer(tcp);
18765826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
18775826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
187876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1887bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1888bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
1889bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		  	continue;
1890553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
18929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
18969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
1897553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
18989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
1899553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1900bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
1901553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
190676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
190776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
190876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1909bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
191076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1911e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
1912e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
1913e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
1914e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
1915e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
1916e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
1917e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
1918e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
1919e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
1920e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
1921e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
1922e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
1923e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
1924e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp->parent
1925e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      : tcp->nclone_detached > 0
1926e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp : NULL);
1927e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1928e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
1929e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (leader != NULL && leader != tcp)
1930e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
1931e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
1932e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
1933e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		droptcb(tcp);	/* Already died.  */
1934e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1935e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
1936e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
1937e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (leader != NULL && leader != tcp) {
1938e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* We need to detach the leader so that the
1939e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   process death will be reported to its real
1940e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent.  But we kill it first to prevent
1941e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   it doing anything before we kill the whole
1942e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   process in a moment.  We can use
1943e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   PTRACE_KILL on a thread that's not already
1944e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   stopped.  Then the value we pass in
1945e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   PTRACE_DETACH just sets the death
1946e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   signal reported to the real parent.  */
1947e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				ptrace(PTRACE_KILL, leader->pid, 0, 0);
1948e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (debug)
1949e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr,
1950e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						" [%d exit %d kills %d]\n",
1951e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						tcp->pid, sig, leader->pid);
1952e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				detach(leader, sig);
1953e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1954e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			detach(tcp, sig);
1955e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1956e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
1957e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			perror("strace: ptrace(PTRACE_CONT, ...)");
1958e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			cleanup();
1959e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return -1;
1960e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1961e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		else {
1962e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (leader != NULL && leader != tcp)
1963e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				droptcb(tcp);
1964e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
1965e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
1966e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
1967e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1968e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1969e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1970e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* Note that TCP and LEADER are no longer valid,
1971e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   but we can still compare against them.  */
1972e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (leader != NULL) {
1973e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		unsigned int i;
1974e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
1975e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			struct tcb *t = tcbtab[i];
1976e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (t != tcp && (t->flags & TCB_CLONE_DETACHED)
1977e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && t->parent == leader)
1978e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				droptcb(t);
1979e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1980e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1981e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1982e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
1983e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
1984e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1985e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
198676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
198776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
198876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
198976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
199076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
19952f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
19962f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman	static int wait4_options = __WALL;
19972f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (nprocs != 0) {
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
20042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
20052f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
20065bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
20072f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
20082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
20092f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
20102f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, wait4_options,
20112f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
20122f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
20135bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
20142f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
20152f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, __WCLONE,
20162f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
20172f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			if (pid == -1) {
20182f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman				fprintf(stderr, "strace: clone wait4 "
20192f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
20202f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
20212f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
20222f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#else
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
20242f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif /* __WALL */
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (wait_errno) {
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ECHILD:
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (nprocs == 0)
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: proc miscount\n");
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				errno = wait_errno;
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: wait");
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2065e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
2066e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (followfork || followvfork) {
2067e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2068e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2069e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2070e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2071e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2072e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2073e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2074e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2075e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2076e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if ((tcp = alloctcb(pid)) == NULL) {
2077e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, " [tcb table full]\n");
2078e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					kill(pid, SIGKILL); /* XXX */
2079e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return 0;
2080e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
2081e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2082e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				newoutf(tcp);
2083e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2084e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2085e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2086e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
20878b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2088e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2089e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2090e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
20918b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif
2092e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2093e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2094e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2095e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2096e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2097e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !LINUX */
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Apparently, doing any ptrace() call on a stopped
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process, provokes the kernel to report the process
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * status again on a subsequent wait(), even if the
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process has not been actually restarted.
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Since we have inspected the arguments of suspended
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * processes we end up here testing for this case.
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
21232efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
21242efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
21252efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
21262efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
21272efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
21282efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2131e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2132e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2133e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
213476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2135e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
213676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "pid %u exited\n", pid);
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					"PANIC: attached pid %u exited\n",
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pid);
21450a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
21460a396906981a03f93c07cb912585d0679dd50899Roland McGrath				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
21470a396906981a03f93c07cb912585d0679dd50899Roland McGrath				    == TCB_INSYSCALL)
21480a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
21490a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
21500a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
21510a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2152e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2153e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2154e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2156e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2166ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_STARTUP) {
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED) {
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Interestingly, the process may stop
217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * with STOPSIG equal to some other signal
217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * than SIGSTOP if we happend to attach
218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * just before the process takes a signal.
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!WIFSTOPPED(status)) {
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr,
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						"pid %u not stopped\n", pid);
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					detach(tcp, WSTOPSIG(status));
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* A child of us stopped at exec */
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (WSTOPSIG(status) == SIGTRAP && followvfork)
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fixvfork(tcp);
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_BPTSET) {
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WSTOPSIG(status) != SIGTRAP) {
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ptrace(PTRACE_SYSCALL,
221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						pid, (char *) 1, 0) < 0) {
221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("trace: ptrace(PTRACE_SYSCALL, ...)");
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
222076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
222176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
222376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
22247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				unsigned long addr = 0, pc = 0;
22257b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#ifdef PT_GETSIGINFO
22267b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#				define PSR_RI	41
22277b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				struct siginfo si;
22287b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				unsigned long psr;
22297b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
22307b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				upeek(pid, PT_CR_IPSR, &psr);
22317b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				upeek(pid, PT_CR_IIP, &pc);
22327b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
22337b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
22347b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
22357b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				addr = (unsigned long) si.si_addr;
22367b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
22387b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tprintf("--- %s (%s) @ %lx (%lx) ---",
2239ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WSTOPSIG(status)),
22407b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					strsignal(WSTOPSIG(status)), pc, addr);
224176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
224376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((tcp->flags & TCB_ATTACHED) &&
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2245e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2246e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2247e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2249e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
225276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
225376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				   WSTOPSIG(status)) < 0) {
225476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("trace: ptrace(PTRACE_SYSCALL, ...)");
225576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (trace_syscall(tcp) < 0) {
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				ptrace(PTRACE_KILL,
226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					tcp->pid, (char *) 1, SIGTERM);
226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
226876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2272e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2273e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2274e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2275e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2276e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2277e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2278e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: ptrace(PTRACE_CONT, ...)");
228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
228676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
228776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
228876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
229176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
229276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
229376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("trace: ptrace(PTRACE_SYSCALL, ...)");
229676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
229776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
229876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
229976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
230076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
230176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
230276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2303bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
230476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol;
230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
230776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b)
231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h>
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a)
231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist)
232076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
232176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl
232276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
232476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
232676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	VA_START(args, fmt);
2327b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2328b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2329b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		if (n < 0 && outf != stderr)
2330b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			perror(outfname == NULL
2331b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			       ? "<writing to pipe>" : outfname);
2332b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		else
2333b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2334b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
233576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
233676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
233776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
233876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
233976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
234076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp)
234176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
234276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
234476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp_last->flags |= TCB_REPRINT;
234576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf(" <unfinished ...>\n");
234676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
234876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
234976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
235076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
235176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
235276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
235376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
235476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
235576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
235676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
235776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
235876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
235976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
236076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
236176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
236276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
236376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
236476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
236576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
236676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
236776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
236876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
236976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
237076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
237176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
237276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
237376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
237476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
237576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
237876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
237976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
238076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
238176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
238276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
238376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
238476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
238576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
238676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
238776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
238876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
238976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
239076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
239176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
239276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprinttrailer(tcp)
239376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
239476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
239576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
239676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
239776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
23989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2399ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
24009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
24019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkermanint mp_ioctl (int fd, int cmd, void *arg, int size) {
24029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
24039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
24049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2405553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
24069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
24079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
24089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
24099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
24109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
24119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
24129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2413553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
24149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	return writev (fd, iov, n);
24159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
24169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
24179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2418