blob: d85f4f2efe6210746a324c1cf480b5e5ae195933 [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...");
53 signal(SIGINT, SIG_IGN);
54 signal(SIGTERM, SIG_IGN);
55 signal(SIGALRM, signal_alarm);
Juan Cespedes28f60191998-04-12 00:04:39 +020056 if (opt_p) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010057 struct opt_p_t *tmp = opt_p;
58 while (tmp) {
59 debug(2, "Sending SIGSTOP to process %u\n", tmp->pid);
Juan Cespedes28f60191998-04-12 00:04:39 +020060 kill(tmp->pid, SIGSTOP);
61 tmp = tmp->next;
62 }
63 }
64 alarm(1);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020065}
66
Juan Cespedesf1350522008-12-16 18:19:58 +010067static void
68normal_exit(void) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010069 output_line(0, 0);
Juan Cespedesda9b9532009-04-07 15:33:50 +020070 if (options.summary) {
Juan Cespedes504a3852003-02-04 23:24:38 +010071 show_summary();
Juan Cespedesd65efa32003-02-03 00:22:30 +010072 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +010073 if (options.output) {
74 fclose(options.output);
75 options.output = NULL;
Juan Cespedesaee09312007-08-31 18:49:48 +020076 }
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020077}
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020078
Juan Cespedesf1350522008-12-16 18:19:58 +010079int
80main(int argc, char **argv) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010081 struct opt_p_t *opt_p_tmp;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020082
83 atexit(normal_exit);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010084 signal(SIGINT, signal_exit); /* Detach processes when interrupted */
85 signal(SIGTERM, signal_exit); /* ... or killed */
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020086
87 argv = process_options(argc, argv);
Juan Cespedesaee09312007-08-31 18:49:48 +020088 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");
Juan Cespedesa413e5b2007-09-04 17:34:53 +020097 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 }
Juan Cespedesaee09312007-08-31 18:49:48 +0200104 } else {
105 read_config_file(opt_F->filename);
106 }
107 opt_F = opt_F->next;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200108 }
Juan Cespedescac15c32003-01-31 18:58:58 +0100109 if (opt_e) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100110 struct opt_e_t *tmp = opt_e;
111 while (tmp) {
112 debug(1, "Option -e: %s\n", tmp->name);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200113 tmp = tmp->next;
114 }
115 }
116 if (command) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100117 execute_program(open_program(command, 0), argv);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200118 }
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 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100124 while (1) {
Juan Cespedese2023f72009-04-07 12:12:08 +0200125 process_event(next_event());
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200126 }
127}