/* This file is part of Mailfromd. Copyright (C) 2007-2020 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[1024]; #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; int n; if (!orig_argc) return; #if __FreeBSD__ >= 4 /* On FreeBSD the process name is prepended automatically */ n = 0; #else /* Otherwise we need to do that manually */ n = snprintf(proctitle_buffer, sizeof(proctitle_buffer), "%s: ", __progname); #endif va_start(ap, fmt); vsnprintf(proctitle_buffer + n, sizeof(proctitle_buffer) - n, fmt, ap); va_end(ap); mf_proctitle_flush(); }