Mercurial > minori
comparison dep/animia/src/util/osx.cc @ 202:71832ffe425a
animia: re-add kvm fd source
this is all being merged from my wildly out-of-date laptop. SORRY!
in other news, I edited the CI file to install the wayland client
as well, so the linux CI build might finally get wayland stuff.
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Tue, 02 Jan 2024 06:05:06 -0500 |
parents | 8548dc425697 |
children | a7d0d543b334 |
comparison
equal
deleted
inserted
replaced
201:8f6f8dd2eb23 | 202:71832ffe425a |
---|---|
1 #include "animia/util/osx.h" | 1 #include "animia/util/osx.h" |
2 | 2 |
3 #include <string> | 3 #include <string> |
4 #include <memory> | 4 #include <memory> |
5 | 5 |
6 #include <sys/sysctl.h> | |
7 #include <libproc.h> | |
8 | |
9 namespace animia::internal::osx::util { | |
10 | |
6 #ifdef HAVE_COREFOUNDATION | 11 #ifdef HAVE_COREFOUNDATION |
7 #include <CoreFoundation/CoreFoundation.h> | |
8 #endif | |
9 | |
10 namespace animia::internal::osx::util { | |
11 | |
12 #ifdef HAVE_COREFOUNDATION | |
13 /* I don't want to have to call CFRelease */ | |
14 template<typename T> | |
15 struct CFDeleter { | |
16 using pointer = T; | |
17 void operator()(pointer p) { CFRelease(p); } | |
18 } | |
19 | |
20 template<typename T> | |
21 typedef CFReference = std::unique_ptr<T, CFDeleter>; | |
22 | |
23 /* all of these LaunchServices things use *internal functions* that are subject | 12 /* all of these LaunchServices things use *internal functions* that are subject |
24 * to change. Granted, it's not very likely that these will change very much | 13 * to change. Granted, it's not very likely that these will change very much |
25 * because I'm fairly sure Apple uses them lots in their own internal code. | 14 * because I'm fairly sure Apple uses them lots in their own internal code. |
26 */ | 15 */ |
27 typedef CFTypeRef (*LSASNCreateWithPidSpec)(CFAllocatorRef, pid_t); | 16 typedef CFTypeRef (*LSASNCreateWithPidSpec)(CFAllocatorRef, pid_t); |
66 static bool LaunchServicesGetProcessName(pid_t pid, std::string& result) { | 55 static bool LaunchServicesGetProcessName(pid_t pid, std::string& result) { |
67 if (!LSCopyApplicationInformation || !LSASNCreateWithPid) | 56 if (!LSCopyApplicationInformation || !LSASNCreateWithPid) |
68 if (!GetLaunchServicesPrivateSymbols()) | 57 if (!GetLaunchServicesPrivateSymbols()) |
69 return false; | 58 return false; |
70 | 59 |
71 CFReference<CFTypeRef> asn = LSASNCreateWithPid(kCFAllocatorDefault, pid); | 60 CFTypeRef asn = LSASNCreateWithPid(kCFAllocatorDefault, pid); |
72 | 61 if (!asn) |
73 CFReference<CFArrayRef> request_array = CFArrayCreate(NULL, (const void **)kLSDisplayNameKey, 1, NULL); | 62 return false; |
74 | 63 |
75 CFReference<CFDictionaryRef> dictionary = LSCopyApplicationInformation(kLaunchServicesMagicConstant, asn, request_array.get()); | 64 CFArrayRef request_array = CFArrayCreate(NULL, (const void **)kLSDisplayNameKey, 1, NULL); |
76 if (!dictionary.get()) | 65 if (!request_array) { |
77 return false; | 66 CFRelease(asn); |
78 | 67 return false; |
79 CFReference<CFStringRef> str; | 68 } |
69 | |
70 CFDictionaryRef dictionary = LSCopyApplicationInformation(kLSDefaultSessionID, asn, request_array); | |
71 | |
72 CFRelease(request_array); | |
73 CFRelease(asn); | |
74 | |
75 if (!dictionary) | |
76 return false; | |
77 | |
80 { | 78 { |
81 CFStringRef rstr; | 79 CFStringRef rstr; |
80 | |
82 if (!CFDictionaryGetValueIfPresent(dictionary, kLSDisplayNameKey, (CFTypeRef*)&rstr) || !rstr) | 81 if (!CFDictionaryGetValueIfPresent(dictionary, kLSDisplayNameKey, (CFTypeRef*)&rstr) || !rstr) |
83 return false; | 82 return false; |
84 str.reset(rstr); | 83 |
85 } | 84 if (!StringFromCFString(rstr, result)) { |
86 | 85 CFRelease(rstr); |
87 result.reserve(CFStringGetMaximumSizeForEncoding(CFStringGetLength(str.get()), kCFStringEncodingUTF8) + 1); | 86 return false; |
88 | 87 } |
89 if (!CFStringGetCString(str.get(), &result.front(), result.length(), result.length())) | 88 |
89 CFRelease(rstr); | |
90 } | |
91 | |
92 result.resize(result.find('\0')); | |
93 | |
94 return true; | |
95 } | |
96 | |
97 bool StringFromCFString(CFStringRef string, std::string& result) { | |
98 if (!string) | |
99 return false; | |
100 | |
101 result.resize(CFStringGetMaximumSizeForEncoding(CFStringGetLength(string), kCFStringEncodingUTF8) + 1); | |
102 if (!CFStringGetCString(string, &result.front(), result.length(), kCFStringEncodingUTF8)) | |
90 return false; | 103 return false; |
91 | 104 |
92 return true; | 105 return true; |
93 } | 106 } |
94 #endif // HAVE_COREFOUNDATION | 107 #endif // HAVE_COREFOUNDATION |
96 static bool GetProcessArgs(pid_t pid, std::string& args) { | 109 static bool GetProcessArgs(pid_t pid, std::string& args) { |
97 /* sysctl shouldn't touch these, so we define them as const */ | 110 /* sysctl shouldn't touch these, so we define them as const */ |
98 const int mib[3] = {CTL_KERN, KERN_PROCARGS2, static_cast<int>(pid)}; | 111 const int mib[3] = {CTL_KERN, KERN_PROCARGS2, static_cast<int>(pid)}; |
99 const size_t mib_size = sizeof(mib)/sizeof(*mib); | 112 const size_t mib_size = sizeof(mib)/sizeof(*mib); |
100 | 113 |
101 /* Get the initial size of the array */ | 114 /* Get the initial size of the array |
115 * | |
116 * NOTE: it IS possible for this value to change inbetween calls to sysctl(). | |
117 * Unfortunately, I couldn't care less about handling this. :) | |
118 */ | |
102 size_t size; | 119 size_t size; |
103 { | 120 { |
104 int ret = sysctl((int*)mib, mib_size, nullptr, &size, nullptr, 0); | 121 int ret = sysctl((int*)mib, mib_size, nullptr, &size, nullptr, 0); |
105 if (ret) | 122 if (ret) |
106 return false; | 123 return false; |
119 /* Is the size big enough to hold at least argc? */ | 136 /* Is the size big enough to hold at least argc? */ |
120 if (size < sizeof(int)) | 137 if (size < sizeof(int)) |
121 return false; | 138 return false; |
122 | 139 |
123 args.resize(size); | 140 args.resize(size); |
141 return true; | |
124 } | 142 } |
125 | 143 |
126 static bool GetProcessNameFromArgs(pid_t pid, std::string& result) { | 144 static bool GetProcessNameFromArgs(pid_t pid, std::string& result) { |
127 if (!GetProcessArgs(pid, result)) | 145 if (!GetProcessArgs(pid, result)) |
128 return false; | 146 return false; |
129 | 147 |
130 /* Get argc using memcpy */ | 148 /* Get argc using memcpy */ |
131 int argc; | 149 int argc; |
132 memcpy(&argc, &args.front(), sizeof(argc)); | 150 memcpy(&result, &result.front(), sizeof(argc)); |
133 | 151 |
134 /* Do we even have argv[0]? */ | 152 /* Do we even have argv[0]? */ |
135 if (argc < 1) | 153 if (argc < 1) |
136 return false; | 154 return false; |
137 | 155 |
138 /* Find the first null character */ | 156 /* Find the first null character */ |
139 size_t null_pos = args.find('\0', sizeof(argc)); | 157 size_t null_pos = result.find('\0', sizeof(argc)); |
140 if (null_pos == std::string::npos) | 158 if (null_pos == std::string::npos) |
141 return false; | 159 return false; |
142 | 160 |
143 /* Find the last slash */ | 161 /* Find the last slash */ |
144 size_t last_slash = args.rfind('/', null_pos); | 162 size_t last_slash = result.rfind('/', null_pos); |
145 if (last_slash == std::string::npos) | 163 if (last_slash == std::string::npos) |
146 return false; | 164 return false; |
147 | 165 |
148 /* Return our result */ | 166 /* Return our result */ |
149 result = args.substr(last_slash + 1, null_pos - last_slash - 1); | 167 result = result.substr(last_slash + 1, null_pos - last_slash - 1); |
150 return true; | 168 return true; |
151 } | 169 } |
152 | 170 |
153 static bool GetProcessNameFromKernel(pid_t pid, std::string& result) { | 171 static bool GetProcessNameFromKernel(pid_t pid, std::string& result) { |
154 result.resize(2 * MAXCOMLEN); | 172 result.resize(2 * MAXCOMLEN); |
159 | 177 |
160 result.resize(size); | 178 result.resize(size); |
161 return true; | 179 return true; |
162 } | 180 } |
163 | 181 |
164 static bool GetProcessName(pid_t pid, std::string& result) { | 182 bool GetProcessName(pid_t pid, std::string& result) { |
165 #ifdef HAVE_COREFOUNDATION | 183 #ifdef HAVE_COREFOUNDATION |
166 if (LaunchServicesGetProcessName(pid, result)) | 184 if (LaunchServicesGetProcessName(pid, result)) |
167 return true; | 185 return true; |
168 #endif // HAVE_COREFOUNDATION | 186 #endif // HAVE_COREFOUNDATION |
169 | 187 |