strace.c revision 76989d7a16cb9683d0a75a6261f18ced66d0c04a
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved.
776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without
976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions
1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met:
1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright
1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer.
1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright
1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer in the
1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    documentation and/or other materials provided with the distribution.
1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products
1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    derived from this software without specific prior written permission.
1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *	$Id$
3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
35795edb11488dd47c4598e2228e3b5431de7ed46dRoland McGrath#include <sys/types.h>
3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h>
4619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h>
4770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath#include <dirent.h>
4876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
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);
288dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			if (max_strlen < 0) {
289dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				fprintf(stderr,
290dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					"%s: invalid -s argument: %s\n",
291dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath					progname, optarg);
292dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath				exit(1);
293dccec72a72e7b6451d9739e5d4611f4abf39f48dRoland McGrath			}
29476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
29576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
29676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
29776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
29876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
29976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
30076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
301de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
302de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
303de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
304de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
305de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
306de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
307de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
30876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
30976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
31076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
31176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
31276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
31376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
314ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath	if (optind == argc && !pflag_seen)
315ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
316ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
31776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
31876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
31976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
32076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
32176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
32276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
32376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
32676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, optarg);
33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
33876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
33976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
34076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
34176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	setreuid(geteuid(), getuid());
34276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
34376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
34476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
34576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
34654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		long f;
34754b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
34837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
34937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
35037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
35137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
35237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
35337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
35437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
35537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
35637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
35737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
35837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
35937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
36037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
36137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if ((outf = popen(outfname + 1, "w")) == NULL) {
36237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "%s: can't popen '%s': %s\n",
36337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname, outfname + 1,
36437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					strerror(errno));
36537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
36637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
36737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		}
36837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		else if ((outf = fopen(outfname, "w")) == NULL) {
36976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: can't fopen '%s': %s\n",
37076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, outfname, strerror(errno));
37176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
37276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
37354b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
37454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		if ((f=fcntl(fileno(outf), F_GETFD)) < 0 ) {
37554b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			perror("failed to get flags for outputfile");
37654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
37754b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
37854b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
37954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		if (fcntl(fileno(outf), F_SETFD, f|FD_CLOEXEC) < 0 ) {
38054b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			perror("failed to set flags for outputfile");
38154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
38254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
38476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
38576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	setreuid(geteuid(), getuid());
38776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
38876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
38937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
39076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
39137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
39276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
39376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
394369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
39576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
396ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (c = 0; c < tcbtabsize; c++) {
397ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[c];
39876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Reinitialize the output since it may have changed. */
39976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->outf = outf;
40076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
40176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
402bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
40376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (proc_open(tcp, 1) < 0) {
40476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "trouble opening proc file\n");
40576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
40676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
40776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
408bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
40970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath# ifdef LINUX
41070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
41170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			continue;
4127b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		if (followfork) {
41370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			char procdir[MAXPATHLEN];
41470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			DIR *dir;
41570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			sprintf(procdir, "/proc/%d/task", tcp->pid);
41670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			dir = opendir(procdir);
41770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			if (dir != NULL) {
41870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				unsigned int ntid = 0, nerr = 0;
41970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				struct dirent *de;
42070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				int tid;
42170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				while ((de = readdir(dir)) != NULL) {
42270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					if (de->d_fileno == 0 ||
42370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					    de->d_name[0] == '.')
42470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						continue;
42570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					tid = atoi(de->d_name);
42670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					if (tid <= 0)
42770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						continue;
42870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					++ntid;
42970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					if (ptrace(PTRACE_ATTACH, tid,
43070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						   (char *) 1, 0) < 0)
43170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						++nerr;
43270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					else if (tid != tcbtab[c]->pid) {
4337b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						if (nprocs == tcbtabsize &&
4347b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    expand_tcbtab())
4357b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath							tcp = NULL;
4367b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						else
4377b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath							tcp = alloctcb(tid);
43870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						if (tcp == NULL) {
43970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath							fprintf(stderr, "%s: out of memory\n",
44070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath								progname);
44170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath							exit(1);
44270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						}
4437b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						tcp->flags |= TCB_ATTACHED|TCB_CLONE_THREAD|TCB_CLONE_DETACHED|TCB_FOLLOWFORK;
44470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						tcbtab[c]->nchildren++;
44570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						tcbtab[c]->nclone_threads++;
44670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						tcbtab[c]->nclone_detached++;
44770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						tcp->parent = tcbtab[c];
44870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					}
44970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				}
45070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				closedir(dir);
45170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				if (nerr == ntid) {
45270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					perror("attach: ptrace(PTRACE_ATTACH, ...)");
45370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					droptcb(tcp);
45470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					continue;
45570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				}
45670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				if (!qflag) {
45770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					ntid -= nerr;
45870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					if (ntid > 1)
45970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						fprintf(stderr, "\
46070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrathProcess %u attached with %u threads - interrupt to quit\n",
46170b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath							tcp->pid, ntid);
46270b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath					else
46370b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath						fprintf(stderr, "\
46470b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrathProcess %u attached - interrupt to quit\n",
46570b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath							tcp->pid);
46670b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				}
46770b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath				continue;
46870b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath			}
46970b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath		}
47070b08530b80a6ee6591c38cf397fe0eeba1b4d7aRoland McGrath# endif
47176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
47276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("attach: ptrace(PTRACE_ATTACH, ...)");
47376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
47476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
47576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
476bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
47776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!qflag)
47876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
47976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"Process %u attached - interrupt to quit\n",
480c3266d51f0b4c0af082000a02649e37f992dbc8bRoland McGrath				tcp->pid);
48176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
48276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
483ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath	if (!pflag_seen) {
48476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct stat statbuf;
48576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char *filename;
48676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char pathname[MAXPATHLEN];
48776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
48876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		filename = argv[optind];
489bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath		if (strchr(filename, '/')) {
490bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath			if (strlen(filename) > sizeof pathname - 1) {
491bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath				errno = ENAMETOOLONG;
492bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath				perror("strace: exec");
493bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath				exit(1);
494bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath			}
49576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(pathname, filename);
496bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath		}
49776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef USE_DEBUGGING_EXEC
49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
49976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Debuggers customarily check the current directory
50076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * first regardless of the path but doing that gives
50176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * security geeks a panic attack.
50276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
50376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (stat(filename, &statbuf) == 0)
50476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(pathname, filename);
50576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* USE_DEBUGGING_EXEC */
50676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
50776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			char *path;
50876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			int m, n, len;
50976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
51076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			for (path = getenv("PATH"); path && *path; path += m) {
51176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (strchr(path, ':')) {
51276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					n = strchr(path, ':') - path;
51376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					m = n + 1;
51476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
51576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
51676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					m = n = strlen(path);
51776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (n == 0) {
51876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					getcwd(pathname, MAXPATHLEN);
51976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					len = strlen(pathname);
52076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
521bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath				else if (n > sizeof pathname - 1)
522bdb09df1866b8c50317011938bb963aa9d694cd6Roland McGrath					continue;
52376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else {
52476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					strncpy(pathname, path, n);
52576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					len = n;
52676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
52776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (len && pathname[len - 1] != '/')
52876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pathname[len++] = '/';
52976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				strcpy(pathname + len, filename);
530ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				if (stat(pathname, &statbuf) == 0 &&
531ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    /* Accept only regular files
532ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				       with some execute bits set.
533ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				       XXX not perfect, might still fail */
534ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    S_ISREG(statbuf.st_mode) &&
535ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    (statbuf.st_mode & 0111))
53676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
53776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
53876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
53976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (stat(pathname, &statbuf) < 0) {
54076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: %s: command not found\n",
54176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, filename);
54276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
54476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (pid = fork()) {
54576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case -1:
54676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("strace: fork");
54776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
54876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
54976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
55076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 0: {
551bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
552bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        if (outf != stderr) close (fileno (outf));
55376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
55476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Kludge for SGI, see proc_open for details. */
55576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sa.sa_handler = foobar;
55676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sa.sa_flags = 0;
55776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigemptyset(&sa.sa_mask);
55876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigaction(SIGINT, &sa, NULL);
55976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
560bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
56176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pause();
562bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
563bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			kill(getpid(), SIGSTOP); /* stop HERE */
564553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
565bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
566553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath			if (outf!=stderr)
5677987cdf192632516d6ba493b0a9943f5a3a7c362Wichert Akkerman				close(fileno (outf));
568bd4125c6bcd20e8f014b682b31d6fc5d0fef3ed0Wichert Akkerman
56976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
57076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: ptrace(PTRACE_TRACEME, ...)");
57176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
57276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
57376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
57476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				kill(getpid(), SIGSTOP);
57576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
57676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (username != NULL || geteuid() == 0) {
57776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				uid_t run_euid = run_uid;
57876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				gid_t run_egid = run_gid;
57976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
58076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (statbuf.st_mode & S_ISUID)
58176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					run_euid = statbuf.st_uid;
58276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (statbuf.st_mode & S_ISGID)
58376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					run_egid = statbuf.st_gid;
58476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
58576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
58676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * It is important to set groups before we
58776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * lose privileges on setuid.
58876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
5895ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman				if (username != NULL) {
5905ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (initgroups(username, run_gid) < 0) {
5915ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("initgroups");
5925ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5935ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
5945ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (setregid(run_gid, run_egid) < 0) {
5955ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("setregid");
5965ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5975ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
5985ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (setreuid(run_uid, run_euid) < 0) {
5995ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("setreuid");
6005ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
6015ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
60276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
60376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
60476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
60576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				setreuid(run_uid, run_uid);
60615dca8e307086cb2a53045046fe4791dc7afe378Roland McGrath
60715dca8e307086cb2a53045046fe4791dc7afe378Roland McGrath			/*
60815dca8e307086cb2a53045046fe4791dc7afe378Roland McGrath			 * Induce an immediate stop so that the parent
60915dca8e307086cb2a53045046fe4791dc7afe378Roland McGrath			 * will resume us with PTRACE_SYSCALL and display
61015dca8e307086cb2a53045046fe4791dc7afe378Roland McGrath			 * this execve call normally.
61115dca8e307086cb2a53045046fe4791dc7afe378Roland McGrath			 */
61215dca8e307086cb2a53045046fe4791dc7afe378Roland McGrath			kill(getpid(), SIGSTOP);
613bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
61476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
61576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			execv(pathname, &argv[optind]);
61676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("strace: exec");
61776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(1);
61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
61976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
62076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((tcp = alloctcb(pid)) == NULL) {
62276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "tcb table full\n");
62376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
626bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_open(tcp, 0) < 0) {
62876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "trouble opening proc file\n");
62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
63176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
632bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
63376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
63476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
63576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
63676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
63776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
63876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
63976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
64076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
64176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
64276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
64376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
64476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
64576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
64676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
64776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
64876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
65176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
65376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
65476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
65576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
65676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
65776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
65876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
65976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
66076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
661bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
66276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
66376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
664553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
665553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
666553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
667553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
668553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
669553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
670553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
671553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
672bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
67376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
67476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
67576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
67676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
67776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(0);
67876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
67976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
68076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
68176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermannewoutf(tcp)
68276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
68376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
68476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char name[MAXPATHLEN];
68576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	FILE *fp;
68676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
68776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname && followfork > 1) {
68876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(name, "%s.%u", outfname, tcp->pid);
68976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
69076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setreuid(geteuid(), getuid());
69176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
69276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fp = fopen(name, "w");
69376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
69476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setreuid(geteuid(), getuid());
69576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
69676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (fp == NULL) {
69776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("fopen");
69876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
69976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
70076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->outf = fp;
70176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
70276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
70376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
70476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
7057b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathint
7067b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrathexpand_tcbtab()
7077b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath{
7087b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	/* Allocate some more TCBs and expand the table.
7097b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   We don't want to relocate the TCBs because our
7107b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   callers have pointers and it would be a pain.
7117b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   So tcbtab is a table of pointers.  Since we never
7127b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	   free the TCBs, we allocate a single chunk of many.  */
7137b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb **newtab = (struct tcb **)
7147b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
7157b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
7167b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath						    sizeof *newtcbs);
7177b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	int i;
7187b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	if (newtab == NULL || newtcbs == NULL) {
7197b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		if (newtab != NULL)
7207b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath			free(newtab);
7217b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		return 1;
7227b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	}
7237b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
7247b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath		newtab[i] = &newtcbs[i - tcbtabsize];
7257b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtabsize *= 2;
7267b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	tcbtab = newtab;
7277b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
7287b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath	return 0;
7297b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath}
7307b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
7317b54a7ae61d0eda798575f77d898a24dda7a0952Roland McGrath
73276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
73376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanalloctcb(pid)
73476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
73576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
73676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
73776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
73876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
739ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
740ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->parent = NULL;
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->nchildren = 0;
7450962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->nzombies = 0;
746e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
747e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_threads = tcp->nclone_detached = 0;
748e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_waiting = 0;
749e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_sec = 0;
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_usec = 0;
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
76176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
762bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_open(tcp, attaching)
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint attaching;
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
770bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
77119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
77219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
775bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
780ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
7819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
7829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
7839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
7849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
7859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
7889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
7899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
7929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
7939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
7969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
7979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
7989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) {
8019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
8029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) {
8059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
8069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
8099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
8109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
8119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) {
8149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
8159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) {
8189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
8199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
823bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
82476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
82576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
826bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
827bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
828bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
829bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
83076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
8339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
8349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
8359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
8389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
8399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
8409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
8419ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
842bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
843bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
844bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
845bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
846bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
847bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
848bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
849bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
850bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
851bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
852bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
853bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
854bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
855bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
856bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
8649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
86676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
8689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
869bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
872bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
87416a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
87576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
87776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
878553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
8829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
88476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
88576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
88676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
88776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
8889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
89276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
893553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
89476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
89576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
89676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
89776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
90176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
902bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
903bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
904bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
905bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
906bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
907bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
908bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
909bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
910bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCSFL");
911bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
912bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
913bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
91476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
915bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
91619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
91719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
91819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
91919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
92019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
92119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
92219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
92319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
92419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
92519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
92619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
92719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
928553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
92919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
93019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
93119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
93219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
93319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
93419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
93519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
93619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
93719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
93819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
93976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
94319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
94819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
94919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
95019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
95119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
95219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
9539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
95719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
95819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
95919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
96019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
96119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
96219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
9639ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
967bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
968bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
969bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
970bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
971bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
972bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
973bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
974bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
98176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
98276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
983553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
9859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
9869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
990553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
991bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
992bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
993bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
994bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
995553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
9989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
99976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
10029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
1003bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
1004bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
100576989d7a16cb9683d0a75a6261f18ced66d0c04aRoland McGrath				if (known_scno(tcp) == SYS_execve)
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
100776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
1009bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
10109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
10119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
1012bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1013bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
1014553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
101576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
101676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
1018bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1019bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
1020bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
1021bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
1022bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
1023bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
1024553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
102576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1026bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1028bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1029bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
1030553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
10312e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
10322e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
10332e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
10342e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
10352e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
10362e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
10372e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
1038553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
10392e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
10402e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
10412e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
10422e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
10432e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
10442e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
10452e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
10462e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
10472e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
10482e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
10492e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
10502e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
10512e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
10522e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
10532e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
10542e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
1055bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
1056bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
106276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
106376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
106776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
106876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1070bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1072e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid)
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
107676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1079ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1080ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid && tcp->pid != pid)
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1089bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1097ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
1098ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
110076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
110176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
110676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1107bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
110976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
111076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
111276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
111376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
111476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1115e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1116e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1117e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1118e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1119e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1120e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1121e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1122e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1123e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1124e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
112576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
112676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1127eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1128e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1129e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1130e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1131e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_DETACHED)
1132e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_detached--;
1133e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1134e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1135e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
11360962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED
11370962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath		if (!(tcp->flags & TCB_CLONE_DETACHED))
11380962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif
11390962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->parent->nzombies++;
1140e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1141e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1142e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1143e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
114476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
114576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
114676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1147bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1148bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1149bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1150bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1151bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1152bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1153bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1154bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1155bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1156553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1157bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1158e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1161eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1162822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1164eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
116776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1168bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
117276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1182e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1183e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1184e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1185e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("resume: ptrace(PTRACE_SYSCALL, ...)");
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
119476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
119576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
119676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1197bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
119876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
119976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* detach traced process; continue with sig */
120076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
120176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
120276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
120376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
120476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
120576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
120676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1207ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
1208e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	int status, resumed;
1209ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
121076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
121176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
121276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sig = SIGKILL;
121376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
121476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
121576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
121676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
12177bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
12187bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
121976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
12207bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
12217bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
12227bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
12237bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
122476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
122576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
12267bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
12277bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
12287bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
12297bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
12307bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
12317bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (kill(tcp->pid, 0) < 0) {
12327bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
12337bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
12347bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
12357bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (kill(tcp->pid, SIGSTOP) < 0) {
12367bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
12377bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
12387bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
12397bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else {
124076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
12417508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
12427508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
12437508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
12447508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
12457508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
12477508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
12487508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
12497508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
12507508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
12517508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
12527508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
12537508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
12547508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
12557508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
12567508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
12577508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
12587508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
12597508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
12607508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
12617508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
12627508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
12637508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
12647508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
12657508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
12667508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
12687508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
127376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
127476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if ((error = ptrace(PTRACE_DETACH,
12757bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath				    tcp->pid, (char *) 1, sig)) < 0) {
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					if (errno != ESRCH)
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						perror("detach: ptrace(PTRACE_DETACH, ...)");
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					/* I died trying. */
127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
128176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
128276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
12837bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			    WSTOPSIG(status) == SIGTRAP ?
12847bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			    0 : WSTOPSIG(status))) < 0) {
128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (errno != ESRCH)
128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: ptrace(PTRACE_CONT, ...)");
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
12917bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: ptrace(PTRACE_DETACH, ...)");
130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1302bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
1303e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	resumed = 0;
1304e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1305e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* XXX This won't always be quite right (but it never was).
1306e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
1307e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   a particular pgrp, which this child might or might not be
1308e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
1309e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
1310e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   difference to wake up a waiter when there might be more
1311e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   traced children, because it could get a false ECHILD
1312e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
1313e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
1314e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   search the system for all pid's in the pgrp to be sure.
1315e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1316e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	     && (t->waitpid == -1 ||
1317e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1318e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1319e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	*/
1320e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1321e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->parent &&
1322e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
1323e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1324e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 		error = resume(tcp->parent);
1325e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		++resumed;
1326e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1327e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1328e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1329e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* Some other threads of our parent are waiting too.  */
1330e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		unsigned int i;
1331e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1332e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
1333e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
1334e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			struct tcb *t = tcbtab[i];
1335e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (t->parent == tcp->parent && t != tcp
1336e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1337e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1338e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && t->waitpid == tcp->pid) {
1339e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				error |= resume (t);
1340e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				++resumed;
1341e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1342e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1343e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (resumed == 0)
1344e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* Noone was waiting for this PID in particular,
1345e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   so now we might need to resume some wildcarders.  */
1346e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
1347e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				struct tcb *t = tcbtab[i];
1348e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (t->parent == tcp->parent && t != tcp
1349e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				    && ((t->flags
1350e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1351e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1352e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				    && t->waitpid <= 0
1353e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					) {
1354e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					error |= resume (t);
1355e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					break;
1356e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
1357e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1358e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1359e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1360e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1361bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1370bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig)
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
137776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
137876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
137976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
138076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
138176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct tcb *tcp;
138276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
138376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pid2tcb(pid);
138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp)
138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
138776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
138876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
138976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1390bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1398ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1399ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf(" <unfinished ...>\n");
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp_last = NULL;
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14306d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
14336d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
14528f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
14536d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
14558f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
14568f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
14578f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
145876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
146776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
146876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
146976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
147576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1478bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
147976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
148076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
148176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1485ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1486ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1487c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1488ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
148946100d07257824da2ae1147da0324b5788c95501Roland McGrath		fprintf(stderr, "%s: out of memory\n", progname);
1490ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1491ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1492ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1493ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1494ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
149576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
149676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
149776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
14989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
149976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
150076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
150176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
150276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
150576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
151076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int arg;
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) {
152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("F_GETFD");
152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) {
152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("F_SETFD");
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1573bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1574bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1575bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		_exit(0);
158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		_exit(0);
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
161476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1615bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
1616bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1617bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1618bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1619bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
16209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
162176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
162276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
162376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
162476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
162576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
162676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
16369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
16539ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
165976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
166076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
166176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
166476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
166576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
16769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
16889dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
1689d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
16909dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
16959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp = pid2tcb(0);
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
171676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
17229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
17239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
17249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
17259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
1726553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
17279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
17289dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
17299dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
17309dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
17319dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
17329dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
17339dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
17349dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
17359dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
17369dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
17379dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
17389dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
17399dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
17409dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
17419dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
17429dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
17439dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
174876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1767b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
17689dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
1769b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
177076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
1772bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
17739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
1774bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1775bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
1776bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
1777bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
1778bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
1779bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
1780bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
1781bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			  	ioctl_result = IOCTL_WSTOP (tcp);
1782553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
178976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
179076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
179176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
179276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
179476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
180276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
1805bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1806bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
1807553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
181176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
181376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
181476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
181576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
181676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18172e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
18182e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
18192e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
18202e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
18212e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
18222e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
1823553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1824553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
182576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
182676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
182776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
182876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
182976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
183076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
183176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
183276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
1833bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1834bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
1835bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
1836bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
1837bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1838bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
1839bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
1840bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1841bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
1842bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
1843bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
1844553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
184576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
184676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
1847bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
184876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
184976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
185076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
18519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
18529ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
1853bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
185476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
18559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
18569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
185776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
185876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
185976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
186076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
186176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
186276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1863bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
186476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
18659dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
18669dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
18679dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
186876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
186976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
187076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
187176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
187276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
187376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
187476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
187576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
187676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
187776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
1878ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
18805826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
18815826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
18825826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
18835826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
18845826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
18855826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printtrailer(tcp);
18865826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
18875826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1897bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1898bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
1899bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		  	continue;
1900553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
19029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
19069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
1907553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
19089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
1909553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1910bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
1911553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
191276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
191376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
191476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
191576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
191776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1919bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1921e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
1922e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
1923e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
1924e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
1925e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
1926e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
1927e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
1928e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
1929e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
1930e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
1931e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
1932e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
1933e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
1934e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp->parent
1935e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      : tcp->nclone_detached > 0
1936e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp : NULL);
1937e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1938e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
19390569095472c93c8513edefcf31013503ce4c0589Roland McGrath		if (leader != NULL && leader != tcp &&
19400569095472c93c8513edefcf31013503ce4c0589Roland McGrath		    !(leader->flags & TCB_GROUP_EXITING))
1941e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
1942e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
1943e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
1944e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		droptcb(tcp);	/* Already died.  */
1945e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1946e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
1947e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
194800dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath		  	if (leader != NULL && leader != tcp) {
194900dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath				if (leader->flags & TCB_ATTACHED) {
195000dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					/* We need to detach the leader so
195100dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   that the process death will be
195200dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   reported to its real parent.
195300dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   But we kill it first to prevent
195400dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   it doing anything before we kill
195500dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   the whole process in a moment.
195600dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   We can use PTRACE_KILL on a
195700dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   thread that's not already
195800dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   stopped.  Then the value we pass
195900dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   in PTRACE_DETACH just sets the
196000dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   death signal reported to the
196100dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					   real parent.  */
196200dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					ptrace(PTRACE_KILL, leader->pid, 0, 0);
196300dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					if (debug)
196400dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath						fprintf(stderr,
196500dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath							" [%d exit %d kills %d]\n",
196600dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath							tcp->pid, sig, leader->pid);
196700dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					detach(leader, sig);
196800dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath				}
196900dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath				else
197000dc13fbe7a4d1bba614c8b75877db110cabb044Roland McGrath					leader->flags |= TCB_GROUP_EXITING;
1971e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1972e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			detach(tcp, sig);
1973e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1974e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
1975e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			perror("strace: ptrace(PTRACE_CONT, ...)");
1976e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			cleanup();
1977e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return -1;
1978e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1979e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		else {
19800569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (leader != NULL)
19810569095472c93c8513edefcf31013503ce4c0589Roland McGrath				leader->flags |= TCB_GROUP_EXITING;
1982e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (leader != NULL && leader != tcp)
1983e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				droptcb(tcp);
1984e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
1985e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
1986e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
1987e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1988e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1989e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1990e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
1991e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
1992e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1993e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
20032f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
20042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman	static int wait4_options = __WALL;
20052f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (nprocs != 0) {
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
20122f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
20132f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
20145bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
20152f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
20162f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
20172f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
20182f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, wait4_options,
20192f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
20202f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
20215bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
20222f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
20232f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, __WCLONE,
20242f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
20252f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			if (pid == -1) {
20262f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman				fprintf(stderr, "strace: clone wait4 "
20272f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
20282f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
20292f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
20302f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#else
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
20322f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif /* __WALL */
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
204376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
204576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (wait_errno) {
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ECHILD:
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (nprocs == 0)
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: proc miscount\n");
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				errno = wait_errno;
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: wait");
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
2073e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
2074e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (followfork || followvfork) {
2075e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
2076e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
2077e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
2078e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
2079e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
2080e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
2081e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
2082e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
2083e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
2084e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if ((tcp = alloctcb(pid)) == NULL) {
2085e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, " [tcb table full]\n");
2086e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					kill(pid, SIGKILL); /* XXX */
2087e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return 0;
2088e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
2089e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
2090e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				newoutf(tcp);
2091e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
2092e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
2093e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
2094e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
20958b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
2096e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
2097e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
2098e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
20998b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif
2100e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
2101e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
2102e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
2103e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
2104e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
2105e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !LINUX */
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Apparently, doing any ptrace() call on a stopped
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process, provokes the kernel to report the process
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * status again on a subsequent wait(), even if the
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process has not been actually restarted.
212276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Since we have inspected the arguments of suspended
212376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * processes we end up here testing for this case.
212476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
212576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
212776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
212876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
212976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
21312efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath				tprintf("+++ killed by %s %s+++",
21322efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					signame(WTERMSIG(status)),
21332efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#ifdef WCOREDUMP
21342efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					WCOREDUMP(status) ? "(core dumped) " :
21352efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath#endif
21362efe879fa8df30bf69c3a4c471dcc5e19ad0b6eaRoland McGrath					"");
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
213876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2139e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2140e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2141e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2143e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "pid %u exited\n", pid);
21490569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if ((tcp->flags & TCB_ATTACHED)
21500569095472c93c8513edefcf31013503ce4c0589Roland McGrath#ifdef TCB_GROUP_EXITING
21510569095472c93c8513edefcf31013503ce4c0589Roland McGrath			    && !(tcp->parent && (tcp->parent->flags &
21520569095472c93c8513edefcf31013503ce4c0589Roland McGrath						 TCB_GROUP_EXITING))
21530569095472c93c8513edefcf31013503ce4c0589Roland McGrath#endif
21540569095472c93c8513edefcf31013503ce4c0589Roland McGrath				)
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					"PANIC: attached pid %u exited\n",
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pid);
21580a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
21590a396906981a03f93c07cb912585d0679dd50899Roland McGrath				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
21600a396906981a03f93c07cb912585d0679dd50899Roland McGrath				    == TCB_INSYSCALL)
21610a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
21620a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
21630a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
21640a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2165e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2166e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2167e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2169e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2179ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_STARTUP) {
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED) {
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Interestingly, the process may stop
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * with STOPSIG equal to some other signal
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * than SIGSTOP if we happend to attach
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * just before the process takes a signal.
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!WIFSTOPPED(status)) {
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr,
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						"pid %u not stopped\n", pid);
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					detach(tcp, WSTOPSIG(status));
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* A child of us stopped at exec */
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (WSTOPSIG(status) == SIGTRAP && followvfork)
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fixvfork(tcp);
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_BPTSET) {
221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WSTOPSIG(status) != SIGTRAP) {
222076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
222176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
222376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
222476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
222576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
222676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
222776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ptrace(PTRACE_SYSCALL,
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						pid, (char *) 1, 0) < 0) {
222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("trace: ptrace(PTRACE_SYSCALL, ...)");
223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
223176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
22377b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				unsigned long addr = 0, pc = 0;
22387b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#ifdef PT_GETSIGINFO
22397b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#				define PSR_RI	41
22407b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				struct siginfo si;
22417b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				unsigned long psr;
22427b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
22437b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				upeek(pid, PT_CR_IPSR, &psr);
22447b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				upeek(pid, PT_CR_IIP, &pc);
22457b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
22467b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
22477b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
22487b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				addr = (unsigned long) si.si_addr;
22493a055d7d64222223da2550ca540043de7e3e232bRoland McGrath#elif defined PTRACE_GETSIGINFO
22503a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				if (WSTOPSIG(status) == SIGSEGV ||
22513a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				    WSTOPSIG(status) == SIGBUS) {
22523a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					siginfo_t si;
22533a055d7d64222223da2550ca540043de7e3e232bRoland McGrath					if (ptrace(PTRACE_GETSIGINFO, pid,
22543a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						   0, &si) == 0)
22553a055d7d64222223da2550ca540043de7e3e232bRoland McGrath						addr = (unsigned long)
22563a055d7d64222223da2550ca540043de7e3e232bRoland McGrath							si.si_addr;
22573a055d7d64222223da2550ca540043de7e3e232bRoland McGrath				}
22587b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
22607b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tprintf("--- %s (%s) @ %lx (%lx) ---",
2261ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WSTOPSIG(status)),
22627b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					strsignal(WSTOPSIG(status)), pc, addr);
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
22650569095472c93c8513edefcf31013503ce4c0589Roland McGrath			if (((tcp->flags & TCB_ATTACHED) ||
22660569095472c93c8513edefcf31013503ce4c0589Roland McGrath			     tcp->nclone_threads > 0) &&
226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2268e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2269e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2270e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2272e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
227576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				   WSTOPSIG(status)) < 0) {
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("trace: ptrace(PTRACE_SYSCALL, ...)");
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (trace_syscall(tcp) < 0) {
228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
228676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
228776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
228876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				ptrace(PTRACE_KILL,
228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					tcp->pid, (char *) 1, SIGTERM);
229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
229176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
229276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
229376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2295e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2296e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2297e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2298e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2299e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2300e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2301e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
230276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
230376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
230476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
230576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: ptrace(PTRACE_CONT, ...)");
230676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
230776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
230876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
230976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
231076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
231176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
231276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
231376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
231476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
231576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
231676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
231776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
231876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("trace: ptrace(PTRACE_SYSCALL, ...)");
231976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
232076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
232176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
232276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
232376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
232476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
232576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2326bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
232776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
232876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol;
232976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
233076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
233176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
233276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b)
233376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
233476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h>
233576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a)
233676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
233776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
233876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
233976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
234076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
234176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
234276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist)
234376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
234476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl
234576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
234676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
234776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
234876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
234976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	VA_START(args, fmt);
2350b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2351b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2352b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		if (n < 0 && outf != stderr)
2353b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			perror(outfname == NULL
2354b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			       ? "<writing to pipe>" : outfname);
2355b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		else
2356b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2357b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
235876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
235976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
236076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
236176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
236276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
236376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp)
236476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
236576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
236676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
236776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp_last->flags |= TCB_REPRINT;
236876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf(" <unfinished ...>\n");
236976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
237076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
237176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
237276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
237376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
237476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
237576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
237676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
237776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
237876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
237976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
238076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
238176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
238276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
238376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
238476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
238576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
238676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
238776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
238876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
238976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
239076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
239176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
239276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
239376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
239476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
239576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
239676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
239776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
239876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
239976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
240076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
240176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
240276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
240376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
240476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
240576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
240676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
240776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
240876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
240976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
241076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
241176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
241276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
241376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
241476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
241576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprinttrailer(tcp)
241676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
241776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
241876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
241976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
242076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
24219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2422ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
24239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
24249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkermanint mp_ioctl (int fd, int cmd, void *arg, int size) {
24259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
24269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
24279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2428553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
24299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
24309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
24319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
24329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
24339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
24349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
24359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2436553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
24379ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	return writev (fd, iov, n);
24389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
24399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
24409ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2441