1 /**********************************************************************
2 * setproctitle.c May 2001
3 * Horms horms@verge.net.au
4 *
5 * The code in this file, setproctitle.c is heavily based on code from
6 * proftpd, please see the licensing information below.
7 *
8 * Code to portably change the title of a programme as displayed
9 * by ps(1).
10 *
11 * perdition
12 * Mail retrieval proxy server
13 * Copyright (C) 1999-2005 Horms
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of the
18 * License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software Foundation,
27 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
28 *
29 **********************************************************************/
30
31 /*
32 * ProFTPD - FTP server daemon
33 * Copyright (c) 1997, 1998 Public Flood Software
34 * Copyright (C) 1999, 2000 MacGyver aka Habeeb J. Dihu <macgyver@tos.net>
35 *
36 * This program is free software; you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
38 * the Free Software Foundation; either version 2 of the License, or
39 * (at your option) any later version.
40 *
41 * This program is distributed in the hope that it will be useful,
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 * GNU General Public License for more details.
45 *
46 * You should have received a copy of the GNU General Public License
47 * along with this program; if not, write to the Free Software Foundation,
48 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
49 *
50 * As a special exemption, Public Flood Software/MacGyver aka Habeeb J. Dihu
51 * and other respective copyright holders give permission to link this program
52 * with OpenSSL, and distribute the resulting executable, without including
53 * the source code for OpenSSL in the source distribution.
54 */
55
56 #ifdef HAVE_CONFIG_H
57 #include "config.h"
58 #endif
59
60 #include <stdlib.h>
61 #include <string.h>
62 #include <stdio.h>
63 #include <unistd.h>
64 #include <stdarg.h>
65
66 #define PF_ARGV_NONE 0
67 #define PF_ARGV_NEW 1
68 #define PF_ARGV_WRITEABLE 2
69 #define PF_ARGV_PSTAT 3
70 #define PF_ARGV_PSSTRINGS 4
71
72 #if PF_ARGV_TYPE == PF_ARGV_PSTAT
73 # include <pstat.h>
74 #endif
75
76 #include "setproctitle.h"
77
78 static char **Argv = NULL;
79 static char *LastArgv = NULL;
80 extern char **environ;
81
82 #ifdef HAVE___PROGNAME
83 extern char *__progname, *__progname_full;
84 #endif /* HAVE___PROGNAME */
85
init_set_proc_title(int argc,char * argv[],char * envp[])86 void init_set_proc_title(int argc, char *argv[], char *envp[])
87 {
88 int i, envpsize;
89 char **p;
90
91 /* Move the environment so setproctitle can use the space.
92 */
93 for(i = envpsize = 0; envp[i] != NULL; i++)
94 envpsize += strlen(envp[i]) + 1;
95
96 if((p = (char **) malloc((i + 1) * sizeof(char *))) != NULL ) {
97 environ = p;
98
99 for(i = 0; envp[i] != NULL; i++) {
100 if((environ[i] = malloc(strlen(envp[i]) + 1)) != NULL)
101 strcpy(environ[i], envp[i]);
102 }
103
104 environ[i] = NULL;
105 }
106
107 Argv = argv;
108
109 for(i = 0; i < argc; i++) {
110 if(!i || (LastArgv + 1 == argv[i]))
111 LastArgv = argv[i] + strlen(argv[i]);
112 }
113
114 for(i = 0; envp[i] != NULL; i++) {
115 if((LastArgv + 1) == envp[i])
116 LastArgv = envp[i] + strlen(envp[i]);
117 }
118
119 #ifdef HAVE___PROGNAME
120 /* Set the __progname and __progname_full variables so glibc and company don't
121 * go nuts. - MacGyver
122 */
123 __progname = strdup(get_progname(argv[0]));
124 __progname_full = strdup(argv[0]);
125 #endif /* HAVE___PROGNAME */
126
127 #if 0
128 /* Save argument/environment globals for use by set_proc_title */
129
130 Argv = argv;
131 while(*envp)
132 envp++;
133
134 LastArgv = envp[-1] + strlen(envp[-1]);
135 #endif
136 }
137
set_proc_title(const char * fmt,...)138 void set_proc_title(const char *fmt,...)
139 {
140 va_list msg;
141 static char statbuf[BUFSIZ];
142
143 #ifndef HAVE_SETPROCTITLE
144 #if PF_ARGV_TYPE == PF_ARGV_PSTAT
145 union pstun pst;
146 #endif /* PF_ARGV_PSTAT */
147 int i;
148 #if PF_ARGV_TYPE == PF_ARGV_WRITEABLE
149 int maxlen = (LastArgv - Argv[0]) - 2;
150 char *p;
151 #endif
152 #endif /* HAVE_SETPROCTITLE */
153
154 va_start(msg,fmt);
155
156 memset(statbuf, 0, sizeof(statbuf));
157 vsnprintf(statbuf, sizeof(statbuf), fmt, msg);
158
159 #ifdef HAVE_SETPROCTITLE
160 /* On systems with setproctitle(), v*printf are used on the arguments.
161 * Prevent any possible format attacks.
162 */
163 setproctitle("%s", statbuf);
164 #endif /* HAVE_SETPROCTITLE */
165
166 va_end(msg);
167
168 #ifdef HAVE_SETPROCTITLE
169 return;
170 #else
171 i = strlen(statbuf);
172
173 #if PF_ARGV_TYPE == PF_ARGV_NEW
174 /* We can just replace argv[] arguments. Nice and easy.
175 */
176 Argv[0] = statbuf;
177 Argv[1] = NULL;
178 #endif /* PF_ARGV_NEW */
179
180 #if PF_ARGV_TYPE == PF_ARGV_WRITEABLE
181 /* We can overwrite individual argv[] arguments. Semi-nice.
182 */
183 snprintf(Argv[0], maxlen, "%s", statbuf);
184 p = &Argv[0][i];
185
186 while(p < LastArgv)
187 *p++ = '\0';
188 Argv[1] = NULL;
189 #endif /* PF_ARGV_WRITEABLE */
190
191 #if PF_ARGV_TYPE == PF_ARGV_PSTAT
192 pst.pst_command = statbuf;
193 pstat(PSTAT_SETCMD, pst, i, 0, 0);
194 #endif /* PF_ARGV_PSTAT */
195
196 #if PF_ARGV_TYPE == PF_ARGV_PSSTRINGS
197 PS_STRINGS->ps_nargvstr = 1;
198 PS_STRINGS->ps_argvstr = statbuf;
199 #endif /* PF_ARGV_PSSTRINGS */
200
201 #endif /* HAVE_SETPROCTITLE */
202 }
203
204
205 const char *
get_progname(const char * argv_0)206 get_progname(const char *argv_0)
207 {
208 const char *progname;
209
210 progname = strrchr(argv_0, '/');
211 if (progname)
212 return progname+1;
213
214 return argv_0;
215 }
216