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
24bool writePid (const char* file_name, const pid_t pid)
25{
26 char *tmp_file_name = (char *)malloc(size: strlen(s: file_name) + 16);
27 strcpy(dest: tmp_file_name, src: file_name);
28 strcat(dest: tmp_file_name, src: "_tmp");
29 int fd = open (file: tmp_file_name, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
30 if (fd == -1)
31 {
32 fprintf (stderr, format: "open(%s) failed: %s\n", tmp_file_name, strerror (errno));
33 free(ptr: tmp_file_name);
34 return false;
35 }
36 char buffer[64];
37 snprintf (s: buffer, maxlen: sizeof(buffer), format: "%ld", (long)pid);
38
39 bool res = true;
40 if (write (fd: fd, buf: buffer, n: strlen (s: buffer)) == -1)
41 {
42 fprintf (stderr, format: "write(%s) failed: %s\n", buffer, strerror (errno));
43 res = false;
44 }
45 close (fd: fd);
46
47 if (rename (old: tmp_file_name, new: file_name) == -1)
48 {
49 fprintf (stderr, format: "rename(%s, %s) failed: %s\n", tmp_file_name, file_name, strerror (errno));
50 res = false;
51 }
52 free(ptr: tmp_file_name);
53
54 return res;
55}
56
57void signal_handler (int)
58{
59}
60
61int main (int argc, char const *argv[])
62{
63 if (argc < 2)
64 {
65 fprintf (stderr, format: "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, format: "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, handler: signal_handler);
81 signal (SIGTERM, handler: signal_handler);
82 if (ptrace (ATTACH_REQUEST, pid, NULL, 0) == -1)
83 {
84 fprintf (stderr, format: "ptrace(ATTACH) failed: %s\n", strerror (errno));
85 }
86 else
87 {
88 if (writePid (file_name: 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, format: "ptrace(DETACH) failed: %s\n", strerror (errno));
93 }
94
95 kill (pid: pid, SIGTERM);
96 int status = 0;
97 if (waitpid (pid: pid, stat_loc: &status, options: 0) == -1)
98 fprintf (stderr, format: "waitpid failed: %s\n", strerror (errno));
99 }
100 else
101 {
102 // child inferior.
103 pause ();
104 }
105
106 printf (format: "Exiting now\n");
107 return 0;
108}
109

source code of lldb/test/API/commands/process/attach/attach_denied/main.cpp