aboutsummaryrefslogtreecommitdiff
path: root/lib/proctitle.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/proctitle.c')
-rw-r--r--lib/proctitle.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/lib/proctitle.c b/lib/proctitle.c
new file mode 100644
index 0000000..f9ff967
--- /dev/null
+++ b/lib/proctitle.c
@@ -0,0 +1,164 @@
+/* This file is part of Mailfromd.
+ Copyright (C) 2007, 2008 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#if MF_PROCTITLE_TYPE == MF_PROCTITLE_PSTAT
+# include <sys/pstat.h>
+#elif MF_PROCTITLE_TYPE == MF_PROCTITLE_PSSTRINGS
+# include <sys/proc.h>
+# include <vm/pmap.h>
+# include <machine/pmap.h>
+# include <machine/vmparam.h>
+# include <sys/exec.h>
+#endif
+
+extern char **environ;
+
+/* Move the environment to prepare more space for argv */
+static int
+move_env (char *env[])
+{
+ size_t size;
+ int i;
+ char **p;
+
+ size = 0;
+ for (i = 0; env[i]; i++)
+ size += strlen (env[i]) + 1;
+
+ p = calloc (i + 1, sizeof (*p));
+ if (!p)
+ return 1;
+
+ for (i = 0; env[i]; i++)
+ if ((p[i] = strdup(env[i])) == NULL) {
+ int j;
+ /* Free allocated memory and return */
+ for (j = 0; j < i; j++)
+ free(p[i]);
+ free(p);
+ return 1;
+ }
+ p[i] = NULL;
+ environ = p;
+ return 0;
+}
+
+static int orig_argc;
+static char **orig_argv;
+static char *orig_argv_end;
+static char *proctitle_buffer;
+#ifdef HAVE___PROGNAME
+extern char *__progname;
+extern char *__progname_full;
+#else
+static char *__progname;
+#endif
+
+void
+mf_proctitle_init (int argc, char *argv[], char *env[])
+{
+ int i;
+
+ move_env (env);
+
+ orig_argc = argc;
+ orig_argv = argv;
+ orig_argv_end = argv[0] + strlen (argv[0]);
+ __progname = strrchr (argv[0], '/');
+ if (__progname)
+ __progname++;
+ else
+ __progname = argv[0];
+ __progname = strdup (__progname);
+#ifdef HAVE___PROGNAME
+ __progname_full = strdup(argv[0]);
+#endif
+
+ for (i = 0; i < orig_argc; i++) {
+ if (orig_argv_end + 1 == argv[i])
+ orig_argv_end = argv[i] + strlen(argv[i]);
+ }
+
+ for (i = 0; env[i]; i++) {
+ if ((orig_argv_end + 1) == env[i])
+ orig_argv_end = env[i] + strlen(env[i]);
+ }
+}
+
+static void
+mf_proctitle_flush ()
+{
+#if MF_PROCTITLE_TYPE == MF_PROCTITLE_SETPROCTITLE
+ setproctitle ("%s", proctitle_buffer);
+#elif MF_PROCTITLE_TYPE == MF_PROCTITLE_REPLACE_ARGV
+ orig_argv[0] = proctitle_buffer;
+ for (i = 1; i < orig_argc; i++) {
+ orig_argv[i] = "";
+ }
+#elif MF_PROCTITLE_TYPE == MF_PROCTITLE_REWRITE_ARGV
+ size_t argv_size = orig_argv_end - orig_argv[0] - 2;
+ size_t len = strlen (proctitle_buffer);
+ memset (orig_argv[0], 0, argv_size);
+ if (len > argv_size)
+ len = argv_size;
+ memcpy (orig_argv[0], proctitle_buffer, len);
+ orig_argv[0][len] = 0;
+#elif MF_PROCTITLE_TYPE == MF_PROCTITLE_PSTAT
+ union pstun pst;
+ pst.pst_command = proc_title_buf;
+ pstat(PSTAT_SETCMD, pst, strlen (proctitle_buffer), 0, 0);
+#elif MF_PROCTITLE_TYPE == MF_PROCTITLE_PSSTRINGS
+ PS_STRINGS->ps_nargvstr = 1;
+ PS_STRINGS->ps_argvstr = proctitle_buffer;
+#endif
+}
+
+void
+mf_proctitle_format (const char *fmt, ...)
+{
+ va_list ap;
+ char *tmp = NULL;
+
+ if (!orig_argc)
+ return;
+ va_start (ap, fmt);
+ vasprintf (&tmp, fmt, ap);
+ va_end (ap);
+ if (tmp) {
+ free (proctitle_buffer);
+#if __FreeBSD__ >= 4
+ /* On FreeBSD the process name is prepended automatically */
+ proctitle_buffer = tmp;
+#else
+ /* Otherwise we need to do that manually */
+ asprintf (&proctitle_buffer, "%s: %s", __progname, tmp);
+ if (proctitle_buffer)
+ free (tmp);
+ else
+ proctitle_buffer = tmp;
+#endif
+ mf_proctitle_flush ();
+ }
+}

Return to:

Send suggestions and report system problems to the System administrator.