2 * ProFTPD - FTP server daemon
3 * Copyright (c) 2007 The ProFTPD Project team //krazy:exclude=copyright
4 * Copyright (c) 2007 Alex Merry <alex.merry@kdemail.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #include "proctitle.h"
24 #include <config-kdeinit.h>
31 #define PF_ARGV_NONE 0
33 #define PF_ARGV_WRITEABLE 2
34 #define PF_ARGV_PSTAT 3
35 #define PF_ARGV_PSSTRINGS 4
37 #ifdef HAVE_SETPROCTITLE
38 # define PF_ARGV_TYPE PF_ARGV_NONE
39 # ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
41 # endif /* HAVE_SYS_TYPES_H */
44 # endif /* HAVE_UNISTD_H */
46 #else /* HAVE_SETPROCTITLE */
48 # define PF_ARGV_TYPE PF_ARGV_NEW
49 # else /* __GNU_HURD__ */
50 # define PF_ARGV_TYPE PF_ARGV_WRITEABLE
52 # if defined(HAVE_SYS_PSTAT_H) && defined(HAVE_PSTAT)
53 # include <sys/pstat.h>
55 # define PF_ARGV_TYPE PF_ARGV_PSTAT
56 # endif /* HAVE_SYS_PSTAT_H && HAVE_PSTAT */
58 # ifdef HAVE_SYS_EXEC_H
59 # include <sys/exec.h>
61 # include <machine/vmparam.h>
63 # define PF_ARGV_TYPE PF_ARGV_PSSTRINGS
64 # endif /* PS_STRINGS */
65 # endif /* HAVE_SYS_EXEC_H */
67 # endif /* !__GNU_HURD__ */
69 #endif /* !HAVE_SETPROCTITLE */
71 #ifdef HAVE___PROGNAME
72 extern char *__progname
;
73 #endif /* HAVE___PROGNAME */
74 #ifdef HAVE___PROGNAME_FULL
75 extern char *__progname_full
;
76 #endif /* HAVE___PROGNAME_FULL */
77 extern char **environ
;
79 static char **Argv
= NULL
;
81 #if PF_ARGV_TYPE == PF_ARGV_WRITEABLE /* Only this mode uses LastArgv */
82 static char *LastArgv
= NULL
;
86 * Set up the memory space for setting the proctitle
88 void proctitle_init(int argc
, char *argv
[], char *envp
[]) {
89 register int i
, envpsize
;
92 /* Move the environment so proctitle_set can use the space. */
93 for ( i
= envpsize
= 0; envp
[i
] != NULL
; i
++ ) {
94 envpsize
+= strlen(envp
[i
]) + 1;
97 if ((p
= (char **) malloc((i
+ 1) * sizeof(char *))) != NULL
) {
100 for (i
= 0; envp
[i
] != NULL
; i
++) {
101 if ((environ
[i
] = static_cast<char *>(malloc(strlen(envp
[i
]) + 1))) != NULL
) {
102 strcpy(environ
[i
], envp
[i
]);
111 # if PF_ARGV_TYPE == PF_ARGV_WRITEABLE /* Only this mode uses LastArgv */
112 for (i
= 0; i
< argc
; i
++) {
113 if (!i
|| (LastArgv
+ 1 == argv
[i
])) {
114 LastArgv
= argv
[i
] + strlen(argv
[i
]);
118 for (i
= 0; envp
[i
] != NULL
; i
++) {
119 /* must not overwrite XDG_SESSION_COOKIE */
120 if (!strncmp(envp
[i
], "XDG_", 4))
122 if ((LastArgv
+ 1) == envp
[i
]) {
123 LastArgv
= envp
[i
] + strlen(envp
[i
]);
128 # ifdef HAVE___PROGNAME
129 /* Set the __progname variable so glibc and company
132 __progname
= strdup("kdeinit4");
133 # endif /* HAVE___PROGNAME */
134 # ifdef HAVE____PROGNAME_FULL
135 /* __progname_full too */
136 __progname_full
= strdup(argv
[0]);
137 # endif /* HAVE___PROGNAME_FULL */
140 void proctitle_set(const char *fmt
, ...) {
142 static char statbuf
[BUFSIZ
];
144 #ifndef HAVE_SETPROCTITLE
145 # if PF_ARGV_TYPE == PF_ARGV_PSTAT
147 # endif /* PF_ARGV_PSTAT */
150 #endif /* HAVE_SETPROCTITLE */
158 memset(statbuf
, 0, sizeof(statbuf
));
160 #ifdef HAVE_SETPROCTITLE
161 # if __FreeBSD__ >= 4 && !defined(FREEBSD4_0) && !defined(FREEBSD4_1)
162 /* FreeBSD's setproctitle() automatically prepends the process name. */
163 vsnprintf(statbuf
, sizeof(statbuf
), fmt
, msg
);
165 # else /* FREEBSD4 */
166 /* Manually append the process name for non-FreeBSD platforms. */
167 snprintf(statbuf
, sizeof(statbuf
), "%s", "kdeinit4: ");
168 vsnprintf(statbuf
+ strlen(statbuf
),
169 sizeof(statbuf
) - strlen(statbuf
),
173 # endif /* FREEBSD4 */
174 setproctitle("%s", statbuf
);
176 #else /* HAVE_SETPROCTITLE */
177 /* Manually append the process name for non-setproctitle() platforms. */
178 snprintf(statbuf
, sizeof(statbuf
), "%s", "kdeinit4: ");
179 vsnprintf(statbuf
+ strlen(statbuf
),
180 sizeof(statbuf
) - strlen(statbuf
),
184 #endif /* HAVE_SETPROCTITLE */
188 #ifdef HAVE_SETPROCTITLE
193 # if PF_ARGV_TYPE == PF_ARGV_NEW
194 /* We can just replace argv[] arguments. Nice and easy. */
197 # endif /* PF_ARGV_NEW */
199 # if PF_ARGV_TYPE == PF_ARGV_WRITEABLE
200 const int maxlen
= (LastArgv
- Argv
[0]) - 1;
201 /* We can overwrite individual argv[] arguments. Semi-nice. */
202 snprintf(Argv
[0], maxlen
, "%s", statbuf
);
205 /* null terminate it, but don't clear the rest of the
206 memory that is usually used for environment variables. Some
207 tools, like ConsoleKit must have access to the process'es initial
208 environment (more exact, the XDG_SESSION_COOKIE variable stored there).
209 If this code causes another side effect, we have to specifically
210 always append those variables to our environment. */
216 # endif /* PF_ARGV_WRITEABLE */
218 # if PF_ARGV_TYPE == PF_ARGV_PSTAT
219 pst
.pst_command
= statbuf
;
220 pstat(PSTAT_SETCMD
, pst
, i
, 0, 0);
221 # endif /* PF_ARGV_PSTAT */
223 # if PF_ARGV_TYPE == PF_ARGV_PSSTRINGS
224 PS_STRINGS
->ps_nargvstr
= 1;
225 PS_STRINGS
->ps_argvstr
= statbuf
;
226 # endif /* PF_ARGV_PSSTRINGS */
228 #endif /* HAVE_SETPROCTITLE */