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