From 989a5bbb74c3620abaa2191ce2c4f8d5968dbf0a Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Tue, 15 Sep 2009 10:40:29 +0300 Subject: Branch off from the Mailfromd project into a separate repository. --- lib/proctitle.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 lib/proctitle.c (limited to 'lib/proctitle.c') 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 . */ + +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#include +#include +#include +#include +#if MF_PROCTITLE_TYPE == MF_PROCTITLE_PSTAT +# include +#elif MF_PROCTITLE_TYPE == MF_PROCTITLE_PSSTRINGS +# include +# include +# include +# include +# include +#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 (); + } +} -- cgit v1.2.1