strace.c revision ce0d15442eec017b1dcbfdd14ac92e73c39c586a
176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/*
276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
54dc8a2aec63e4fb5ee2688544c4de323ed5de3efWichert Akkerman * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * All rights reserved.
776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * Redistribution and use in source and binary forms, with or without
976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * modification, are permitted provided that the following conditions
1076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * are met:
1176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 1. Redistributions of source code must retain the above copyright
1276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer.
1376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 2. Redistributions in binary form must reproduce the above copyright
1476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    notice, this list of conditions and the following disclaimer in the
1576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    documentation and/or other materials provided with the distribution.
1676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * 3. The name of the author may not be used to endorse or promote products
1776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *    derived from this software without specific prior written permission.
1876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
1976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *
3076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman *	$Id$
3176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman */
3276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
332ee6e45f36566e8735b35ffad40bfcc626a25a98Wichert Akkerman#include <sys/types.h>
3476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include "defs.h"
3576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
3676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <signal.h>
3776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <errno.h>
3876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/param.h>
3976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <fcntl.h>
4076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/resource.h>
4176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/wait.h>
4276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stat.h>
4376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <pwd.h>
4476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <grp.h>
4576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <string.h>
4619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#include <limits.h>
4776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
487b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#if defined(IA64) && defined(LINUX)
497b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman# include <asm/ptrace_offsets.h>
507b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
517b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
52bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
53bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#include <poll.h>
54bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
55bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
5676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
5776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <sys/stropts.h>
58ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
591d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#ifdef HAVE_SYS_UIO_H
609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#include <sys/uio.h>
619ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
6276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
631d08dcf46dd4b2cfe3e27723c05b0aec9955c591John Hughes#endif
6476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
6576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint debug = 0, followfork = 0, followvfork = 0, interactive = 0;
6676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint rflag = 0, tflag = 0, dtime = 0, cflag = 0;
6776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint iflag = 0, xflag = 0, qflag = 0;
6876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pflag_seen = 0;
6976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
7017f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig/* Sometimes we want to print only succeeding syscalls. */
7117f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvigint not_failing_only = 0;
7217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig
7376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *username = NULL;
7476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanuid_t run_uid;
7576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermangid_t run_gid;
7676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
7776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint acolumn = DEFAULT_ACOLUMN;
7876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint max_strlen = DEFAULT_STRLEN;
7976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *outfname = NULL;
8076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *outf;
81ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstruct tcb **tcbtab;
82ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathunsigned int nprocs, tcbtabsize;
8376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *progname;
8476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char **environ;
8576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
8676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int trace P((void));
8776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void cleanup P((void));
8876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void interrupt P((int sig));
8976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic sigset_t empty_set, blocked_set;
9076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
9176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_SIG_ATOMIC_T
9276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile sig_atomic_t interrupted;
9376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_SIG_ATOMIC_T */
9476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
9576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic volatile int interrupted;
9676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !__STDC__ */
9776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int interrupted;
9876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !__STDC__ */
9976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_SIG_ATOMIC_T */
10076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
101bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
10276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *pfd2tcb P((int pfd));
10476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void reaper P((int sig));
10576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void rebuild_pollv P((void));
106ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrathstatic struct pollfd *pollv;
10776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
10876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
10976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poll_open P((void));
11176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void proc_poller P((int pfd));
11276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct proc_pollfd {
11476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int fd;
11576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int revents;
11676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
11776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman};
11876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
11976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int poller_pid;
12076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int proc_poll_pipe[2] = { -1, -1 };
12176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
12276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
12376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
124ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
1259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLWRNORM
1269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
1279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#define POLLWANT	POLLPRI
1289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
129bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
13076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
13276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage(ofp, exitval)
13376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert AkkermanFILE *ofp;
13476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint exitval;
13576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
13676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(ofp, "\
13776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanusage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
138de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...\n\
139de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
140de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath   or: strace -c [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...\n\
141de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath              [command [arg ...]]\n\
14276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-c -- count time, calls, and errors for each syscall and report summary\n\
14376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-f -- follow forks, -ff -- with output into separate files\n\
14476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-F -- attempt to follow vforks, -h -- print help message\n\
14576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-i -- print instruction pointer at time of syscall\n\
14676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-q -- suppress messages about attaching, detaching, etc.\n\
14776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
14876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-T -- print time spent in each syscall, -V -- print version\n\
14976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
15076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
15176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-a column -- alignment COLUMN for printing syscall results (default %d)\n\
15276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
15376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman   options: trace, abbrev, verbose, raw, signal, read, or write\n\
15476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-o file -- send trace output to FILE instead of stderr\n\
15576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
15676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-p pid -- trace process with process id PID, may be repeated\n\
15776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
15876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
15976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman-u username -- run command as username handling setuid and/or setgid\n\
160de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var=val -- put var=val in the environment for command\n\
161de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath-E var -- remove var from the environment for command\n\
162de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath" /* this is broken, so don't document it
16317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig-z -- print only succeeding syscalls\n\
164de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath  */
165de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath, DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
16676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(exitval);
16776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
16876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
16976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SVR4
17076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
17176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
17276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanfoobar()
17376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
17476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
17576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
17676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SVR4 */
17776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
17976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanmain(argc, argv)
18076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint argc;
18176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *argv[];
18276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
18376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	extern int optind;
18476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	extern char *optarg;
18576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
18676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int c, pid = 0;
18776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
18876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
18976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[BUFSIZ];
19076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
191ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	/* Allocate the initial tcbtab.  */
192ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtabsize = argc;	/* Surely enough for all -p args.  */
193ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtab = (struct tcb **) malloc (tcbtabsize * sizeof tcbtab[0]);
194ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	tcbtab[0] = (struct tcb *) calloc (tcbtabsize, sizeof *tcbtab[0]);
195ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (tcp = tcbtab[0]; tcp < &tcbtab[0][tcbtabsize]; ++tcp)
196ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcbtab[tcp - tcbtab[0]] = &tcbtab[0][tcp - tcbtab[0]];
197ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
19876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	progname = argv[0];
19976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	outf = stderr;
20076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interactive = 1;
20176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("trace=all");
20276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("abbrev=all");
20376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("verbose=all");
20476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	qualify("signal=all");
20576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	set_sortby(DEFAULT_SORTBY);
20676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	set_personality(DEFAULT_PERSONALITY);
20776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((c = getopt(argc, argv,
208de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		"+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
20976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (c) {
21076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'c':
21176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cflag++;
21276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
21376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
21476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'd':
21576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			debug++;
21676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
21776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'f':
21876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followfork++;
21976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
22076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'F':
22176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			followvfork++;
22276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
22376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'h':
22476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stdout, 0);
22576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
22676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'i':
22776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			iflag++;
22876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
22976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'q':
23076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qflag++;
23176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
23276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'r':
23376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			rflag++;
23476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
23576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
23676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 't':
23776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tflag++;
23876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
23976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'T':
24076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			dtime++;
24176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
24276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'x':
24376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			xflag++;
24476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
24576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'v':
24676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify("abbrev=none");
24776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
24876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'V':
2499c9a2534e361b683f1e4e08804b7166a01475bf1Roland McGrath			printf("%s -- version %s\n", PACKAGE_NAME, VERSION);
25076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(0);
25176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
25217f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig		case 'z':
25317f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			not_failing_only = 1;
25417f8fb3484e94976882f65b7a3aaffc6f24cd75dMichal Ludvig			break;
25576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'a':
25676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			acolumn = atoi(optarg);
25776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
25876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'e':
25976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			qualify(optarg);
26076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
26176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'o':
26276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			outfname = strdup(optarg);
26376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
26476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'O':
26576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_overhead(atoi(optarg));
26676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
26776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'p':
268de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if ((pid = atoi(optarg)) <= 0) {
26976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "%s: Invalid process id: %s\n",
27076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname, optarg);
27176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
27276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
27376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pid == getpid()) {
27454a4767f8609abfe2d7cb1802bc9e8dca97dd08fWichert Akkerman				fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
27576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
27676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
27776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((tcp = alloctcb(pid)) == NULL) {
278de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
27976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					progname);
28076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
28176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
28276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags |= TCB_ATTACHED;
28376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pflag_seen++;
28476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
28576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 's':
28676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			max_strlen = atoi(optarg);
28776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
28876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'S':
28976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			set_sortby(optarg);
29076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
29176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 'u':
29276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			username = strdup(optarg);
29376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
294de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath		case 'E':
295de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			if (putenv(optarg) < 0) {
296de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				fprintf(stderr, "%s: out of memory\n",
297de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath					progname);
298de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath				exit(1);
299de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			}
300de6e53308ca58da7d357f8114afc74fff7a18043Roland McGrath			break;
30176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
30276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			usage(stderr, 1);
30376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
30476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
30576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
30676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
307ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath	if (optind == argc && !pflag_seen)
308ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath		usage(stderr, 1);
309ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath
31076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
31176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
31276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
31376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
31476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
31576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
31676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
31776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
31876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
31976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
32076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
32176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
32276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, optarg);
32376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
32676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	setreuid(geteuid(), getuid());
33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
33876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
33954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		long f;
34054b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
34137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		/* See if they want to pipe the output. */
34237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		if (outfname[0] == '|' || outfname[0] == '!') {
34337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			/*
34437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * We can't do the <outfname>.PID funny business
34537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 * when using popen, so prohibit it.
34637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			 */
34737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if (followfork > 1) {
34837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "\
34937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath%s: piping the output and -ff are mutually exclusive options\n",
35037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname);
35137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
35237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
35337b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath
35437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			if ((outf = popen(outfname + 1, "w")) == NULL) {
35537b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				fprintf(stderr, "%s: can't popen '%s': %s\n",
35637b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					progname, outfname + 1,
35737b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath					strerror(errno));
35837b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath				exit(1);
35937b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath			}
36037b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		}
36137b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath		else if ((outf = fopen(outfname, "w")) == NULL) {
36276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: can't fopen '%s': %s\n",
36376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, outfname, strerror(errno));
36476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
36576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
36654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
36754b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		if ((f=fcntl(fileno(outf), F_GETFD)) < 0 ) {
36854b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			perror("failed to get flags for outputfile");
36954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
37054b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
37154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
37254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		if (fcntl(fileno(outf), F_SETFD, f|FD_CLOEXEC) < 0 ) {
37354b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			perror("failed to set flags for outputfile");
37454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
37554b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
37676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
37876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
37976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	setreuid(geteuid(), getuid());
38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
38237b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (!outfname || outfname[0] == '|' || outfname[0] == '!')
38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
38437b9a66dd4cf063c4a3d1002f4196cd7ef9ae5b7Roland McGrath	if (outfname && optind < argc) {
38576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
387369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
38876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
389ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (c = 0; c < tcbtabsize; c++) {
390ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[c];
39176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Reinitialize the output since it may have changed. */
39276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->outf = outf;
39376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
39476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
395bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
39676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (proc_open(tcp, 1) < 0) {
39776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "trouble opening proc file\n");
39876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
39976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
40076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
401bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
40276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
40376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("attach: ptrace(PTRACE_ATTACH, ...)");
40476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
40576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
40676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
407bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
40876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!qflag)
40976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
41076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"Process %u attached - interrupt to quit\n",
41176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pid);
41276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
41376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
414ce0d15442eec017b1dcbfdd14ac92e73c39c586aRoland McGrath	if (!pflag_seen) {
41576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct stat statbuf;
41676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char *filename;
41776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char pathname[MAXPATHLEN];
41876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
41976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		filename = argv[optind];
42076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (strchr(filename, '/'))
42176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(pathname, filename);
42276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef USE_DEBUGGING_EXEC
42376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
42476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Debuggers customarily check the current directory
42576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * first regardless of the path but doing that gives
42676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * security geeks a panic attack.
42776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
42876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (stat(filename, &statbuf) == 0)
42976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(pathname, filename);
43076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* USE_DEBUGGING_EXEC */
43176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
43276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			char *path;
43376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			int m, n, len;
43476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
43576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			for (path = getenv("PATH"); path && *path; path += m) {
43676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (strchr(path, ':')) {
43776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					n = strchr(path, ':') - path;
43876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					m = n + 1;
43976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
44076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
44176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					m = n = strlen(path);
44276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (n == 0) {
44376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					getcwd(pathname, MAXPATHLEN);
44476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					len = strlen(pathname);
44576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
44676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else {
44776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					strncpy(pathname, path, n);
44876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					len = n;
44976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
45076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (len && pathname[len - 1] != '/')
45176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pathname[len++] = '/';
45276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				strcpy(pathname + len, filename);
453ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				if (stat(pathname, &statbuf) == 0 &&
454ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    /* Accept only regular files
455ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				       with some execute bits set.
456ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				       XXX not perfect, might still fail */
457ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    S_ISREG(statbuf.st_mode) &&
458ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    (statbuf.st_mode & 0111))
45976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
46076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
46176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
46276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (stat(pathname, &statbuf) < 0) {
46376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: %s: command not found\n",
46476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, filename);
46576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
46676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
46776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (pid = fork()) {
46876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case -1:
46976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("strace: fork");
47076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
47176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
47276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
47376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 0: {
474bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
475bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        if (outf != stderr) close (fileno (outf));
47676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
47776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Kludge for SGI, see proc_open for details. */
47876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sa.sa_handler = foobar;
47976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sa.sa_flags = 0;
48076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigemptyset(&sa.sa_mask);
48176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigaction(SIGINT, &sa, NULL);
48276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
483bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
48476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pause();
485bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
486bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			kill(getpid(), SIGSTOP); /* stop HERE */
487553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
488bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
489553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath			if (outf!=stderr)
4907987cdf192632516d6ba493b0a9943f5a3a7c362Wichert Akkerman				close(fileno (outf));
491bd4125c6bcd20e8f014b682b31d6fc5d0fef3ed0Wichert Akkerman
49276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
49376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: ptrace(PTRACE_TRACEME, ...)");
49476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
49576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
49676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
49776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				kill(getpid(), SIGSTOP);
49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
49976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (username != NULL || geteuid() == 0) {
50076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				uid_t run_euid = run_uid;
50176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				gid_t run_egid = run_gid;
50276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
50376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (statbuf.st_mode & S_ISUID)
50476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					run_euid = statbuf.st_uid;
50576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (statbuf.st_mode & S_ISGID)
50676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					run_egid = statbuf.st_gid;
50776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
50876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
50976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * It is important to set groups before we
51076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * lose privileges on setuid.
51176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
5125ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman				if (username != NULL) {
5135ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (initgroups(username, run_gid) < 0) {
5145ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("initgroups");
5155ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5165ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
5175ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (setregid(run_gid, run_egid) < 0) {
5185ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("setregid");
5195ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5205ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
5215ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (setreuid(run_uid, run_euid) < 0) {
5225ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("setreuid");
5235ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5245ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
52576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
52676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
52776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
52876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				setreuid(run_uid, run_uid);
529bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
53076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
53176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			execv(pathname, &argv[optind]);
53276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("strace: exec");
53376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(1);
53476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
53576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
53676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
53776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((tcp = alloctcb(pid)) == NULL) {
53876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "tcb table full\n");
53976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
54076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
54176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
542bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_open(tcp, 0) < 0) {
54476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "trouble opening proc file\n");
54576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
54676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
54776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
548bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
549bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
55076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fake_execve(tcp, pathname, &argv[optind], environ);
551bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
55276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
55376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
55476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
55576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
55676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
55776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
55876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
55976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
56076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
56176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
56276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
56376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
56476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
56576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
56676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
56776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
56876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
56976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
57076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
57176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
57276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
57376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
57476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
57576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
57676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
57776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
57876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
57976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
580bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
58176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
58276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
583553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
584553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
585553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
586553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
587553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
588553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
589553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
590553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
591bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
59276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
59376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
59476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
59576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
59676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(0);
59776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
59876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
59976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
60076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermannewoutf(tcp)
60176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
60276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
60376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char name[MAXPATHLEN];
60476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	FILE *fp;
60576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
60676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname && followfork > 1) {
60776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(name, "%s.%u", outfname, tcp->pid);
60876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
60976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setreuid(geteuid(), getuid());
61076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
61176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fp = fopen(name, "w");
61276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
61376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setreuid(geteuid(), getuid());
61476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
61576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (fp == NULL) {
61676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("fopen");
61776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
61976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->outf = fp;
62076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
62276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
62376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanalloctcb(pid)
62676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
62876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
62976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
63076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
631ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
632ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
63376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
63476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
63576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->parent = NULL;
63676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->nchildren = 0;
6370962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->nzombies = 0;
638e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
639e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_threads = tcp->nclone_detached = 0;
640e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_waiting = 0;
641e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
64276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
64376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
64476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_sec = 0;
64576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_usec = 0;
64676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
64776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
64876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
65176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
65376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
654bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
65576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
65676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_open(tcp, attaching)
65776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
65876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint attaching;
65976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
66076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
66176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
662bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
66319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
66419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
66576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
66676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
667bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
66876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
66976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
67076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
67176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
672ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
6739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
6749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
6759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
6769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
6779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
6809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
6819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
6849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
6859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
6889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
6899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
6909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) {
6939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
6949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) {
6979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
6989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
7019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
7029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
7039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) {
7069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
7079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) {
7109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
7119ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
71476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
715bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
71676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
71776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
718bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
719bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
720bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
721bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
72276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
72376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
72476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
7259ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
7269ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
7279ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7299ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
7309ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
7319ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7329ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7339ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
734bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
735bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
736bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
737bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
738bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
739bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
740bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
741bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
742bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
743bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
744bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
745bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
746bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
747bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
748bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
75176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
75276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
75576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
7569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
75776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
7609ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
761bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
764bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
76576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
76616a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
770553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
77176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
7749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
77676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
7809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
785553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
78676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
78776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
78876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
78976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
79076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
79176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
79276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
79376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
794bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
795bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
796bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
797bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
798bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
799bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
800bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
801bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
802bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCSFL");
803bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
804bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
805bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
80676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
807bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
80819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
80919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
81019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
81119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
81219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
81319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
81419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
81519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
81619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
81719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
81819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
81919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
820553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
82119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
82219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
82319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
82419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
82519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
82619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
82719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
82819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
82919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
83019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
83176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
83276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
83376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
83419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
83519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
83676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
83919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
84019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
84119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
84219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
84319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
84419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
8459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
84676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
84919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
85019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
85119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
85219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
85319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
85419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
8559ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
85676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
85776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
859bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
860bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
861bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
862bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
863bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
864bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
865bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
866bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
86876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
86976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
87376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
87476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
875553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
87676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
8779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
8789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
88176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
882553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
883bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
884bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
885bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
886bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
887553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
88876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
8909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
89276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
89376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
8949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
895bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
896bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
897bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				if (tcp->scno == SYS_execve)
89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
901bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
9029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
9039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
904bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
905bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
906553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
90776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
90976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
910bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
911bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
912bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
913bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
914bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
915bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
916553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
91776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
918bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
91976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
920bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
921bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
922553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
9232e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
9242e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
9252e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
9262e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
9272e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
9282e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
9292e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
930553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
9312e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
9322e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
9332e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
9342e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
9352e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
9362e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
9372e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
9382e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
9392e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
9402e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
9412e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
9422e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
9432e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
9442e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
9452e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
9462e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
947bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
948bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
95376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
95576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
962bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
96376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
964e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid)
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
971ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
972ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid && tcp->pid != pid)
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
98076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
981bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
98276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
989ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
990ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
99876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
999bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
100076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
100176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
100276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
100376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
100476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
100576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
100676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
1007e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1008e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1009e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1010e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1011e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1012e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1013e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1014e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1015e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1016e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
101776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
101876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1019eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1020e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1021e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1022e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1023e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_DETACHED)
1024e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_detached--;
1025e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1026e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1027e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
10280962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED
10290962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath		if (!(tcp->flags & TCB_CLONE_DETACHED))
10300962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif
10310962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->parent->nzombies++;
1032e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1033e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1034e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1035e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
103676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
103776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
103876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1039bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1040bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1041bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1042bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1043bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1044bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1045bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1046bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1047bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1048553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1049bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1050e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
105176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1053eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1054822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1056eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1060bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
106276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
106376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
106576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
106676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
106776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
106876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1074e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1075e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1076e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1077e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
108076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("resume: ptrace(PTRACE_SYSCALL, ...)");
108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1089bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
109076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
109176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* detach traced process; continue with sig */
109276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1099ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
1100e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	int status, resumed;
1101ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
110376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
110476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sig = SIGKILL;
110576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
110676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
11097bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
11107bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
111176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
11127bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
11137bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
11147bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
11157bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
111676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
111776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
11187bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
11197bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
11207bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
11217bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
11227bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
11237bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (kill(tcp->pid, 0) < 0) {
11247bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
11257bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
11267bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
11277bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (kill(tcp->pid, SIGSTOP) < 0) {
11287bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
11297bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
11307bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
11317bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else {
113276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
11337508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
11347508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
11357508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
11367508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
11377508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
113876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
11397508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
11407508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
11417508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
11427508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
11437508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
11447508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
11457508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
11467508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
11477508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
11487508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
11497508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
11507508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
11517508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
11527508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
11537508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
11547508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
11557508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
11567508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
11577508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
11587508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
11607508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
116276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
116476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
116676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if ((error = ptrace(PTRACE_DETACH,
11677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath				    tcp->pid, (char *) 1, sig)) < 0) {
116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					if (errno != ESRCH)
116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						perror("detach: ptrace(PTRACE_DETACH, ...)");
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					/* I died trying. */
117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
117276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
117476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
11757bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			    WSTOPSIG(status) == SIGTRAP ?
11767bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			    0 : WSTOPSIG(status))) < 0) {
117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (errno != ESRCH)
117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: ptrace(PTRACE_CONT, ...)");
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
11837bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
118576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
118676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
118776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
118876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
118976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
119076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
119176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: ptrace(PTRACE_DETACH, ...)");
119276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
119376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1194bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
1195e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	resumed = 0;
1196e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1197e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* XXX This won't always be quite right (but it never was).
1198e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
1199e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   a particular pgrp, which this child might or might not be
1200e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
1201e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
1202e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   difference to wake up a waiter when there might be more
1203e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   traced children, because it could get a false ECHILD
1204e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
1205e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
1206e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   search the system for all pid's in the pgrp to be sure.
1207e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1208e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	     && (t->waitpid == -1 ||
1209e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1210e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1211e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	*/
1212e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1213e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->parent &&
1214e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
1215e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1216e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 		error = resume(tcp->parent);
1217e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		++resumed;
1218e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1219e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1220e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1221e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* Some other threads of our parent are waiting too.  */
1222e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		unsigned int i;
1223e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1224e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
1225e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
1226e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			struct tcb *t = tcbtab[i];
1227e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (t->parent == tcp->parent && t != tcp
1228e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1229e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1230e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && t->waitpid == tcp->pid) {
1231e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				error |= resume (t);
1232e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				++resumed;
1233e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1234e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1235e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (resumed == 0)
1236e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* Noone was waiting for this PID in particular,
1237e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   so now we might need to resume some wildcarders.  */
1238e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
1239e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				struct tcb *t = tcbtab[i];
1240e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (t->parent == tcp->parent && t != tcp
1241e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				    && ((t->flags
1242e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1243e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1244e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				    && t->waitpid <= 0
1245e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					) {
1246e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					error |= resume (t);
1247e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					break;
1248e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
1249e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1250e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1251e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1252e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1253bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1262bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
126476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
126576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig)
126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
127376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct tcb *tcp;
127476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
127576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pid2tcb(pid);
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp)
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
128176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1282bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
128476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1290ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1291ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf(" <unfinished ...>\n");
130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp_last = NULL;
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
131376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
131676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13226d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
13256d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
133576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
133676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
133876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
133976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
134076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13448f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
13456d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
13478f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
13488f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
13498f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
136176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
136976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1370bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
137176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
137276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
137376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
137476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
137576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
137676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1377ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1378ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1379c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1380ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
1381ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		fprintf(stderr, "strace: out of memory for poll vector\n");
1382ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1383ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1384ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1385ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1386ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
138776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
138876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
138976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
13909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int arg;
140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) {
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("F_GETFD");
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) {
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("F_SETFD");
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
145676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
145776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
145876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1465bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1466bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1467bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
146876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
146976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		_exit(0);
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
147576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
147976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
148076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
148176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
148676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
148876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
148976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
149076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
149576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
149676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		_exit(0);
149776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
149876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
149976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
150076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
150176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
150276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
150376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
150576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1507bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
1508bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1509bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1510bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1511bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
15129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
151976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
15289ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
15459ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
155976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
15689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
157176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
157276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
157376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
157876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15809dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
1581d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
15829dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
15879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp = pid2tcb(0);
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
160576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
160676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
160776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
160876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
160976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
161076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
161176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
161276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
161376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
16149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
16159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
16169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
16179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
1618553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
16199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
16209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
16219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
16229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
16239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
16249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
16259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
16269dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
16279dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
16289dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
16299dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
16309dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
16319dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
16329dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
16339dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
16349dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
16359dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
165076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
165176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
165276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
165576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
165676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
165776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
165876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1659b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
16609dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
1661b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
166276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
166376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
1664bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
16659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
1666bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1667bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
1668bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
1669bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
1670bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
1671bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
1672bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
1673bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			  	ioctl_result = IOCTL_WSTOP (tcp);
1674553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
168976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
169076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
1697bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1698bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
1699553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
170076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
170176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
170276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
170376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
170476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
170576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
170676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
170776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17092e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
17102e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
17112e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
17122e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
17132e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
17142e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
1715553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1716553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
171776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
171876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
171976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
172176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
172276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
172376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
172476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
1725bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1726bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
1727bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
1728bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
1729bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1730bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
1731bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
1732bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1733bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
1734bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
1735bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
1736553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
173876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
1739bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
17439ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
17449ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
1745bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
174676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
17479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
17489ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
174976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
175076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1755bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
17579dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
17589dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
17599dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
176176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
176376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
176476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
176576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
176676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
176776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
176876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
176976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
1770ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
17725826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
17735826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
17745826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
17755826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
17765826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
17775826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printtrailer(tcp);
17785826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
17795826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
178076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
178176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
178276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
178376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
178576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1789bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1790bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
1791bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		  	continue;
1792553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
179376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
17949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
17989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
1799553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
18009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
1801553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1802bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
1803553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
180476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
180576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
180676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
180776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
180876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
180976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
181076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1811bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
181276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1813e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
1814e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
1815e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
1816e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
1817e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
1818e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
1819e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
1820e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
1821e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
1822e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
1823e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
1824e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
1825e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
1826e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp->parent
1827e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      : tcp->nclone_detached > 0
1828e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp : NULL);
1829e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1830e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
1831e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (leader != NULL && leader != tcp)
1832e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
1833e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
1834e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
1835e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		droptcb(tcp);	/* Already died.  */
1836e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1837e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
1838e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
1839e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (leader != NULL && leader != tcp) {
1840e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* We need to detach the leader so that the
1841e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   process death will be reported to its real
1842e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent.  But we kill it first to prevent
1843e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   it doing anything before we kill the whole
1844e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   process in a moment.  We can use
1845e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   PTRACE_KILL on a thread that's not already
1846e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   stopped.  Then the value we pass in
1847e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   PTRACE_DETACH just sets the death
1848e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   signal reported to the real parent.  */
1849e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				ptrace(PTRACE_KILL, leader->pid, 0, 0);
1850e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (debug)
1851e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr,
1852e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						" [%d exit %d kills %d]\n",
1853e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						tcp->pid, sig, leader->pid);
1854e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				detach(leader, sig);
1855e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1856e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			detach(tcp, sig);
1857e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1858e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
1859e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			perror("strace: ptrace(PTRACE_CONT, ...)");
1860e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			cleanup();
1861e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return -1;
1862e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1863e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		else {
1864e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (leader != NULL && leader != tcp)
1865e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				droptcb(tcp);
1866e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
1867e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
1868e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
1869e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1870e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1871e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1872e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* Note that TCP and LEADER are no longer valid,
1873e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   but we can still compare against them.  */
1874e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (leader != NULL) {
1875e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		unsigned int i;
1876e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
1877e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			struct tcb *t = tcbtab[i];
1878e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (t != tcp && (t->flags & TCB_CLONE_DETACHED)
1879e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && t->parent == leader)
1880e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				droptcb(t);
1881e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1882e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1883e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1884e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
1885e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
1886e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1887e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
188876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
188976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
189076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
18972f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
18982f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman	static int wait4_options = __WALL;
18992f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
190076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
190176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
190276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (nprocs != 0) {
190376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
190476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
190576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
19062f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
19072f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
19085bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
19092f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
19102f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
19112f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
19122f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, wait4_options,
19132f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
19142f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
19155bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
19162f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
19172f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, __WCLONE,
19182f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
19192f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			if (pid == -1) {
19202f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman				fprintf(stderr, "strace: clone wait4 "
19212f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
19222f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
19232f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
19242f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#else
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
19262f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif /* __WALL */
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (wait_errno) {
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ECHILD:
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (nprocs == 0)
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: proc miscount\n");
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				errno = wait_errno;
195876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: wait");
195976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
196076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
196176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
196276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
196376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
196476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
196576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
196676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
1967e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
1968e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (followfork || followvfork) {
1969e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
1970e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
1971e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
1972e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
1973e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
1974e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
1975e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
1976e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
1977e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
1978e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if ((tcp = alloctcb(pid)) == NULL) {
1979e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, " [tcb table full]\n");
1980e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					kill(pid, SIGKILL); /* XXX */
1981e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return 0;
1982e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
1983e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
1984e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				newoutf(tcp);
1985e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
1986e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
1987e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
1988e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
19898b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
1990e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
1991e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
1992e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
19938b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif
1994e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
1995e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
1996e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
1997e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
1998e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
1999e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !LINUX */
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Apparently, doing any ptrace() call on a stopped
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process, provokes the kernel to report the process
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * status again on a subsequent wait(), even if the
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process has not been actually restarted.
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Since we have inspected the arguments of suspended
201776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * processes we end up here testing for this case.
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
202076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
202176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
202276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
202476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("+++ killed by %s +++",
2026ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WTERMSIG(status)));
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2029e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2030e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2031e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2033e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
203476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
203576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
203676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
203776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
203876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "pid %u exited\n", pid);
203976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
204076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
204176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					"PANIC: attached pid %u exited\n",
204276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pid);
20430a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
20440a396906981a03f93c07cb912585d0679dd50899Roland McGrath				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
20450a396906981a03f93c07cb912585d0679dd50899Roland McGrath				    == TCB_INSYSCALL)
20460a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
20470a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
20480a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
20490a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2050e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2051e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2052e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2054e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
205576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2064ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_STARTUP) {
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED) {
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Interestingly, the process may stop
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * with STOPSIG equal to some other signal
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * than SIGSTOP if we happend to attach
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * just before the process takes a signal.
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!WIFSTOPPED(status)) {
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr,
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						"pid %u not stopped\n", pid);
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					detach(tcp, WSTOPSIG(status));
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* A child of us stopped at exec */
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (WSTOPSIG(status) == SIGTRAP && followvfork)
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fixvfork(tcp);
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_BPTSET) {
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WSTOPSIG(status) != SIGTRAP) {
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ptrace(PTRACE_SYSCALL,
211376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						pid, (char *) 1, 0) < 0) {
211476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("trace: ptrace(PTRACE_SYSCALL, ...)");
211576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
211676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
211776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
211876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
211976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
212076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
212176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
21227b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				unsigned long addr = 0, pc = 0;
21237b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#ifdef PT_GETSIGINFO
21247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#				define PSR_RI	41
21257b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				struct siginfo si;
21267b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				unsigned long psr;
21277b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
21287b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				upeek(pid, PT_CR_IPSR, &psr);
21297b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				upeek(pid, PT_CR_IIP, &pc);
21307b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
21317b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
21327b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
21337b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				addr = (unsigned long) si.si_addr;
21347b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
213576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
21367b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tprintf("--- %s (%s) @ %lx (%lx) ---",
2137ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WSTOPSIG(status)),
21387b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					strsignal(WSTOPSIG(status)), pc, addr);
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((tcp->flags & TCB_ATTACHED) &&
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2143e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2144e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2145e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2147e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				   WSTOPSIG(status)) < 0) {
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("trace: ptrace(PTRACE_SYSCALL, ...)");
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (trace_syscall(tcp) < 0) {
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
216176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
216276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
216376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				ptrace(PTRACE_KILL,
216476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					tcp->pid, (char *) 1, SIGTERM);
216576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
216676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
216776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2170e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2171e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2172e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2173e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2174e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2175e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2176e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: ptrace(PTRACE_CONT, ...)");
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
219276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("trace: ptrace(PTRACE_SYSCALL, ...)");
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2201bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol;
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b)
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h>
221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a)
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
221676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
221776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist)
221876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
221976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl
222076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
222176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
222276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
222376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
222476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	VA_START(args, fmt);
2225b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2226b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2227b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		if (n < 0 && outf != stderr)
2228b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			perror(outfname == NULL
2229b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			       ? "<writing to pipe>" : outfname);
2230b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		else
2231b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2232b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
223876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp)
223976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
224076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
224176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp_last->flags |= TCB_REPRINT;
224376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf(" <unfinished ...>\n");
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
224676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
224776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
224976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
225276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
225376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
225476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
225576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
226876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
227576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
228676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
228776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
228876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
228976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
229076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprinttrailer(tcp)
229176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
229276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
229376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
229476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
229576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
22969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2297ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
22989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
22999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkermanint mp_ioctl (int fd, int cmd, void *arg, int size) {
23009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
23019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
23029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2303553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
23049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
23059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
23069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
23079ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
23089ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
23099ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
23109ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2311553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
23129ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	return writev (fd, iov, n);
23139ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
23149ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
23159ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2316