]> source.dussan.org Git - rspamd.git/commitdiff
[Minor] Try better to set proctitle on darwin
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 14 Jul 2019 08:54:20 +0000 (09:54 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 14 Jul 2019 08:54:20 +0000 (09:54 +0100)
src/libutil/util.c

index 1f83194ad77544ee0cca9f5c9ca608912d4c348d..86358e46eba090fcc3ef06c4f540c23ca051902b 100644 (file)
@@ -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