This source file includes following definitions.
- save_ps_args
- is_ps_title_available
- ps_title_errno
- set_ps_title
- get_ps_title
- cleanup_ps_args
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 #include "ps_title.h"
32 #include <stdio.h>
33
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include <string.h>
39 #include <stdlib.h>
40
41 #ifdef PHP_WIN32
42 #include "config.w32.h"
43 #include <windows.h>
44 #include <process.h>
45 #else
46 #include "php_config.h"
47 extern char** environ;
48 #endif
49
50 #ifdef HAVE_SYS_PSTAT_H
51 #include <sys/pstat.h>
52 #endif
53 #ifdef HAVE_PS_STRINGS
54 #include <machine/vmparam.h>
55 #include <sys/exec.h>
56 #endif
57 #if defined(DARWIN)
58 #include <crt_externs.h>
59 #endif
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 #if defined(HAVE_SETPROCTITLE)
86 #define PS_USE_SETPROCTITLE
87 #elif defined(HAVE_SYS_PSTAT_H) && defined(PSTAT_SETCMD)
88 #define PS_USE_PSTAT
89 #elif defined(HAVE_PS_STRINGS)
90 #define PS_USE_PS_STRINGS
91 #elif defined(BSD) && !defined(DARWIN)
92 #define PS_USE_CHANGE_ARGV
93 #elif defined(__linux__) || defined(_AIX) || defined(__sgi) || (defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__osf__) || defined(DARWIN)
94 #define PS_USE_CLOBBER_ARGV
95 #elif defined(PHP_WIN32)
96 #define PS_USE_WIN32
97 #else
98 #define PS_USE_NONE
99 #endif
100
101
102 #if defined(_AIX) || defined(__linux__) || defined(DARWIN)
103 #define PS_PADDING '\0'
104 #else
105 #define PS_PADDING ' '
106 #endif
107
108 #ifdef PS_USE_WIN32
109 static char windows_error_details[64];
110 static char ps_buffer[MAX_PATH];
111 static const size_t ps_buffer_size = MAX_PATH;
112 typedef BOOL (WINAPI *MySetConsoleTitle)(LPCTSTR);
113 typedef DWORD (WINAPI *MyGetConsoleTitle)(LPTSTR, DWORD);
114 #elif defined(PS_USE_CLOBBER_ARGV)
115 static char *ps_buffer;
116 static size_t ps_buffer_size;
117 static char *empty_environ[] = {0};
118 #else
119 #define PS_BUFFER_SIZE 256
120 static char ps_buffer[PS_BUFFER_SIZE];
121 static const size_t ps_buffer_size = PS_BUFFER_SIZE;
122 #endif
123
124 static size_t ps_buffer_cur_len;
125
126
127 static int save_argc;
128 static char** save_argv;
129
130
131
132
133
134 #if defined(PS_USE_CLOBBER_ARGV)
135 static char** frozen_environ, **new_environ;
136 #endif
137
138
139
140
141
142
143
144
145 char** save_ps_args(int argc, char** argv)
146 {
147 save_argc = argc;
148 save_argv = argv;
149
150 #if defined(PS_USE_CLOBBER_ARGV)
151
152
153
154
155 {
156 char* end_of_area = NULL;
157 int non_contiguous_area = 0;
158 int i;
159
160
161
162
163 for (i = 0; (non_contiguous_area == 0) && (i < argc); i++)
164 {
165 if (i != 0 && end_of_area + 1 != argv[i])
166 non_contiguous_area = 1;
167 end_of_area = argv[i] + strlen(argv[i]);
168 }
169
170
171
172
173 for (i = 0; (non_contiguous_area == 0) && (environ[i] != NULL); i++)
174 {
175 if (end_of_area + 1 != environ[i])
176 non_contiguous_area = 1;
177 end_of_area = environ[i] + strlen(environ[i]);
178 }
179
180 if (non_contiguous_area != 0)
181 goto clobber_error;
182
183 ps_buffer = argv[0];
184 ps_buffer_size = end_of_area - argv[0];
185
186
187
188
189 new_environ = (char **) malloc((i + 1) * sizeof(char *));
190 frozen_environ = (char **) malloc((i + 1) * sizeof(char *));
191 if (!new_environ || !frozen_environ)
192 goto clobber_error;
193 for (i = 0; environ[i] != NULL; i++)
194 {
195 new_environ[i] = strdup(environ[i]);
196 if (!new_environ[i])
197 goto clobber_error;
198 }
199 new_environ[i] = NULL;
200 environ = new_environ;
201 memcpy((char *)frozen_environ, (char *)new_environ, sizeof(char *) * (i + 1));
202
203 }
204 #endif
205
206 #if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
207
208
209
210
211
212
213
214
215
216
217 {
218 char** new_argv;
219 int i;
220
221 new_argv = (char **) malloc((argc + 1) * sizeof(char *));
222 if (!new_argv)
223 goto clobber_error;
224 for (i = 0; i < argc; i++)
225 {
226 new_argv[i] = strdup(argv[i]);
227 if (!new_argv[i])
228 goto clobber_error;
229 }
230 new_argv[argc] = NULL;
231
232 #if defined(DARWIN)
233
234
235
236
237 *_NSGetArgv() = new_argv;
238 #endif
239
240 argv = new_argv;
241
242 }
243 #endif
244
245 #if defined(PS_USE_CLOBBER_ARGV)
246 {
247
248 int i;
249 for (i = 1; i < save_argc; i++)
250 save_argv[i] = ps_buffer + ps_buffer_size;
251 }
252 #endif
253
254 #ifdef PS_USE_CHANGE_ARGV
255 save_argv[0] = ps_buffer;
256 save_argv[1] = NULL;
257 #endif
258
259 return argv;
260
261 #if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
262 clobber_error:
263
264
265
266
267 save_argv = NULL;
268 save_argc = 0;
269 ps_buffer = NULL;
270 ps_buffer_size = 0;
271 return argv;
272 #endif
273 }
274
275
276
277
278
279
280 int is_ps_title_available()
281 {
282 #ifdef PS_USE_NONE
283 return PS_TITLE_NOT_AVAILABLE;
284 #endif
285
286 if (!save_argv)
287 return PS_TITLE_NOT_INITIALIZED;
288
289 #ifdef PS_USE_CLOBBER_ARGV
290 if (!ps_buffer)
291 return PS_TITLE_BUFFER_NOT_AVAILABLE;
292 #endif
293
294 return PS_TITLE_SUCCESS;
295 }
296
297
298
299
300 const char* ps_title_errno(int rc)
301 {
302 switch(rc)
303 {
304 case PS_TITLE_SUCCESS:
305 return "Success";
306
307 case PS_TITLE_NOT_AVAILABLE:
308 return "Not available on this OS";
309
310 case PS_TITLE_NOT_INITIALIZED:
311 return "Not initialized correctly";
312
313 case PS_TITLE_BUFFER_NOT_AVAILABLE:
314 return "Buffer not contiguous";
315
316 #ifdef PS_USE_WIN32
317 case PS_TITLE_WINDOWS_ERROR:
318 sprintf(windows_error_details, "Windows error code: %lu", GetLastError());
319 return windows_error_details;
320 #endif
321 }
322
323 return "Unknown error code";
324 }
325
326
327
328
329
330
331
332
333 int set_ps_title(const char* title)
334 {
335 int rc = is_ps_title_available();
336 if (rc != PS_TITLE_SUCCESS)
337 return rc;
338
339 strncpy(ps_buffer, title, ps_buffer_size);
340 ps_buffer[ps_buffer_size - 1] = '\0';
341 ps_buffer_cur_len = strlen(ps_buffer);
342
343 #ifdef PS_USE_SETPROCTITLE
344 setproctitle("%s", ps_buffer);
345 #endif
346
347 #ifdef PS_USE_PSTAT
348 {
349 union pstun pst;
350
351 pst.pst_command = ps_buffer;
352 pstat(PSTAT_SETCMD, pst, ps_buffer_cur_len, 0, 0);
353 }
354 #endif
355
356 #ifdef PS_USE_PS_STRINGS
357 PS_STRINGS->ps_nargvstr = 1;
358 PS_STRINGS->ps_argvstr = ps_buffer;
359 #endif
360
361 #ifdef PS_USE_CLOBBER_ARGV
362
363 if (ps_buffer_cur_len < ps_buffer_size)
364 {
365 memset(ps_buffer + ps_buffer_cur_len, PS_PADDING,
366 ps_buffer_size - ps_buffer_cur_len);
367 }
368 #endif
369
370 #ifdef PS_USE_WIN32
371 {
372 MySetConsoleTitle set_title = NULL;
373 HMODULE hMod = LoadLibrary("kernel32.dll");
374
375 if (!hMod) {
376 return PS_TITLE_WINDOWS_ERROR;
377 }
378
379
380 set_title = (MySetConsoleTitle)GetProcAddress(hMod, "SetConsoleTitleA");
381 if (!set_title) {
382 return PS_TITLE_WINDOWS_ERROR;
383 }
384
385 if (!set_title(ps_buffer)) {
386 return PS_TITLE_WINDOWS_ERROR;
387 }
388 }
389 #endif
390
391 return PS_TITLE_SUCCESS;
392 }
393
394
395
396
397
398
399
400 int get_ps_title(int *displen, const char** string)
401 {
402 int rc = is_ps_title_available();
403 if (rc != PS_TITLE_SUCCESS)
404 return rc;
405
406 #ifdef PS_USE_WIN32
407 {
408 MyGetConsoleTitle get_title = NULL;
409 HMODULE hMod = LoadLibrary("kernel32.dll");
410
411 if (!hMod) {
412 return PS_TITLE_WINDOWS_ERROR;
413 }
414
415
416 get_title = (MyGetConsoleTitle)GetProcAddress(hMod, "GetConsoleTitleA");
417 if (!get_title) {
418 return PS_TITLE_WINDOWS_ERROR;
419 }
420
421 if (!(ps_buffer_cur_len = get_title(ps_buffer, (DWORD)ps_buffer_size))) {
422 return PS_TITLE_WINDOWS_ERROR;
423 }
424 }
425 #endif
426 *displen = (int)ps_buffer_cur_len;
427 *string = ps_buffer;
428 return PS_TITLE_SUCCESS;
429 }
430
431
432
433
434
435
436
437
438 void cleanup_ps_args(char **argv)
439 {
440 #ifndef PS_USE_NONE
441 if (save_argv)
442 {
443 save_argv = NULL;
444 save_argc = 0;
445
446 #ifdef PS_USE_CLOBBER_ARGV
447 {
448 int i;
449 for (i = 0; frozen_environ[i] != NULL; i++)
450 free(frozen_environ[i]);
451 free(frozen_environ);
452 free(new_environ);
453
454
455 environ = empty_environ;
456 }
457 #endif
458
459 #if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
460 {
461 int i;
462 for (i=0; argv[i] != NULL; i++)
463 free(argv[i]);
464 free(argv);
465 }
466 #endif
467 }
468 #endif
469
470 return;
471 }