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 |
