setproctitle.cpp
00001 /* 00002 * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 00003 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 00004 * Copyright (c) 1988, 1993 00005 * The Regents of the University of California. All rights reserved. 00006 * 00007 * By using this file, you agree to the terms and conditions set 00008 * forth in the LICENSE file which can be found at the top level of 00009 * the sendmail distribution. 00010 * 00011 * A copy of the above mentioned LICENSE file can be found in 00012 * LICENSE.setproctitle. 00013 * 00014 * Ported for use with KDE by Waldo Bastian <bastian@kde.org> 00015 */ 00016 00017 #include "setproctitle.h" 00018 00019 #ifdef HAVE_CONFIG_H 00020 #include <config.h> 00021 #endif 00022 00023 /* _GNU_SOURCE might already be defined in <config.h> */ 00024 #ifndef _GNU_SOURCE 00025 # define _GNU_SOURCE 00026 #endif 00027 #include <stdio.h> 00028 #include <stdarg.h> 00029 #include <sys/ioctl.h> 00030 #include <sys/param.h> 00031 #include <limits.h> 00032 #include <stdlib.h> 00033 #include <string.h> 00034 #include <unistd.h> 00035 00036 /* _PATH_KMEM should be defined in <paths.h> */ 00037 #ifndef _PATH_KMEM 00038 # define _PATH_KMEM "/dev/kmem" 00039 #endif 00040 00041 #define SPACELEFT(buf, ptr) (sizeof buf - ((ptr) - buf)) 00042 00043 00044 /* 00045 ** SETPROCTITLE -- set process title for ps 00046 ** 00047 ** Parameters: 00048 ** fmt -- a printf style format string. 00049 ** a, b, c -- possible parameters to fmt. 00050 ** 00051 ** Returns: 00052 ** none. 00053 ** 00054 ** Side Effects: 00055 ** Clobbers argv of our main procedure so ps(1) will 00056 ** display the title. 00057 */ 00058 00059 #define SPT_NONE 0 /* don't use it at all */ 00060 #define SPT_REUSEARGV 1 /* cover argv with title information */ 00061 #define SPT_BUILTIN 2 /* use libc builtin */ 00062 #define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */ 00063 #define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */ 00064 #define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */ 00065 #define SPT_SCO 6 /* write kernel u. area */ 00066 #define SPT_CHANGEARGV 7 /* write our own strings into argv[] */ 00067 00068 #ifndef SPT_TYPE 00069 # define SPT_TYPE SPT_REUSEARGV 00070 #endif 00071 00072 #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN 00073 00074 # if SPT_TYPE == SPT_PSTAT 00075 # include <sys/pstat.h> 00076 # endif 00077 # if SPT_TYPE == SPT_PSSTRINGS 00078 # include <machine/vmparam.h> 00079 # ifdef HAVE_SYS_EXEC_H 00080 # include <sys/exec.h> 00081 # endif 00082 # ifndef PS_STRINGS /* hmmmm.... apparently not available after all */ 00083 # undef SPT_TYPE 00084 # define SPT_TYPE SPT_REUSEARGV 00085 # else 00086 # ifndef NKPDE /* FreeBSD 2.0 */ 00087 # define NKPDE 63 00088 typedef unsigned int *pt_entry_t; 00089 # endif 00090 # endif 00091 # endif 00092 00093 # if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV 00094 # define SETPROC_STATIC static 00095 # else 00096 # define SETPROC_STATIC 00097 # endif 00098 00099 # if SPT_TYPE == SPT_SYSMIPS 00100 # include <sys/sysmips.h> 00101 # include <sys/sysnews.h> 00102 # endif 00103 00104 # if SPT_TYPE == SPT_SCO 00105 # include <sys/immu.h> 00106 # include <sys/dir.h> 00107 # include <sys/user.h> 00108 # include <sys/fs/s5param.h> 00109 # if PSARGSZ > MAXLINE 00110 # define SPT_BUFSIZE PSARGSZ 00111 # endif 00112 # endif 00113 00114 # ifndef SPT_PADCHAR 00115 # ifdef _AIX 00116 # define SPT_PADCHAR '\0' 00117 # else 00118 # define SPT_PADCHAR ' ' 00119 # endif 00120 # endif 00121 00122 #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */ 00123 00124 # ifndef SPT_BUFSIZE 00125 # define SPT_BUFSIZE 2048 00126 # endif 00127 00128 /* 00129 ** Pointers for setproctitle. 00130 ** This allows "ps" listings to give more useful information. 00131 */ 00132 00133 char **Argv = NULL; /* pointer to argument vector */ 00134 char *LastArgv = NULL; /* end of argv */ 00135 00136 void 00137 tdeinit_initsetproctitle(int argc, char **argv, char **envp) 00138 { 00139 int i, envpsize = 0; 00140 #if !defined(HAVE_NSGETENVIRON) || !defined(HAVE_CRT_EXTERNS_H) 00141 extern char **environ; 00142 #endif 00143 00144 /* 00145 ** Move the environment so setproctitle can use the space at 00146 ** the top of memory. 00147 */ 00148 00149 for (i = 0; envp[i] != NULL; i++) 00150 envpsize += strlen(envp[i]) + 1; 00151 environ = (char **) malloc(sizeof (char *) * (i + 1)); 00152 if (environ == NULL) 00153 return; 00154 00155 for (i = 0; envp[i] != NULL; i++) 00156 environ[i] = strdup(envp[i]); 00157 environ[i] = NULL; 00158 00159 /* 00160 ** Save start and extent of argv for setproctitle. 00161 */ 00162 00163 Argv = argv; 00164 00165 /* 00166 ** Determine how much space we can use for setproctitle. 00167 ** Use all contiguous argv and envp pointers starting at argv[0] 00168 */ 00169 for (i = 0; i < argc; i++) 00170 { 00171 if (i==0 || LastArgv + 1 == argv[i]) 00172 LastArgv = argv[i] + strlen(argv[i]); 00173 else 00174 continue; 00175 } 00176 00177 /* 00178 * On linux, we don't want to reuse the memory allocated for 00179 * the environment, as there are tools that try to read our environment 00180 * variables while we're running (ConsoleKit does that). 00181 * There is no way to move or resize it, so just not touchint it 00182 * seems to be the only option 00183 */ 00184 #ifndef __linux__ 00185 for (i=0; envp[i] != NULL; i++) 00186 { 00187 if (LastArgv + 1 == envp[i]) 00188 LastArgv = envp[i] + strlen(envp[i]); 00189 else 00190 continue; 00191 } 00192 #endif 00193 } 00194 00195 #if SPT_TYPE != SPT_BUILTIN 00196 00197 /*VARARGS1*/ 00198 static void 00199 setproctitle(const char *fmt, ...) 00200 { 00201 # if SPT_TYPE != SPT_NONE 00202 char *p; 00203 int i; 00204 SETPROC_STATIC char buf[SPT_BUFSIZE]; 00205 va_list ap; 00206 # if SPT_TYPE == SPT_PSTAT 00207 union pstun pst; 00208 # endif 00209 # if SPT_TYPE == SPT_SCO 00210 off_t seek_off; 00211 static int kmem = -1; 00212 #warning (rikkus) kmempid is declared as int, should be long 00213 static int kmempid = -1; 00214 struct user u; 00215 # endif 00216 00217 p = buf; 00218 00219 /* print the argument string */ 00220 va_start(ap, fmt); 00221 (void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap); 00222 va_end(ap); 00223 00224 i = strlen(buf); 00225 00226 # if SPT_TYPE == SPT_PSTAT 00227 pst.pst_command = buf; 00228 pstat(PSTAT_SETCMD, pst, i, 0, 0); 00229 # endif 00230 # if SPT_TYPE == SPT_PSSTRINGS 00231 PS_STRINGS->ps_nargvstr = 1; 00232 PS_STRINGS->ps_argvstr = buf; 00233 # endif 00234 # if SPT_TYPE == SPT_SYSMIPS 00235 sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf); 00236 # endif 00237 # if SPT_TYPE == SPT_SCO 00238 if (kmem < 0 || kmempid != getpid()) 00239 { 00240 if (kmem >= 0) 00241 close(kmem); 00242 kmem = open(_PATH_KMEM, O_RDWR, 0); 00243 if (kmem < 0) 00244 return; 00245 (void) fcntl(kmem, F_SETFD, 1); 00246 kmempid = getpid(); 00247 } 00248 buf[PSARGSZ - 1] = '\0'; 00249 seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u; 00250 if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off) 00251 (void) write(kmem, buf, PSARGSZ); 00252 # endif 00253 # if SPT_TYPE == SPT_REUSEARGV 00254 if (i > LastArgv - Argv[0] - 2) 00255 { 00256 i = LastArgv - Argv[0] - 2; 00257 buf[i] = '\0'; 00258 } 00259 (void) strcpy(Argv[0], buf); 00260 p = &Argv[0][i]; 00261 while (p < LastArgv) 00262 *p++ = SPT_PADCHAR; 00263 Argv[1] = NULL; 00264 # endif 00265 # if SPT_TYPE == SPT_CHANGEARGV 00266 Argv[0] = buf; 00267 Argv[1] = 0; 00268 # endif 00269 # endif /* SPT_TYPE != SPT_NONE */ 00270 } 00271 00272 #endif /* SPT_TYPE != SPT_BUILTIN */ 00273 /* 00274 ** SM_SETPROCTITLE -- set process task and set process title for ps 00275 ** 00276 ** Possibly set process status and call setproctitle() to 00277 ** change the ps display. 00278 ** 00279 ** Parameters: 00280 ** status -- whether or not to store as process status 00281 ** fmt -- a printf style format string. 00282 ** a, b, c -- possible parameters to fmt. 00283 ** 00284 ** Returns: 00285 ** none. 00286 */ 00287 00288 /*VARARGS2*/ 00289 void 00290 tdeinit_setproctitle(const char *fmt, ...) 00291 { 00292 char buf[SPT_BUFSIZE]; 00293 00294 va_list ap; 00295 /* print the argument string */ 00296 va_start(ap, fmt); 00297 (void) vsnprintf(buf, SPT_BUFSIZE, fmt, ap); 00298 va_end(ap); 00299 00300 setproctitle("%s", buf); 00301 } 00302