Mercurial > minori
diff dep/animia/src/util/osx.cc @ 163:44c5e6dd9488
dep/animia/osx: move GetProcessName to util/osx so we can use it in quartz
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Sat, 18 Nov 2023 00:47:40 -0500 |
parents | 61b76c7b656a |
children | 8937fb7f2d66 |
line wrap: on
line diff
--- a/dep/animia/src/util/osx.cc Fri Nov 17 16:49:57 2023 -0500 +++ b/dep/animia/src/util/osx.cc Sat Nov 18 00:47:40 2023 -0500 @@ -1,55 +1,59 @@ -/* A wrapper around multiple LaunchServices things */ - #include "animia/util/osx.h" +#ifdef HAVE_COREFOUNDATION #include <CoreFoundation/CoreFoundation.h> - -#include <iostream> +#endif namespace animia::internal::osx::util { -#define RDSymbolNameStr(symbol) (CFSTR("_"#symbol)) +#ifdef HAVE_COREFOUNDATION +/* All of these LaunchServices things use *internal functions* that are subject +** to change. Granted, it's not very likely that these will change very much +** because I'm fairly sure Apple uses them lots in their own internal code. +*/ -static constexpr int kLaunchServicesMagicConstant = -2; // or -1, dunno the difference - +/* from RDProcess */ typedef CFTypeRef (*LSASNCreateWithPidSpec)(CFAllocatorRef, pid_t); typedef CFDictionaryRef (*LSCopyApplicationInformationSpec)(int, CFTypeRef, CFArrayRef); static LSCopyApplicationInformationSpec LSCopyApplicationInformation = nullptr; static LSASNCreateWithPidSpec LSASNCreateWithPid = nullptr; -static CFStringRef (kLSDisplayNameKey) = nullptr; -static CFStringRef (kLSPIDKey) = nullptr; +/* retrieved from LaunchServicesSPI.h in WebKit */ +static constexpr int kLSDefaultSessionID = -2; +static const CFStringRef kLaunchServicesBundleID = CFSTR("com.apple.LaunchServices"); -static CFStringRef (kLaunchServicesBundleID) = CFSTR("com.apple.LaunchServices"); +/* retrieved dynamically */ +static CFStringRef kLSDisplayNameKey = nullptr; +static CFStringRef kLSPIDKey = nullptr; -static bool FindLaunchServicesPrivateSymbols() { +static bool GetLaunchServicesPrivateSymbols() { CFBundleRef launch_services_bundle = CFBundleGetBundleWithIdentifier(kLaunchServicesBundleID); if (!launch_services_bundle) return false; - LSCopyApplicationInformation = (LSCopyApplicationInformationSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, RDSymbolNameStr(LSCopyApplicationInformation)); + LSCopyApplicationInformation = (LSCopyApplicationInformationSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, CFSTR("_LSCopyApplicationInformation")); if (!LSCopyApplicationInformation) return false; - LSASNCreateWithPid = (LSASNCreateWithPidSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, RDSymbolNameStr(LSASNCreateWithPid)); + LSASNCreateWithPid = (LSASNCreateWithPidSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, CFSTR("_LSASNCreateWithPid")); if (!LSASNCreateWithPid) return false; - kLSDisplayNameKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, RDSymbolNameStr(kLSDisplayNameKey)); + kLSDisplayNameKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, CFSTR("_kLSDisplayNameKey")); if (!kLSDisplayNameKey) return false; - kLSPIDKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, RDSymbolNameStr(kLSPIDKey)); + kLSPIDKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, CFSTR("_kLSPIDKey")); if (!kLSPIDKey) return false; return true; } -bool LaunchServicesGetProcessName(pid_t pid, std::string& result) { +static bool LaunchServicesGetProcessName(pid_t pid, std::string& result) { if (!LSCopyApplicationInformation || !LSASNCreateWithPid) - if (!FindLaunchServicesPrivateSymbols()) + if (!GetLaunchServicesPrivateSymbols()) return false; CFTypeRef asn = LSASNCreateWithPid(kCFAllocatorDefault, pid); @@ -82,5 +86,92 @@ return true; } +#endif // HAVE_COREFOUNDATION + +static bool GetProcessArgs(pid_t pid, std::string& args) { + /* sysctl shouldn't touch these, so we define them as const */ + const int mib[3] = {CTL_KERN, KERN_PROCARGS2, static_cast<int>(pid)}; + const size_t mib_size = sizeof(mib)/sizeof(*mib); + + /* Get the initial size of the array */ + size_t size; + { + int ret = sysctl((int*)mib, mib_size, nullptr, &size, nullptr, 0); + if (ret) + return false; + } + + /* Reserve the space for it in args */ + args.resize(size); + + /* Get the contents of argc and argv */ + { + int ret = sysctl((int*)mib, mib_size, &args.front(), &size, NULL, 0); + if (ret) + return false; + } + + /* Is the size big enough to hold at least argc? */ + if (size < sizeof(int)) + return false; + + args.resize(size); +} + +static bool GetProcessNameFromArgs(pid_t pid, std::string& result) { + if (!GetProcessArgs(pid, result)) + return false; + + /* Get argc using memcpy */ + int argc; + memcpy(&argc, &args.front(), sizeof(argc)); + + /* Do we even have argv[0]? */ + if (argc < 1) + return false; + + /* Find the first null character */ + size_t null_pos = args.find('\0', sizeof(argc)); + if (null_pos == std::string::npos) + return false; + + /* Find the last slash */ + size_t last_slash = args.rfind('/', null_pos); + if (last_slash == std::string::npos) + return false; + + /* Return our result */ + result = args.substr(last_slash + 1, null_pos - last_slash - 1); + return true; +} + +static bool GetProcessNameFromKernel(pid_t pid, std::string& result) { + result.reserve(2*MAXCOMLEN); + if (!proc_name(pid, &result.front(), result.length())) + return false; + + result.shrink_to_fit(); + return true; +} + +static bool GetProcessName(pid_t pid, std::string& result) { +#ifdef HAVE_COREFOUNDATION + if (LaunchServicesGetProcessName(pid, result)) + return true; +#endif // HAVE_COREFOUNDATION + + /* Try parsing the arguments, this prevents the process name being + cut off to 2*MAXCOMLEN (32 chars) */ + if (GetProcessNameFromArgs(pid, result)) + return true; + + /* Then attempt getting it from the kernel, which results in the + process name being cut to 32 chars (worse, 16 chars if p_name is + unavailable) */ + if (GetProcessNameFromKernel(pid, result)) + return true; + + return false; +} }