blob: 5408fb6023c1b5f22ddb072797ad8b07ad158bd3 [file] [log] [blame]
Juan Cespedesf7281232009-06-25 16:11:21 +02001#include "config.h"
Juan Cespedesf7281232009-06-25 16:11:21 +02002
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <string.h>
7#include <errno.h>
8#include <sys/param.h>
9#include <signal.h>
10#include <sys/wait.h>
11
12#include "common.h"
Juan Cespedesf7281232009-06-25 16:11:21 +020013
14char *command = NULL;
15Process *list_of_processes = NULL;
16
17int exiting = 0; /* =1 if a SIGINT or SIGTERM has been received */
18
19static void
20signal_alarm(int sig) {
21 Process *tmp = list_of_processes;
22
23 signal(SIGALRM, SIG_DFL);
24 while (tmp) {
25 struct opt_p_t *tmp2 = opt_p;
26 while (tmp2) {
27 if (tmp->pid == tmp2->pid) {
28 tmp = tmp->next;
29 if (!tmp) {
30 return;
31 }
32 tmp2 = opt_p;
33 continue;
34 }
35 tmp2 = tmp2->next;
36 }
37 debug(2, "Sending SIGSTOP to process %u\n", tmp->pid);
38 kill(tmp->pid, SIGSTOP);
39 tmp = tmp->next;
40 }
41}
42
43static void
44signal_exit(int sig) {
45 exiting = 1;
46 debug(1, "Received interrupt signal; exiting...");
47 signal(SIGINT, SIG_IGN);
48 signal(SIGTERM, SIG_IGN);
49 signal(SIGALRM, signal_alarm);
50 if (opt_p) {
51 struct opt_p_t *tmp = opt_p;
52 while (tmp) {
53 debug(2, "Sending SIGSTOP to process %u\n", tmp->pid);
54 kill(tmp->pid, SIGSTOP);
55 tmp = tmp->next;
56 }
57 }
58 alarm(1);
59}
60
61static void
62normal_exit(void) {
63 output_line(0, 0);
64 if (options.summary) {
65 show_summary();
66 }
67 if (options.output) {
68 fclose(options.output);
69 options.output = NULL;
70 }
71}
72
73void
74ltrace_init(int argc, char **argv) {
75 struct opt_p_t *opt_p_tmp;
76
77 atexit(normal_exit);
78 signal(SIGINT, signal_exit); /* Detach processes when interrupted */
79 signal(SIGTERM, signal_exit); /* ... or killed */
80
81 argv = process_options(argc, argv);
82 while (opt_F) {
83 /* If filename begins with ~, expand it to the user's home */
84 /* directory. This does not correctly handle ~yoda, but that */
85 /* isn't as bad as it seems because the shell will normally */
86 /* be doing the expansion for us; only the hardcoded */
87 /* ~/.ltrace.conf should ever use this code. */
88 if (opt_F->filename[0] == '~') {
89 char path[PATH_MAX];
90 char *home_dir = getenv("HOME");
91 if (home_dir) {
92 strncpy(path, home_dir, PATH_MAX - 1);
93 path[PATH_MAX - 1] = '\0';
94 strncat(path, opt_F->filename + 1,
95 PATH_MAX - strlen(path) - 1);
96 read_config_file(path);
97 }
98 } else {
99 read_config_file(opt_F->filename);
100 }
101 opt_F = opt_F->next;
102 }
103 if (opt_e) {
104 struct opt_e_t *tmp = opt_e;
105 while (tmp) {
106 debug(1, "Option -e: %s\n", tmp->name);
107 tmp = tmp->next;
108 }
109 }
110 if (command) {
Petr Machatac7585b62011-07-08 22:58:12 +0200111 open_program(command, execute_program(command, argv), 0);
Juan Cespedesf7281232009-06-25 16:11:21 +0200112 }
113 opt_p_tmp = opt_p;
114 while (opt_p_tmp) {
Juan Cespedes8d1b92b2009-07-03 10:39:34 +0200115 open_pid(opt_p_tmp->pid);
Juan Cespedesf7281232009-06-25 16:11:21 +0200116 opt_p_tmp = opt_p_tmp->next;
117 }
118}
119
Juan Cespedes61da3372009-07-03 11:55:44 +0200120static int num_ltrace_callbacks[EVENT_MAX];
121static callback_func * ltrace_callbacks[EVENT_MAX];
Juan Cespedes40dc6352009-06-25 19:54:10 +0200122
123void
Juan Cespedes61da3372009-07-03 11:55:44 +0200124ltrace_add_callback(callback_func func, Event_type type) {
125 ltrace_callbacks[type] = realloc(ltrace_callbacks[type], (num_ltrace_callbacks[type]+1)*sizeof(callback_func));
126 ltrace_callbacks[type][num_ltrace_callbacks[type]++] = func;
127}
Juan Cespedes40dc6352009-06-25 19:54:10 +0200128
Juan Cespedes61da3372009-07-03 11:55:44 +0200129static void
130dispatch_callbacks(Event * ev) {
131 int i;
132 /* Ignoring case 1: signal into a dying tracer */
133 if (ev->type==EVENT_SIGNAL &&
134 exiting && ev->e_un.signum == SIGSTOP) {
135 return;
136 }
137 /* Ignoring case 2: process being born before a clone event */
138 if (ev->proc && ev->proc->state == STATE_IGNORED) {
139 return;
140 }
141 for (i=0; i<num_ltrace_callbacks[ev->type]; i++) {
142 ltrace_callbacks[ev->type][i](ev);
Juan Cespedes40dc6352009-06-25 19:54:10 +0200143 }
144}
145
Juan Cespedesf7281232009-06-25 16:11:21 +0200146void
147ltrace_main(void) {
Juan Cespedes40dc6352009-06-25 19:54:10 +0200148 Event * ev;
Juan Cespedesf7281232009-06-25 16:11:21 +0200149 while (1) {
Juan Cespedes40dc6352009-06-25 19:54:10 +0200150 ev = next_event();
Juan Cespedes61da3372009-07-03 11:55:44 +0200151 dispatch_callbacks(ev);
Juan Cespedes03192f82009-07-03 10:16:22 +0200152 handle_event(ev);
Juan Cespedesf7281232009-06-25 16:11:21 +0200153 }
154}