1 /*
2 * setproctitle.c
3 *
4 * The code in this file, setproctitle.c is heavily based on code from
5 * proftpd, please see the licening information below.
6 *
7 * This file added to the heartbeat tree by Horms <horms@vergenet.net>
8 *
9 * Code to portably change the title of a programme as displayed
10 * by ps(1).
11 *
12 * heartbeat: Linux-HA heartbeat code
13 *
14 * Copyright (C) 1999,2000,2001 Alan Robertson <alanr@unix.sh>
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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
48 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, 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 #include <lha_internal.h>
57
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdio.h>
61 #include <unistd.h>
62 #include <stdarg.h>
63
64 #define PF_ARGV_NONE 0
65 #define PF_ARGV_NEW 1
66 #define PF_ARGV_WRITEABLE 2
67 #define PF_ARGV_PSTAT 3
68 #define PF_ARGV_PSSTRINGS 4
69
70 #if PF_ARGV_TYPE == PF_ARGV_PSTAT
71 # include <pstat.h>
72 #endif
73
74 #include <clplumbing/setproctitle.h>
75
76 #if PF_ARGV_TYPE != PF_ARGV_NONE
77 static char **Argv = NULL;
78 static char *LastArgv = NULL;
79 #endif /* PF_ARGV_TYPE != PF_ARGV_NONE */
80
81 extern char **environ;
82
83 #ifdef HAVE___PROGNAME
84 extern char *__progname;
85 extern char *__progname_full;
86 #endif /* HAVE___PROGNAME */
87
88 int
init_set_proc_title(int argc,char * argv[],char * envp[])89 init_set_proc_title(int argc, char *argv[], char *envp[])
90 {
91 #if PF_ARGV_TYPE == PF_ARGV_NONE
92 return 0;
93 #else
94 int i;
95 int envpsize;
96 char **p;
97
98 /* Move the environment so setproctitle can use the space.
99 */
100 for(i = envpsize = 0; envp[i] != NULL; i++) {
101 envpsize += strlen(envp[i]) + 1;
102 }
103
104 p = (char **) malloc((i + 1) * sizeof(char *));
105 if (p == NULL) {
106 return -1;
107 }
108
109 environ = p;
110
111 for(i = 0; envp[i] != NULL; i++) {
112 environ[i] = strdup(envp[i]);
113 if(environ[i] == NULL) {
114 goto error_environ;
115 }
116 }
117 environ[i] = NULL;
118
119 Argv = argv;
120
121 for(i = 0; i < argc; i++) {
122 if(!i || (LastArgv + 1 == argv[i]))
123 LastArgv = argv[i] + strlen(argv[i]);
124 }
125
126 for(i = 0; envp[i] != NULL; i++) {
127 if((LastArgv + 1) == envp[i]) {
128 LastArgv = envp[i] + strlen(envp[i]);
129 }
130 }
131
132 #ifdef HAVE___PROGNAME
133 /* Set the __progname and __progname_full variables so glibc and
134 * company don't go nuts. - MacGyver
135 */
136
137 __progname = strdup("heartbeat");
138 if (__progname == NULL) {
139 goto error_environ;
140 }
141 __progname_full = strdup(argv[0]);
142 if (__progname_full == NULL) {
143 goto error_environ;
144 }
145 #endif /* HAVE___PROGNAME */
146
147 return 0;
148
149 error_environ:
150 for(i = 0; environ[i] != NULL; i++) {
151 free(environ[i]);
152 }
153 free(environ);
154 return -1;
155 #endif /* PF_ARGV_TYPE == PF_ARGV_NONE */
156 }
157
set_proc_title(const char * fmt,...)158 void set_proc_title(const char *fmt,...)
159 {
160 #if PF_ARGV_TYPE != PF_ARGV_NONE
161 va_list msg;
162 static char statbuf[BUFSIZ];
163
164 #ifndef HAVE_SETPROCTITLE
165 #if PF_ARGV_TYPE == PF_ARGV_PSTAT
166 union pstun pst;
167 #endif /* PF_ARGV_PSTAT */
168 int i,maxlen = (LastArgv - Argv[0]) - 2;
169 char *p;
170 #endif /* HAVE_SETPROCTITLE */
171
172 va_start(msg,fmt);
173
174 memset(statbuf, 0, sizeof(statbuf));
175
176
177 #ifdef HAVE_SETPROCTITLE
178 # if (__FreeBSD__ >= 4 && !defined(FREEBSD4_0) && !defined(FREEBSD4_1)) || defined(__DragonFly__)
179 /* FreeBSD's setproctitle() automatically prepends the process name. */
180 vsnprintf(statbuf, sizeof(statbuf), fmt, msg);
181
182 # else /* FREEBSD4 */
183 /* Manually append the process name for non-FreeBSD platforms. */
184 vsnprintf(statbuf + strlen(statbuf), sizeof(statbuf) - strlen(statbuf),
185 fmt, msg);
186
187 # endif /* FREEBSD4 */
188 setproctitle("%s", statbuf);
189
190 #else /* HAVE_SETPROCTITLE */
191 /* Manually append the process name for non-setproctitle() platforms. */
192 vsnprintf(statbuf + strlen(statbuf), sizeof(statbuf) - strlen(statbuf),
193 fmt, msg);
194
195 #endif /* HAVE_SETPROCTITLE */
196
197 va_end(msg);
198
199 #ifdef HAVE_SETPROCTITLE
200 return;
201 #else
202 i = strlen(statbuf);
203
204 #if PF_ARGV_TYPE == PF_ARGV_NEW
205 /* We can just replace argv[] arguments. Nice and easy.
206 */
207 Argv[0] = statbuf;
208 Argv[1] = NULL;
209 #endif /* PF_ARGV_NEW */
210
211 #if PF_ARGV_TYPE == PF_ARGV_WRITEABLE
212 /* We can overwrite individual argv[] arguments. Semi-nice.
213 */
214 snprintf(Argv[0], maxlen, "%s", statbuf);
215 p = &Argv[0][i];
216
217 while(p < LastArgv)
218 *p++ = '\0';
219 Argv[1] = NULL;
220 #endif /* PF_ARGV_WRITEABLE */
221
222 #if PF_ARGV_TYPE == PF_ARGV_PSTAT
223 pst.pst_command = statbuf;
224 pstat(PSTAT_SETCMD, pst, i, 0, 0);
225 #endif /* PF_ARGV_PSTAT */
226
227 #if PF_ARGV_TYPE == PF_ARGV_PSSTRINGS
228 PS_STRINGS->ps_nargvstr = 1;
229 PS_STRINGS->ps_argvstr = statbuf;
230 #endif /* PF_ARGV_PSSTRINGS */
231
232 #endif /* HAVE_SETPROCTITLE */
233
234 #endif /* PF_ARGV_TYPE != PF_ARGV_NONE */
235 }
236