blob: 3c7d661e5f6045c314d20ee58332415fb587fcea [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
Ian Wienand2d45b1a2006-02-20 22:48:07 +010026static void signal_alarm(int sig)
27{
28 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
Ian Wienand2d45b1a2006-02-20 22:48:07 +010050static void signal_exit(int sig)
51{
52 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
Ian Wienand2d45b1a2006-02-20 22:48:07 +010072static void normal_exit(void)
73{
74 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);
80 }
Juan Cespedes5e0acdb1998-04-04 08:34:07 +020081}
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020082
Ian Wienand2d45b1a2006-02-20 22:48:07 +010083static void guess_cols(void)
84{
Juan Cespedesa0ccf392003-02-01 19:02:37 +010085 struct winsize ws;
Ian Wienand2d45b1a2006-02-20 22:48:07 +010086 char *c;
Juan Cespedesa0ccf392003-02-01 19:02:37 +010087
88 opt_a = DEFAULT_ACOLUMN;
89 c = getenv("COLUMNS");
90 if (c && *c) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010091 char *endptr;
Juan Cespedesa0ccf392003-02-01 19:02:37 +010092 int cols;
93 cols = strtol(c, &endptr, 0);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010094 if (cols > 0 && !*endptr) {
95 opt_a = cols * 5 / 8;
Juan Cespedesa0ccf392003-02-01 19:02:37 +010096 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010097 } else if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col > 0) {
98 opt_a = ws.ws_col * 5 / 8;
Juan Cespedesa0ccf392003-02-01 19:02:37 +010099 }
100}
101
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100102int main(int argc, char **argv)
103{
104 struct opt_p_t *opt_p_tmp;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200105
106 atexit(normal_exit);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100107 signal(SIGINT, signal_exit); /* Detach processes when interrupted */
108 signal(SIGTERM, signal_exit); /* ... or killed */
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200109
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100110 guess_cols();
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200111 argv = process_options(argc, argv);
Juan Cespedesaee09312007-08-31 18:49:48 +0200112 while (opt_F) {
113 /* If filename begins with ~, expand it to the user's home */
114 /* directory. This does not correctly handle ~yoda, but that */
115 /* isn't as bad as it seems because the shell will normally */
116 /* be doing the expansion for us; only the hardcoded */
117 /* ~/.ltrace.conf should ever use this code. */
118 if (opt_F->filename[0] == '~') {
119 char path[PATH_MAX];
120 char *home_dir = getenv("HOME");
121 strncpy(path, home_dir, PATH_MAX - 1);
122 path[PATH_MAX - 1] = '\0';
123 strncat(path, opt_F->filename + 1,
124 PATH_MAX - strlen(path) - 1);
125 read_config_file(path);
126 } else {
127 read_config_file(opt_F->filename);
128 }
129 opt_F = opt_F->next;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200130 }
Juan Cespedescac15c32003-01-31 18:58:58 +0100131 if (opt_e) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100132 struct opt_e_t *tmp = opt_e;
133 while (tmp) {
134 debug(1, "Option -e: %s\n", tmp->name);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200135 tmp = tmp->next;
136 }
137 }
138 if (command) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100139 execute_program(open_program(command, 0), argv);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200140 }
141 opt_p_tmp = opt_p;
142 while (opt_p_tmp) {
143 open_pid(opt_p_tmp->pid, 1);
144 opt_p_tmp = opt_p_tmp->next;
145 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100146 while (1) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200147 process_event(wait_for_something());
148 }
149}