diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2019-07-14 09:54:20 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2019-07-14 09:54:20 +0100 |
commit | 7a356c782ee05cf9b942e92e381f453d205a9cc1 (patch) | |
tree | f1766647dc01802cea4d18f084a6cdb875adc6c3 /src/libutil/util.c | |
parent | 7fadb1f3c8ffcfb2d392cf7b5386b7ab7c82b722 (diff) | |
download | rspamd-7a356c782ee05cf9b942e92e381f453d205a9cc1.tar.gz rspamd-7a356c782ee05cf9b942e92e381f453d205a9cc1.zip |
[Minor] Try better to set proctitle on darwin
Diffstat (limited to 'src/libutil/util.c')
-rw-r--r-- | src/libutil/util.c | 340 |
1 files changed, 274 insertions, 66 deletions
diff --git a/src/libutil/util.c b/src/libutil/util.c index 1f83194ad..86358e46e 100644 --- a/src/libutil/util.c +++ b/src/libutil/util.c @@ -785,102 +785,221 @@ rspamd_pass_signal (GHashTable * workers, gint signo) #ifndef HAVE_SETPROCTITLE -#if !defined(DARWIN) && !defined(SOLARIS) && !defined(__APPLE__) +#ifdef LINUX static gchar *title_buffer = 0; static size_t title_buffer_size = 0; static gchar *title_progname, *title_progname_full; #endif -gint -setproctitle (const gchar *fmt, ...) +#ifdef LINUX +static void +rspamd_title_dtor (gpointer d) { -#if defined(DARWIN) || defined(SOLARIS) || defined(__APPLE__) - GString *dest; - va_list ap; + gchar **env = (gchar **)d; + guint i; - dest = g_string_new (""); - va_start (ap, fmt); - rspamd_vprintf_gstring (dest, fmt, ap); - va_end (ap); + for (i = 0; env[i] != NULL; i++) { + g_free (env[i]); + } - g_set_prgname (dest->str); - g_string_free (dest, TRUE); + g_free (env); +} +#endif - return 0; -#else - if (!title_buffer || !title_buffer_size) { - errno = ENOMEM; - return -1; +#ifdef __APPLE__ + +/* Code is based on darwin-proctitle.c used almost everywhere */ + +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <dlfcn.h> +#include <TargetConditionals.h> +#include <CoreFoundation/CoreFoundation.h> +#include <ApplicationServices/ApplicationServices.h> + +/* Darwin is just brain damaged */ +static int (*dynamic_pthread_setname_np)(const char* name); +static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, + const char*, + CFStringEncoding); +static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); +static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); +static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); +static CFTypeRef (*pLSGetCurrentApplicationASN)(void); +static OSStatus (*pLSSetApplicationInformationItem)(int, + CFTypeRef, + CFStringRef, + CFStringRef, + CFDictionaryRef*); +static CFBundleRef launch_services_bundle; +static CFStringRef* display_name_key; +static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); +static CFBundleRef (*pCFBundleGetMainBundle)(void); +static CFBundleRef hi_services_bundle; +static OSStatus (*pSetApplicationIsDaemon)(int); +static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); +static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, + void*); +#define APPLE_S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) +/* Dlfunc handles */ +struct rspamd_osx_handles { + gpointer application_services_handle; + gpointer core_foundation_handle; +}; + +static +void rspamd_darwin_title_dtor (void *ud) +{ + struct rspamd_osx_handles *hdls = (struct rspamd_osx_handles *)ud; + + if (hdls->core_foundation_handle != NULL) { + dlclose (hdls->core_foundation_handle); } - memset (title_buffer, '\0', title_buffer_size); + if (hdls->application_services_handle != NULL) { + dlclose (hdls->application_services_handle); + } +} - ssize_t written; +static void +rspamd_darwin_init_title (struct rspamd_main *rspamd_main) +{ + struct rspamd_osx_handles *hdls; + /* Assumed that pthreads are already linked */ + *(void **)(&dynamic_pthread_setname_np) = + dlsym (RTLD_DEFAULT, "pthread_setname_np"); + + hdls = rspamd_mempool_alloc0 (rspamd_main->server_pool, sizeof (*hdls)); + + hdls->application_services_handle = dlopen("/System/Library/Frameworks/" + "ApplicationServices.framework/" + "Versions/A/ApplicationServices", + RTLD_LAZY | RTLD_LOCAL); + hdls->core_foundation_handle = dlopen("/System/Library/Frameworks/" + "CoreFoundation.framework/" + "Versions/A/CoreFoundation", + RTLD_LAZY | RTLD_LOCAL); + + if (hdls->application_services_handle == NULL || + hdls->core_foundation_handle == NULL) { + goto out; + } - if (fmt) { - ssize_t written2; - va_list ap; + /* Fill procedures via dlsym */ + *(void **)(&pCFStringCreateWithCString) = + dlsym (hdls->core_foundation_handle, "CFStringCreateWithCString"); + *(void **)(&pCFBundleGetBundleWithIdentifier) = + dlsym (hdls->core_foundation_handle, "CFBundleGetBundleWithIdentifier"); + *(void **)(&pCFBundleGetDataPointerForName) = + dlsym (hdls->core_foundation_handle, "CFBundleGetDataPointerForName"); + *(void **)(&pCFBundleGetFunctionPointerForName) = + dlsym (hdls->core_foundation_handle, "CFBundleGetFunctionPointerForName"); + + if (pCFStringCreateWithCString == NULL || + pCFBundleGetBundleWithIdentifier == NULL || + pCFBundleGetDataPointerForName == NULL || + pCFBundleGetFunctionPointerForName == NULL) { + goto out; + } - written = snprintf (title_buffer, - title_buffer_size, - "%s: ", - title_progname); - if (written < 0 || (size_t) written >= title_buffer_size) - return -1; + launch_services_bundle = + pCFBundleGetBundleWithIdentifier(APPLE_S("com.apple.LaunchServices")); - va_start (ap, fmt); - written2 = vsnprintf (title_buffer + written, - title_buffer_size - written, - fmt, - ap); - va_end (ap); - if (written2 < 0 || (size_t) written2 >= title_buffer_size - written) - return -1; + if (launch_services_bundle == NULL) { + goto out; } - else { - written = snprintf (title_buffer, - title_buffer_size, - "%s", - title_progname); - if (written < 0 || (size_t) written >= title_buffer_size) - return -1; + + *(void **)(&pLSGetCurrentApplicationASN) = + pCFBundleGetFunctionPointerForName(launch_services_bundle, + APPLE_S("_LSGetCurrentApplicationASN")); + + if (pLSGetCurrentApplicationASN == NULL) { + goto out; } - written = strlen (title_buffer); - memset (title_buffer + written, '\0', title_buffer_size - written); + *(void **)(&pLSSetApplicationInformationItem) = + pCFBundleGetFunctionPointerForName(launch_services_bundle, + APPLE_S("_LSSetApplicationInformationItem")); - return 0; -#endif -} + if (pLSSetApplicationInformationItem == NULL) { + goto out; + } -#if !(defined(DARWIN) || defined(SOLARIS) || defined(__APPLE__)) -static void -rspamd_title_dtor (gpointer d) -{ - gchar **env = (gchar **)d; - guint i; + display_name_key = pCFBundleGetDataPointerForName(launch_services_bundle, + APPLE_S("_kLSDisplayNameKey")); - for (i = 0; env[i] != NULL; i++) { - g_free (env[i]); + if (display_name_key == NULL || *display_name_key == NULL) { + goto out; } - g_free (env); + *(void **)(&pCFBundleGetInfoDictionary) = dlsym (hdls->core_foundation_handle, + "CFBundleGetInfoDictionary"); + *(void **)(&pCFBundleGetMainBundle) = dlsym (hdls->core_foundation_handle, + "CFBundleGetMainBundle"); + + if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) { + goto out; + } + + /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */ + hi_services_bundle = + pCFBundleGetBundleWithIdentifier(APPLE_S("com.apple.HIServices")); + + if (hi_services_bundle == NULL) { + goto out; + } + + *(void **)(&pSetApplicationIsDaemon) = pCFBundleGetFunctionPointerForName( + hi_services_bundle, + APPLE_S("SetApplicationIsDaemon")); + *(void **)(&pLSApplicationCheckIn) = pCFBundleGetFunctionPointerForName( + launch_services_bundle, + APPLE_S("_LSApplicationCheckIn")); + *(void **)(&pLSSetApplicationLaunchServicesServerConnectionStatus) = + pCFBundleGetFunctionPointerForName( + launch_services_bundle, + APPLE_S("_LSSetApplicationLaunchServicesServerConnectionStatus")); + + if (pSetApplicationIsDaemon == NULL || + pLSApplicationCheckIn == NULL || + pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) { + goto out; + } + + rspamd_mempool_add_destructor (rspamd_main->server_pool, + rspamd_darwin_title_dtor, hdls); + + return; + +out: + rspamd_darwin_title_dtor (hdls); } -#endif -/* - It has to be _init function, because __attribute__((constructor)) - functions gets called without arguments. - */ +#endif gint init_title (struct rspamd_main *rspamd_main, gint argc, gchar *argv[], gchar *envp[]) { -#if defined(DARWIN) || defined(SOLARIS) || defined(__APPLE__) - /* XXX: try to handle these OSes too */ - return 0; -#else +#ifdef LINUX gchar *begin_of_buffer = 0, *end_of_buffer = 0; gint i; @@ -936,10 +1055,99 @@ init_title (struct rspamd_main *rspamd_main, rspamd_mempool_add_destructor (rspamd_main->server_pool, rspamd_title_dtor, new_environ); +#elif defined(__APPLE__) + rspamd_darwin_init_title (rspamd_main); +#endif return 0; +} + +gint +setproctitle (const gchar *fmt, ...) +{ +#if defined(LINUX) + if (!title_buffer || !title_buffer_size) { + errno = ENOMEM; + return -1; + } + + memset (title_buffer, '\0', title_buffer_size); + + ssize_t written; + + if (fmt) { + ssize_t written2; + va_list ap; + + written = rspamd_snprintf (title_buffer, + title_buffer_size, + "%s: ", + title_progname); + if (written < 0 || (size_t) written >= title_buffer_size) + return -1; + + va_start (ap, fmt); + written2 = rspamd_vsnprintf (title_buffer + written, + title_buffer_size - written, + fmt, + ap); + va_end (ap); + if (written2 < 0 || (size_t) written2 >= title_buffer_size - written) + return -1; + } + else { + written = rspamd_snprintf (title_buffer, + title_buffer_size, + "%s", + title_progname); + if (written < 0 || (size_t) written >= title_buffer_size) + return -1; + } + + written = strlen (title_buffer); + memset (title_buffer + written, '\0', title_buffer_size - written); +#elif defined(__APPLE__) + static gchar titlebuf[128]; + + va_list ap; + int r; + va_start (ap, fmt); + r = rspamd_snprintf (titlebuf, sizeof (titlebuf), "rspamd: "); + rspamd_vsnprintf (titlebuf + r, sizeof (titlebuf) - r, fmt, ap); + va_end (ap); + + if (pSetApplicationIsDaemon != NULL && pSetApplicationIsDaemon (1) != noErr) { + CFTypeRef asn; + pLSSetApplicationLaunchServicesServerConnectionStatus (0, NULL); + pLSApplicationCheckIn (/* Magic value */ -2, + pCFBundleGetInfoDictionary (pCFBundleGetMainBundle())); + asn = pLSGetCurrentApplicationASN (); + pLSSetApplicationInformationItem (/* Magic value */ -2, asn, + *display_name_key, APPLE_S (titlebuf), NULL); + } + + if (dynamic_pthread_setname_np != NULL) { + char namebuf[64]; /* MAXTHREADNAMESIZE */ + rspamd_strlcpy (namebuf, titlebuf, sizeof(namebuf)); + dynamic_pthread_setname_np (namebuf); + } +#else + /* Last resort (usually broken, but eh...) */ + GString *dest; + va_list ap; + + dest = g_string_new (""); + va_start (ap, fmt); + rspamd_vprintf_gstring (dest, fmt, ap); + va_end (ap); + + g_set_prgname (dest->str); + g_string_free (dest, TRUE); + #endif + return 0; } + #endif #ifndef HAVE_PIDFILE |