libltrace.c revision 366c2f46d844f040458df9b7e35fc3b8527ed2d3
1#include "config.h" 2 3#include <stdio.h> 4#include <stdlib.h> 5#include <unistd.h> 6#include <string.h> 7#include <errno.h> 8#include <sys/param.h> 9#include <signal.h> 10#include <sys/wait.h> 11 12#include "common.h" 13#include "proc.h" 14 15char *command = NULL; 16 17int exiting = 0; /* =1 if a SIGINT or SIGTERM has been received */ 18 19static enum pcb_status 20stop_non_p_processes (Process * proc, void * data) 21{ 22 int stop = 1; 23 24 struct opt_p_t *it; 25 for (it = opt_p; it != NULL; it = it->next) { 26 Process * p_proc = pid2proc(it->pid); 27 if (p_proc == NULL) { 28 printf("stop_non_p_processes: %d terminated?\n", it->pid); 29 continue; 30 } 31 if (p_proc == proc || p_proc->leader == proc->leader) { 32 stop = 0; 33 break; 34 } 35 } 36 37 if (stop) { 38 debug(2, "Sending SIGSTOP to process %u", proc->pid); 39 kill(proc->pid, SIGSTOP); 40 } 41 42 return pcb_cont; 43} 44 45static void 46signal_alarm(int sig) { 47 signal(SIGALRM, SIG_DFL); 48 each_process(NULL, &stop_non_p_processes, NULL); 49} 50 51static void 52signal_exit(int sig) 53{ 54 debug(1, "Received interrupt signal; exiting..."); 55 if (exiting != 0) 56 return; 57 58 exiting = 1 + !!os_ltrace_exiting_sighandler(); 59 60 signal(SIGINT, SIG_IGN); 61 signal(SIGTERM, SIG_IGN); 62 signal(SIGALRM, signal_alarm); 63 //alarm(1); 64} 65 66static void 67normal_exit(void) { 68 output_line(0, 0); 69 if (options.summary) { 70 show_summary(); 71 } 72 if (options.output) { 73 fclose(options.output); 74 options.output = NULL; 75 } 76} 77 78void 79ltrace_init(int argc, char **argv) { 80 struct opt_p_t *opt_p_tmp; 81 82 atexit(normal_exit); 83 signal(SIGINT, signal_exit); /* Detach processes when interrupted */ 84 signal(SIGTERM, signal_exit); /* ... or killed */ 85 86 argv = process_options(argc, argv); 87 while (opt_F) { 88 /* If filename begins with ~, expand it to the user's home */ 89 /* directory. This does not correctly handle ~yoda, but that */ 90 /* isn't as bad as it seems because the shell will normally */ 91 /* be doing the expansion for us; only the hardcoded */ 92 /* ~/.ltrace.conf should ever use this code. */ 93 if (opt_F->filename[0] == '~') { 94 char path[PATH_MAX]; 95 char *home_dir = getenv("HOME"); 96 if (home_dir) { 97 strncpy(path, home_dir, PATH_MAX - 1); 98 path[PATH_MAX - 1] = '\0'; 99 strncat(path, opt_F->filename + 1, 100 PATH_MAX - strlen(path) - 1); 101 read_config_file(path); 102 } 103 } else { 104 read_config_file(opt_F->filename); 105 } 106 opt_F = opt_F->next; 107 } 108 if (opt_e) { 109 struct opt_e_t *tmp = opt_e; 110 while (tmp) { 111 debug(1, "Option -e: %s\n", tmp->name); 112 tmp = tmp->next; 113 } 114 } 115 if (command) { 116 /* Check that the binary ABI is supported before 117 * calling execute_program. */ 118 struct ltelf lte = {}; 119 open_elf(<e, command); 120 121 open_program(command, execute_program(command, argv), 0); 122 } 123 opt_p_tmp = opt_p; 124 while (opt_p_tmp) { 125 open_pid(opt_p_tmp->pid); 126 opt_p_tmp = opt_p_tmp->next; 127 } 128} 129 130static int num_ltrace_callbacks[EVENT_MAX]; 131static callback_func * ltrace_callbacks[EVENT_MAX]; 132 133void 134ltrace_add_callback(callback_func func, Event_type type) { 135 ltrace_callbacks[type] = realloc(ltrace_callbacks[type], (num_ltrace_callbacks[type]+1)*sizeof(callback_func)); 136 ltrace_callbacks[type][num_ltrace_callbacks[type]++] = func; 137} 138 139static void 140dispatch_callbacks(Event * ev) { 141 int i; 142 /* Ignoring case 1: signal into a dying tracer */ 143 if (ev->type==EVENT_SIGNAL && 144 exiting && ev->e_un.signum == SIGSTOP) { 145 return; 146 } 147 /* Ignoring case 2: process being born before a clone event */ 148 if (ev->proc && ev->proc->state == STATE_IGNORED) { 149 return; 150 } 151 for (i=0; i<num_ltrace_callbacks[ev->type]; i++) { 152 ltrace_callbacks[ev->type][i](ev); 153 } 154} 155 156void 157ltrace_main(void) { 158 Event * ev; 159 while (1) { 160 ev = next_event(); 161 dispatch_callbacks(ev); 162 handle_event(ev); 163 } 164} 165