]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Fixed Linux proctitle hack and enabled it by default now.
authorTimo Sirainen <tss@iki.fi>
Mon, 26 Oct 2009 22:52:10 +0000 (18:52 -0400)
committerTimo Sirainen <tss@iki.fi>
Mon, 26 Oct 2009 22:52:10 +0000 (18:52 -0400)
--HG--
branch : HEAD

configure.in
src/lib-master/master-service.c
src/lib/process-title.c
src/lib/process-title.h
src/util/rawlog.c

index e99db0ccf8ba49c1fe10f7cf754cb6e39b09aaa1..d8867dbf42e0f348d641d4a83966e3f20c1a0cdc 100644 (file)
@@ -588,6 +588,9 @@ case "$host_os" in
                LIBS="-lxnet $LIBS"
                AC_DEFINE(PREAD_BROKEN,, Defint if pread/pwrite implementation is broken)
                ;;
+       linux*)
+               AC_DEFINE(PROCTITLE_HACK,, Define if process title can be changed by modifying argv)
+               ;;
        *)
                ;;
 esac
index ff7efede8989da16b59e5af582420f775427ffb7..4c86a89007e62e1383d70883d9c116901de61e6d 100644 (file)
@@ -85,7 +85,6 @@ struct master_service *
 master_service_init(const char *name, enum master_service_flags flags,
                    int *argc, char **argv[], const char *getopt_str)
 {
-       extern char **environ;
        struct master_service *service;
        const char *str;
 
@@ -112,7 +111,7 @@ master_service_init(const char *name, enum master_service_flags flags,
        if (getenv(MASTER_UID_ENV) == NULL)
                flags |= MASTER_SERVICE_FLAG_STANDALONE;
 
-       process_title_init(argv, environ);
+       process_title_init(argv);
 
        service = i_new(struct master_service, 1);
        service->argc = *argc;
index 69f7d56680e9783c2f6a3faf19c1f0eb4b194563..c247367c750cb0529ec4fd85cef6675f988baca0 100644 (file)
@@ -1,51 +1,55 @@
 /* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
 
-/*
-   LINUX_PROCTITLE_HACK code from:
-   http://lightconsulting.com/~thalakan/process-title-notes.html
-*/
-
 #include "lib.h"
 #include "process-title.h"
 
 #include <stdlib.h> /* NetBSD, OpenBSD */
 #include <unistd.h> /* FreeBSD */
 
-/* NOTE: This really is a horrible hack, I don't recommend using it for
-   anything else than debugging. */
-/*#define LINUX_PROCTITLE_HACK*/
-
 static char *process_name = NULL;
 
-#ifdef LINUX_PROCTITLE_HACK
-static char *process_title;
-static size_t process_title_len;
+#ifdef HAVE_SETPROCTITLE
+#  undef PROCTITLE_HACK
+#endif
 
-static void linux_proctitle_init(char *argv[], char *envp[])
-{
-       extern char **environ;
-       char **p;
-       int i;
+#ifdef PROCTITLE_HACK
 
-       /* copy environment elsewhere */
-       for (i = 0; envp[i] != NULL; i++)
-               ;
+#define PROCTITLE_CLEAR_CHAR 0xab
 
-       if ((p = malloc((i + 1) * sizeof(char *))) == NULL)
-               i_fatal_status(FATAL_OUTOFMEM, "malloc() failed: %m");
-       environ = p;
+static char *process_title;
+static size_t process_title_len, process_title_clean_pos;
 
-       for (i = 0; envp[i] != NULL; i++) {
-               if ((environ[i] = strdup(envp[i])) == NULL)
-                       i_fatal_status(FATAL_OUTOFMEM, "strdup() failed: %m");
+static void proctitle_hack_init(char *argv[], char *env[])
+{
+       char *last;
+       unsigned int i;
+       bool clear_env;
+
+       /* find the last argv or environment string. it should always be the
+          last string in environ, but don't rely on it. this is what openssh
+          does, so hopefully it's safe enough. */
+       last = argv[0] + strlen(argv[0]) + 1;
+       for (i = 1; argv[i] != NULL; i++) {
+               if (argv[i] == last)
+                       last = argv[i] + strlen(argv[i]) + 1;
+       }
+       clear_env = last == env[0];
+       for (i = 0; env[i] != NULL; i++) {
+               if (env[i] == last)
+                       last = env[i] + strlen(env[i]) + 1;
        }
-       environ[i] = NULL;
 
-       /* memory is allocated so that argv[] comes first, environment next.
-          Calculate the max. size for process name with by checking the
-          address for last environment and it's length. */
        process_title = argv[0];
-       process_title_len = (size_t) (envp[i-1] - argv[0]) + strlen(envp[i-1]);
+       process_title_len = last - argv[0];
+
+       /* if there are problems with this approach, try to make sure we
+          notice it */
+       if (clear_env) {
+               memset(env[0], PROCTITLE_CLEAR_CHAR, last - env[0]);
+               process_title_clean_pos = env[0] - process_title;
+       } else {
+               process_title_clean_pos = 0;
+       }
 }
 
 static char **argv_dup(char *old_argv[])
@@ -56,6 +60,8 @@ static char **argv_dup(char *old_argv[])
        for (count = 0; old_argv[count] != NULL; count++) ;
 
        new_argv = malloc(sizeof(char *) * (count + 1));
+       if (new_argv == NULL)
+               i_fatal_status(FATAL_OUTOFMEM, "malloc() failed: %m");
        for (i = 0; i < count; i++) {
                new_argv[i] = strdup(old_argv[i]);
                if (new_argv[i] == NULL)
@@ -65,18 +71,37 @@ static char **argv_dup(char *old_argv[])
        return new_argv;
 }
 
-static void linux_proctitle_set(const char *title)
+static void proctitle_hack_set(const char *title)
 {
-       i_strocpy(process_title, title, process_title_len);
+       size_t len = strlen(title);
+
+       if (len >= process_title_len)
+               len = process_title_len - 1;
+
+       memcpy(process_title, title, len);
+       process_title[len++] = '\0';
+
+       if (len < process_title_clean_pos) {
+               memset(process_title + len, PROCTITLE_CLEAR_CHAR,
+                      process_title_clean_pos - len);
+               process_title_clean_pos = len;
+       } else if (process_title_clean_pos != 0) {
+               process_title_clean_pos = len;
+       }
 }
 
 #endif
 
-void process_title_init(char **argv[], char *envp[] ATTR_UNUSED)
+void process_title_init(char **argv[])
 {
-#ifdef LINUX_PROCTITLE_HACK
-       *argv = argv_dup(*argv);
-       linux_proctitle_init(*argv, envp);
+#ifdef PROCTITLE_HACK
+       extern char **environ;
+       char **orig_argv = *argv;
+       char **orig_environ = environ;
+
+       *argv = argv_dup(orig_argv);
+       environ = argv_dup(orig_environ);
+       proctitle_hack_init(orig_argv, orig_environ);
 #endif
        process_name = (*argv)[0];
 }
@@ -90,7 +115,7 @@ void process_title_set(const char *title ATTR_UNUSED)
                setproctitle(NULL);
        else
                setproctitle("%s", title);
-#elif defined(LINUX_PROCTITLE_HACK)
-       linux_proctitle_set(t_strconcat(process_name, " ", title, NULL));
+#elif defined(PROCTITLE_HACK)
+       proctitle_hack_set(t_strconcat(process_name, " ", title, NULL));
 #endif
 }
index ef1110e8df8673253d46d9878ab0dba9d4924cec..5e610b01215267abda818913b8656310d622fae0 100644 (file)
@@ -2,7 +2,7 @@
 #define PROCESS_TITLE_H
 
 /* Initialize title changing. */
-void process_title_init(char **argv[], char *envp[]);
+void process_title_init(char **argv[]);
 
 /* Change the process title if possible. */
 void process_title_set(const char *title);
index ed080194d3a88337ab1d947593d71bd913455fa9..c160184df51d00dab84c047231617d023c04f267 100644 (file)
@@ -339,7 +339,7 @@ static void rawlog_open(enum rawlog_flags flags)
        exit(0);
 }
 
-int main(int argc, char *argv[], char *envp[])
+int main(int argc, char *argv[])
 {
        char *executable, *p;
        enum rawlog_flags flags;
@@ -348,7 +348,7 @@ int main(int argc, char *argv[], char *envp[])
 
        lib_init();
        i_set_failure_internal();
-       process_title_init(&argv, envp);
+       process_title_init(&argv);
 
        argc--;
        argv++;