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