1 #include <errno.h> 2 #include <fcntl.h> 3 #include <signal.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <unistd.h> 8 9 #include <sys/types.h> 10 #include <sys/ptrace.h> 11 #include <sys/stat.h> 12 #include <sys/wait.h> 13 14 #if defined(PTRACE_ATTACH) 15 #define ATTACH_REQUEST PTRACE_ATTACH 16 #define DETACH_REQUEST PTRACE_DETACH 17 #elif defined(PT_ATTACH) 18 #define ATTACH_REQUEST PT_ATTACH 19 #define DETACH_REQUEST PT_DETACH 20 #else 21 #error "Unsupported platform" 22 #endif 23 24 bool writePid (const char* file_name, const pid_t pid) 25 { 26 char *tmp_file_name = (char *)malloc(strlen(file_name) + 16); 27 strcpy(tmp_file_name, file_name); 28 strcat(tmp_file_name, "_tmp"); 29 int fd = open (tmp_file_name, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); 30 if (fd == -1) 31 { 32 fprintf (stderr, "open(%s) failed: %s\n", tmp_file_name, strerror (errno)); 33 free(tmp_file_name); 34 return false; 35 } 36 char buffer[64]; 37 snprintf (buffer, sizeof(buffer), "%ld", (long)pid); 38 39 bool res = true; 40 if (write (fd, buffer, strlen (buffer)) == -1) 41 { 42 fprintf (stderr, "write(%s) failed: %s\n", buffer, strerror (errno)); 43 res = false; 44 } 45 close (fd); 46 47 if (rename (tmp_file_name, file_name) == -1) 48 { 49 fprintf (stderr, "rename(%s, %s) failed: %s\n", tmp_file_name, file_name, strerror (errno)); 50 res = false; 51 } 52 free(tmp_file_name); 53 54 return res; 55 } 56 57 void signal_handler (int) 58 { 59 } 60 61 int main (int argc, char const *argv[]) 62 { 63 if (argc < 2) 64 { 65 fprintf (stderr, "invalid number of command line arguments\n"); 66 return 1; 67 } 68 69 const pid_t pid = fork (); 70 if (pid == -1) 71 { 72 fprintf (stderr, "fork failed: %s\n", strerror (errno)); 73 return 1; 74 } 75 76 if (pid > 0) 77 { 78 // Make pause call to return when a signal is received. Normally this happens when the 79 // test runner tries to terminate us. 80 signal (SIGHUP, signal_handler); 81 signal (SIGTERM, signal_handler); 82 if (ptrace (ATTACH_REQUEST, pid, NULL, 0) == -1) 83 { 84 fprintf (stderr, "ptrace(ATTACH) failed: %s\n", strerror (errno)); 85 } 86 else 87 { 88 if (writePid (argv[1], pid)) 89 pause (); // Waiting for the debugger trying attach to the child. 90 91 if (ptrace (DETACH_REQUEST, pid, NULL, 0) != 0) 92 fprintf (stderr, "ptrace(DETACH) failed: %s\n", strerror (errno)); 93 } 94 95 kill (pid, SIGTERM); 96 int status = 0; 97 if (waitpid (pid, &status, 0) == -1) 98 fprintf (stderr, "waitpid failed: %s\n", strerror (errno)); 99 } 100 else 101 { 102 // child inferior. 103 pause (); 104 } 105 106 printf ("Exiting now\n"); 107 return 0; 108 } 109