blob: 33b573be80a01ab155c068b191c97ca1b8685d42 [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 Cespedesa0ccf392003-02-01 19:02:37 +010013#include <sys/ioctl.h>
Juan Cespedes1c2be911997-06-09 01:12:01 +020014
Juan Cespedes5e01f651998-03-08 22:31:44 +010015#include "ltrace.h"
Juan Cespedes3268a161997-08-25 16:45:22 +020016#include "output.h"
Juan Cespedes28f60191998-04-12 00:04:39 +020017#include "read_config_file.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010018#include "options.h"
Juan Cespedescac15c32003-01-31 18:58:58 +010019#include "debug.h"
Juan Cespedes96935a91997-08-09 23:45:39 +020020
Ian Wienand2d45b1a2006-02-20 22:48:07 +010021char *command = NULL;
22struct process *list_of_processes = NULL;
Juan Cespedes24c82531997-06-25 00:02:58 +020023
Ian Wienand2d45b1a2006-02-20 22:48:07 +010024int exiting = 0; /* =1 if a SIGINT or SIGTERM has been received */
Juan Cespedes28f60191998-04-12 00:04:39 +020025
Juan Cespedesf1350522008-12-16 18:19:58 +010026static void
27signal_alarm(int sig) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010028 struct process *tmp = list_of_processes;
Juan Cespedes28f60191998-04-12 00:04:39 +020029
Ian Wienand2d45b1a2006-02-20 22:48:07 +010030 signal(SIGALRM, SIG_DFL);
31 while (tmp) {
32 struct opt_p_t *tmp2 = opt_p;
33 while (tmp2) {
Juan Cespedes28f60191998-04-12 00:04:39 +020034 if (tmp->pid == tmp2->pid) {
35 tmp = tmp->next;
36 if (!tmp) {
37 return;
38 }
Juan Cespedesaee09312007-08-31 18:49:48 +020039 tmp2 = opt_p;
40 continue;
Juan Cespedes28f60191998-04-12 00:04:39 +020041 }
42 tmp2 = tmp2->next;
43 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010044 debug(2, "Sending SIGSTOP to process %u\n", tmp->pid);
Juan Cespedes28f60191998-04-12 00:04:39 +020045 kill(tmp->pid, SIGSTOP);
46 tmp = tmp->next;
47 }
48}
49
Juan Cespedesf1350522008-12-16 18:19:58 +010050static void
51signal_exit(int sig) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010052 exiting = 1;
53 debug(1, "Received interrupt signal; exiting...");
Juan Cespedesaee09312007-08-31 18:49:48 +020054 if (opt_o) {
55 fclose(output);
56 opt_o = 0;
57 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010058 signal(SIGINT, SIG_IGN);
59 signal(SIGTERM, SIG_IGN);
60 signal(SIGALRM, signal_alarm);
Juan Cespedes28f60191998-04-12 00:04:39 +020061 if (opt_p) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010062 struct opt_p_t *tmp = opt_p;
63 while (tmp) {
64 debug(2, "Sending SIGSTOP to process %u\n", tmp->pid);
Juan Cespedes28f60191998-04-12 00:04:39 +020065 kill(tmp->pid, SIGSTOP);
66 tmp = tmp->next;
67 }
68 }
69 alarm(1);
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020070}
71
Juan Cespedesf1350522008-12-16 18:19:58 +010072static void
73normal_exit(void) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010074 output_line(0, 0);
Juan Cespedesd65efa32003-02-03 00:22:30 +010075 if (opt_c) {
Juan Cespedes504a3852003-02-04 23:24:38 +010076 show_summary();
Juan Cespedesd65efa32003-02-03 00:22:30 +010077 }
Juan Cespedesaee09312007-08-31 18:49:48 +020078 if (opt_o) {
79 fclose(output);
Juan Cespedes63184be2008-12-10 13:30:12 +010080 opt_o = 0;
Juan Cespedesaee09312007-08-31 18:49:48 +020081 }
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020082}
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020083
Juan Cespedesf1350522008-12-16 18:19:58 +010084static void
85guess_cols(void) {
Juan Cespedesa0ccf392003-02-01 19:02:37 +010086 struct winsize ws;
Ian Wienand2d45b1a2006-02-20 22:48:07 +010087 char *c;
Juan Cespedesa0ccf392003-02-01 19:02:37 +010088
89 opt_a = DEFAULT_ACOLUMN;
90 c = getenv("COLUMNS");
91 if (c && *c) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010092 char *endptr;
Juan Cespedesa0ccf392003-02-01 19:02:37 +010093 int cols;
94 cols = strtol(c, &endptr, 0);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010095 if (cols > 0 && !*endptr) {
96 opt_a = cols * 5 / 8;
Juan Cespedesa0ccf392003-02-01 19:02:37 +010097 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010098 } else if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col > 0) {
99 opt_a = ws.ws_col * 5 / 8;
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100100 }
101}
102
Juan Cespedesf1350522008-12-16 18:19:58 +0100103int
104main(int argc, char **argv) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100105 struct opt_p_t *opt_p_tmp;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200106
107 atexit(normal_exit);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100108 signal(SIGINT, signal_exit); /* Detach processes when interrupted */
109 signal(SIGTERM, signal_exit); /* ... or killed */
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200110
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100111 guess_cols();
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200112 argv = process_options(argc, argv);
Juan Cespedesaee09312007-08-31 18:49:48 +0200113 while (opt_F) {
114 /* If filename begins with ~, expand it to the user's home */
115 /* directory. This does not correctly handle ~yoda, but that */
116 /* isn't as bad as it seems because the shell will normally */
117 /* be doing the expansion for us; only the hardcoded */
118 /* ~/.ltrace.conf should ever use this code. */
119 if (opt_F->filename[0] == '~') {
120 char path[PATH_MAX];
121 char *home_dir = getenv("HOME");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200122 if (home_dir) {
123 strncpy(path, home_dir, PATH_MAX - 1);
124 path[PATH_MAX - 1] = '\0';
125 strncat(path, opt_F->filename + 1,
126 PATH_MAX - strlen(path) - 1);
127 read_config_file(path);
128 }
Juan Cespedesaee09312007-08-31 18:49:48 +0200129 } else {
130 read_config_file(opt_F->filename);
131 }
132 opt_F = opt_F->next;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200133 }
Juan Cespedescac15c32003-01-31 18:58:58 +0100134 if (opt_e) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100135 struct opt_e_t *tmp = opt_e;
136 while (tmp) {
137 debug(1, "Option -e: %s\n", tmp->name);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200138 tmp = tmp->next;
139 }
140 }
141 if (command) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100142 execute_program(open_program(command, 0), argv);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200143 }
144 opt_p_tmp = opt_p;
145 while (opt_p_tmp) {
146 open_pid(opt_p_tmp->pid, 1);
147 opt_p_tmp = opt_p_tmp->next;
148 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100149 while (1) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200150 process_event(wait_for_something());
151 }
152}