1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 * Permission is hereby granted, free of charge, to any person obtaining a copy 3 * of this software and associated documentation files (the "Software"), to 4 * deal in the Software without restriction, including without limitation the 5 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 6 * sell copies of the Software, and to permit persons to whom the Software is 7 * furnished to do so, subject to the following conditions: 8 * 9 * The above copyright notice and this permission notice shall be included in 10 * all copies or substantial portions of the Software. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 18 * IN THE SOFTWARE. 19 */ 20 21 #include "uv.h" 22 #include "internal.h" 23 24 #include <dlfcn.h> 25 #include <errno.h> 26 #include <pthread.h> 27 #include <stdlib.h> 28 #include <string.h> 29 30 #include <TargetConditionals.h> 31 32 #if !TARGET_OS_IPHONE 33 #include "darwin-stub.h" 34 #endif 35 36 37 static int uv__pthread_setname_np(const char* name) { 38 char namebuf[64]; /* MAXTHREADNAMESIZE */ 39 int err; 40 41 strncpy(namebuf, name, sizeof(namebuf) - 1); 42 namebuf[sizeof(namebuf) - 1] = '\0'; 43 44 err = pthread_setname_np(namebuf); 45 if (err) 46 return UV__ERR(err); 47 48 return 0; 49 } 50 51 52 int uv__set_process_title(const char* title) { 53 #if TARGET_OS_IPHONE 54 return uv__pthread_setname_np(title); 55 #else 56 CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, 57 const char*, 58 CFStringEncoding); 59 CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); 60 void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); 61 void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); 62 CFTypeRef (*pLSGetCurrentApplicationASN)(void); 63 OSStatus (*pLSSetApplicationInformationItem)(int, 64 CFTypeRef, 65 CFStringRef, 66 CFStringRef, 67 CFDictionaryRef*); 68 void* application_services_handle; 69 void* core_foundation_handle; 70 CFBundleRef launch_services_bundle; 71 CFStringRef* display_name_key; 72 CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); 73 CFBundleRef (*pCFBundleGetMainBundle)(void); 74 CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); 75 void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, 76 void*); 77 CFTypeRef asn; 78 int err; 79 80 err = UV_ENOENT; 81 application_services_handle = dlopen("/System/Library/Frameworks/" 82 "ApplicationServices.framework/" 83 "Versions/A/ApplicationServices", 84 RTLD_LAZY | RTLD_LOCAL); 85 core_foundation_handle = dlopen("/System/Library/Frameworks/" 86 "CoreFoundation.framework/" 87 "Versions/A/CoreFoundation", 88 RTLD_LAZY | RTLD_LOCAL); 89 90 if (application_services_handle == NULL || core_foundation_handle == NULL) 91 goto out; 92 93 *(void **)(&pCFStringCreateWithCString) = 94 dlsym(core_foundation_handle, "CFStringCreateWithCString"); 95 *(void **)(&pCFBundleGetBundleWithIdentifier) = 96 dlsym(core_foundation_handle, "CFBundleGetBundleWithIdentifier"); 97 *(void **)(&pCFBundleGetDataPointerForName) = 98 dlsym(core_foundation_handle, "CFBundleGetDataPointerForName"); 99 *(void **)(&pCFBundleGetFunctionPointerForName) = 100 dlsym(core_foundation_handle, "CFBundleGetFunctionPointerForName"); 101 102 if (pCFStringCreateWithCString == NULL || 103 pCFBundleGetBundleWithIdentifier == NULL || 104 pCFBundleGetDataPointerForName == NULL || 105 pCFBundleGetFunctionPointerForName == NULL) { 106 goto out; 107 } 108 109 #define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) 110 111 launch_services_bundle = 112 pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices")); 113 114 if (launch_services_bundle == NULL) 115 goto out; 116 117 *(void **)(&pLSGetCurrentApplicationASN) = 118 pCFBundleGetFunctionPointerForName(launch_services_bundle, 119 S("_LSGetCurrentApplicationASN")); 120 121 if (pLSGetCurrentApplicationASN == NULL) 122 goto out; 123 124 *(void **)(&pLSSetApplicationInformationItem) = 125 pCFBundleGetFunctionPointerForName(launch_services_bundle, 126 S("_LSSetApplicationInformationItem")); 127 128 if (pLSSetApplicationInformationItem == NULL) 129 goto out; 130 131 display_name_key = pCFBundleGetDataPointerForName(launch_services_bundle, 132 S("_kLSDisplayNameKey")); 133 134 if (display_name_key == NULL || *display_name_key == NULL) 135 goto out; 136 137 *(void **)(&pCFBundleGetInfoDictionary) = dlsym(core_foundation_handle, 138 "CFBundleGetInfoDictionary"); 139 *(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle, 140 "CFBundleGetMainBundle"); 141 if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) 142 goto out; 143 144 *(void **)(&pLSApplicationCheckIn) = pCFBundleGetFunctionPointerForName( 145 launch_services_bundle, 146 S("_LSApplicationCheckIn")); 147 148 if (pLSApplicationCheckIn == NULL) 149 goto out; 150 151 *(void **)(&pLSSetApplicationLaunchServicesServerConnectionStatus) = 152 pCFBundleGetFunctionPointerForName( 153 launch_services_bundle, 154 S("_LSSetApplicationLaunchServicesServerConnectionStatus")); 155 156 if (pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) 157 goto out; 158 159 pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); 160 161 /* Check into process manager?! */ 162 pLSApplicationCheckIn(-2, 163 pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); 164 165 asn = pLSGetCurrentApplicationASN(); 166 167 err = UV_EBUSY; 168 if (asn == NULL) 169 goto out; 170 171 err = UV_EINVAL; 172 if (pLSSetApplicationInformationItem(-2, /* Magic value. */ 173 asn, 174 *display_name_key, 175 S(title), 176 NULL) != noErr) { 177 goto out; 178 } 179 180 uv__pthread_setname_np(title); /* Don't care if it fails. */ 181 err = 0; 182 183 out: 184 if (core_foundation_handle != NULL) 185 dlclose(core_foundation_handle); 186 187 if (application_services_handle != NULL) 188 dlclose(application_services_handle); 189 190 return err; 191 #endif /* !TARGET_OS_IPHONE */ 192 } 193