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