blob: b76865f4ca280ff24aefd29ed26fbb2882e2b474 [file] [log] [blame]
Juan Cespedesd44c6b81998-09-25 14:48:42 +02001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
Juan Cespedes1c2be911997-06-09 01:12:01 +02005#include <stdio.h>
Juan Cespedes23658aa1997-08-27 22:27:36 +02006#include <stdlib.h>
Juan Cespedes1c2be911997-06-09 01:12:01 +02007#include <unistd.h>
Juan Cespedes23658aa1997-08-27 22:27:36 +02008#include <string.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01009#include <errno.h>
10#include <sys/param.h>
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020011#include <signal.h>
Juan Cespedes28f60191998-04-12 00:04:39 +020012#include <sys/wait.h>
Juan Cespedes1c2be911997-06-09 01:12:01 +020013
Juan Cespedes5e01f651998-03-08 22:31:44 +010014#include "ltrace.h"
Juan Cespedes3268a161997-08-25 16:45:22 +020015#include "output.h"
Juan Cespedes28f60191998-04-12 00:04:39 +020016#include "read_config_file.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010017#include "options.h"
Juan Cespedescac15c32003-01-31 18:58:58 +010018#include "debug.h"
Juan Cespedes96935a91997-08-09 23:45:39 +020019
Ian Wienand2d45b1a2006-02-20 22:48:07 +010020char *command = NULL;
21struct process *list_of_processes = NULL;
Juan Cespedes24c82531997-06-25 00:02:58 +020022
Ian Wienand2d45b1a2006-02-20 22:48:07 +010023int exiting = 0; /* =1 if a SIGINT or SIGTERM has been received */
Juan Cespedes28f60191998-04-12 00:04:39 +020024
Juan Cespedesf1350522008-12-16 18:19:58 +010025static void
26signal_alarm(int sig) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010027 struct process *tmp = list_of_processes;
Juan Cespedes28f60191998-04-12 00:04:39 +020028
Ian Wienand2d45b1a2006-02-20 22:48:07 +010029 signal(SIGALRM, SIG_DFL);
30 while (tmp) {
31 struct opt_p_t *tmp2 = opt_p;
32 while (tmp2) {
Juan Cespedes28f60191998-04-12 00:04:39 +020033 if (tmp->pid == tmp2->pid) {
34 tmp = tmp->next;
35 if (!tmp) {
36 return;
37 }
Juan Cespedesaee09312007-08-31 18:49:48 +020038 tmp2 = opt_p;
39 continue;
Juan Cespedes28f60191998-04-12 00:04:39 +020040 }
41 tmp2 = tmp2->next;
42 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010043 debug(2, "Sending SIGSTOP to process %u\n", tmp->pid);
Juan Cespedes28f60191998-04-12 00:04:39 +020044 kill(tmp->pid, SIGSTOP);
45 tmp = tmp->next;
46 }
47}
48
Juan Cespedesf1350522008-12-16 18:19:58 +010049static void
50signal_exit(int sig) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010051 exiting = 1;
52 debug(1, "Received interrupt signal; exiting...");
Juan Cespedesb65bdc52008-12-16 19:50:16 +010053 if (options.output) {
54 fclose(options.output);
55 options.output = NULL;
Juan Cespedesaee09312007-08-31 18:49:48 +020056 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010057 signal(SIGINT, SIG_IGN);
58 signal(SIGTERM, SIG_IGN);
59 signal(SIGALRM, signal_alarm);
Juan Cespedes28f60191998-04-12 00:04:39 +020060 if (opt_p) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010061 struct opt_p_t *tmp = opt_p;
62 while (tmp) {
63 debug(2, "Sending SIGSTOP to process %u\n", tmp->pid);
Juan Cespedes28f60191998-04-12 00:04:39 +020064 kill(tmp->pid, SIGSTOP);
65 tmp = tmp->next;
66 }
67 }
68 alarm(1);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020069}
70
Juan Cespedesf1350522008-12-16 18:19:58 +010071static void
72normal_exit(void) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010073 output_line(0, 0);
Juan Cespedesd65efa32003-02-03 00:22:30 +010074 if (opt_c) {
Juan Cespedes504a3852003-02-04 23:24:38 +010075 show_summary();
Juan Cespedesd65efa32003-02-03 00:22:30 +010076 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +010077 if (options.output) {
78 fclose(options.output);
79 options.output = NULL;
Juan Cespedesaee09312007-08-31 18:49:48 +020080 }
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020081}
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020082
Juan Cespedesf1350522008-12-16 18:19:58 +010083int
84main(int argc, char **argv) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010085 struct opt_p_t *opt_p_tmp;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020086
87 atexit(normal_exit);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010088 signal(SIGINT, signal_exit); /* Detach processes when interrupted */
89 signal(SIGTERM, signal_exit); /* ... or killed */
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020090
91 argv = process_options(argc, argv);
Juan Cespedesaee09312007-08-31 18:49:48 +020092 while (opt_F) {
93 /* If filename begins with ~, expand it to the user's home */
94 /* directory. This does not correctly handle ~yoda, but that */
95 /* isn't as bad as it seems because the shell will normally */
96 /* be doing the expansion for us; only the hardcoded */
97 /* ~/.ltrace.conf should ever use this code. */
98 if (opt_F->filename[0] == '~') {
99 char path[PATH_MAX];
100 char *home_dir = getenv("HOME");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200101 if (home_dir) {
102 strncpy(path, home_dir, PATH_MAX - 1);
103 path[PATH_MAX - 1] = '\0';
104 strncat(path, opt_F->filename + 1,
105 PATH_MAX - strlen(path) - 1);
106 read_config_file(path);
107 }
Juan Cespedesaee09312007-08-31 18:49:48 +0200108 } else {
109 read_config_file(opt_F->filename);
110 }
111 opt_F = opt_F->next;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200112 }
Juan Cespedescac15c32003-01-31 18:58:58 +0100113 if (opt_e) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100114 struct opt_e_t *tmp = opt_e;
115 while (tmp) {
116 debug(1, "Option -e: %s\n", tmp->name);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200117 tmp = tmp->next;
118 }
119 }
120 if (command) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100121 execute_program(open_program(command, 0), argv);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200122 }
123 opt_p_tmp = opt_p;
124 while (opt_p_tmp) {
125 open_pid(opt_p_tmp->pid, 1);
126 opt_p_tmp = opt_p_tmp->next;
127 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100128 while (1) {
Juan Cespedese2023f72009-04-07 12:12:08 +0200129 process_event(next_event());
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200130 }
131}