Mercurial > minori
comparison 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 |
comparison
equal
deleted
inserted
replaced
162:61b76c7b656a | 163:44c5e6dd9488 |
---|---|
1 /* A wrapper around multiple LaunchServices things */ | |
2 | |
3 #include "animia/util/osx.h" | 1 #include "animia/util/osx.h" |
4 | 2 |
3 #ifdef HAVE_COREFOUNDATION | |
5 #include <CoreFoundation/CoreFoundation.h> | 4 #include <CoreFoundation/CoreFoundation.h> |
6 | 5 #endif |
7 #include <iostream> | |
8 | 6 |
9 namespace animia::internal::osx::util { | 7 namespace animia::internal::osx::util { |
10 | 8 |
11 #define RDSymbolNameStr(symbol) (CFSTR("_"#symbol)) | 9 #ifdef HAVE_COREFOUNDATION |
10 /* All of these LaunchServices things use *internal functions* that are subject | |
11 ** to change. Granted, it's not very likely that these will change very much | |
12 ** because I'm fairly sure Apple uses them lots in their own internal code. | |
13 */ | |
12 | 14 |
13 static constexpr int kLaunchServicesMagicConstant = -2; // or -1, dunno the difference | 15 /* from RDProcess */ |
14 | |
15 typedef CFTypeRef (*LSASNCreateWithPidSpec)(CFAllocatorRef, pid_t); | 16 typedef CFTypeRef (*LSASNCreateWithPidSpec)(CFAllocatorRef, pid_t); |
16 typedef CFDictionaryRef (*LSCopyApplicationInformationSpec)(int, CFTypeRef, CFArrayRef); | 17 typedef CFDictionaryRef (*LSCopyApplicationInformationSpec)(int, CFTypeRef, CFArrayRef); |
17 | 18 |
18 static LSCopyApplicationInformationSpec LSCopyApplicationInformation = nullptr; | 19 static LSCopyApplicationInformationSpec LSCopyApplicationInformation = nullptr; |
19 static LSASNCreateWithPidSpec LSASNCreateWithPid = nullptr; | 20 static LSASNCreateWithPidSpec LSASNCreateWithPid = nullptr; |
20 | 21 |
21 static CFStringRef (kLSDisplayNameKey) = nullptr; | 22 /* retrieved from LaunchServicesSPI.h in WebKit */ |
22 static CFStringRef (kLSPIDKey) = nullptr; | 23 static constexpr int kLSDefaultSessionID = -2; |
24 static const CFStringRef kLaunchServicesBundleID = CFSTR("com.apple.LaunchServices"); | |
23 | 25 |
24 static CFStringRef (kLaunchServicesBundleID) = CFSTR("com.apple.LaunchServices"); | 26 /* retrieved dynamically */ |
27 static CFStringRef kLSDisplayNameKey = nullptr; | |
28 static CFStringRef kLSPIDKey = nullptr; | |
25 | 29 |
26 static bool FindLaunchServicesPrivateSymbols() { | 30 static bool GetLaunchServicesPrivateSymbols() { |
27 CFBundleRef launch_services_bundle = CFBundleGetBundleWithIdentifier(kLaunchServicesBundleID); | 31 CFBundleRef launch_services_bundle = CFBundleGetBundleWithIdentifier(kLaunchServicesBundleID); |
28 if (!launch_services_bundle) | 32 if (!launch_services_bundle) |
29 return false; | 33 return false; |
30 | 34 |
31 LSCopyApplicationInformation = (LSCopyApplicationInformationSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, RDSymbolNameStr(LSCopyApplicationInformation)); | 35 LSCopyApplicationInformation = (LSCopyApplicationInformationSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, CFSTR("_LSCopyApplicationInformation")); |
32 if (!LSCopyApplicationInformation) | 36 if (!LSCopyApplicationInformation) |
33 return false; | 37 return false; |
34 | 38 |
35 LSASNCreateWithPid = (LSASNCreateWithPidSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, RDSymbolNameStr(LSASNCreateWithPid)); | 39 LSASNCreateWithPid = (LSASNCreateWithPidSpec)CFBundleGetFunctionPointerForName(launch_services_bundle, CFSTR("_LSASNCreateWithPid")); |
36 if (!LSASNCreateWithPid) | 40 if (!LSASNCreateWithPid) |
37 return false; | 41 return false; |
38 | 42 |
39 kLSDisplayNameKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, RDSymbolNameStr(kLSDisplayNameKey)); | 43 kLSDisplayNameKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, CFSTR("_kLSDisplayNameKey")); |
40 if (!kLSDisplayNameKey) | 44 if (!kLSDisplayNameKey) |
41 return false; | 45 return false; |
42 | 46 |
43 kLSPIDKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, RDSymbolNameStr(kLSPIDKey)); | 47 kLSPIDKey = *(CFStringRef*)CFBundleGetDataPointerForName(launch_services_bundle, CFSTR("_kLSPIDKey")); |
44 if (!kLSPIDKey) | 48 if (!kLSPIDKey) |
45 return false; | 49 return false; |
46 | 50 |
47 return true; | 51 return true; |
48 } | 52 } |
49 | 53 |
50 bool LaunchServicesGetProcessName(pid_t pid, std::string& result) { | 54 static bool LaunchServicesGetProcessName(pid_t pid, std::string& result) { |
51 if (!LSCopyApplicationInformation || !LSASNCreateWithPid) | 55 if (!LSCopyApplicationInformation || !LSASNCreateWithPid) |
52 if (!FindLaunchServicesPrivateSymbols()) | 56 if (!GetLaunchServicesPrivateSymbols()) |
53 return false; | 57 return false; |
54 | 58 |
55 CFTypeRef asn = LSASNCreateWithPid(kCFAllocatorDefault, pid); | 59 CFTypeRef asn = LSASNCreateWithPid(kCFAllocatorDefault, pid); |
56 | 60 |
57 CFArrayRef request_array = CFArrayCreate(NULL, (const void **)kLSDisplayNameKey, 1, NULL); | 61 CFArrayRef request_array = CFArrayCreate(NULL, (const void **)kLSDisplayNameKey, 1, NULL); |
80 | 84 |
81 CFRelease(str); | 85 CFRelease(str); |
82 | 86 |
83 return true; | 87 return true; |
84 } | 88 } |
89 #endif // HAVE_COREFOUNDATION | |
90 | |
91 static bool GetProcessArgs(pid_t pid, std::string& args) { | |
92 /* sysctl shouldn't touch these, so we define them as const */ | |
93 const int mib[3] = {CTL_KERN, KERN_PROCARGS2, static_cast<int>(pid)}; | |
94 const size_t mib_size = sizeof(mib)/sizeof(*mib); | |
95 | |
96 /* Get the initial size of the array */ | |
97 size_t size; | |
98 { | |
99 int ret = sysctl((int*)mib, mib_size, nullptr, &size, nullptr, 0); | |
100 if (ret) | |
101 return false; | |
102 } | |
103 | |
104 /* Reserve the space for it in args */ | |
105 args.resize(size); | |
106 | |
107 /* Get the contents of argc and argv */ | |
108 { | |
109 int ret = sysctl((int*)mib, mib_size, &args.front(), &size, NULL, 0); | |
110 if (ret) | |
111 return false; | |
112 } | |
113 | |
114 /* Is the size big enough to hold at least argc? */ | |
115 if (size < sizeof(int)) | |
116 return false; | |
117 | |
118 args.resize(size); | |
119 } | |
120 | |
121 static bool GetProcessNameFromArgs(pid_t pid, std::string& result) { | |
122 if (!GetProcessArgs(pid, result)) | |
123 return false; | |
124 | |
125 /* Get argc using memcpy */ | |
126 int argc; | |
127 memcpy(&argc, &args.front(), sizeof(argc)); | |
128 | |
129 /* Do we even have argv[0]? */ | |
130 if (argc < 1) | |
131 return false; | |
132 | |
133 /* Find the first null character */ | |
134 size_t null_pos = args.find('\0', sizeof(argc)); | |
135 if (null_pos == std::string::npos) | |
136 return false; | |
137 | |
138 /* Find the last slash */ | |
139 size_t last_slash = args.rfind('/', null_pos); | |
140 if (last_slash == std::string::npos) | |
141 return false; | |
142 | |
143 /* Return our result */ | |
144 result = args.substr(last_slash + 1, null_pos - last_slash - 1); | |
145 return true; | |
146 } | |
147 | |
148 static bool GetProcessNameFromKernel(pid_t pid, std::string& result) { | |
149 result.reserve(2*MAXCOMLEN); | |
150 if (!proc_name(pid, &result.front(), result.length())) | |
151 return false; | |
152 | |
153 result.shrink_to_fit(); | |
154 return true; | |
155 } | |
156 | |
157 static bool GetProcessName(pid_t pid, std::string& result) { | |
158 #ifdef HAVE_COREFOUNDATION | |
159 if (LaunchServicesGetProcessName(pid, result)) | |
160 return true; | |
161 #endif // HAVE_COREFOUNDATION | |
162 | |
163 /* Try parsing the arguments, this prevents the process name being | |
164 cut off to 2*MAXCOMLEN (32 chars) */ | |
165 if (GetProcessNameFromArgs(pid, result)) | |
166 return true; | |
167 | |
168 /* Then attempt getting it from the kernel, which results in the | |
169 process name being cut to 32 chars (worse, 16 chars if p_name is | |
170 unavailable) */ | |
171 if (GetProcessNameFromKernel(pid, result)) | |
172 return true; | |
173 | |
174 return false; | |
175 } | |
85 | 176 |
86 } | 177 } |