]> granicus.if.org Git - strace/blob - strace.c
Merge Harald Böhme's solaris patches
[strace] / strace.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  *      $Id$
31  */
32
33 #include <sys/types.h>
34 #include "defs.h"
35
36 #include <signal.h>
37 #include <errno.h>
38 #include <sys/param.h>
39 #include <fcntl.h>
40 #include <sys/resource.h>
41 #include <sys/wait.h>
42 #include <sys/stat.h>
43 #include <pwd.h>
44 #include <grp.h>
45 #include <string.h>
46
47 #ifdef USE_PROCFS
48 #include <poll.h>
49 #endif
50
51 #ifdef SVR4
52 #include <sys/stropts.h>
53 #ifdef HAVE_MP_PROCFS
54 #include <sys/uio.h>
55 #endif
56 #endif
57
58 int debug = 0, followfork = 0, followvfork = 0, interactive = 0;
59 int rflag = 0, tflag = 0, dtime = 0, cflag = 0;
60 int iflag = 0, xflag = 0, qflag = 0;
61 int pflag_seen = 0;
62
63 char *username = NULL;
64 uid_t run_uid;
65 gid_t run_gid;
66
67 int acolumn = DEFAULT_ACOLUMN;
68 int max_strlen = DEFAULT_STRLEN;
69 char *outfname = NULL;
70 FILE *outf;
71 struct tcb tcbtab[MAX_PROCS];
72 int nprocs;
73 char *progname;
74 extern char version[];
75 extern char **environ;
76
77 static struct tcb *pid2tcb P((int pid));
78 static int trace P((void));
79 static void cleanup P((void));
80 static void interrupt P((int sig));
81 static sigset_t empty_set, blocked_set;
82
83 #ifdef HAVE_SIG_ATOMIC_T
84 static volatile sig_atomic_t interrupted;
85 #else /* !HAVE_SIG_ATOMIC_T */
86 #ifdef __STDC__
87 static volatile int interrupted;
88 #else /* !__STDC__ */
89 static int interrupted;
90 #endif /* !__STDC__ */
91 #endif /* !HAVE_SIG_ATOMIC_T */
92
93 #ifdef USE_PROCFS
94
95 static struct tcb *pfd2tcb P((int pfd));
96 static void reaper P((int sig));
97 static void rebuild_pollv P((void));
98 struct pollfd pollv[MAX_PROCS];
99
100 #ifndef HAVE_POLLABLE_PROCFS
101
102 static void proc_poll_open P((void));
103 static void proc_poller P((int pfd));
104
105 struct proc_pollfd {
106         int fd;
107         int revents;
108         int pid;
109 };
110
111 static int poller_pid;
112 static int proc_poll_pipe[2] = { -1, -1 };
113
114 #endif /* !HAVE_POLLABLE_PROCFS */
115
116 #ifdef HAVE_MP_PROCFS
117 #define POLLWANT        POLLWRNORM
118 #else
119 #define POLLWANT        POLLPRI
120 #endif
121 #endif /* USE_PROCFS */
122
123 static void
124 usage(ofp, exitval)
125 FILE *ofp;
126 int exitval;
127 {
128         fprintf(ofp, "\
129 usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]\n\
130               [-p pid] ... [-s strsize] [-u username] [command [arg ...]]\n\
131    or: strace -c [-e expr] ... [-O overhead] [-S sortby] [command [arg ...]]\n\
132 -c -- count time, calls, and errors for each syscall and report summary\n\
133 -f -- follow forks, -ff -- with output into separate files\n\
134 -F -- attempt to follow vforks, -h -- print help message\n\
135 -i -- print instruction pointer at time of syscall\n\
136 -q -- suppress messages about attaching, detaching, etc.\n\
137 -r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
138 -T -- print time spent in each syscall, -V -- print version\n\
139 -v -- verbose mode: print unabbreviated argv, stat, termio[s], etc. args\n\
140 -x -- print non-ascii strings in hex, -xx -- print all strings in hex\n\
141 -a column -- alignment COLUMN for printing syscall results (default %d)\n\
142 -e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...\n\
143    options: trace, abbrev, verbose, raw, signal, read, or write\n\
144 -o file -- send trace output to FILE instead of stderr\n\
145 -O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
146 -p pid -- trace process with process id PID, may be repeated\n\
147 -s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
148 -S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
149 -u username -- run command as username handling setuid and/or setgid\n\
150 ", DEFAULT_ACOLUMN, DEFAULT_STRLEN, DEFAULT_SORTBY);
151         exit(exitval);
152 }
153
154 #ifdef SVR4
155 #ifdef MIPS
156 void
157 foobar()
158 {
159 }
160 #endif /* MIPS */
161 #endif /* SVR4 */
162
163 int
164 main(argc, argv)
165 int argc;
166 char *argv[];
167 {
168         extern int optind;
169         extern char *optarg;
170         struct tcb *tcp;
171         int c, pid = 0;
172         struct sigaction sa;
173
174         static char buf[BUFSIZ];
175
176         progname = argv[0];
177         outf = stderr;
178         interactive = 1;
179         qualify("trace=all");
180         qualify("abbrev=all");
181         qualify("verbose=all");
182         qualify("signal=all");
183         set_sortby(DEFAULT_SORTBY);
184         set_personality(DEFAULT_PERSONALITY);
185         while ((c = getopt(argc, argv,
186                 "+cdfFhiqrtTvVxa:e:o:O:p:s:S:u:")) != EOF) {
187                 switch (c) {
188                 case 'c':
189                         cflag++;
190                         dtime++;
191                         break;
192                 case 'd':
193                         debug++;
194                         break;
195                 case 'f':
196                         followfork++;
197                         break;
198                 case 'F':
199                         followvfork++;
200                         break;
201                 case 'h':
202                         usage(stdout, 0);
203                         break;
204                 case 'i':
205                         iflag++;
206                         break;
207                 case 'q':
208                         qflag++;
209                         break;
210                 case 'r':
211                         rflag++;
212                         tflag++;
213                         break;
214                 case 't':
215                         tflag++;
216                         break;
217                 case 'T':
218                         dtime++;
219                         break;
220                 case 'x':
221                         xflag++;
222                         break;
223                 case 'v':
224                         qualify("abbrev=none");
225                         break;
226                 case 'V':
227                         printf("%s\n", version);
228                         exit(0);
229                         break;
230                 case 'a':
231                         acolumn = atoi(optarg);
232                         break;
233                 case 'e':
234                         qualify(optarg);
235                         break;
236                 case 'o':
237                         outfname = strdup(optarg);
238                         break;
239                 case 'O':
240                         set_overhead(atoi(optarg));
241                         break;
242                 case 'p':
243                         if ((pid = atoi(optarg)) == 0) {
244                                 fprintf(stderr, "%s: Invalid process id: %s\n",
245                                         progname, optarg);
246                                 break;
247                         }
248                         if (pid == getpid()) {
249                                 fprintf(stderr, "%s: I'm sorry, I can't let you do that, Dave.\n", progname);
250                                 break;
251                         }
252                         if ((tcp = alloctcb(pid)) == NULL) {
253                                 fprintf(stderr, "%s: tcb table full, please recompile strace\n",
254                                         progname);
255                                 exit(1);
256                         }
257                         tcp->flags |= TCB_ATTACHED;
258                         pflag_seen++;
259                         break;
260                 case 's':
261                         max_strlen = atoi(optarg);
262                         break;
263                 case 'S':
264                         set_sortby(optarg);
265                         break;
266                 case 'u':
267                         username = strdup(optarg);
268                         break;
269                 default:
270                         usage(stderr, 1);
271                         break;
272                 }
273         }
274
275         /* See if they want to run as another user. */
276         if (username != NULL) {
277                 struct passwd *pent;
278
279                 if (getuid() != 0 || geteuid() != 0) {
280                         fprintf(stderr,
281                                 "%s: you must be root to use the -u option\n",
282                                 progname);
283                         exit(1);
284                 }
285                 if ((pent = getpwnam(username)) == NULL) {
286                         fprintf(stderr, "%s: cannot find user `%s'\n",
287                                 progname, optarg);
288                         exit(1);
289                 }
290                 run_uid = pent->pw_uid;
291                 run_gid = pent->pw_gid;
292         }
293         else {
294                 run_uid = getuid();
295                 run_gid = getgid();
296         }
297
298 #ifndef SVR4
299         setreuid(geteuid(), getuid());
300 #endif
301
302         /* See if they want to pipe the output. */
303         if (outfname && (outfname[0] == '|' || outfname[0] == '!')) {
304                 if ((outf = popen(outfname + 1, "w")) == NULL) {
305                         fprintf(stderr, "%s: can't popen '%s': %s\n",
306                                 progname, outfname + 1, strerror(errno));
307                         exit(1);
308                 }
309                 free(outfname);
310                 outfname = NULL;
311         }
312
313         /* Check if they want to redirect the output. */
314         if (outfname) {
315                 if ((outf = fopen(outfname, "w")) == NULL) {
316                         fprintf(stderr, "%s: can't fopen '%s': %s\n",
317                                 progname, outfname, strerror(errno));
318                         exit(1);
319                 }
320         }
321
322 #ifndef SVR4
323         setreuid(geteuid(), getuid());
324 #endif
325
326         if (!outfname) {
327                 qflag = 1;
328                 setvbuf(outf, buf, _IOLBF, BUFSIZ);
329         }
330         else if (optind < argc)
331                 interactive = 0;
332         else
333                 qflag = 1;
334
335         for (c = 0, tcp = tcbtab; c < MAX_PROCS; c++, tcp++) {
336                 /* Reinitialize the output since it may have changed. */
337                 tcp->outf = outf;
338                 if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
339                         continue;
340 #ifdef USE_PROCFS
341                 if (proc_open(tcp, 1) < 0) {
342                         fprintf(stderr, "trouble opening proc file\n");
343                         droptcb(tcp);
344                         continue;
345                 }
346 #else /* !USE_PROCFS */
347                 if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
348                         perror("attach: ptrace(PTRACE_ATTACH, ...)");
349                         droptcb(tcp);
350                         continue;
351                 }
352 #endif /* !USE_PROCFS */
353                 if (!qflag)
354                         fprintf(stderr,
355                                 "Process %u attached - interrupt to quit\n",
356                                 pid);
357         }
358
359         if (optind < argc) {
360                 struct stat statbuf;
361                 char *filename;
362                 char pathname[MAXPATHLEN];
363
364                 filename = argv[optind];
365                 if (strchr(filename, '/'))
366                         strcpy(pathname, filename);
367 #ifdef USE_DEBUGGING_EXEC
368                 /*
369                  * Debuggers customarily check the current directory
370                  * first regardless of the path but doing that gives
371                  * security geeks a panic attack.
372                  */
373                 else if (stat(filename, &statbuf) == 0)
374                         strcpy(pathname, filename);
375 #endif /* USE_DEBUGGING_EXEC */
376                 else {
377                         char *path;
378                         int m, n, len;
379
380                         for (path = getenv("PATH"); path && *path; path += m) {
381                                 if (strchr(path, ':')) {
382                                         n = strchr(path, ':') - path;
383                                         m = n + 1;
384                                 }
385                                 else
386                                         m = n = strlen(path);
387                                 if (n == 0) {
388                                         getcwd(pathname, MAXPATHLEN);
389                                         len = strlen(pathname);
390                                 }
391                                 else {
392                                         strncpy(pathname, path, n);
393                                         len = n;
394                                 }
395                                 if (len && pathname[len - 1] != '/')
396                                         pathname[len++] = '/';
397                                 strcpy(pathname + len, filename);
398                                 if (stat(pathname, &statbuf) == 0)
399                                         break;
400                         }
401                 }
402                 if (stat(pathname, &statbuf) < 0) {
403                         fprintf(stderr, "%s: %s: command not found\n",
404                                 progname, filename);
405                         exit(1);
406                 }
407                 switch (pid = fork()) {
408                 case -1:
409                         perror("strace: fork");
410                         cleanup();
411                         exit(1);
412                         break;
413                 case 0: {
414 #ifdef USE_PROCFS
415                         if (outf != stderr) close (fileno (outf));
416 #ifdef MIPS
417                         /* Kludge for SGI, see proc_open for details. */
418                         sa.sa_handler = foobar;
419                         sa.sa_flags = 0;
420                         sigemptyset(&sa.sa_mask);
421                         sigaction(SIGINT, &sa, NULL);
422 #endif /* MIPS */
423 #ifndef FREEBSD
424                         pause();
425 #else /* FREEBSD */
426                         kill(getpid(), SIGSTOP); /* stop HERE */
427 #endif /* FREEBSD */                    
428 #else /* !USE_PROCFS */
429                         if (outf!=stderr)       
430                                 close(fileno (outf));
431
432                         if (ptrace(PTRACE_TRACEME, 0, (char *) 1, 0) < 0) {
433                                 perror("strace: ptrace(PTRACE_TRACEME, ...)");
434                                 return -1;
435                         }
436                         if (debug)
437                                 kill(getpid(), SIGSTOP);
438
439                         if (username != NULL || geteuid() == 0) {
440                                 uid_t run_euid = run_uid;
441                                 gid_t run_egid = run_gid;
442
443                                 if (statbuf.st_mode & S_ISUID)
444                                         run_euid = statbuf.st_uid;
445                                 if (statbuf.st_mode & S_ISGID)
446                                         run_egid = statbuf.st_gid;
447
448                                 /*
449                                  * It is important to set groups before we
450                                  * lose privileges on setuid.
451                                  */
452                                 if (username != NULL) {
453                                         if (initgroups(username, run_gid) < 0) {
454                                                 perror("initgroups");
455                                                 exit(1);
456                                         }
457                                         if (setregid(run_gid, run_egid) < 0) {
458                                                 perror("setregid");
459                                                 exit(1);
460                                         }
461                                         if (setreuid(run_uid, run_euid) < 0) {
462                                                 perror("setreuid");
463                                                 exit(1);
464                                         }
465                                 }
466                         }
467                         else
468                                 setreuid(run_uid, run_uid);
469 #endif /* !USE_PROCFS */
470
471                         execv(pathname, &argv[optind]);
472                         perror("strace: exec");
473                         _exit(1);
474                         break;
475                 }
476                 default:
477                         if ((tcp = alloctcb(pid)) == NULL) {
478                                 fprintf(stderr, "tcb table full\n");
479                                 cleanup();
480                                 exit(1);
481                         }
482 #ifdef USE_PROCFS
483                         if (proc_open(tcp, 0) < 0) {
484                                 fprintf(stderr, "trouble opening proc file\n");
485                                 cleanup();
486                                 exit(1);
487                         }
488 #endif /* USE_PROCFS */
489 #ifndef USE_PROCFS
490                         fake_execve(tcp, pathname, &argv[optind], environ);
491 #endif /* !USE_PROCFS */
492                         break;
493                 }
494         }
495         else if (pflag_seen == 0)
496                 usage(stderr, 1);
497
498         sigemptyset(&empty_set);
499         sigemptyset(&blocked_set);
500         sa.sa_handler = SIG_IGN;
501         sigemptyset(&sa.sa_mask);
502         sa.sa_flags = 0;
503         sigaction(SIGTTOU, &sa, NULL);
504         sigaction(SIGTTIN, &sa, NULL);
505         if (interactive) {
506                 sigaddset(&blocked_set, SIGHUP);
507                 sigaddset(&blocked_set, SIGINT);
508                 sigaddset(&blocked_set, SIGQUIT);
509                 sigaddset(&blocked_set, SIGPIPE);
510                 sigaddset(&blocked_set, SIGTERM);
511                 sa.sa_handler = interrupt;
512 #ifdef SUNOS4
513                 /* POSIX signals on sunos4.1 are a little broken. */
514                 sa.sa_flags = SA_INTERRUPT;
515 #endif /* SUNOS4 */
516         }
517         sigaction(SIGHUP, &sa, NULL);
518         sigaction(SIGINT, &sa, NULL);
519         sigaction(SIGQUIT, &sa, NULL);
520         sigaction(SIGPIPE, &sa, NULL);
521         sigaction(SIGTERM, &sa, NULL);
522 #ifdef USE_PROCFS
523         sa.sa_handler = reaper;
524         sigaction(SIGCHLD, &sa, NULL);
525 #endif /* USE_PROCFS */
526
527         if (trace() < 0)
528                 exit(1);
529         cleanup();
530         exit(0);
531 }
532
533 void
534 newoutf(tcp)
535 struct tcb *tcp;
536 {
537         char name[MAXPATHLEN];
538         FILE *fp;
539
540         if (outfname && followfork > 1) {
541                 sprintf(name, "%s.%u", outfname, tcp->pid);
542 #ifndef SVR4
543                 setreuid(geteuid(), getuid());
544 #endif
545                 fp = fopen(name, "w");
546 #ifndef SVR4
547                 setreuid(geteuid(), getuid());
548 #endif
549                 if (fp == NULL) {
550                         perror("fopen");
551                         return;
552                 }
553                 tcp->outf = fp;
554         }
555         return;
556 }
557
558 struct tcb *
559 alloctcb(pid)
560 int pid;
561 {
562         int i;
563         struct tcb *tcp;
564
565         for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) {
566                 if ((tcp->flags & TCB_INUSE) == 0) {
567                         tcp->pid = pid;
568                         tcp->parent = NULL;
569                         tcp->nchildren = 0;
570                         tcp->flags = TCB_INUSE | TCB_STARTUP;
571                         tcp->outf = outf; /* Initialise to current out file */
572                         tcp->stime.tv_sec = 0;
573                         tcp->stime.tv_usec = 0;
574                         tcp->pfd = -1;
575                         nprocs++;
576                         return tcp;
577                 }
578         }
579         return NULL;
580 }
581
582 #ifdef USE_PROCFS
583 int
584 proc_open(tcp, attaching)
585 struct tcb *tcp;
586 int attaching;
587 {
588         char proc[32];
589         long arg;
590 #ifdef SVR4
591         sysset_t sc_enter, sc_exit;
592         sigset_t signals;
593         fltset_t faults;
594 #endif
595 #ifndef HAVE_POLLABLE_PROCFS
596         static int last_pfd;
597 #endif
598
599 #ifdef HAVE_MP_PROCFS
600         /* Open the process pseudo-files in /proc. */
601         sprintf(proc, "/proc/%d/ctl", tcp->pid);
602         if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
603                 perror("strace: open(\"/proc/...\", ...)");
604                 return -1;
605         }
606         if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
607                 perror("F_GETFD");
608                 return -1;
609         }
610         if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
611                 perror("F_SETFD");
612                 return -1;
613         }
614         sprintf(proc, "/proc/%d/status", tcp->pid);
615         if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
616                 perror("strace: open(\"/proc/...\", ...)");
617                 return -1;
618         }
619         if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) {
620                 perror("F_GETFD");
621                 return -1;
622         }
623         if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) {
624                 perror("F_SETFD");
625                 return -1;
626         }
627         sprintf(proc, "/proc/%d/as", tcp->pid);
628         if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
629                 perror("strace: open(\"/proc/...\", ...)");
630                 return -1;
631         }
632         if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) {
633                 perror("F_GETFD");
634                 return -1;
635         }
636         if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) {
637                 perror("F_SETFD");
638                 return -1;
639         }
640 #else
641         /* Open the process pseudo-file in /proc. */
642 #ifndef FREEBSD
643         sprintf(proc, "/proc/%d", tcp->pid);
644         if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
645 #else /* FREEBSD */
646         sprintf(proc, "/proc/%d/mem", tcp->pid);
647         if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
648 #endif /* FREEBSD */
649                 perror("strace: open(\"/proc/...\", ...)");
650                 return -1;
651         }
652         if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
653                 perror("F_GETFD");
654                 return -1;
655         }
656         if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
657                 perror("F_SETFD");
658                 return -1;
659         }
660 #endif
661 #ifdef FREEBSD
662         sprintf(proc, "/proc/%d/regs", tcp->pid);
663         if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
664                 perror("strace: open(\"/proc/.../regs\", ...)");
665                 return -1;
666         }
667         if (cflag) {
668                 sprintf(proc, "/proc/%d/status", tcp->pid);
669                 if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
670                         perror("strace: open(\"/proc/.../status\", ...)");
671                         return -1;
672                 }
673         } else
674                 tcp->pfd_status = -1;
675 #endif /* FREEBSD */
676         rebuild_pollv();
677         if (!attaching) {
678                 /*
679                  * Wait for the child to pause.  Because of a race
680                  * condition we have to poll for the event.
681                  */
682                 for (;;) {
683                         if (IOCTL_STATUS (tcp) < 0) {
684                                 perror("strace: PIOCSTATUS");
685                                 return -1;
686                         }
687                         if (tcp->status.PR_FLAGS & PR_ASLEEP)
688                             break;
689                 }
690         }
691 #ifndef FREEBSD
692         /* Stop the process so that we own the stop. */
693         if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
694                 perror("strace: PIOCSTOP");
695                 return -1;
696         }
697 #endif  
698 #ifdef PIOCSET
699         /* Set Run-on-Last-Close. */
700         arg = PR_RLC;
701         if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
702                 perror("PIOCSET PR_RLC");
703                 return -1;
704         }
705         /* Set or Reset Inherit-on-Fork. */
706         arg = PR_FORK;
707         if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
708                 perror("PIOC{SET,RESET} PR_FORK");
709                 return -1;
710         }
711 #else  /* !PIOCSET */
712 #ifndef FREEBSD 
713         if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
714                 perror("PIOCSRLC");
715                 return -1;
716         }
717         if (ioctl(tcp->pfd, followfork ? PIOCSFORK : PIOCRFORK) < 0) {
718                 perror("PIOC{S,R}FORK");
719                 return -1;
720         }
721 #else /* FREEBSD */
722         /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
723         if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
724                 perror("PIOCGFL");
725                 return -1;
726         }
727         arg &= ~PF_LINGER;
728         if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
729                 perror("PIOCSFL");
730                 return -1;
731         }
732 #endif /* FREEBSD */
733 #endif /* !PIOCSET */
734 #ifndef FREEBSD
735         /* Enable all syscall entries. */
736         prfillset(&sc_enter);
737         if (IOCTL(tcp->pfd, PIOCSENTRY, &sc_enter) < 0) {
738                 perror("PIOCSENTRY");
739                 return -1;
740         }
741         /* Enable all syscall exits. */
742         prfillset(&sc_exit);
743         if (IOCTL(tcp->pfd, PIOCSEXIT, &sc_exit) < 0) {
744                 perror("PIOSEXIT");
745                 return -1;
746         }
747         /* Enable all signals. */
748         prfillset(&signals);
749         if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
750                 perror("PIOCSTRACE");
751                 return -1;
752         }
753         /* Enable all faults. */
754         prfillset(&faults);
755         if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
756                 perror("PIOCSFAULT");
757                 return -1;
758         }
759 #else /* FREEBSD */
760         /* set events flags. */
761         arg = S_SIG | S_SCE | S_SCX ;
762         if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
763                 perror("PIOCBIS");
764                 return -1;
765         }
766 #endif /* FREEBSD */
767         if (!attaching) {
768 #ifdef MIPS
769                 /*
770                  * The SGI PRSABORT doesn't work for pause() so
771                  * we send it a caught signal to wake it up.
772                  */
773                 kill(tcp->pid, SIGINT);
774 #else /* !MIPS */
775 #ifdef PRSABORT 
776                 /* The child is in a pause(), abort it. */
777                 arg = PRSABORT;
778                 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
779                         perror("PIOCRUN");
780                         return -1;
781                 }
782 #endif          
783 #endif /* !MIPS*/
784 #ifdef FREEBSD
785                 /* wake up the child if it received the SIGSTOP */
786                 kill(tcp->pid, SIGCONT);
787 #endif          
788                 for (;;) {
789                         /* Wait for the child to do something. */
790                         if (IOCTL_WSTOP (tcp) < 0) {
791                                 perror("PIOCWSTOP");
792                                 return -1;
793                         }
794                         if (tcp->status.PR_WHY == PR_SYSENTRY) {
795                                 tcp->flags &= ~TCB_INSYSCALL;
796                                 get_scno(tcp);
797                                 if (tcp->scno == SYS_execve)
798                                         break;
799                         }
800                         /* Set it running: maybe execve will be next. */
801 #ifndef FREEBSD
802                         arg = 0;
803                         if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
804 #else /* FREEBSD */
805                         if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
806 #endif /* FREEBSD */                      
807                                 perror("PIOCRUN");
808                                 return -1;
809                         }
810 #ifdef FREEBSD
811                         /* handle the case where we "opened" the child before
812                            it did the kill -STOP */
813                         if (tcp->status.PR_WHY == PR_SIGNALLED &&
814                             tcp->status.PR_WHAT == SIGSTOP)
815                                 kill(tcp->pid, SIGCONT);
816 #endif                  
817                 }
818 #ifndef FREEBSD
819         }
820 #else /* FREEBSD */
821         } else {
822                 if (attaching < 2) { 
823                         /* We are attaching to an already running process.
824                          * Try to figure out the state of the process in syscalls,
825                          * to handle the first event well.
826                          * This is done by having a look at the "wchan" property of the
827                          * process, which tells where it is stopped (if it is). */
828                         FILE * status;
829                         char wchan[20]; /* should be enough */
830                         
831                         sprintf(proc, "/proc/%d/status", tcp->pid);
832                         status = fopen(proc, "r");
833                         if (status &&
834                             (fscanf(status, "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d"
835                                     "%*d,%*d %*d,%*d %19s", wchan) == 1) &&
836                             strcmp(wchan, "nochan") && strcmp(wchan, "spread") &&
837                             strcmp(wchan, "stopevent")) {
838                                 /* The process is asleep in the middle of a syscall.
839                                    Fake the syscall entry event */
840                                 tcp->flags &= ~(TCB_INSYSCALL|TCB_STARTUP);
841                                 tcp->status.PR_WHY = PR_SYSENTRY;
842                                 trace_syscall(tcp);
843                         }
844                         if (status)
845                                 fclose(status);
846                 } /* otherwise it's a fork being followed */
847         }
848 #endif /* FREEBSD */
849 #ifndef HAVE_POLLABLE_PROCFS
850         if (proc_poll_pipe[0] != -1)
851                 proc_poller(tcp->pfd);
852         else if (nprocs > 1) {
853                 proc_poll_open();
854                 proc_poller(last_pfd);
855                 proc_poller(tcp->pfd);
856         }
857         last_pfd = tcp->pfd;
858 #endif /* !HAVE_POLLABLE_PROCFS */
859         return 0;
860 }
861
862 #endif /* USE_PROCFS */
863
864 static struct tcb *
865 pid2tcb(pid)
866 int pid;
867 {
868         int i;
869         struct tcb *tcp;
870
871         for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) {
872                 if (pid && tcp->pid != pid)
873                         continue;
874                 if (tcp->flags & TCB_INUSE)
875                         return tcp;
876         }
877         return NULL;
878 }
879
880 #ifdef USE_PROCFS
881
882 static struct tcb *
883 pfd2tcb(pfd)
884 int pfd;
885 {
886         int i;
887         struct tcb *tcp;
888
889         for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) {
890                 if (tcp->pfd != pfd)
891                         continue;
892                 if (tcp->flags & TCB_INUSE)
893                         return tcp;
894         }
895         return NULL;
896 }
897
898 #endif /* USE_PROCFS */
899
900 void
901 droptcb(tcp)
902 struct tcb *tcp;
903 {
904         if (tcp->pid == 0)
905                 return;
906         nprocs--;
907         tcp->pid = 0;
908         tcp->flags = 0;
909         if (tcp->pfd != -1) {
910                 close(tcp->pfd);
911                 tcp->pfd = -1;
912 #ifdef FREEBSD
913                 if (tcp->pfd_reg != -1) {
914                         close(tcp->pfd_reg);
915                         tcp->pfd_reg = -1;
916                 }
917                 if (tcp->pfd_status != -1) {
918                         close(tcp->pfd_status);
919                         tcp->pfd_status = -1;
920                 }
921 #endif /* !FREEBSD */           
922 #ifdef USE_PROCFS
923                 rebuild_pollv();
924 #endif
925         }
926         if (tcp->parent != NULL) {
927                 tcp->parent->nchildren--;
928                 tcp->parent = NULL;
929         }
930 #if 0
931         if (tcp->outf != stderr)
932                 fclose(tcp->outf);
933 #endif
934         tcp->outf = 0;
935 }
936
937 #ifndef USE_PROCFS
938
939 static int
940 resume(tcp)
941 struct tcb *tcp;
942 {
943         if (tcp == NULL)
944                 return -1;
945
946         if (!(tcp->flags & TCB_SUSPENDED)) {
947                 fprintf(stderr, "PANIC: pid %u not suspended\n", tcp->pid);
948                 return -1;
949         }
950         tcp->flags &= ~TCB_SUSPENDED;
951
952         if (ptrace(PTRACE_SYSCALL, tcp->pid, (char *) 1, 0) < 0) {
953                 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
954                 return -1;
955         }
956
957         if (!qflag)
958                 fprintf(stderr, "Process %u resumed\n", tcp->pid);
959         return 0;
960 }
961
962 #endif /* !USE_PROCFS */
963
964 /* detach traced process; continue with sig */
965
966 static int
967 detach(tcp, sig)
968 struct tcb *tcp;
969 int sig;
970 {
971         int error = 0;
972 #ifdef LINUX
973         int status;
974 #endif
975
976         if (tcp->flags & TCB_BPTSET)
977                 sig = SIGKILL;
978
979 #ifdef LINUX
980         /*
981          * Linux wrongly insists the child be stopped
982          * before detaching.  Arghh.  We go through hoops
983          * to make a clean break of things.
984          */
985 #if defined(SPARC)
986 #undef PTRACE_DETACH
987 #define PTRACE_DETACH PTRACE_SUNDETACH
988 #endif
989         if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) == 0) {
990                 /* On a clear day, you can see forever. */
991         }
992         else if (errno != ESRCH) {
993                 /* Shouldn't happen. */
994                 perror("detach: ptrace(PTRACE_DETACH, ...)");
995         }
996         else if (kill(tcp->pid, 0) < 0) {
997                 if (errno != ESRCH)
998                         perror("detach: checking sanity");
999         }
1000         else if (kill(tcp->pid, SIGSTOP) < 0) {
1001                 if (errno != ESRCH)
1002                         perror("detach: stopping child");
1003         }
1004         else {
1005                 for (;;) {
1006                         if (waitpid(tcp->pid, &status, 0) < 0) {
1007                                 if (errno != ECHILD)
1008                                         perror("detach: waiting");
1009                                 break;
1010                         }
1011                         if (!WIFSTOPPED(status)) {
1012                                 /* Au revoir, mon ami. */
1013                                 break;
1014                         }
1015                         if (WSTOPSIG(status) == SIGSTOP) {
1016                                 if ((error = ptrace(PTRACE_DETACH,
1017                                     tcp->pid, (char *) 1, sig)) < 0) {
1018                                         if (errno != ESRCH)
1019                                                 perror("detach: ptrace(PTRACE_DETACH, ...)");
1020                                         /* I died trying. */
1021                                 }
1022                                 break;
1023                         }
1024                         if ((error = ptrace(PTRACE_CONT, tcp->pid, (char *) 1,
1025                             WSTOPSIG(status) == SIGTRAP ?
1026                             0 : WSTOPSIG(status))) < 0) {
1027                                 if (errno != ESRCH)
1028                                         perror("detach: ptrace(PTRACE_CONT, ...)");
1029                                 break;
1030                         }
1031                 }
1032         }
1033 #endif /* LINUX */
1034
1035 #if defined(SUNOS4)
1036         /* PTRACE_DETACH won't respect `sig' argument, so we post it here. */
1037         if (sig && kill(tcp->pid, sig) < 0)
1038                 perror("detach: kill");
1039         sig = 0;
1040         if ((error = ptrace(PTRACE_DETACH, tcp->pid, (char *) 1, sig)) < 0)
1041                 perror("detach: ptrace(PTRACE_DETACH, ...)");
1042 #endif /* SUNOS4 */
1043
1044 #ifndef USE_PROCFS
1045         if (waiting_parent(tcp))
1046                 error = resume(tcp->parent);
1047 #endif /* !USE_PROCFS */
1048
1049         if (!qflag)
1050                 fprintf(stderr, "Process %u detached\n", tcp->pid);
1051
1052         droptcb(tcp);
1053         return error;
1054 }
1055
1056 #ifdef USE_PROCFS
1057
1058 static void
1059 reaper(sig)
1060 int sig;
1061 {
1062         int pid;
1063         int status;
1064
1065         while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
1066 #if 0
1067                 struct tcb *tcp;
1068
1069                 tcp = pid2tcb(pid);
1070                 if (tcp)
1071                         droptcb(tcp);
1072 #endif
1073         }
1074 }
1075
1076 #endif /* USE_PROCFS */
1077
1078 static void
1079 cleanup()
1080 {
1081         int i;
1082         struct tcb *tcp;
1083
1084         for (i = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) {
1085                 if (!(tcp->flags & TCB_INUSE))
1086                         continue;
1087                 if (debug)
1088                         fprintf(stderr,
1089                                 "cleanup: looking at pid %u\n", tcp->pid);
1090                 if (tcp_last &&
1091                     (!outfname || followfork < 2 || tcp_last == tcp)) {
1092                         tprintf(" <unfinished ...>\n");
1093                         tcp_last = NULL;
1094                 }
1095                 if (tcp->flags & TCB_ATTACHED)
1096                         detach(tcp, 0);
1097                 else {
1098                         kill(tcp->pid, SIGCONT);
1099                         kill(tcp->pid, SIGTERM);
1100                 }
1101         }
1102         if (cflag)
1103                 call_summary(outf);
1104 }
1105
1106 static void
1107 interrupt(sig)
1108 int sig;
1109 {
1110         interrupted = 1;
1111 }
1112
1113 #ifndef HAVE_STRERROR
1114
1115 #ifndef SYS_ERRLIST_DECLARED
1116 extern int sys_nerr;
1117 extern char *sys_errlist[];
1118 #endif /* SYS_ERRLIST_DECLARED */
1119
1120 const char *
1121 strerror(errno)
1122 int errno;
1123 {
1124         static char buf[64];
1125
1126         if (errno < 1 || errno >= sys_nerr) {
1127                 sprintf(buf, "Unknown error %d", errno);
1128                 return buf;
1129         }
1130         return sys_errlist[errno];
1131 }
1132
1133 #endif /* HAVE_STERRROR */
1134
1135 #ifndef HAVE_STRSIGNAL
1136
1137 #ifndef SYS_SIGLIST_DECLARED
1138 #ifdef HAVE__SYS_SIGLIST
1139         extern char *_sys_siglist[];
1140 #else
1141         extern char *sys_siglist[];
1142 #endif
1143 #endif /* SYS_SIGLIST_DECLARED */
1144
1145 const char *
1146 strsignal(sig)
1147 int sig;
1148 {
1149         static char buf[64];
1150
1151         if (sig < 1 || sig >= NSIG) {
1152                 sprintf(buf, "Unknown signal %d", sig);
1153                 return buf;
1154         }
1155 #ifdef HAVE__SYS_SIGLIST
1156         return _sys_siglist[sig];
1157 #else
1158         return sys_siglist[sig];
1159 #endif
1160 }
1161
1162 #endif /* HAVE_STRSIGNAL */
1163
1164 #ifdef USE_PROCFS
1165
1166 static void
1167 rebuild_pollv()
1168 {
1169         int i, j;
1170         struct tcb *tcp;
1171
1172         for (i = j = 0, tcp = tcbtab; i < MAX_PROCS; i++, tcp++) {
1173                 if (!(tcp->flags & TCB_INUSE))
1174                         continue;
1175                 pollv[j].fd = tcp->pfd;
1176                 pollv[j].events = POLLWANT;
1177                 j++;
1178         }
1179         if (j != nprocs) {
1180                 fprintf(stderr, "strace: proc miscount\n");
1181                 exit(1);
1182         }
1183 }
1184
1185 #ifndef HAVE_POLLABLE_PROCFS
1186
1187 static void
1188 proc_poll_open()
1189 {
1190         int arg;
1191         int i;
1192
1193         if (pipe(proc_poll_pipe) < 0) {
1194                 perror("pipe");
1195                 exit(1);
1196         }
1197         for (i = 0; i < 2; i++) {
1198                 if ((arg = fcntl(proc_poll_pipe[i], F_GETFD)) < 0) {
1199                         perror("F_GETFD");
1200                         exit(1);
1201                 }
1202                 if (fcntl(proc_poll_pipe[i], F_SETFD, arg|FD_CLOEXEC) < 0) {
1203                         perror("F_SETFD");
1204                         exit(1);
1205                 }
1206         }
1207 }
1208
1209 static int
1210 proc_poll(pollv, nfds, timeout)
1211 struct pollfd *pollv;
1212 int nfds;
1213 int timeout;
1214 {
1215         int i;
1216         int n;
1217         struct proc_pollfd pollinfo;
1218
1219         if ((n = read(proc_poll_pipe[0], &pollinfo, sizeof(pollinfo))) < 0)
1220                 return n;
1221         if (n != sizeof(struct proc_pollfd)) {
1222                 fprintf(stderr, "panic: short read: %d\n", n);
1223                 exit(1);
1224         }
1225         for (i = 0; i < nprocs; i++) {
1226                 if (pollv[i].fd == pollinfo.fd)
1227                         pollv[i].revents = pollinfo.revents;
1228                 else
1229                         pollv[i].revents = 0;
1230         }
1231         poller_pid = pollinfo.pid;
1232         return 1;
1233 }
1234
1235 static void
1236 wakeup_handler(sig)
1237 int sig;
1238 {
1239 }
1240
1241 static void
1242 proc_poller(pfd)
1243 int pfd;
1244 {
1245         struct proc_pollfd pollinfo;
1246         struct sigaction sa;
1247         sigset_t blocked_set, empty_set;
1248         int i;
1249         int n;
1250         struct rlimit rl;
1251 #ifdef FREEBSD
1252         struct procfs_status pfs;
1253 #endif /* FREEBSD */
1254
1255         switch (fork()) {
1256         case -1:
1257                 perror("fork");
1258                 _exit(0);
1259         case 0:
1260                 break;
1261         default:
1262                 return;
1263         }
1264
1265         sa.sa_handler = interactive ? SIG_DFL : SIG_IGN;
1266         sa.sa_flags = 0;
1267         sigemptyset(&sa.sa_mask);
1268         sigaction(SIGHUP, &sa, NULL);
1269         sigaction(SIGINT, &sa, NULL);
1270         sigaction(SIGQUIT, &sa, NULL);
1271         sigaction(SIGPIPE, &sa, NULL);
1272         sigaction(SIGTERM, &sa, NULL);
1273         sa.sa_handler = wakeup_handler;
1274         sigaction(SIGUSR1, &sa, NULL);
1275         sigemptyset(&blocked_set);
1276         sigaddset(&blocked_set, SIGUSR1);
1277         sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1278         sigemptyset(&empty_set);
1279
1280         if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1281                 perror("getrlimit(RLIMIT_NOFILE, ...)");
1282                 _exit(0);
1283         }
1284         n = rl.rlim_cur;
1285         for (i = 0; i < n; i++) {
1286                 if (i != pfd && i != proc_poll_pipe[1])
1287                         close(i);
1288         }
1289
1290         pollinfo.fd = pfd;
1291         pollinfo.pid = getpid();
1292         for (;;) {
1293 #ifndef FREEBSD
1294                 if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
1295 #else /* FREEBSD */
1296                 if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
1297 #endif /* FREEBSD */
1298                 {
1299                         switch (errno) {
1300                         case EINTR:
1301                                 continue;
1302                         case EBADF:
1303                                 pollinfo.revents = POLLERR;
1304                                 break;
1305                         case ENOENT:
1306                                 pollinfo.revents = POLLHUP;
1307                                 break;
1308                         default:
1309                                 perror("proc_poller: PIOCWSTOP");
1310                         }
1311                         write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1312                         _exit(0);
1313                 }
1314                 pollinfo.revents = POLLWANT;
1315                 write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
1316                 sigsuspend(&empty_set);
1317         }
1318 }
1319
1320 #endif /* !HAVE_POLLABLE_PROCFS */
1321
1322 static int
1323 choose_pfd()
1324 {
1325         int i, j;
1326         struct tcb *tcp;
1327
1328         static int last;
1329
1330         if (followfork < 2 &&
1331             last < nprocs && (pollv[last].revents & POLLWANT)) {
1332                 /*
1333                  * The previous process is ready to run again.  We'll
1334                  * let it do so if it is currently in a syscall.  This
1335                  * heuristic improves the readability of the trace.
1336                  */
1337                 tcp = pfd2tcb(pollv[last].fd);
1338                 if (tcp && (tcp->flags & TCB_INSYSCALL))
1339                         return pollv[last].fd;
1340         }
1341
1342         for (i = 0; i < nprocs; i++) {
1343                 /* Let competing children run round robin. */
1344                 j = (i + last + 1) % nprocs;
1345                 if (pollv[j].revents & (POLLHUP | POLLERR)) {
1346                         tcp = pfd2tcb(pollv[j].fd);
1347                         if (!tcp) {
1348                                 fprintf(stderr, "strace: lost proc\n");
1349                                 exit(1);
1350                         }
1351                         droptcb(tcp);
1352                         return -1;
1353                 }
1354                 if (pollv[j].revents & POLLWANT) {
1355                         last = j;
1356                         return pollv[j].fd;
1357                 }
1358         }
1359         fprintf(stderr, "strace: nothing ready\n");
1360         exit(1);
1361 }
1362
1363 static int
1364 trace()
1365 {
1366 #ifdef POLL_HACK
1367         struct tcb *in_syscall;
1368 #endif
1369         struct tcb *tcp;
1370         int pfd;
1371         int what;
1372         int ioctl_result = 0, ioctl_errno = 0;
1373         long arg;
1374
1375         for (;;) {
1376                 if (interactive)
1377                         sigprocmask(SIG_SETMASK, &empty_set, NULL);
1378
1379                 if (nprocs == 0)
1380                         break;
1381
1382                 switch (nprocs) {
1383                 case 1:
1384 #ifndef HAVE_POLLABLE_PROCFS
1385                         if (proc_poll_pipe[0] == -1) {
1386 #endif
1387                                 tcp = pid2tcb(0);
1388                                 if (!tcp)
1389                                         continue;
1390                                 pfd = tcp->pfd;
1391                                 if (pfd == -1)
1392                                         continue;
1393                                 break;
1394 #ifndef HAVE_POLLABLE_PROCFS
1395                         }
1396                         /* fall through ... */
1397 #endif /* !HAVE_POLLABLE_PROCFS */
1398                 default:
1399 #ifdef HAVE_POLLABLE_PROCFS
1400 #ifdef POLL_HACK
1401                         /* On some systems (e.g. UnixWare) we get too much ugly
1402                            "unfinished..." stuff when multiple proceses are in
1403                            syscalls.  Here's a nasty hack */
1404                     
1405                         if (in_syscall) {
1406                                 struct pollfd pv;
1407                                 tcp = in_syscall;
1408                                 in_syscall = NULL;
1409                                 pv.fd = tcp->pfd;
1410                                 pv.events = POLLWANT;
1411                                 if ((what = poll (&pv, 1, 1)) < 0) {
1412                                         if (interrupted)
1413                                                 return 0;
1414                                         continue;
1415                                 }
1416                                 else if (what == 1 && pv.revents & POLLWANT) {
1417                                         goto FOUND;
1418                                 }
1419                         }
1420 #endif
1421
1422                         if (poll(pollv, nprocs, INFTIM) < 0) {
1423                                 if (interrupted)
1424                                         return 0;
1425                                 continue;
1426                         }
1427 #else /* !HAVE_POLLABLE_PROCFS */
1428                         if (proc_poll(pollv, nprocs, INFTIM) < 0) {
1429                                 if (interrupted)
1430                                         return 0;
1431                                 continue;
1432                         }
1433 #endif /* !HAVE_POLLABLE_PROCFS */
1434                         pfd = choose_pfd();
1435                         if (pfd == -1)
1436                                 continue;
1437                         break;
1438                 }
1439
1440                 /* Look up `pfd' in our table. */
1441                 if ((tcp = pfd2tcb(pfd)) == NULL) {
1442                         fprintf(stderr, "unknown pfd: %u\n", pfd);
1443                         exit(1);
1444                 }
1445         FOUND:
1446                 /* Get the status of the process. */
1447                 if (!interrupted) {
1448 #ifndef FREEBSD
1449                         ioctl_result = IOCTL_WSTOP (tcp);
1450 #else /* FREEBSD */
1451                         /* Thanks to some scheduling mystery, the first poller
1452                            sometimes waits for the already processed end of fork
1453                            event. Doing a non blocking poll here solves the problem. */
1454                         if (proc_poll_pipe[0] != -1)
1455                                 ioctl_result = IOCTL_STATUS (tcp);
1456                         else
1457                                 ioctl_result = IOCTL_WSTOP (tcp);
1458 #endif /* FREEBSD */                      
1459                         ioctl_errno = errno;
1460 #ifndef HAVE_POLLABLE_PROCFS
1461                         if (proc_poll_pipe[0] != -1) {
1462                                 if (ioctl_result < 0)
1463                                         kill(poller_pid, SIGKILL);
1464                                 else
1465                                         kill(poller_pid, SIGUSR1);
1466                         }
1467 #endif /* !HAVE_POLLABLE_PROCFS */
1468                 }
1469                 if (interrupted)
1470                         return 0;
1471
1472                 if (interactive)
1473                         sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1474
1475                 if (ioctl_result < 0) {
1476                         /* Find out what happened if it failed. */
1477                         switch (ioctl_errno) {
1478                         case EINTR:
1479                         case EBADF:
1480                                 continue;
1481 #ifdef FREEBSD
1482                         case ENOTTY:
1483 #endif                    
1484                         case ENOENT:
1485                                 droptcb(tcp);
1486                                 continue;
1487                         default:
1488                                 perror("PIOCWSTOP");
1489                                 exit(1);
1490                         }
1491                 }
1492
1493 #ifdef FREEBSD
1494                 if ((tcp->flags & TCB_STARTUP) && (tcp->status.PR_WHY == PR_SYSEXIT)) {
1495                         /* discard first event for a syscall we never entered */
1496                         IOCTL (tcp->pfd, PIOCRUN, 0);
1497                         continue;
1498                 }
1499 #endif          
1500                 
1501                 /* clear the just started flag */
1502                 tcp->flags &= ~TCB_STARTUP;
1503
1504                 /* set current output file */
1505                 outf = tcp->outf;
1506
1507                 if (cflag) {
1508                         struct timeval stime;
1509 #ifdef FREEBSD
1510                         char buf[1024];
1511                         int len;
1512
1513                         if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
1514                                 buf[len] = '\0';
1515                                 sscanf(buf,
1516                                        "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
1517                                        &stime.tv_sec, &stime.tv_usec);
1518                         } else
1519                                 stime.tv_sec = stime.tv_usec = 0;
1520 #else /* !FREEBSD */                    
1521                         stime.tv_sec = tcp->status.pr_stime.tv_sec;
1522                         stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
1523 #endif /* !FREEBSD */
1524                         tv_sub(&tcp->dtime, &stime, &tcp->stime);
1525                         tcp->stime = stime;
1526                 }
1527                 what = tcp->status.PR_WHAT;
1528                 switch (tcp->status.PR_WHY) {
1529 #ifndef FREEBSD
1530                 case PR_REQUESTED:
1531                         if (tcp->status.PR_FLAGS & PR_ASLEEP) {
1532                                 tcp->status.PR_WHY = PR_SYSENTRY;
1533                                 if (trace_syscall(tcp) < 0) {
1534                                         fprintf(stderr, "syscall trouble\n");
1535                                         exit(1);
1536                                 }
1537                         }
1538                         break;
1539 #endif /* !FREEBSD */
1540                 case PR_SYSENTRY:
1541 #ifdef POLL_HACK
1542                         in_syscall = tcp;
1543 #endif
1544                 case PR_SYSEXIT:
1545                         if (trace_syscall(tcp) < 0) {
1546                                 fprintf(stderr, "syscall trouble\n");
1547                                 exit(1);
1548                         }
1549                         break;
1550                 case PR_SIGNALLED:
1551                         if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) {
1552                                 printleader(tcp);
1553                                 tprintf("--- %s (%s) ---",
1554                                         signame(what), strsignal(what));
1555                                 printtrailer(tcp);
1556                         }
1557                         break;
1558                 case PR_FAULTED:
1559                         if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
1560                                 printleader(tcp);
1561                                 tprintf("=== FAULT %d ===", what);
1562                                 printtrailer(tcp);
1563                         }
1564                         break;
1565 #ifdef FREEBSD
1566                 case 0: /* handle case we polled for nothing */
1567                         continue;
1568 #endif                  
1569                 default:
1570                         fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
1571                         exit(1);
1572                         break;
1573                 }
1574                 arg = 0;
1575 #ifndef FREEBSD         
1576                 if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
1577 #else             
1578                 if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
1579 #endif            
1580                         perror("PIOCRUN");
1581                         exit(1);
1582                 }
1583         }
1584         return 0;
1585 }
1586
1587 #else /* !USE_PROCFS */
1588
1589 static int
1590 trace()
1591 {
1592         int pid;
1593         int wait_errno;
1594         int status;
1595         struct tcb *tcp;
1596 #ifdef LINUX
1597         struct rusage ru;
1598 #endif /* LINUX */
1599
1600         while (nprocs != 0) {
1601                 if (interactive)
1602                         sigprocmask(SIG_SETMASK, &empty_set, NULL);
1603 #ifdef LINUX
1604                 pid = wait4(-1, &status, 0, cflag ? &ru : NULL);
1605 #endif /* LINUX */
1606 #ifdef SUNOS4
1607                 pid = wait(&status);
1608 #endif /* SUNOS4 */
1609                 wait_errno = errno;
1610                 if (interactive)
1611                         sigprocmask(SIG_BLOCK, &blocked_set, NULL);
1612
1613                 if (interrupted)
1614                         return 0;
1615
1616                 if (pid == -1) {
1617                         switch (wait_errno) {
1618                         case EINTR:
1619                                 continue;
1620                         case ECHILD:
1621                                 /*
1622                                  * We would like to verify this case
1623                                  * but sometimes a race in Solbourne's
1624                                  * version of SunOS sometimes reports
1625                                  * ECHILD before sending us SIGCHILD.
1626                                  */
1627 #if 0
1628                                 if (nprocs == 0)
1629                                         return 0;
1630                                 fprintf(stderr, "strace: proc miscount\n");
1631                                 exit(1);
1632 #endif
1633                                 return 0;
1634                         default:
1635                                 errno = wait_errno;
1636                                 perror("strace: wait");
1637                                 return -1;
1638                         }
1639                 }
1640                 if (debug)
1641                         fprintf(stderr, " [wait(%#x) = %u]\n", status, pid);
1642
1643                 /* Look up `pid' in our table. */
1644                 if ((tcp = pid2tcb(pid)) == NULL) {
1645 #if 0 /* XXX davidm */ /* WTA: disabled again */
1646                         struct tcb *tcpchild;
1647
1648                         if ((tcpchild = alloctcb(pid)) == NULL) {
1649                                 fprintf(stderr, " [tcb table full]\n");
1650                                 kill(pid, SIGKILL); /* XXX */
1651                                 return 0;
1652                         }
1653                         tcpchild->flags |= TCB_ATTACHED;
1654                         newoutf(tcpchild);
1655                         tcp->nchildren++;
1656                         if (!qflag)
1657                                 fprintf(stderr, "Process %d attached\n", pid);
1658 #else
1659                         fprintf(stderr, "unknown pid: %u\n", pid);
1660                         if (WIFSTOPPED(status))
1661                                 ptrace(PTRACE_CONT, pid, (char *) 1, 0);
1662                         exit(1);
1663 #endif
1664                 }
1665                 /* set current output file */
1666                 outf = tcp->outf;
1667                 if (cflag) {
1668 #ifdef LINUX
1669                         tv_sub(&tcp->dtime, &ru.ru_stime, &tcp->stime);
1670                         tcp->stime = ru.ru_stime;
1671 #endif /* !LINUX */
1672                 }
1673
1674                 if (tcp->flags & TCB_SUSPENDED) {
1675                         /*
1676                          * Apparently, doing any ptrace() call on a stopped
1677                          * process, provokes the kernel to report the process
1678                          * status again on a subsequent wait(), even if the
1679                          * process has not been actually restarted.
1680                          * Since we have inspected the arguments of suspended
1681                          * processes we end up here testing for this case.
1682                          */
1683                         continue;
1684                 }
1685                 if (WIFSIGNALED(status)) {
1686                         if (!cflag
1687                             && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
1688                                 printleader(tcp);
1689                                 tprintf("+++ killed by %s +++",
1690                                         signame(WTERMSIG(status)));
1691                                 printtrailer(tcp);
1692                         }
1693                         droptcb(tcp);
1694                         continue;
1695                 }
1696                 if (WIFEXITED(status)) {
1697                         if (debug)
1698                                 fprintf(stderr, "pid %u exited\n", pid);
1699                         if (tcp->flags & TCB_ATTACHED)
1700                                 fprintf(stderr,
1701                                         "PANIC: attached pid %u exited\n",
1702                                         pid);
1703                         droptcb(tcp);
1704                         continue;
1705                 }
1706                 if (!WIFSTOPPED(status)) {
1707                         fprintf(stderr, "PANIC: pid %u not stopped\n", pid);
1708                         droptcb(tcp);
1709                         continue;
1710                 }
1711                 if (debug)
1712                         fprintf(stderr, "pid %u stopped, [%s]\n",
1713                                 pid, signame(WSTOPSIG(status)));
1714
1715                 if (tcp->flags & TCB_STARTUP) {
1716                         /*
1717                          * This flag is there to keep us in sync.
1718                          * Next time this process stops it should
1719                          * really be entering a system call.
1720                          */
1721                         tcp->flags &= ~TCB_STARTUP;
1722                         if (tcp->flags & TCB_ATTACHED) {
1723                                 /*
1724                                  * Interestingly, the process may stop
1725                                  * with STOPSIG equal to some other signal
1726                                  * than SIGSTOP if we happend to attach
1727                                  * just before the process takes a signal.
1728                                  */
1729                                 if (!WIFSTOPPED(status)) {
1730                                         fprintf(stderr,
1731                                                 "pid %u not stopped\n", pid);
1732                                         detach(tcp, WSTOPSIG(status));
1733                                         continue;
1734                                 }
1735                         }
1736                         else {
1737 #ifdef SUNOS4
1738                                 /* A child of us stopped at exec */
1739                                 if (WSTOPSIG(status) == SIGTRAP && followvfork)
1740                                         fixvfork(tcp);
1741 #endif /* SUNOS4 */
1742                         }
1743                         if (tcp->flags & TCB_BPTSET) {
1744                                 if (clearbpt(tcp) < 0) /* Pretty fatal */ {
1745                                         droptcb(tcp);
1746                                         cleanup();
1747                                         return -1;
1748                                 }
1749                         }
1750                         goto tracing;
1751                 }
1752
1753                 if (WSTOPSIG(status) != SIGTRAP) {
1754                         if (WSTOPSIG(status) == SIGSTOP &&
1755                                         (tcp->flags & TCB_SIGTRAPPED)) {
1756                                 /*
1757                                  * Trapped attempt to block SIGTRAP
1758                                  * Hope we are back in control now.
1759                                  */
1760                                 tcp->flags &= ~(TCB_INSYSCALL | TCB_SIGTRAPPED);
1761                                 if (ptrace(PTRACE_SYSCALL,
1762                                                 pid, (char *) 1, 0) < 0) {
1763                                         perror("trace: ptrace(PTRACE_SYSCALL, ...)");
1764                                         cleanup();
1765                                         return -1;
1766                                 }
1767                                 continue;
1768                         }
1769                         if (!cflag
1770                             && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
1771                                 printleader(tcp);
1772                                 tprintf("--- %s (%s) ---",
1773                                         signame(WSTOPSIG(status)),
1774                                         strsignal(WSTOPSIG(status)));
1775                                 printtrailer(tcp);
1776                         }
1777                         if ((tcp->flags & TCB_ATTACHED) &&
1778                                 !sigishandled(tcp, WSTOPSIG(status))) {
1779                                 detach(tcp, WSTOPSIG(status));
1780                                 continue;
1781                         }
1782                         if (ptrace(PTRACE_SYSCALL, pid, (char *) 1,
1783                                    WSTOPSIG(status)) < 0) {
1784                                 perror("trace: ptrace(PTRACE_SYSCALL, ...)");
1785                                 cleanup();
1786                                 return -1;
1787                         }
1788                         tcp->flags &= ~TCB_SUSPENDED;
1789                         continue;
1790                 }
1791                 if (trace_syscall(tcp) < 0) {
1792                         if (tcp->flags & TCB_ATTACHED)
1793                                 detach(tcp, 0);
1794                         else {
1795                                 ptrace(PTRACE_KILL,
1796                                         tcp->pid, (char *) 1, SIGTERM);
1797                                 droptcb(tcp);
1798                         }
1799                         continue;
1800                 }
1801                 if (tcp->flags & TCB_EXITING) {
1802                         if (tcp->flags & TCB_ATTACHED)
1803                                 detach(tcp, 0);
1804                         else if (ptrace(PTRACE_CONT, pid, (char *) 1, 0) < 0) {
1805                                 perror("strace: ptrace(PTRACE_CONT, ...)");
1806                                 cleanup();
1807                                 return -1;
1808                         }
1809                         continue;
1810                 }
1811                 if (tcp->flags & TCB_SUSPENDED) {
1812                         if (!qflag)
1813                                 fprintf(stderr, "Process %u suspended\n", pid);
1814                         continue;
1815                 }
1816         tracing:
1817                 if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
1818                         perror("trace: ptrace(PTRACE_SYSCALL, ...)");
1819                         cleanup();
1820                         return -1;
1821                 }
1822         }
1823         return 0;
1824 }
1825
1826 #endif /* !USE_PROCFS */
1827
1828 static int curcol;
1829
1830 #ifdef __STDC__
1831 #include <stdarg.h>
1832 #define VA_START(a, b) va_start(a, b)
1833 #else
1834 #include <varargs.h>
1835 #define VA_START(a, b) va_start(a)
1836 #endif
1837
1838 void
1839 #ifdef __STDC__
1840 tprintf(const char *fmt, ...)
1841 #else
1842 tprintf(fmt, va_alist)
1843 char *fmt;
1844 va_dcl
1845 #endif
1846 {
1847         va_list args;
1848
1849         VA_START(args, fmt);
1850         if (outf)
1851                 curcol += vfprintf(outf, fmt, args);
1852         va_end(args);
1853         return;
1854 }
1855
1856 void
1857 printleader(tcp)
1858 struct tcb *tcp;
1859 {
1860         if (tcp_last && (!outfname || followfork < 2 || tcp_last == tcp)) {
1861                 tcp_last->flags |= TCB_REPRINT;
1862                 tprintf(" <unfinished ...>\n");
1863         }
1864         curcol = 0;
1865         if ((followfork == 1 || pflag_seen > 1) && outfname)
1866                 tprintf("%-5d ", tcp->pid);
1867         else if (nprocs > 1 && !outfname)
1868                 tprintf("[pid %5u] ", tcp->pid);
1869         if (tflag) {
1870                 char str[sizeof("HH:MM:SS")];
1871                 struct timeval tv, dtv;
1872                 static struct timeval otv;
1873
1874                 gettimeofday(&tv, NULL);
1875                 if (rflag) {
1876                         if (otv.tv_sec == 0)
1877                                 otv = tv;
1878                         tv_sub(&dtv, &tv, &otv);
1879                         tprintf("%6ld.%06ld ",
1880                                 (long) dtv.tv_sec, (long) dtv.tv_usec);
1881                         otv = tv;
1882                 }
1883                 else if (tflag > 2) {
1884                         tprintf("%ld.%06ld ",
1885                                 (long) tv.tv_sec, (long) tv.tv_usec);
1886                 }
1887                 else {
1888                         time_t local = tv.tv_sec;
1889                         strftime(str, sizeof(str), "%T", localtime(&local));
1890                         if (tflag > 1)
1891                                 tprintf("%s.%06ld ", str, (long) tv.tv_usec);
1892                         else
1893                                 tprintf("%s ", str);
1894                 }
1895         }
1896         if (iflag)
1897                 printcall(tcp);
1898 }
1899
1900 void
1901 tabto(col)
1902 int col;
1903 {
1904         if (curcol < col)
1905                 tprintf("%*s", col - curcol, "");
1906 }
1907
1908 void
1909 printtrailer(tcp)
1910 struct tcb *tcp;
1911 {
1912         tprintf("\n");
1913         tcp_last = NULL;
1914 }
1915
1916 #ifdef HAVE_MP_PROCFS
1917
1918 int mp_ioctl (int fd, int cmd, void *arg, int size) {
1919
1920         struct iovec iov[2];
1921         int n = 1;
1922         
1923         iov[0].iov_base = &cmd;
1924         iov[0].iov_len = sizeof cmd;
1925         if (arg) {
1926                 ++n;
1927                 iov[1].iov_base = arg;
1928                 iov[1].iov_len = size;
1929         }
1930         
1931         return writev (fd, iov, n);
1932 }
1933
1934 #endif