Mercurial > minori
comparison dep/animia/src/fd/xnu.cc @ 160:900b5b530883
dep/animia: fd/xnu: use path args to get executable filename
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Fri, 17 Nov 2023 12:37:31 -0500 |
parents | 18c8eb5d1edc |
children | 61b76c7b656a |
comparison
equal
deleted
inserted
replaced
157:18c8eb5d1edc | 160:900b5b530883 |
---|---|
7 | 7 |
8 #include <cassert> | 8 #include <cassert> |
9 #include <string> | 9 #include <string> |
10 #include <unordered_map> | 10 #include <unordered_map> |
11 #include <vector> | 11 #include <vector> |
12 #include <memory> | |
12 | 13 |
13 #include <fcntl.h> | 14 #include <fcntl.h> |
14 #include <libproc.h> | 15 #include <libproc.h> |
15 #include <sys/sysctl.h> | 16 #include <sys/sysctl.h> |
16 #include <sys/types.h> | 17 #include <sys/types.h> |
17 #include <sys/user.h> | 18 #include <sys/user.h> |
18 | 19 |
20 #include <iostream> | |
21 | |
19 namespace animia::internal::xnu { | 22 namespace animia::internal::xnu { |
20 | 23 |
21 static std::string GetProcessName(pid_t pid) { | 24 static bool GetProcessNameFromArgs(pid_t pid, std::string& result) { |
22 char name[2*MAXCOMLEN]; | 25 /* sysctl shouldn't touch these, so we define them as const */ |
23 proc_name(pid, name, sizeof(name)); | 26 const int mib[3] = {CTL_KERN, KERN_PROCARGS2, static_cast<int>(pid)}; |
27 const size_t mib_size = sizeof(mib)/sizeof(*mib); | |
24 | 28 |
25 return name; | 29 /* Get the initial size of the array */ |
30 size_t size; | |
31 int ret = sysctl((int*)mib, mib_size, nullptr, &size, nullptr, 0); | |
32 if (ret) | |
33 return false; | |
34 | |
35 /* Reserve the space for it in a std::string */ | |
36 std::string args; | |
37 args.resize(size); | |
38 | |
39 /* Get the contents of argc and argv */ | |
40 ret = sysctl((int*)mib, mib_size, &args.front(), &size, NULL, 0); | |
41 if (ret) | |
42 return false; | |
43 | |
44 /* Is the size big enough to hold at least argc? */ | |
45 if (size < sizeof(int)) | |
46 return false; | |
47 | |
48 args.resize(size); | |
49 | |
50 /* Get argc using memcpy */ | |
51 int argc; | |
52 memcpy(&argc, &args.front(), sizeof(argc)); | |
53 | |
54 /* Check for a condition that, realistically, would never happen, | |
55 but better to be safe than sorry */ | |
56 if (argc < 1) | |
57 return false; | |
58 | |
59 /* Find the first null character */ | |
60 size_t null_pos = args.find('\0', sizeof(argc)); | |
61 if (null_pos == std::string::npos) | |
62 return false; | |
63 | |
64 /* Find the last slash */ | |
65 size_t last_slash = args.rfind('/', null_pos); | |
66 if (last_slash == std::string::npos) | |
67 return false; | |
68 | |
69 /* Return our result */ | |
70 result = args.substr(last_slash + 1, null_pos - last_slash - 1); | |
71 return true; | |
72 } | |
73 | |
74 static bool GetProcessNameFromKernel(pid_t pid, std::string& result) { | |
75 result.reserve(2*MAXCOMLEN); | |
76 if (!proc_name(pid, &result.front(), result.length())) | |
77 return false; | |
78 | |
79 result.shrink_to_fit(); | |
80 return true; | |
81 } | |
82 | |
83 static bool GetProcessName(pid_t pid, std::string& result) { | |
84 /* First try parsing the arguments, this prevents the process name being | |
85 cut off to 2*MAXCOMLEN (32 chars) */ | |
86 if (GetProcessNameFromArgs(pid, result)) | |
87 return true; | |
88 | |
89 /* Then attempt getting it from the kernel, which results in the process name | |
90 being cut to 32 chars (16 chars if p_name is unavailable) */ | |
91 if (GetProcessNameFromKernel(pid, result)) | |
92 return true; | |
93 | |
94 return false; | |
26 } | 95 } |
27 | 96 |
28 bool XnuFdTools::EnumerateOpenProcesses(process_proc_t process_proc) { | 97 bool XnuFdTools::EnumerateOpenProcesses(process_proc_t process_proc) { |
29 std::vector<pid_t> pids; | 98 size_t pids_size = 512; |
30 pids.reserve(1024); | 99 std::unique_ptr<pid_t[]> pids; |
31 | 100 |
32 for (int returned_size = pids.capacity(); pids.capacity() > returned_size; pids.reserve(pids.capacity() * 2)) { | 101 int returned_size = 0; |
33 returned_size = proc_listpids(PROC_ALL_PIDS, 0, pids.data(), pids.capacity() * sizeof(pid_t)); | 102 do { |
103 pids.reset(new pid_t[pids_size]); | |
104 returned_size = proc_listpids(PROC_ALL_PIDS, 0, pids.get(), pids_size * sizeof(pid_t)); | |
34 if (returned_size == -1) | 105 if (returned_size == -1) |
35 return false; | 106 return false; |
36 } | 107 } while ((pids_size * sizeof(size_t)) < returned_size); |
37 | 108 |
38 for (const auto& pid : pids) { | 109 for (int i = 0; i < pids_size; i++) { |
39 if (!process_proc({pid, GetProcessName(pid)})) | 110 std::string result; |
111 GetProcessName(pids[i], result); | |
112 if (!process_proc({pids[i], result})) | |
40 return false; | 113 return false; |
41 } | 114 } |
42 | 115 |
43 return true; | 116 return true; |
44 } | 117 } |