strace.c revision b310a0c26b3b31d52aa4b25549e06113284bd5bb
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
30776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to run as another user. */
30876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (username != NULL) {
30976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct passwd *pent;
31076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
31176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (getuid() != 0 || geteuid() != 0) {
31276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
31376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"%s: you must be root to use the -u option\n",
31476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname);
31576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
31676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
31776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((pent = getpwnam(username)) == NULL) {
31876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: cannot find user `%s'\n",
31976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, optarg);
32076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
32176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
32276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = pent->pw_uid;
32376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = pent->pw_gid;
32476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
32576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else {
32676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_uid = getuid();
32776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		run_gid = getgid();
32876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
32976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
33176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	setreuid(geteuid(), getuid());
33276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
33376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
33476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* See if they want to pipe the output. */
33576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname && (outfname[0] == '|' || outfname[0] == '!')) {
33676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((outf = popen(outfname + 1, "w")) == NULL) {
33776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: can't popen '%s': %s\n",
33876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, outfname + 1, strerror(errno));
33976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
34076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
34176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		free(outfname);
34276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outfname = NULL;
34376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
34476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
34576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Check if they want to redirect the output. */
34676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname) {
34754b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		long f;
34854b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
34976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((outf = fopen(outfname, "w")) == NULL) {
35076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: can't fopen '%s': %s\n",
35176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, outfname, strerror(errno));
35276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
35376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
35454b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
35554b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		if ((f=fcntl(fileno(outf), F_GETFD)) < 0 ) {
35654b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			perror("failed to get flags for outputfile");
35754b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
35854b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
35954b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman
36054b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		if (fcntl(fileno(outf), F_SETFD, f|FD_CLOEXEC) < 0 ) {
36154b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			perror("failed to set flags for outputfile");
36254b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman			exit(1);
36354b4f79216c819ec93aaf5031acb1772fccef7a9Wichert Akkerman		}
36476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
36576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
36676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
36776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	setreuid(geteuid(), getuid());
36876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
36976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
37076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!outfname) {
37176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setvbuf(outf, buf, _IOLBF, BUFSIZ);
37276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
373369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	else if (optind < argc) {
37476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		interactive = 0;
37576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		qflag = 1;
376369310502bfca4b202d72be9452c8cdb55bb6d5eRoland McGrath	}
37776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
378ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (c = 0; c < tcbtabsize; c++) {
379ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[c];
38076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Reinitialize the output since it may have changed. */
38176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->outf = outf;
38276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
38376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
384bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
38576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (proc_open(tcp, 1) < 0) {
38676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "trouble opening proc file\n");
38776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
38876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
38976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
390bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
39176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
39276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("attach: ptrace(PTRACE_ATTACH, ...)");
39376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
39476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
39576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
396bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
39776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!qflag)
39876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
39976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"Process %u attached - interrupt to quit\n",
40076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pid);
40176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
40276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
40376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (optind < argc) {
40476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct stat statbuf;
40576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char *filename;
40676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char pathname[MAXPATHLEN];
40776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
40876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		filename = argv[optind];
40976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (strchr(filename, '/'))
41076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(pathname, filename);
41176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef USE_DEBUGGING_EXEC
41276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
41376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Debuggers customarily check the current directory
41476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * first regardless of the path but doing that gives
41576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * security geeks a panic attack.
41676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
41776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (stat(filename, &statbuf) == 0)
41876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strcpy(pathname, filename);
41976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* USE_DEBUGGING_EXEC */
42076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
42176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			char *path;
42276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			int m, n, len;
42376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
42476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			for (path = getenv("PATH"); path && *path; path += m) {
42576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (strchr(path, ':')) {
42676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					n = strchr(path, ':') - path;
42776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					m = n + 1;
42876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
42976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
43076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					m = n = strlen(path);
43176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (n == 0) {
43276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					getcwd(pathname, MAXPATHLEN);
43376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					len = strlen(pathname);
43476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
43576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else {
43676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					strncpy(pathname, path, n);
43776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					len = n;
43876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
43976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (len && pathname[len - 1] != '/')
44076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pathname[len++] = '/';
44176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				strcpy(pathname + len, filename);
442ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				if (stat(pathname, &statbuf) == 0 &&
443ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    /* Accept only regular files
444ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				       with some execute bits set.
445ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				       XXX not perfect, might still fail */
446ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    S_ISREG(statbuf.st_mode) &&
447ed64516fa4f4ce25308a1f2ad3b84f8734c3e783Roland McGrath				    (statbuf.st_mode & 0111))
44876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
44976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
45076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
45176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (stat(pathname, &statbuf) < 0) {
45276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "%s: %s: command not found\n",
45376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				progname, filename);
45476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
45576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
45676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (pid = fork()) {
45776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case -1:
45876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("strace: fork");
45976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
46076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
46176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
46276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 0: {
463bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
464bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        if (outf != stderr) close (fileno (outf));
46576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
46676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Kludge for SGI, see proc_open for details. */
46776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sa.sa_handler = foobar;
46876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sa.sa_flags = 0;
46976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigemptyset(&sa.sa_mask);
47076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigaction(SIGINT, &sa, NULL);
47176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* MIPS */
472bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
47376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pause();
474bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
475bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			kill(getpid(), SIGSTOP); /* stop HERE */
476553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
477bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
478553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath			if (outf!=stderr)
4797987cdf192632516d6ba493b0a9943f5a3a7c362Wichert Akkerman				close(fileno (outf));
480bd4125c6bcd20e8f014b682b31d6fc5d0fef3ed0Wichert Akkerman
48176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
48276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: ptrace(PTRACE_TRACEME, ...)");
48376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
48476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
48576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
48676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				kill(getpid(), SIGSTOP);
48776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
48876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (username != NULL || geteuid() == 0) {
48976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				uid_t run_euid = run_uid;
49076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				gid_t run_egid = run_gid;
49176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
49276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (statbuf.st_mode & S_ISUID)
49376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					run_euid = statbuf.st_uid;
49476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (statbuf.st_mode & S_ISGID)
49576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					run_egid = statbuf.st_gid;
49676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
49776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
49876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * It is important to set groups before we
49976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * lose privileges on setuid.
50076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
5015ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman				if (username != NULL) {
5025ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (initgroups(username, run_gid) < 0) {
5035ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("initgroups");
5045ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5055ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
5065ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (setregid(run_gid, run_egid) < 0) {
5075ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("setregid");
5085ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5095ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
5105ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					if (setreuid(run_uid, run_euid) < 0) {
5115ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						perror("setreuid");
5125ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman						exit(1);
5135ae21ead9f83597452f9a0517e8a51fa4823f921Wichert Akkerman					}
51476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
51576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
51676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
51776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				setreuid(run_uid, run_uid);
518bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
51976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
52076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			execv(pathname, &argv[optind]);
52176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("strace: exec");
52276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(1);
52376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
52476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
52576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
52676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((tcp = alloctcb(pid)) == NULL) {
52776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "tcb table full\n");
52876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
52976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
53076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
531bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
53276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_open(tcp, 0) < 0) {
53376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "trouble opening proc file\n");
53476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
53576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
53676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
537bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
538bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
53976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fake_execve(tcp, pathname, &argv[optind], environ);
540bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
54176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
54276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
54376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
54476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (pflag_seen == 0)
54576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		usage(stderr, 1);
54676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
54776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
54876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
54976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = SIG_IGN;
55076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
55176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
55276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTOU, &sa, NULL);
55376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTTIN, &sa, NULL);
55476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (interactive) {
55576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGHUP);
55676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGINT);
55776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGQUIT);
55876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGPIPE);
55976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigaddset(&blocked_set, SIGTERM);
56076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_handler = interrupt;
56176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
56276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* POSIX signals on sunos4.1 are a little broken. */
56376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sa.sa_flags = SA_INTERRUPT;
56476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
56576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
56676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
56776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
56876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
56976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
57076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
571bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
57276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = reaper;
57376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGCHLD, &sa, NULL);
574553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
575553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	/* Make sure SIGCHLD has the default action so that waitpid
576553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   definitely works without losing track of children.  The user
577553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   should not have given us a bogus state to inherit, but he might
578553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   have.  Arguably we should detect SIG_IGN here and pass it on
579553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	   to children, but probably noone really needs that.  */
580553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sa.sa_handler = SIG_DFL;
581553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath	sigaction(SIGCHLD, &sa, NULL);
582bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
58376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
58476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (trace() < 0)
58576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
58676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	cleanup();
58776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(0);
58876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
58976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
59076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
59176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermannewoutf(tcp)
59276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
59376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
59476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char name[MAXPATHLEN];
59576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	FILE *fp;
59676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
59776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (outfname && followfork > 1) {
59876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(name, "%s.%u", outfname, tcp->pid);
59976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
60076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setreuid(geteuid(), getuid());
60176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
60276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fp = fopen(name, "w");
60376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef SVR4
60476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		setreuid(geteuid(), getuid());
60576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
60676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (fp == NULL) {
60776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("fopen");
60876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return;
60976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
61076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->outf = fp;
61176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
61276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
61376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
61476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
61576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *
61676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanalloctcb(pid)
61776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
61876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
61976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
62076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
62176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
622ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
623ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
62476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp->flags & TCB_INUSE) == 0) {
62576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pid = pid;
62676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->parent = NULL;
62776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->nchildren = 0;
6280962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->nzombies = 0;
629e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
630e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_threads = tcp->nclone_detached = 0;
631e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			tcp->nclone_waiting = 0;
632e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
63376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags = TCB_INUSE | TCB_STARTUP;
63476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->outf = outf; /* Initialise to current out file */
63576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_sec = 0;
63676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime.tv_usec = 0;
63776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->pfd = -1;
63876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			nprocs++;
63976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
64076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
64176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
64276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
64376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
64476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
645bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
64676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint
64776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_open(tcp, attaching)
64876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
64976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint attaching;
65076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
65176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	char proc[32];
65276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	long arg;
653bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef SVR4
65419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	int i;
65519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	sysset_t syscalls;
65676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t signals;
65776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fltset_t faults;
658bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif
65976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
66076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last_pfd;
66176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
66276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
663ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
6649ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	/* Open the process pseudo-files in /proc. */
6659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/ctl", tcp->pid);
6669ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
6679ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
6689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6709ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
6719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
6729ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6739ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6749ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
6759ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
6769ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6779ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/status", tcp->pid);
6799ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
6809ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
6819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6829ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6839ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) {
6849ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
6859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6869ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) {
6889ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
6899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	sprintf(proc, "/proc/%d/as", tcp->pid);
6929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
6939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
6949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
6969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) {
6979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
6989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
6999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) {
7019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
7029ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#else
70576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Open the process pseudo-file in /proc. */
706bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
70776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sprintf(proc, "/proc/%d", tcp->pid);
70876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
709bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
710bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/mem", tcp->pid);
711bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
712bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
71376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: open(\"/proc/...\", ...)");
71476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
71576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
7169ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
7179ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_GETFD");
7189ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7209ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
7219ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		perror("F_SETFD");
7229ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		return -1;
7239ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
7249ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
725bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
726bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	sprintf(proc, "/proc/%d/regs", tcp->pid);
727bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
728bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("strace: open(\"/proc/.../regs\", ...)");
729bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
730bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
731bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (cflag) {
732bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		sprintf(proc, "/proc/%d/status", tcp->pid);
733bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
734bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			perror("strace: open(\"/proc/.../status\", ...)");
735bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			return -1;
736bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
737bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else
738bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		tcp->pfd_status = -1;
739bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
74076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	rebuild_pollv();
74176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
74276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
74376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * Wait for the child to pause.  Because of a race
74476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * condition we have to poll for the event.
74576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
74676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
7479ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_STATUS (tcp) < 0) {
74876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: PIOCSTATUS");
74976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
75076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
7519ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP)
752bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    break;
75376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
75476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
755bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
75676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Stop the process so that we own the stop. */
75716a03d2e97415afe6cf34172a0aea97a95a0b160Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
75876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("strace: PIOCSTOP");
75976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
76076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
761553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
76276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef PIOCSET
76376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set Run-on-Last-Close. */
76476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_RLC;
7659ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
76676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSET PR_RLC");
76776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
76876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
76976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* Set or Reset Inherit-on-Fork. */
77076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	arg = PR_FORK;
7719ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
77276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{SET,RESET} PR_FORK");
77376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
77476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
77576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else  /* !PIOCSET */
776553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
77776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
77876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSRLC");
77976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
78076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
78176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
78276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOC{S,R}FORK");
78376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
78476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
785bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
786bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* just unset the PF_LINGER flag for the Run-on-Last-Close. */
787bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
788bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCGFL");
789bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
790bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
791bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg &= ~PF_LINGER;
792bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
793bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        perror("PIOCSFL");
794bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        return -1;
795bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
796bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
79776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !PIOCSET */
798bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
79919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable all syscall entries we care about. */
80019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&syscalls);
80119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
80219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof syscalls) * CHAR_BIT) break;
80319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_TRACE) praddset (&syscalls, i);
80419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
80519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	praddset (&syscalls, SYS_execve);
80619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (followfork) {
80719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork);
80819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_forkall
80919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_forkall);
81019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
811553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef SYS_fork1
81219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_fork1);
81319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
81419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rfork1
81519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rfork1);
81619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
81719e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#ifdef SYS_rforkall
81819e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		praddset (&syscalls, SYS_rforkall);
81919e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes#endif
82019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
82119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSENTRY, &syscalls) < 0) {
82276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSENTRY");
82376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
82476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
82519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable the syscall exits. */
82619e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	if (IOCTL(tcp->pfd, PIOCSEXIT, &syscalls) < 0) {
82776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOSEXIT");
82876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
82976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
83019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable signals we care about. */
83119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&signals);
83219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
83319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof signals) * CHAR_BIT) break;
83419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_SIGNAL) praddset (&signals, i);
83519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
8369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
83776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSTRACE");
83876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
83976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
84019e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	/* Enable faults we care about */
84119e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	premptyset(&faults);
84219e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	for (i = 1; i < MAX_QUALS; ++i) {
84319e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (i > (sizeof faults) * CHAR_BIT) break;
84419e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes		if (qual_flags [i] & QUAL_FAULT) praddset (&faults, i);
84519e49984acc8f12dfaf0b7835ad17ca24f854c47John Hughes	}
8469ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
84776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("PIOCSFAULT");
84876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
84976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
850bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
851bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	/* set events flags. */
852bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	arg = S_SIG | S_SCE | S_SCX ;
853bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
854bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		perror("PIOCBIS");
855bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		return -1;
856bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
857bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
85876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!attaching) {
85976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef MIPS
86076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
86176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The SGI PRSABORT doesn't work for pause() so
86276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * we send it a caught signal to wake it up.
86376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
86476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		kill(tcp->pid, SIGINT);
86576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !MIPS */
866553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifdef PRSABORT
86776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* The child is in a pause(), abort it. */
8689ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = PRSABORT;
8699ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
87076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
87176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
87276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
873553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
874bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !MIPS*/
875bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
876bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		/* wake up the child if it received the SIGSTOP */
877bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		kill(tcp->pid, SIGCONT);
878553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
87976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
88076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Wait for the child to do something. */
8819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL_WSTOP (tcp) < 0) {
88276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
88376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
88476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
8859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_WHY == PR_SYSENTRY) {
886bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				tcp->flags &= ~TCB_INSYSCALL;
887bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				get_scno(tcp);
888bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				if (tcp->scno == SYS_execve)
88976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					break;
89076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
89176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Set it running: maybe execve will be next. */
892bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
8939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			arg = 0;
8949ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
895bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
896bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
897553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
89876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCRUN");
89976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
90076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
901bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
902bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* handle the case where we "opened" the child before
903bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   it did the kill -STOP */
904bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (tcp->status.PR_WHY == PR_SIGNALLED &&
905bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			    tcp->status.PR_WHAT == SIGSTOP)
906bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			        kill(tcp->pid, SIGCONT);
907553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
90876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
909bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
91076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
911bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
912bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	} else {
913553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath		if (attaching < 2) {
9142e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* We are attaching to an already running process.
9152e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * Try to figure out the state of the process in syscalls,
9162e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * to handle the first event well.
9172e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * This is done by having a look at the "wchan" property of the
9182e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			 * process, which tells where it is stopped (if it is). */
9192e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			FILE * status;
9202e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			char wchan[20]; /* should be enough */
921553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
9222e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			sprintf(proc, "/proc/%d/status", tcp->pid);
9232e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			status = fopen(proc, "r");
9242e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status &&
9252e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
9262e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				    "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
9272e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
9282e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			    strcmp(wchan, "stopevent")) {
9292e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				/* The process is asleep in the middle of a syscall.
9302e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				   Fake the syscall entry event */
9312e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
9322e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
9332e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				trace_syscall(tcp);
9342e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			}
9352e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			if (status)
9362e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman				fclose(status);
9372e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		} /* otherwise it's a fork being followed */
938bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	}
939bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
94076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
94176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (proc_poll_pipe[0] != -1)
94276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
94376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1) {
94476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poll_open();
94576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(last_pfd);
94676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		proc_poller(tcp->pfd);
94776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
94876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	last_pfd = tcp->pfd;
94976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
95076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
95176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
95276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
953bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
95476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
955e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstruct tcb *
95676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpid2tcb(pid)
95776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pid;
95876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
95976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
96076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
96176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
962ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
963ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
96476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid && tcp->pid != pid)
96576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
96676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
96776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
96876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
96976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
97076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
97176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
972bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
97376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
97476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic struct tcb *
97576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanpfd2tcb(pfd)
97676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
97776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
97876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
97976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
980ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = 0; i < tcbtabsize; i++) {
981ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
98276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->pfd != pfd)
98376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
98476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_INUSE)
98576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return tcp;
98676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
98776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return NULL;
98876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
98976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
990bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
99176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
99276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
99376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandroptcb(tcp)
99476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
99576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
99676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pid == 0)
99776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
998e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
999e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->nclone_threads > 0) {
1000e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* There are other threads left in this process, but this
1001e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   is the one whose PID represents the whole process.
1002e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   We need to keep this record around as a zombie until
1003e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		   all the threads die.  */
1004e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->flags |= TCB_EXITING;
1005e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		return;
1006e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1007e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
100876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	nprocs--;
100976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->pid = 0;
1010eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1011e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	if (tcp->parent != NULL) {
1012e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent->nchildren--;
1013e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#ifdef TCB_CLONE_THREAD
1014e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_DETACHED)
1015e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_detached--;
1016e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		if (tcp->flags & TCB_CLONE_THREAD)
1017e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath			tcp->parent->nclone_threads--;
1018e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath#endif
10190962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#ifdef TCB_CLONE_DETACHED
10200962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath		if (!(tcp->flags & TCB_CLONE_DETACHED))
10210962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath#endif
10220962345a5775e0eea75c3ec408fb4807e851e7f0Roland McGrath			tcp->parent->nzombies++;
1023e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		tcp->parent = NULL;
1024e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	}
1025e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath
1026e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath	tcp->flags = 0;
102776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->pfd != -1) {
102876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		close(tcp->pfd);
102976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->pfd = -1;
1030bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1031bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_reg != -1) {
1032bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        close(tcp->pfd_reg);
1033bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		        tcp->pfd_reg = -1;
1034bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1035bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (tcp->pfd_status != -1) {
1036bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			close(tcp->pfd_status);
1037bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			tcp->pfd_status = -1;
1038bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		}
1039553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* !FREEBSD */
1040bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
1041e29341c02f4fb658a34bca1f36c5d587257970d6Roland McGrath		rebuild_pollv(); /* Note, flags needs to be cleared by now.  */
104276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
104376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
1044eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
1045822f0c9a84a4c992cc126766c83726e7275a5572Wichert Akkerman	if (outfname && followfork > 1 && tcp->outf)
104676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fclose(tcp->outf);
1047eb8ebdad122a20ecae0ce8e3e60cb71d8e4a7152Wichert Akkerman
104876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->outf = 0;
104976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
105076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1051bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
105276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
105376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
105476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanresume(tcp)
105576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
105676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
105776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp == NULL)
105876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
105976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
106076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!(tcp->flags & TCB_SUSPENDED)) {
106176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
106276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
106376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
106476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp->flags &= ~TCB_SUSPENDED;
1065e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1066e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->flags & TCB_CLONE_THREAD)
1067e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		tcp->parent->nclone_waiting--;
1068e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
106976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
107076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
107176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("resume: ptrace(PTRACE_SYSCALL, ...)");
107276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return -1;
107376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
107476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
107576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
107676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u resumed\n", tcp->pid);
107776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
107876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
107976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1080bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
108176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
108276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman/* detach traced process; continue with sig */
108376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
108476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
108576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermandetach(tcp, sig)
108676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
108776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
108876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
108976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int error = 0;
1090ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#ifdef LINUX
1091e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	int status, resumed;
1092ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath#endif
109376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
109476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp->flags & TCB_BPTSET)
109576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sig = SIGKILL;
109676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
109776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
109876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/*
109976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 * Linux wrongly insists the child be stopped
11007bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * before detaching.  Arghh.  We go through hoops
11017bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	 * to make a clean break of things.
110276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	 */
11037bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#if defined(SPARC)
11047bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#undef PTRACE_DETACH
11057bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#define PTRACE_DETACH PTRACE_SUNDETACH
11067bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif
110776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
110876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* On a clear day, you can see forever. */
11097bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
11107bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (errno != ESRCH) {
11117bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		/* Shouldn't happen. */
11127bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		perror("detach: ptrace(PTRACE_DETACH, ...)");
11137bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
11147bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (kill(tcp->pid, 0) < 0) {
11157bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
11167bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: checking sanity");
11177bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
11187bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else if (kill(tcp->pid, SIGSTOP) < 0) {
11197bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath		if (errno != ESRCH)
11207bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			perror("detach: stopping child");
11217bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	}
11227bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath	else {
112376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		for (;;) {
11247508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
11257508cb4678141d146d819120f6b5b428c103882eRoland McGrath			if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
11267508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno == ECHILD) /* Already gone.  */
11277508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
11287508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (errno != EINVAL) {
112976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: waiting");
11307508cb4678141d146d819120f6b5b428c103882eRoland McGrath					break;
11317508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
11327508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WALL */
11337508cb4678141d146d819120f6b5b428c103882eRoland McGrath				/* No __WALL here.  */
11347508cb4678141d146d819120f6b5b428c103882eRoland McGrath				if (waitpid(tcp->pid, &status, 0) < 0) {
11357508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (errno != ECHILD) {
11367508cb4678141d146d819120f6b5b428c103882eRoland McGrath						perror("detach: waiting");
11377508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
11387508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
11397508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WCLONE
11407508cb4678141d146d819120f6b5b428c103882eRoland McGrath					/* If no processes, try clones.  */
11417508cb4678141d146d819120f6b5b428c103882eRoland McGrath					if (wait4(tcp->pid, &status, __WCLONE,
11427508cb4678141d146d819120f6b5b428c103882eRoland McGrath						  NULL) < 0) {
11437508cb4678141d146d819120f6b5b428c103882eRoland McGrath						if (errno != ECHILD)
11447508cb4678141d146d819120f6b5b428c103882eRoland McGrath							perror("detach: waiting");
11457508cb4678141d146d819120f6b5b428c103882eRoland McGrath						break;
11467508cb4678141d146d819120f6b5b428c103882eRoland McGrath					}
11477508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif /* __WCLONE */
11487508cb4678141d146d819120f6b5b428c103882eRoland McGrath				}
11497508cb4678141d146d819120f6b5b428c103882eRoland McGrath#ifdef __WALL
115076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
11517508cb4678141d146d819120f6b5b428c103882eRoland McGrath#endif
115276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!WIFSTOPPED(status)) {
115376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* Au revoir, mon ami. */
115476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
115576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
115676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP) {
115776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if ((error = ptrace(PTRACE_DETACH,
11587bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath				    tcp->pid, (char *) 1, sig)) < 0) {
115976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					if (errno != ESRCH)
116076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						perror("detach: ptrace(PTRACE_DETACH, ...)");
116176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					/* I died trying. */
116276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
116376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
116476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
116576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
11667bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			    WSTOPSIG(status) == SIGTRAP ?
11677bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath			    0 : WSTOPSIG(status))) < 0) {
116876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (errno != ESRCH)
116976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("detach: ptrace(PTRACE_CONT, ...)");
117076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
117176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
117276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
117376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
11747bf10474b981aa27f6b8c5b5e3f563d21f2eafcaRoland McGrath#endif /* LINUX */
117576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
117676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if defined(SUNOS4)
117776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	/* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
117876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig && kill(tcp->pid, sig) < 0)
117976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: kill");
118076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sig = 0;
118176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
118276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("detach: ptrace(PTRACE_DETACH, ...)");
118376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
118476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1185bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef USE_PROCFS
1186e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	resumed = 0;
1187e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1188e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* XXX This won't always be quite right (but it never was).
1189e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   A waiter with argument 0 or < -1 is waiting for any pid in
1190e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   a particular pgrp, which this child might or might not be
1191e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   in.  The waiter will only wake up if it's argument is -1
1192e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   or if it's waiting for tcp->pid's pgrp.  It makes a
1193e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   difference to wake up a waiter when there might be more
1194e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   traced children, because it could get a false ECHILD
1195e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   error.  OTOH, if this was the last child in the pgrp, then
1196e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   it ought to wake up and get ECHILD.  We would have to
1197e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   search the system for all pid's in the pgrp to be sure.
1198e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1199e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	     && (t->waitpid == -1 ||
1200e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		 (t->waitpid == 0 && getpgid (tcp->pid) == getpgid (t->pid))
1201e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		 || (t->waitpid < 0 && t->waitpid == -getpid (t->pid)))
1202e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	*/
1203e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1204e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->parent &&
1205e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	    (tcp->parent->flags & TCB_SUSPENDED) &&
1206e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	    (tcp->parent->waitpid <= 0 || tcp->parent->waitpid == tcp->pid)) {
1207e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath 		error = resume(tcp->parent);
1208e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		++resumed;
1209e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1210e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_CLONE_THREAD
1211e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (tcp->parent && tcp->parent->nclone_waiting > 0) {
1212e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* Some other threads of our parent are waiting too.  */
1213e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		unsigned int i;
1214e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1215e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		/* Resume all the threads that were waiting for this PID.  */
1216e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
1217e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			struct tcb *t = tcbtab[i];
1218e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (t->parent == tcp->parent && t != tcp
1219e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && ((t->flags & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1220e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1221e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && t->waitpid == tcp->pid) {
1222e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				error |= resume (t);
1223e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				++resumed;
1224e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1225e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1226e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (resumed == 0)
1227e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* Noone was waiting for this PID in particular,
1228e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   so now we might need to resume some wildcarders.  */
1229e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			for (i = 0; i < tcbtabsize; i++) {
1230e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				struct tcb *t = tcbtab[i];
1231e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (t->parent == tcp->parent && t != tcp
1232e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				    && ((t->flags
1233e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					 & (TCB_CLONE_THREAD|TCB_SUSPENDED))
1234e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					== (TCB_CLONE_THREAD|TCB_SUSPENDED))
1235e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				    && t->waitpid <= 0
1236e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					) {
1237e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					error |= resume (t);
1238e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					break;
1239e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
1240e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1241e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1242e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1243e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1244bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
124576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
124676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (!qflag)
124776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "Process %u detached\n", tcp->pid);
124876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
124976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	droptcb(tcp);
125076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return error;
125176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
125276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1253bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
125476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
125576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
125676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanreaper(sig)
125776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
125876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
125976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
126076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
126176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
126276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
126376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
126476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct tcb *tcp;
126576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
126676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pid2tcb(pid);
126776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp)
126876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
126976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
127076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
127176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
127276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1273bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* USE_PROCFS */
127476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
127576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
127676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermancleanup()
127776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
127876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
127976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
128076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1281ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	for (i = 0; i < tcbtabsize; i++) {
1282ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		tcp = tcbtab[i];
128376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
128476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
128576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
128676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr,
128776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				"cleanup: looking at pid %u\n", tcp->pid);
128876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp_last &&
128976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		    (!outfname || followfork < 2 || tcp_last == tcp)) {
129076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf(" <unfinished ...>\n");
129176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp_last = NULL;
129276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
129376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_ATTACHED)
129476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			detach(tcp, 0);
129576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
129676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGCONT);
129776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			kill(tcp->pid, SIGTERM);
129876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
129976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
130076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (cflag)
130176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		call_summary(outf);
130276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
130376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
130476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
130576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermaninterrupt(sig)
130676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
130776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
130876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	interrupted = 1;
130976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
131076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
131176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRERROR
131276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13136d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#if !HAVE_DECL_SYS_ERRLIST
131476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern int sys_nerr;
131576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanextern char *sys_errlist[];
13166d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrath#endif /* HAVE_DECL_SYS_ERRLIST */
131776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
131876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
131976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrerror(errno)
132076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint errno;
132176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
132276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
132376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
132476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (errno < 1 || errno >= sys_nerr) {
132576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown error %d", errno);
132676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
132776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
132876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_errlist[errno];
132976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
133076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
133176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STERRROR */
133276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
133376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_STRSIGNAL
133476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
13358f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS_SIGLIST && !defined HAVE_DECL_SYS_SIGLIST
13366d2b34971b33d379c89c36c5ad1b0c6d5d12c453Roland McGrathextern char *sys_siglist[];
133776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
13388f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#if defined HAVE_SYS__SIGLIST && !defined HAVE_DECL__SYS_SIGLIST
13398f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrathextern char *_sys_siglist[];
13408f474e087ebb77b57eb87f4fdc557d53c64ca933Roland McGrath#endif
134176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
134276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanconst char *
134376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstrsignal(sig)
134476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
134576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
134676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static char buf[64];
134776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
134876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (sig < 1 || sig >= NSIG) {
134976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sprintf(buf, "Unknown signal %d", sig);
135076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return buf;
135176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
135276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE__SYS_SIGLIST
135376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return _sys_siglist[sig];
135476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
135576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return sys_siglist[sig];
135676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
135776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
135876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
135976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* HAVE_STRSIGNAL */
136076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1361bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef USE_PROCFS
136276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
136376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
136476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanrebuild_pollv()
136576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
136676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
136776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1368ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv != NULL)
1369ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		free (pollv);
1370c012d223a6b915f06ef32b8aaa52b984015d192eRoland McGrath	pollv = (struct pollfd *) malloc(nprocs * sizeof pollv[0]);
1371ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	if (pollv == NULL) {
1372ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		fprintf(stderr, "strace: out of memory for poll vector\n");
1373ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath		exit(1);
1374ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath	}
1375ee9d435275fd7abf736992f84b5053ee16ec4fc7Roland McGrath
1376ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath	for (i = j = 0; i < tcbtabsize; i++) {
1377ca16be8be9521b61bd2c5d945aa115519ebcb4daRoland McGrath		struct tcb *tcp = tcbtab[i];
137876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!(tcp->flags & TCB_INUSE))
137976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
138076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pollv[j].fd = tcp->pfd;
13819ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollv[j].events = POLLWANT;
138276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j++;
138376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
138476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (j != nprocs) {
138576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "strace: proc miscount\n");
138676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
138776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
138876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
138976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
139076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
139176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
139276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
139376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll_open()
139476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
139576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int arg;
139676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
139776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
139876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (pipe(proc_poll_pipe) < 0) {
139976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("pipe");
140076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
140176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
140276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < 2; i++) {
140376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) {
140476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("F_GETFD");
140576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
140676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
140776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) {
140876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("F_SETFD");
140976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
141076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
141176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
141276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
141376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
141476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
141576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poll(pollv, nfds, timeout)
141676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct pollfd *pollv;
141776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint nfds;
141876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint timeout;
141976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
142076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
142176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
142276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
142376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
142476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
142576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return n;
142676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (n != sizeof(struct proc_pollfd)) {
142776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		fprintf(stderr, "panic: short read: %d\n", n);
142876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		exit(1);
142976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
143076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
143176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[i].fd == pollinfo.fd)
143276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = pollinfo.revents;
143376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else
143476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pollv[i].revents = 0;
143576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
143676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	poller_pid = pollinfo.pid;
143776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 1;
143876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
143976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
144176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanwakeup_handler(sig)
144276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint sig;
144376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
144476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
144576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
144676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic void
144776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanproc_poller(pfd)
144876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint pfd;
144976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
145076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct proc_pollfd pollinfo;
145176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct sigaction sa;
145276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigset_t blocked_set, empty_set;
145376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i;
145476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int n;
145576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rlimit rl;
1456bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1457bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	struct procfs_status pfs;
1458bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
145976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
146076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	switch (fork()) {
146176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case -1:
146276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("fork");
146376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		_exit(0);
146476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	case 0:
146576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		break;
146676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	default:
146776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		return;
146876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
146976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
147076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
147176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_flags = 0;
147276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&sa.sa_mask);
147376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGHUP, &sa, NULL);
147476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGINT, &sa, NULL);
147576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGQUIT, &sa, NULL);
147676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGPIPE, &sa, NULL);
147776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGTERM, &sa, NULL);
147876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sa.sa_handler = wakeup_handler;
147976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaction(SIGUSR1, &sa, NULL);
148076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&blocked_set);
148176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigaddset(&blocked_set, SIGUSR1);
148276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigprocmask(SIG_BLOCK, &blocked_set, NULL);
148376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	sigemptyset(&empty_set);
148476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
148576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
148676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		perror("getrlimit(RLIMIT_NOFILE, ...)");
148776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		_exit(0);
148876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
148976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	n = rl.rlim_cur;
149076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < n; i++) {
149176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (i != pfd && i != proc_poll_pipe[1])
149276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			close(i);
149376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
149476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
149576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.fd = pfd;
149676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	pollinfo.pid = getpid();
149776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
1498bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
1499bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1500bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1501bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman	        if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1502bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* FREEBSD */
15039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		{
150476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (errno) {
150576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
150676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
150776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
150876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLERR;
150976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
151076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
151176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pollinfo.revents = POLLHUP;
151276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
151376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
151476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("proc_poller: PIOCWSTOP");
151576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
151676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
151776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			_exit(0);
151876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
15199ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		pollinfo.revents = POLLWANT;
152076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
152176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		sigsuspend(&empty_set);
152276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
152376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
152476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
152576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
152676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
152776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
152876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchoose_pfd()
152976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
153076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int i, j;
153176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
153276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	static int last;
153476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
153576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (followfork < 2 &&
15369ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	    last < nprocs && (pollv[last].revents & POLLWANT)) {
153776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/*
153876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * The previous process is ready to run again.  We'll
153976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * let it do so if it is currently in a syscall.  This
154076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 * heuristic improves the readability of the trace.
154176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		 */
154276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp = pfd2tcb(pollv[last].fd);
154376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp && (tcp->flags & TCB_INSYSCALL))
154476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[last].fd;
154576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
154676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
154776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (i = 0; i < nprocs; i++) {
154876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Let competing children run round robin. */
154976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		j = (i + last + 1) % nprocs;
155076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pollv[j].revents & (POLLHUP | POLLERR)) {
155176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp = pfd2tcb(pollv[j].fd);
155276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!tcp) {
155376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: lost proc\n");
155476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
155576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
155676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
155776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
155876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
15599ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (pollv[j].revents & POLLWANT) {
156076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			last = j;
156176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return pollv[j].fd;
156276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
156376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
156476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	fprintf(stderr, "strace: nothing ready\n");
156576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	exit(1);
156676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
156776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
156876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
156976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
157076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
15719dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
1572d870b3c31a0139b335a66a829169bacc74624c44John Hughes	struct tcb *in_syscall = NULL;
15739dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
157476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
157576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pfd;
157676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int what;
157776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int ioctl_result = 0, ioctl_errno = 0;
15789ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	long arg;
157976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
158076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	for (;;) {
158176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
158276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
158376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
158476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (nprocs == 0)
158576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
158676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
158776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		switch (nprocs) {
158876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case 1:
158976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
159076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] == -1) {
159176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
159276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp = pid2tcb(0);
159376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!tcp)
159476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
159576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				pfd = tcp->pfd;
159676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (pfd == -1)
159776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
159876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				break;
159976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
160076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
160176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* fall through ... */
160276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
160376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
160476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef HAVE_POLLABLE_PROCFS
16059dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
16069dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        /* On some systems (e.g. UnixWare) we get too much ugly
16079dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   "unfinished..." stuff when multiple proceses are in
16089dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			   syscalls.  Here's a nasty hack */
1609553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
16109dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			if (in_syscall) {
16119dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				struct pollfd pv;
16129dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				tcp = in_syscall;
16139dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				in_syscall = NULL;
16149dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.fd = tcp->pfd;
16159dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				pv.events = POLLWANT;
16169dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				if ((what = poll (&pv, 1, 1)) < 0) {
16179dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					if (interrupted)
16189dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman						return 0;
16199dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					continue;
16209dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
16219dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				else if (what == 1 && pv.revents & POLLWANT) {
16229dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman					goto FOUND;
16239dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman				}
16249dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman			}
16259dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
16269dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman
162776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (poll(pollv, nprocs, INFTIM) < 0) {
162876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
162976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
163076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
163176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
163276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else /* !HAVE_POLLABLE_PROCFS */
163376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll(pollv, nprocs, INFTIM) < 0) {
163476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (interrupted)
163576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
163676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
163776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
163876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
163976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			pfd = choose_pfd();
164076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (pfd == -1)
164176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
164276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
164376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
164476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
164576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pfd' in our table. */
164676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pfd2tcb(pfd)) == NULL) {
164776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "unknown pfd: %u\n", pfd);
164876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
164976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
1650b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#ifdef POLL_HACK
16519dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman	FOUND:
1652b664308560d655bc1fb333663eb0d0fb3395409fJohn Hughes#endif
165376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Get the status of the process. */
165476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!interrupted) {
1655bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
16569ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			ioctl_result = IOCTL_WSTOP (tcp);
1657bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* FREEBSD */
1658bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			/* Thanks to some scheduling mystery, the first poller
1659bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   sometimes waits for the already processed end of fork
1660bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			   event. Doing a non blocking poll here solves the problem. */
1661bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if (proc_poll_pipe[0] != -1)
1662bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				ioctl_result = IOCTL_STATUS (tcp);
1663bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			else
1664bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			  	ioctl_result = IOCTL_WSTOP (tcp);
1665553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif /* FREEBSD */
166676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			ioctl_errno = errno;
166776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifndef HAVE_POLLABLE_PROCFS
166876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (proc_poll_pipe[0] != -1) {
166976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ioctl_result < 0)
167076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGKILL);
167176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				else
167276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					kill(poller_pid, SIGUSR1);
167376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
167476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !HAVE_POLLABLE_PROCFS */
167576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
167676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
167776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
167876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
167976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
168076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
168176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
168276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ioctl_result < 0) {
168376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/* Find out what happened if it failed. */
168476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (ioctl_errno) {
168576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
168676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EBADF:
168776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
1688bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1689bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			case ENOTTY:
1690553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
169176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ENOENT:
169276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
169376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
169476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
169576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("PIOCWSTOP");
169676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
169776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
169876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
169976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
17002e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman#ifdef FREEBSD
17012e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
17022e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			/* discard first event for a syscall we never entered */
17032e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			IOCTL (tcp->pfd, PIOCRUN, 0);
17042e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman			continue;
17052e4ffe59b588159eb80e236f068278ba47735932Wichert Akkerman		}
1706553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
1707553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
170876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* clear the just started flag */
170976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp->flags &= ~TCB_STARTUP;
171076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
171276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
171376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
171476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
171576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			struct timeval stime;
1716bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1717bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			char buf[1024];
1718bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			int len;
1719bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman
1720bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1721bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				buf[len] = '\0';
1722bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				sscanf(buf,
1723bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1724bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				       &stime.tv_sec, &stime.tv_usec);
1725bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman			} else
1726bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman				stime.tv_sec = stime.tv_usec = 0;
1727553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else /* !FREEBSD */
172876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_sec = tcp->status.pr_stime.tv_sec;
172976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
1730bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
173176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &stime, &tcp->stime);
173276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = stime;
173376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
17349ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		what = tcp->status.PR_WHAT;
17359ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		switch (tcp->status.PR_WHY) {
1736bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifndef FREEBSD
173776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_REQUESTED:
17389ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			if (tcp->status.PR_FLAGS & PR_ASLEEP) {
17399ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman				tcp->status.PR_WHY = PR_SYSENTRY;
174076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (trace_syscall(tcp) < 0) {
174176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr, "syscall trouble\n");
174276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					exit(1);
174376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
174476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
174576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1746bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !FREEBSD */
174776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSENTRY:
17489dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#ifdef POLL_HACK
17499dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman		        in_syscall = tcp;
17509dbf15466e9c178ac4090eba2c1232e2fe0706f9Wichert Akkerman#endif
175176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SYSEXIT:
175276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (trace_syscall(tcp) < 0) {
175376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "syscall trouble\n");
175476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
175576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
175676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
175776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_SIGNALLED:
175876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
175976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
176076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("--- %s (%s) ---",
1761ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(what), strsignal(what));
176276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
17635826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#ifdef PR_INFO
17645826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				if (tcp->status.PR_INFO.si_signo == what) {
17655826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printleader(tcp);
17665826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					tprintf("    siginfo=");
17675826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printsiginfo(&tcp->status.PR_INFO, 1);
17685826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes					printtrailer(tcp);
17695826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes				}
17705826589d8e210c2d34c8ce496d5b7a0f54188ef0John Hughes#endif
177176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
177276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
177376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		case PR_FAULTED:
177476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
177576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
177676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("=== FAULT %d ===", what);
177776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
177876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
177976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
1780bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#ifdef FREEBSD
1781bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		case 0: /* handle case we polled for nothing */
1782bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		  	continue;
1783553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
178476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		default:
17859ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman			fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
178676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
178776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			break;
178876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
17899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		arg = 0;
1790553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#ifndef FREEBSD
17919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
1792553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#else
1793bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman		if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
1794553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath#endif
179576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("PIOCRUN");
179676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			exit(1);
179776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
179876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
179976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
180076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
180176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1802bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#else /* !USE_PROCFS */
180376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
1804e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
1805e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath/* Handle an exit detach or death signal that is taking all the
1806e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   related clone threads with it.  This is called in three circumstances:
1807e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == -1	TCP has already died (TCB_ATTACHED is clear, strace is parent).
1808e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == 0	Continuing TCP will perform an exit_group syscall.
1809e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath   SIG == other	Continuing TCP with SIG will kill the process.
1810e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath*/
1811e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathstatic int
1812e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathhandle_group_exit(struct tcb *tcp, int sig)
1813e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath{
1814e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* We need to locate our records of all the clone threads
1815e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   related to TCP, either its children or siblings.  */
1816e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD)
1817e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp->parent
1818e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      : tcp->nclone_detached > 0
1819e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			      ? tcp : NULL);
1820e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1821e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (sig < 0) {
1822e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (leader != NULL && leader != tcp)
1823e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			fprintf(stderr,
1824e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				"PANIC: handle_group_exit: %d leader %d\n",
1825e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->pid, leader ? leader->pid : -1);
1826e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		droptcb(tcp);	/* Already died.  */
1827e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1828e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	else {
1829e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		if (tcp->flags & TCB_ATTACHED) {
1830e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (leader != NULL && leader != tcp) {
1831e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* We need to detach the leader so that the
1832e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   process death will be reported to its real
1833e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent.  But we kill it first to prevent
1834e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   it doing anything before we kill the whole
1835e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   process in a moment.  We can use
1836e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   PTRACE_KILL on a thread that's not already
1837e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   stopped.  Then the value we pass in
1838e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   PTRACE_DETACH just sets the death
1839e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   signal reported to the real parent.  */
1840e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				ptrace(PTRACE_KILL, leader->pid, 0, 0);
1841e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (debug)
1842e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr,
1843e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						" [%d exit %d kills %d]\n",
1844e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						tcp->pid, sig, leader->pid);
1845e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				detach(leader, sig);
1846e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
1847e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			detach(tcp, sig);
1848e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1849e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
1850e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			perror("strace: ptrace(PTRACE_CONT, ...)");
1851e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			cleanup();
1852e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return -1;
1853e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1854e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		else {
1855e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (leader != NULL && leader != tcp)
1856e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				droptcb(tcp);
1857e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			/* The leader will report to us as parent now,
1858e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			   and then we'll get to the SIG==-1 case.  */
1859e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			return 0;
1860e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1861e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1862e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1863e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	/* Note that TCP and LEADER are no longer valid,
1864e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	   but we can still compare against them.  */
1865e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	if (leader != NULL) {
1866e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		unsigned int i;
1867e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		for (i = 0; i < tcbtabsize; i++) {
1868e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			struct tcb *t = tcbtab[i];
1869e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (t != tcp && (t->flags & TCB_CLONE_DETACHED)
1870e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			    && t->parent == leader)
1871e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				droptcb(t);
1872e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath		}
1873e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	}
1874e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
1875e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath	return 0;
1876e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath}
1877e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
1878e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath
187976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int
188076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantrace()
188176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
188276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int pid;
188376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int wait_errno;
188476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	int status;
188576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct tcb *tcp;
188676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
188776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	struct rusage ru;
18882f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
18892f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman	static int wait4_options = __WALL;
18902f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif
189176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
189276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
189376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	while (nprocs != 0) {
189476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
189576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_SETMASK, &empty_set, NULL);
189676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
18972f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#ifdef __WALL
18982f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		pid = wait4(-1, &status, wait4_options, cflag ? &ru : NULL);
18995bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && (wait4_options & __WALL) && errno == EINVAL) {
19002f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* this kernel does not support __WALL */
19012f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			wait4_options &= ~__WALL;
19022f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			errno = 0;
19032f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, wait4_options,
19042f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
19052f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
19065bc05558bb9f9acd1f895ea128f3326ef4b03338Roland McGrath		if (pid < 0 && !(wait4_options & __WALL) && errno == ECHILD) {
19072f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			/* most likely a "cloned" process */
19082f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			pid = wait4(-1, &status, __WCLONE,
19092f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman					cflag ? &ru : NULL);
19102f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			if (pid == -1) {
19112f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman				fprintf(stderr, "strace: clone wait4 "
19122f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman						"failed: %s\n", strerror(errno));
19132f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman			}
19142f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman		}
19152f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#else
191676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
19172f1d87e74ff68004b99901f964a1cbab89da09dbWichert Akkerman#endif /* __WALL */
191876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* LINUX */
191976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
192076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		pid = wait(&status);
192176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
192276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		wait_errno = errno;
192376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interactive)
192476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			sigprocmask(SIG_BLOCK, &blocked_set, NULL);
192576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (interrupted)
192776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return 0;
192876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
192976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (pid == -1) {
193076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			switch (wait_errno) {
193176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case EINTR:
193276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
193376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			case ECHILD:
193476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
193576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * We would like to verify this case
193676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * but sometimes a race in Solbourne's
193776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * version of SunOS sometimes reports
193876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * ECHILD before sending us SIGCHILD.
193976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
194076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#if 0
194176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (nprocs == 0)
194276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return 0;
194376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "strace: proc miscount\n");
194476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				exit(1);
194576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
194676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return 0;
194776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			default:
194876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				errno = wait_errno;
194976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: wait");
195076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
195176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
195276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
195376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
195476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
195576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
195676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* Look up `pid' in our table. */
195776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if ((tcp = pid2tcb(pid)) == NULL) {
1958e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef LINUX
1959e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (followfork || followvfork) {
1960e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This is needed to go with the CLONE_PTRACE
1961e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   changes in process.c/util.c: we might see
1962e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   the child's initial trap before we see the
1963e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   parent return from the clone syscall.
1964e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   Leave the child suspended until the parent
1965e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   returns from its system call.  Only then
1966e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   will we have the association of parent and
1967e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   child so that we know how to do clearbpt
1968e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   in the child.  */
1969e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if ((tcp = alloctcb(pid)) == NULL) {
1970e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, " [tcb table full]\n");
1971e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					kill(pid, SIGKILL); /* XXX */
1972e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return 0;
1973e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				}
1974e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				tcp->flags |= TCB_ATTACHED | TCB_SUSPENDED;
1975e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				newoutf(tcp);
1976e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (!qflag)
1977e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					fprintf(stderr, "\
1978e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrathProcess %d attached (waiting for parent)\n",
1979e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath						pid);
19808b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman			}
1981e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			else
1982e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				/* This can happen if a clone call used
1983e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				   CLONE_PTRACE itself.  */
19848b1b40cd8b49151374d0ac2a5b1a4b459f9e0ae5Wichert Akkerman#endif
1985e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			{
1986e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				fprintf(stderr, "unknown pid: %u\n", pid);
1987e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (WIFSTOPPED(status))
1988e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					ptrace(PTRACE_CONT, pid, (char *) 1, 0);
1989e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				exit(1);
1990e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
199176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
199276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		/* set current output file */
199376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		outf = tcp->outf;
199476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (cflag) {
199576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef LINUX
199676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
199776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->stime = ru.ru_stime;
199876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* !LINUX */
199976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
200076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
200176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
200276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
200376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Apparently, doing any ptrace() call on a stopped
200476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process, provokes the kernel to report the process
200576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * status again on a subsequent wait(), even if the
200676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * process has not been actually restarted.
200776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Since we have inspected the arguments of suspended
200876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * processes we end up here testing for this case.
200976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
201076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
201176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
201276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFSIGNALED(status)) {
201376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
201476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
201576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
201676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("+++ killed by %s +++",
2017ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WTERMSIG(status)));
201876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
201976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
2020e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2021e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2022e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
202376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2024e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
202576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
202676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
202776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WIFEXITED(status)) {
202876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (debug)
202976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "pid %u exited\n", pid);
203076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
203176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr,
203276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					"PANIC: attached pid %u exited\n",
203376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					pid);
20340a396906981a03f93c07cb912585d0679dd50899Roland McGrath			if (tcp == tcp_last) {
20350a396906981a03f93c07cb912585d0679dd50899Roland McGrath				if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT))
20360a396906981a03f93c07cb912585d0679dd50899Roland McGrath				    == TCB_INSYSCALL)
20370a396906981a03f93c07cb912585d0679dd50899Roland McGrath					tprintf(" <unfinished ... exit status %d>\n",
20380a396906981a03f93c07cb912585d0679dd50899Roland McGrath						WEXITSTATUS(status));
20390a396906981a03f93c07cb912585d0679dd50899Roland McGrath				tcp_last = NULL;
20400a396906981a03f93c07cb912585d0679dd50899Roland McGrath			}
2041e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2042e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			handle_group_exit(tcp, -1);
2043e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
204476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
2045e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
204676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
204776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
204876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (!WIFSTOPPED(status)) {
204976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
205076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			droptcb(tcp);
205176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
205276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
205376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (debug)
205476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			fprintf(stderr, "pid %u stopped, [%s]\n",
2055ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons				pid, signame(WSTOPSIG(status)));
205676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
205776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_STARTUP) {
205876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			/*
205976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * This flag is there to keep us in sync.
206076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * Next time this process stops it should
206176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 * really be entering a system call.
206276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			 */
206376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_STARTUP;
206476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED) {
206576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
206676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Interestingly, the process may stop
206776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * with STOPSIG equal to some other signal
206876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * than SIGSTOP if we happend to attach
206976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * just before the process takes a signal.
207076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
207176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (!WIFSTOPPED(status)) {
207276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fprintf(stderr,
207376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						"pid %u not stopped\n", pid);
207476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					detach(tcp, WSTOPSIG(status));
207576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					continue;
207676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
207776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
207876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
207976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef SUNOS4
208076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/* A child of us stopped at exec */
208176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (WSTOPSIG(status) == SIGTRAP && followvfork)
208276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					fixvfork(tcp);
208376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif /* SUNOS4 */
208476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
208576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_BPTSET) {
208676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (clearbpt(tcp) < 0) /* Pretty fatal */ {
208776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					droptcb(tcp);
208876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
208976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
209076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
209176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
209276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			goto tracing;
209376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
209476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
209576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (WSTOPSIG(status) != SIGTRAP) {
209676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (WSTOPSIG(status) == SIGSTOP &&
209776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					(tcp->flags & TCB_SIGTRAPPED)) {
209876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				/*
209976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Trapped attempt to block SIGTRAP
210076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 * Hope we are back in control now.
210176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				 */
210276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
210376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				if (ptrace(PTRACE_SYSCALL,
210476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman						pid, (char *) 1, 0) < 0) {
210576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					perror("trace: ptrace(PTRACE_SYSCALL, ...)");
210676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					cleanup();
210776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					return -1;
210876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				}
210976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
211076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
211176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!cflag
211276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			    && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
21137b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				unsigned long addr = 0, pc = 0;
21147b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#ifdef PT_GETSIGINFO
21157b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#				define PSR_RI	41
21167b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				struct siginfo si;
21177b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				unsigned long psr;
21187b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
21197b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				upeek(pid, PT_CR_IPSR, &psr);
21207b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				upeek(pid, PT_CR_IIP, &pc);
21217b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman
21227b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				pc += (psr >> PSR_RI) & 0x3;
21237b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				ptrace(PT_GETSIGINFO, pid, 0, (long) &si);
21247b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				addr = (unsigned long) si.si_addr;
21257b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman#endif
212676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printleader(tcp);
21277b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman				tprintf("--- %s (%s) @ %lx (%lx) ---",
2128ce780fc9e6067b15b65ca2904c698c77503bf635Nate Sammons					signame(WSTOPSIG(status)),
21297b3346be42d6a1f539e95d385ee498f8b3c529f8Wichert Akkerman					strsignal(WSTOPSIG(status)), pc, addr);
213076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				printtrailer(tcp);
213176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
213276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if ((tcp->flags & TCB_ATTACHED) &&
213376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				!sigishandled(tcp, WSTOPSIG(status))) {
2134e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2135e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				handle_group_exit(tcp, WSTOPSIG(status));
2136e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#else
213776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, WSTOPSIG(status));
2138e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
213976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				continue;
214076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
214176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
214276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				   WSTOPSIG(status)) < 0) {
214376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("trace: ptrace(PTRACE_SYSCALL, ...)");
214476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
214576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
214676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
214776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tcp->flags &= ~TCB_SUSPENDED;
214876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
214976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
215076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (trace_syscall(tcp) < 0) {
215176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
215276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
215376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else {
215476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				ptrace(PTRACE_KILL,
215576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman					tcp->pid, (char *) 1, SIGTERM);
215676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				droptcb(tcp);
215776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
215876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
215976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
216076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_EXITING) {
2161e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#ifdef TCB_GROUP_EXITING
2162e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			if (tcp->flags & TCB_GROUP_EXITING) {
2163e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				if (handle_group_exit(tcp, 0) < 0)
2164e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath					return -1;
2165e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath				continue;
2166e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath			}
2167e85bbfe9ab55854cc3a6227d2f9001587fe64996Roland McGrath#endif
216876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tcp->flags & TCB_ATTACHED)
216976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				detach(tcp, 0);
217076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
217176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				perror("strace: ptrace(PTRACE_CONT, ...)");
217276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				cleanup();
217376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				return -1;
217476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			}
217576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
217676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
217776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (tcp->flags & TCB_SUSPENDED) {
217876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (!qflag)
217976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				fprintf(stderr, "Process %u suspended\n", pid);
218076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			continue;
218176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
218276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tracing:
218376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
218476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			perror("trace: ptrace(PTRACE_SYSCALL, ...)");
218576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			cleanup();
218676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			return -1;
218776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
218876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
218976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return 0;
219076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
219176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
2192bf79f2e16b090ffe59cd1e1820935680a2da7b78Wichert Akkerman#endif /* !USE_PROCFS */
219376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
219476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstatic int curcol;
219576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
219676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
219776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <stdarg.h>
219876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a, b)
219976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
220076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#include <varargs.h>
220176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#define VA_START(a, b) va_start(a)
220276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
220376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
220476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
220576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#ifdef __STDC__
220676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(const char *fmt, ...)
220776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#else
220876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantprintf(fmt, va_alist)
220976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanchar *fmt;
221076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanva_dcl
221176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman#endif
221276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
221376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_list args;
221476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
221576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	VA_START(args, fmt);
2216b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	if (outf) {
2217b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		int n = vfprintf(outf, fmt, args);
2218b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		if (n < 0 && outf != stderr)
2219b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			perror(outfname == NULL
2220b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			       ? "<writing to pipe>" : outfname);
2221b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath		else
2222b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath			curcol += n;
2223b310a0c26b3b31d52aa4b25549e06113284bd5bbRoland McGrath	}
222476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	va_end(args);
222576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	return;
222676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
222776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
222876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
222976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprintleader(tcp)
223076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
223176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
223276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
223376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tcp_last->flags |= TCB_REPRINT;
223476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf(" <unfinished ...>\n");
223576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
223676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	curcol = 0;
223776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if ((followfork == 1 || pflag_seen > 1) && outfname)
223876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%-5d ", tcp->pid);
223976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	else if (nprocs > 1 && !outfname)
224076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("[pid %5u] ", tcp->pid);
224176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (tflag) {
224276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		char str[sizeof("HH:MM:SS")];
224376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		struct timeval tv, dtv;
224476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		static struct timeval otv;
224576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
224676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		gettimeofday(&tv, NULL);
224776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		if (rflag) {
224876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (otv.tv_sec == 0)
224976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				otv = tv;
225076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tv_sub(&dtv, &tv, &otv);
225176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%6ld.%06ld ",
225276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) dtv.tv_sec, (long) dtv.tv_usec);
225376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			otv = tv;
225476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
225576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else if (tflag > 2) {
225676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			tprintf("%ld.%06ld ",
225776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				(long) tv.tv_sec, (long) tv.tv_usec);
225876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
225976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		else {
226076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			time_t local = tv.tv_sec;
226176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			strftime(str, sizeof(str), "%T", localtime(&local));
226276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			if (tflag > 1)
226376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s.%06ld ", str, (long) tv.tv_usec);
226476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman			else
226576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman				tprintf("%s ", str);
226676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		}
226776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	}
226876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (iflag)
226976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		printcall(tcp);
227076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
227176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
227276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
227376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermantabto(col)
227476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanint col;
227576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
227676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	if (curcol < col)
227776baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman		tprintf("%*s", col - curcol, "");
227876baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
227976baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman
228076baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanvoid
228176baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanprinttrailer(tcp)
228276baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkermanstruct tcb *tcp;
228376baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman{
228476baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tprintf("\n");
228576baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman	tcp_last = NULL;
228676baf7c9f6dd61a15524ad43c1b690c252cf5b7Wichert Akkerman}
22879ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
2288ea78f0f77185f7d6d0b2055805139d96e1be816cWichert Akkerman#ifdef HAVE_MP_PROCFS
22899ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
22909ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkermanint mp_ioctl (int fd, int cmd, void *arg, int size) {
22919ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
22929ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	struct iovec iov[2];
22939ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	int n = 1;
2294553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
22959ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_base = &cmd;
22969ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	iov[0].iov_len = sizeof cmd;
22979ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	if (arg) {
22989ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		++n;
22999ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_base = arg;
23009ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman		iov[1].iov_len = size;
23019ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	}
2302553a609807074e95eed5a0bffba334b7fb3d3751Roland McGrath
23039ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman	return writev (fd, iov, n);
23049ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman}
23059ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman
23069ce1a63eb20b069607c06f9645ac5a17b418a5f3Wichert Akkerman#endif
2307