KInit
proctitle.cpp
Go to the documentation of this file.
00001 /* 00002 * ProFTPD - FTP server daemon 00003 * Copyright (c) 2007 The ProFTPD Project team //krazy:exclude=copyright 00004 * Copyright (c) 2007 Alex Merry <alex.merry@kdemail.net> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the 00018 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "proctitle.h" 00023 #include <config.h> 00024 #include <config-kdeinit.h> 00025 00026 #include <string.h> 00027 #include <stdio.h> 00028 #include <stdarg.h> 00029 #include <stdlib.h> 00030 00031 #define PF_ARGV_NONE 0 00032 #define PF_ARGV_NEW 1 00033 #define PF_ARGV_WRITEABLE 2 00034 #define PF_ARGV_PSTAT 3 00035 #define PF_ARGV_PSSTRINGS 4 00036 00037 #ifdef HAVE_SETPROCTITLE 00038 # define PF_ARGV_TYPE PF_ARGV_NONE 00039 # ifdef HAVE_SYS_TYPES_H 00040 # include <sys/types.h> 00041 # endif /* HAVE_SYS_TYPES_H */ 00042 # ifdef HAVE_UNISTD_H 00043 # include <unistd.h> 00044 # endif /* HAVE_UNISTD_H */ 00045 00046 #else /* HAVE_SETPROCTITLE */ 00047 # ifdef __GNU_HURD__ 00048 # define PF_ARGV_TYPE PF_ARGV_NEW 00049 # else /* __GNU_HURD__ */ 00050 # define PF_ARGV_TYPE PF_ARGV_WRITEABLE 00051 00052 # if defined(HAVE_SYS_PSTAT_H) && defined(HAVE_PSTAT) 00053 # include <sys/pstat.h> 00054 # undef PF_ARGV_TYPE 00055 # define PF_ARGV_TYPE PF_ARGV_PSTAT 00056 # endif /* HAVE_SYS_PSTAT_H && HAVE_PSTAT */ 00057 00058 # ifdef HAVE_SYS_EXEC_H 00059 # include <sys/exec.h> 00060 # ifdef PS_STRINGS 00061 # include <machine/vmparam.h> 00062 # undef PF_ARGV_TYPE 00063 # define PF_ARGV_TYPE PF_ARGV_PSSTRINGS 00064 # endif /* PS_STRINGS */ 00065 # endif /* HAVE_SYS_EXEC_H */ 00066 00067 # endif /* !__GNU_HURD__ */ 00068 00069 #endif /* !HAVE_SETPROCTITLE */ 00070 00071 #ifdef HAVE___PROGNAME 00072 extern char *__progname; 00073 #endif /* HAVE___PROGNAME */ 00074 #ifdef HAVE___PROGNAME_FULL 00075 extern char *__progname_full; 00076 #endif /* HAVE___PROGNAME_FULL */ 00077 extern char **environ; 00078 00079 static char **Argv = NULL; 00080 00081 #if PF_ARGV_TYPE == PF_ARGV_WRITEABLE /* Only this mode uses LastArgv */ 00082 static char *LastArgv = NULL; 00083 static char *cleanUpTo = NULL; 00084 #endif 00085 00089 void proctitle_init(int argc, char *argv[], char *envp[]) { 00090 register int i, envpsize; 00091 char **p; 00092 00093 /* Move the environment so proctitle_set can use the space. */ 00094 for ( i = envpsize = 0; envp[i] != NULL; i++ ) { 00095 envpsize += strlen(envp[i]) + 1; 00096 } 00097 00098 if ((p = (char **) malloc((i + 1) * sizeof(char *))) != NULL) { 00099 environ = p; 00100 00101 for (i = 0; envp[i] != NULL; i++) { 00102 if ((environ[i] = static_cast<char *>(malloc(strlen(envp[i]) + 1))) != NULL) { 00103 strcpy(environ[i], envp[i]); 00104 } 00105 } 00106 00107 environ[i] = NULL; 00108 } 00109 00110 Argv = argv; 00111 00112 # if PF_ARGV_TYPE == PF_ARGV_WRITEABLE /* Only this mode uses LastArgv */ 00113 for (i = 0; i < argc; i++) { 00114 if (!i || (LastArgv + 1 == argv[i])) { 00115 LastArgv = argv[i] + strlen(argv[i]); 00116 } 00117 } 00118 cleanUpTo = LastArgv; 00119 00120 for (i = 0; envp[i] != NULL; i++) { 00121 /* must not overwrite XDG_SESSION_COOKIE */ 00122 if (!strncmp(envp[i], "XDG_", 4)) 00123 break; 00124 if ((LastArgv + 1) == envp[i]) { 00125 LastArgv = envp[i] + strlen(envp[i]); 00126 } 00127 } 00128 #endif 00129 00130 # ifdef HAVE___PROGNAME 00131 /* Set the __progname variable so glibc and company 00132 * don't go nuts. 00133 */ 00134 __progname = strdup("kdeinit4"); 00135 # endif /* HAVE___PROGNAME */ 00136 # ifdef HAVE___PROGNAME_FULL 00137 /* __progname_full too */ 00138 __progname_full = strdup(argv[0]); 00139 # endif /* HAVE___PROGNAME_FULL */ 00140 } 00141 00142 void proctitle_set(const char *fmt, ...) { 00143 va_list msg; 00144 static char statbuf[BUFSIZ]; 00145 00146 #ifndef HAVE_SETPROCTITLE 00147 # if PF_ARGV_TYPE == PF_ARGV_PSTAT 00148 union pstun pst; 00149 # endif /* PF_ARGV_PSTAT */ 00150 char *p; 00151 int i; 00152 #endif /* HAVE_SETPROCTITLE */ 00153 00154 if ( !fmt ) { 00155 return; 00156 } 00157 00158 va_start(msg, fmt); 00159 00160 memset(statbuf, 0, sizeof(statbuf)); 00161 00162 #ifdef HAVE_SETPROCTITLE 00163 # if __FreeBSD__ >= 4 && !defined(FREEBSD4_0) && !defined(FREEBSD4_1) 00164 /* FreeBSD's setproctitle() automatically prepends the process name. */ 00165 vsnprintf(statbuf, sizeof(statbuf), fmt, msg); 00166 00167 # else /* FREEBSD4 */ 00168 /* Manually append the process name for non-FreeBSD platforms. */ 00169 snprintf(statbuf, sizeof(statbuf), "%s", "kdeinit4: "); 00170 vsnprintf(statbuf + strlen(statbuf), 00171 sizeof(statbuf) - strlen(statbuf), 00172 fmt, 00173 msg); 00174 00175 # endif /* FREEBSD4 */ 00176 setproctitle("%s", statbuf); 00177 00178 #else /* HAVE_SETPROCTITLE */ 00179 /* Manually append the process name for non-setproctitle() platforms. */ 00180 snprintf(statbuf, sizeof(statbuf), "%s", "kdeinit4: "); 00181 vsnprintf(statbuf + strlen(statbuf), 00182 sizeof(statbuf) - strlen(statbuf), 00183 fmt, 00184 msg); 00185 00186 #endif /* HAVE_SETPROCTITLE */ 00187 00188 va_end(msg); 00189 00190 #ifdef HAVE_SETPROCTITLE 00191 return; 00192 #else 00193 i = strlen(statbuf); 00194 00195 # if PF_ARGV_TYPE == PF_ARGV_NEW 00196 /* We can just replace argv[] arguments. Nice and easy. */ 00197 Argv[0] = statbuf; 00198 Argv[1] = NULL; 00199 # endif /* PF_ARGV_NEW */ 00200 00201 # if PF_ARGV_TYPE == PF_ARGV_WRITEABLE 00202 const int maxlen = (LastArgv - Argv[0]) - 1; 00203 /* We can overwrite individual argv[] arguments. Semi-nice. */ 00204 snprintf(Argv[0], maxlen, "%s", statbuf); 00205 p = &Argv[0][i]; 00206 /* Clear the rest used by arguments, but don't clear the memory 00207 that is usually used for environment variables. Some 00208 tools, like ConsoleKit must have access to the process'es initial 00209 environment (more exact, the XDG_SESSION_COOKIE variable stored there). 00210 If this code causes another side effect, we have to specifically 00211 always append those variables to our environment. */ 00212 while (p < cleanUpTo) 00213 *p++ = '\0'; 00214 00215 Argv[1] = NULL; 00216 # endif /* PF_ARGV_WRITEABLE */ 00217 00218 # if PF_ARGV_TYPE == PF_ARGV_PSTAT 00219 pst.pst_command = statbuf; 00220 pstat(PSTAT_SETCMD, pst, i, 0, 0); 00221 # endif /* PF_ARGV_PSTAT */ 00222 00223 # if PF_ARGV_TYPE == PF_ARGV_PSSTRINGS 00224 PS_STRINGS->ps_nargvstr = 1; 00225 PS_STRINGS->ps_argvstr = statbuf; 00226 # endif /* PF_ARGV_PSSTRINGS */ 00227 00228 #endif /* HAVE_SETPROCTITLE */ 00229 }
KDE 4.6 API Reference