main.c revision 3df476b28e4a9cdb43cf29fff8e89481310eb30d
1#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
8#include <string.h>
9#include <errno.h>
10#include <sys/param.h>
11#include <signal.h>
12#include <sys/wait.h>
13
14#include "main.h"
15#include "output.h"
16#include "read_config_file.h"
17#include "options.h"
18#include "debug.h"
19
20char *command = NULL;
21Process *list_of_processes = NULL;
22
23int exiting = 0;		/* =1 if a SIGINT or SIGTERM has been received */
24
25static void
26signal_alarm(int sig) {
27	Process *tmp = list_of_processes;
28
29	signal(SIGALRM, SIG_DFL);
30	while (tmp) {
31		struct opt_p_t *tmp2 = opt_p;
32		while (tmp2) {
33			if (tmp->pid == tmp2->pid) {
34				tmp = tmp->next;
35				if (!tmp) {
36					return;
37				}
38				tmp2 = opt_p;
39				continue;
40			}
41			tmp2 = tmp2->next;
42		}
43		debug(2, "Sending SIGSTOP to process %u\n", tmp->pid);
44		kill(tmp->pid, SIGSTOP);
45		tmp = tmp->next;
46	}
47}
48
49static void
50signal_exit(int sig) {
51	exiting = 1;
52	debug(1, "Received interrupt signal; exiting...");
53	signal(SIGINT, SIG_IGN);
54	signal(SIGTERM, SIG_IGN);
55	signal(SIGALRM, signal_alarm);
56	if (opt_p) {
57		struct opt_p_t *tmp = opt_p;
58		while (tmp) {
59			debug(2, "Sending SIGSTOP to process %u\n", tmp->pid);
60			kill(tmp->pid, SIGSTOP);
61			tmp = tmp->next;
62		}
63	}
64	alarm(1);
65}
66
67static void
68normal_exit(void) {
69	output_line(0, 0);
70	if (options.summary) {
71		show_summary();
72	}
73	if (options.output) {
74		fclose(options.output);
75		options.output = NULL;
76	}
77}
78
79void
80ltrace_init(int argc, char **argv) {
81	struct opt_p_t *opt_p_tmp;
82
83	atexit(normal_exit);
84	signal(SIGINT, signal_exit);	/* Detach processes when interrupted */
85	signal(SIGTERM, signal_exit);	/*  ... or killed */
86
87	argv = process_options(argc, argv);
88	while (opt_F) {
89		/* If filename begins with ~, expand it to the user's home */
90		/* directory. This does not correctly handle ~yoda, but that */
91		/* isn't as bad as it seems because the shell will normally */
92		/* be doing the expansion for us; only the hardcoded */
93		/* ~/.ltrace.conf should ever use this code. */
94		if (opt_F->filename[0] == '~') {
95			char path[PATH_MAX];
96			char *home_dir = getenv("HOME");
97			if (home_dir) {
98				strncpy(path, home_dir, PATH_MAX - 1);
99				path[PATH_MAX - 1] = '\0';
100				strncat(path, opt_F->filename + 1,
101						PATH_MAX - strlen(path) - 1);
102				read_config_file(path);
103			}
104		} else {
105			read_config_file(opt_F->filename);
106		}
107		opt_F = opt_F->next;
108	}
109	if (opt_e) {
110		struct opt_e_t *tmp = opt_e;
111		while (tmp) {
112			debug(1, "Option -e: %s\n", tmp->name);
113			tmp = tmp->next;
114		}
115	}
116	if (command) {
117		execute_program(open_program(command, 0), argv);
118	}
119	opt_p_tmp = opt_p;
120	while (opt_p_tmp) {
121		open_pid(opt_p_tmp->pid, 1);
122		opt_p_tmp = opt_p_tmp->next;
123	}
124}
125
126void
127ltrace_main(void) {
128	while (1) {
129		process_event(next_event());
130	}
131}
132