/* This file is part of GNU Pies. Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff GNU Pies 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. GNU Pies 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 GNU Pies. 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 (); } }