mirror of
https://github.com/php/php-src.git
synced 2024-09-22 18:37:25 +00:00
Merge branch 'pull-request/300' into PHP-5.5
* pull-request/300: Support for CLI process title (https://wiki.php.net/rfc/cli_process_title)
This commit is contained in:
commit
5543035a70
@ -6,6 +6,23 @@ PHP_ARG_ENABLE(cli,,
|
||||
[ --disable-cli Disable building CLI version of PHP
|
||||
(this forces --without-pear)], yes, no)
|
||||
|
||||
AC_CHECK_FUNCS(setproctitle)
|
||||
|
||||
AC_CHECK_HEADERS([sys/pstat.h])
|
||||
|
||||
AC_CACHE_CHECK([for PS_STRINGS], [cli_cv_var_PS_STRINGS],
|
||||
[AC_TRY_LINK(
|
||||
[#include <machine/vmparam.h>
|
||||
#include <sys/exec.h>
|
||||
],
|
||||
[PS_STRINGS->ps_nargvstr = 1;
|
||||
PS_STRINGS->ps_argvstr = "foo";],
|
||||
[cli_cv_var_PS_STRINGS=yes],
|
||||
[cli_cv_var_PS_STRINGS=no])])
|
||||
if test "$cli_cv_var_PS_STRINGS" = yes ; then
|
||||
AC_DEFINE([HAVE_PS_STRINGS], [], [Define to 1 if the PS_STRINGS thing exists.])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(for CLI build)
|
||||
if test "$PHP_CLI" != "no"; then
|
||||
PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/cli/Makefile.frag)
|
||||
@ -14,7 +31,7 @@ if test "$PHP_CLI" != "no"; then
|
||||
SAPI_CLI_PATH=sapi/cli/php
|
||||
|
||||
dnl Select SAPI
|
||||
PHP_SELECT_SAPI(cli, program, php_cli.c php_http_parser.c php_cli_server.c,, '$(SAPI_CLI_PATH)')
|
||||
PHP_SELECT_SAPI(cli, program, php_cli.c php_http_parser.c php_cli_server.c ps_title.c php_cli_process_title.c,, '$(SAPI_CLI_PATH)')
|
||||
|
||||
case $host_alias in
|
||||
*aix*)
|
||||
|
@ -6,7 +6,7 @@ ARG_ENABLE('crt-debug', 'Enable CRT memory dumps for debugging sent to STDERR',
|
||||
ARG_ENABLE('cli-win32', 'Build console-less CLI version of PHP', 'no');
|
||||
|
||||
if (PHP_CLI == "yes") {
|
||||
SAPI('cli', 'php_cli.c php_http_parser.c php_cli_server.c', 'php.exe');
|
||||
SAPI('cli', 'php_cli.c php_http_parser.c php_cli_server.c php_cli_process_title.c ps_title.c', 'php.exe');
|
||||
ADD_FLAG("LIBS_CLI", "ws2_32.lib");
|
||||
if (PHP_CRT_DEBUG == "yes") {
|
||||
ADD_FLAG("CFLAGS_CLI", "/D PHP_WIN32_DEBUG_HEAP");
|
||||
@ -15,7 +15,7 @@ if (PHP_CLI == "yes") {
|
||||
}
|
||||
|
||||
if (PHP_CLI_WIN32 == "yes") {
|
||||
SAPI('cli_win32', 'cli_win32.c', 'php-win.exe');
|
||||
SAPI('cli_win32', 'cli_win32.c php_cli_process_title.c ps_title.c', 'php-win.exe');
|
||||
ADD_FLAG("LDFLAGS_CLI_WIN32", "/stack:8388608");
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,9 @@
|
||||
#include "php_cli_server.h"
|
||||
#endif
|
||||
|
||||
#include "ps_title.h"
|
||||
#include "php_cli_process_title.h"
|
||||
|
||||
#ifndef PHP_WIN32
|
||||
# define php_select(m, r, w, e, t) select(m, r, w, e, t)
|
||||
#else
|
||||
@ -478,6 +481,8 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
static const zend_function_entry additional_functions[] = {
|
||||
ZEND_FE(dl, arginfo_dl)
|
||||
PHP_FE(cli_set_process_title, arginfo_cli_set_process_title)
|
||||
PHP_FE(cli_get_process_title, arginfo_cli_get_process_title)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@ -1200,6 +1205,7 @@ int main(int argc, char *argv[])
|
||||
int argc = __argc;
|
||||
char **argv = __argv;
|
||||
#endif
|
||||
|
||||
int c;
|
||||
int exit_status = SUCCESS;
|
||||
int module_started = 0, sapi_started = 0;
|
||||
@ -1211,6 +1217,12 @@ int main(int argc, char *argv[])
|
||||
int ini_ignore = 0;
|
||||
sapi_module_struct *sapi_module = &cli_sapi_module;
|
||||
|
||||
/*
|
||||
* Do not move this initialization. It needs to happen before argv is used
|
||||
* in any way.
|
||||
*/
|
||||
argv = save_ps_args(argc, argv);
|
||||
|
||||
cli_sapi_module.additional_functions = additional_functions;
|
||||
|
||||
#if defined(PHP_WIN32) && defined(_DEBUG) && defined(PHP_WIN32_DEBUG_HEAP)
|
||||
@ -1299,6 +1311,7 @@ int main(int argc, char *argv[])
|
||||
#ifndef PHP_CLI_WIN32_NO_CONSOLE
|
||||
case 'S':
|
||||
sapi_module = &cli_server_sapi_module;
|
||||
cli_server_sapi_module.additional_functions = server_additional_functions;
|
||||
break;
|
||||
#endif
|
||||
case 'h': /* help & quit */
|
||||
@ -1385,6 +1398,11 @@ out:
|
||||
tsrm_shutdown();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do not move this de-initialization. It needs to happen right before
|
||||
* exiting.
|
||||
*/
|
||||
cleanup_ps_args(argv);
|
||||
exit(exit_status);
|
||||
}
|
||||
/* }}} */
|
||||
|
80
sapi/cli/php_cli_process_title.c
Normal file
80
sapi/cli/php_cli_process_title.c
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2013 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Keyur Govande (kgovande@gmail.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#include "php_cli_process_title.h"
|
||||
#include "ps_title.h"
|
||||
|
||||
/* {{{ proto boolean cli_set_process_title(string arg)
|
||||
Return a boolean to confirm if the process title was successfully changed or not */
|
||||
PHP_FUNCTION(cli_set_process_title)
|
||||
{
|
||||
char *title = NULL;
|
||||
int title_len;
|
||||
int rc;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &title, &title_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
rc = set_ps_title(title);
|
||||
if (rc == PS_TITLE_SUCCESS) {
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cli_set_process_title had an error: %s", ps_title_errno(rc));
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string cli_get_process_title()
|
||||
Return a string with the current process title. NULL if error. */
|
||||
PHP_FUNCTION(cli_get_process_title)
|
||||
{
|
||||
int length = 0;
|
||||
const char* title = NULL;
|
||||
int rc;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
rc = get_ps_title(&length, &title);
|
||||
if (rc != PS_TITLE_SUCCESS) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cli_get_process_title had an error: %s", ps_title_errno(rc));
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
RETURN_STRINGL(title, length, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: noet sw=4 ts=4 fdm=marker
|
||||
* vim<600: noet sw=4 ts=4
|
||||
*/
|
43
sapi/cli/php_cli_process_title.h
Normal file
43
sapi/cli/php_cli_process_title.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2013 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Keyur Govande (kgovande@gmail.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef PHP_PS_TITLE_HEADER
|
||||
#define PHP_PS_TITLE_HEADER
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_cli_set_process_title, 0)
|
||||
ZEND_ARG_INFO(0, title)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_cli_get_process_title, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PHP_FUNCTION(cli_set_process_title);
|
||||
PHP_FUNCTION(cli_get_process_title);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: noet sw=4 ts=4 fdm=marker
|
||||
* vim<600: noet sw=4 ts=4
|
||||
*/
|
@ -103,6 +103,8 @@
|
||||
#include "php_http_parser.h"
|
||||
#include "php_cli_server.h"
|
||||
|
||||
#include "php_cli_process_title.h"
|
||||
|
||||
#define OUTPUT_NOT_CHECKED -1
|
||||
#define OUTPUT_IS_TTY 1
|
||||
#define OUTPUT_NOT_TTY 0
|
||||
@ -429,6 +431,12 @@ zend_module_entry cli_server_module_entry = {
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
const zend_function_entry server_additional_functions[] = {
|
||||
PHP_FE(cli_set_process_title, arginfo_cli_set_process_title)
|
||||
PHP_FE(cli_get_process_title, arginfo_cli_get_process_title)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int sapi_cli_server_startup(sapi_module_struct *sapi_module) /* {{{ */
|
||||
{
|
||||
if (php_module_startup(sapi_module, &cli_server_module_entry, 1) == FAILURE) {
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "SAPI.h"
|
||||
|
||||
extern const zend_function_entry server_additional_functions[];
|
||||
extern sapi_module_struct cli_server_sapi_module;
|
||||
extern int do_cli_server(int argc, char **argv TSRMLS_DC);
|
||||
|
||||
|
426
sapi/cli/ps_title.c
Normal file
426
sapi/cli/ps_title.c
Normal file
@ -0,0 +1,426 @@
|
||||
/*
|
||||
* PostgreSQL is released under the PostgreSQL License, a liberal Open Source
|
||||
* license, similar to the BSD or MIT licenses.
|
||||
* PostgreSQL Database Management System (formerly known as Postgres, then as
|
||||
* Postgres95)
|
||||
*
|
||||
* Portions Copyright (c) 1996-2013, The PostgreSQL Global Development Group
|
||||
*
|
||||
* Portions Copyright (c) 1994, The Regents of the University of California
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose, without fee, and without a written
|
||||
* agreement is hereby granted, provided that the above copyright notice
|
||||
* and this paragraph and the following two paragraphs appear in all copies.
|
||||
*
|
||||
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
|
||||
* LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
|
||||
* EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
|
||||
* "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* The following code is adopted from the PostgreSQL's ps_status(.h/.c).
|
||||
*/
|
||||
|
||||
#include "ps_title.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#include "config.w32.h"
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include "php_config.h"
|
||||
extern char** environ;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PSTAT_H
|
||||
#include <sys/pstat.h> /* for HP-UX */
|
||||
#endif
|
||||
#ifdef HAVE_PS_STRINGS
|
||||
#include <machine/vmparam.h> /* for old BSD */
|
||||
#include <sys/exec.h>
|
||||
#endif
|
||||
#if defined(DARWIN)
|
||||
#include <crt_externs.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ways of updating ps display:
|
||||
*
|
||||
* PS_USE_SETPROCTITLE
|
||||
* use the function setproctitle(const char *, ...)
|
||||
* (newer BSD systems)
|
||||
* PS_USE_PSTAT
|
||||
* use the pstat(PSTAT_SETCMD, )
|
||||
* (HPUX)
|
||||
* PS_USE_PS_STRINGS
|
||||
* assign PS_STRINGS->ps_argvstr = "string"
|
||||
* (some BSD systems)
|
||||
* PS_USE_CHANGE_ARGV
|
||||
* assign argv[0] = "string"
|
||||
* (some other BSD systems)
|
||||
* PS_USE_CLOBBER_ARGV
|
||||
* write over the argv and environment area
|
||||
* (Linux and most SysV-like systems)
|
||||
* PS_USE_WIN32
|
||||
* push the string out as the name of a Windows event
|
||||
* PS_USE_NONE
|
||||
* don't update ps display
|
||||
* (This is the default, as it is safest.)
|
||||
*/
|
||||
#if defined(HAVE_SETPROCTITLE)
|
||||
#define PS_USE_SETPROCTITLE
|
||||
#elif defined(HAVE_SYS_PSTAT_H) && defined(PSTAT_SETCMD)
|
||||
#define PS_USE_PSTAT
|
||||
#elif defined(HAVE_PS_STRINGS)
|
||||
#define PS_USE_PS_STRINGS
|
||||
#elif defined(BSD) && !defined(DARWIN)
|
||||
#define PS_USE_CHANGE_ARGV
|
||||
#elif defined(__linux__) || defined(_AIX) || defined(__sgi) || (defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__osf__) || defined(DARWIN)
|
||||
#define PS_USE_CLOBBER_ARGV
|
||||
#elif defined(PHP_WIN32)
|
||||
#define PS_USE_WIN32
|
||||
#else
|
||||
#define PS_USE_NONE
|
||||
#endif
|
||||
|
||||
/* Different systems want the buffer padded differently */
|
||||
#if defined(_AIX) || defined(__linux__) || defined(DARWIN)
|
||||
#define PS_PADDING '\0'
|
||||
#else
|
||||
#define PS_PADDING ' '
|
||||
#endif
|
||||
|
||||
#ifdef PS_USE_WIN32
|
||||
static char windows_error_details[64];
|
||||
static char ps_buffer[MAX_PATH];
|
||||
static const size_t ps_buffer_size = MAX_PATH;
|
||||
#elif defined(PS_USE_CLOBBER_ARGV)
|
||||
static char *ps_buffer; /* will point to argv area */
|
||||
static size_t ps_buffer_size; /* space determined at run time */
|
||||
#else
|
||||
#define PS_BUFFER_SIZE 256
|
||||
static char ps_buffer[PS_BUFFER_SIZE];
|
||||
static const size_t ps_buffer_size = PS_BUFFER_SIZE;
|
||||
#endif
|
||||
|
||||
static size_t ps_buffer_cur_len; /* actual string length in ps_buffer */
|
||||
|
||||
/* save the original argv[] location here */
|
||||
static int save_argc;
|
||||
static char** save_argv;
|
||||
|
||||
|
||||
/*
|
||||
* Call this method early, before any code has used the original argv passed in
|
||||
* from main().
|
||||
* If needed, this code will make deep copies of argv and environ and return
|
||||
* these to the caller for further use. The original argv is then 'clobbered'
|
||||
* to store the process title.
|
||||
*/
|
||||
char** save_ps_args(int argc, char** argv)
|
||||
{
|
||||
save_argc = argc;
|
||||
save_argv = argv;
|
||||
|
||||
#if defined(PS_USE_CLOBBER_ARGV)
|
||||
/*
|
||||
* If we're going to overwrite the argv area, count the available space.
|
||||
* Also move the environment to make additional room.
|
||||
*/
|
||||
{
|
||||
char* end_of_area = NULL;
|
||||
int non_contiguous_area = 0;
|
||||
char** new_environ;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* check for contiguous argv strings
|
||||
*/
|
||||
for (i = 0; (non_contiguous_area == 0) && (i < argc); i++)
|
||||
{
|
||||
if (i != 0 && end_of_area + 1 != argv[i])
|
||||
non_contiguous_area = 1;
|
||||
end_of_area = argv[i] + strlen(argv[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* check for contiguous environ strings following argv
|
||||
*/
|
||||
for (i = 0; (non_contiguous_area == 0) && (environ[i] != NULL); i++)
|
||||
{
|
||||
if (end_of_area + 1 != environ[i])
|
||||
non_contiguous_area = 1;
|
||||
end_of_area = environ[i] + strlen(environ[i]);
|
||||
}
|
||||
|
||||
if (non_contiguous_area != 0)
|
||||
goto clobber_error;
|
||||
|
||||
ps_buffer = argv[0];
|
||||
ps_buffer_size = end_of_area - argv[0];
|
||||
|
||||
/*
|
||||
* move the environment out of the way
|
||||
*/
|
||||
new_environ = (char **) malloc((i + 1) * sizeof(char *));
|
||||
if (!new_environ)
|
||||
goto clobber_error;
|
||||
for (i = 0; environ[i] != NULL; i++)
|
||||
{
|
||||
new_environ[i] = strdup(environ[i]);
|
||||
if (!new_environ[i])
|
||||
goto clobber_error;
|
||||
}
|
||||
new_environ[i] = NULL;
|
||||
environ = new_environ;
|
||||
|
||||
}
|
||||
#endif /* PS_USE_CLOBBER_ARGV */
|
||||
|
||||
#if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
|
||||
/*
|
||||
* If we're going to change the original argv[] then make a copy for
|
||||
* argument parsing purposes.
|
||||
*
|
||||
* (NB: do NOT think to remove the copying of argv[]!
|
||||
* On some platforms, getopt() keeps pointers into the argv array, and
|
||||
* will get horribly confused when it is re-called to analyze a subprocess'
|
||||
* argument string if the argv storage has been clobbered meanwhile.
|
||||
* Other platforms have other dependencies on argv[].)
|
||||
*/
|
||||
{
|
||||
char** new_argv;
|
||||
int i;
|
||||
|
||||
new_argv = (char **) malloc((argc + 1) * sizeof(char *));
|
||||
if (!new_argv)
|
||||
goto clobber_error;
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
new_argv[i] = strdup(argv[i]);
|
||||
if (!new_argv[i])
|
||||
goto clobber_error;
|
||||
}
|
||||
new_argv[argc] = NULL;
|
||||
|
||||
#if defined(DARWIN)
|
||||
/*
|
||||
* Darwin (and perhaps other NeXT-derived platforms?) has a static
|
||||
* copy of the argv pointer, which we may fix like so:
|
||||
*/
|
||||
*_NSGetArgv() = new_argv;
|
||||
#endif
|
||||
|
||||
argv = new_argv;
|
||||
|
||||
}
|
||||
#endif /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */
|
||||
|
||||
#if defined(PS_USE_CLOBBER_ARGV)
|
||||
{
|
||||
/* make extra argv slots point at end_of_area (a NUL) */
|
||||
int i;
|
||||
for (i = 1; i < save_argc; i++)
|
||||
save_argv[i] = ps_buffer + ps_buffer_size;
|
||||
}
|
||||
#endif /* PS_USE_CLOBBER_ARGV */
|
||||
|
||||
#ifdef PS_USE_CHANGE_ARGV
|
||||
save_argv[0] = ps_buffer; /* ps_buffer here is a static const array of size PS_BUFFER_SIZE */
|
||||
save_argv[1] = NULL;
|
||||
#endif /* PS_USE_CHANGE_ARGV */
|
||||
|
||||
return argv;
|
||||
|
||||
#if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
|
||||
clobber_error:
|
||||
/* probably can't happen?!
|
||||
* if we ever get here, argv still points to originally passed
|
||||
* in argument
|
||||
*/
|
||||
save_argv = NULL;
|
||||
save_argc = 0;
|
||||
ps_buffer = NULL;
|
||||
ps_buffer_size = 0;
|
||||
return argv;
|
||||
#endif /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns PS_TITLE_SUCCESS if the OS supports this functionality
|
||||
* and the init function was called.
|
||||
* Otherwise returns NOT_AVAILABLE or NOT_INITIALIZED
|
||||
*/
|
||||
int is_ps_title_available()
|
||||
{
|
||||
#ifdef PS_USE_NONE
|
||||
return PS_TITLE_NOT_AVAILABLE; /* disabled functionality */
|
||||
#endif
|
||||
|
||||
if (!save_argv)
|
||||
return PS_TITLE_NOT_INITIALIZED;
|
||||
|
||||
#ifdef PS_USE_CLOBBER_ARGV
|
||||
if (!ps_buffer)
|
||||
return PS_TITLE_BUFFER_NOT_AVAILABLE;
|
||||
#endif /* PS_USE_CLOBBER_ARGV */
|
||||
|
||||
return PS_TITLE_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert error codes into error strings
|
||||
*/
|
||||
const char* ps_title_errno(int rc)
|
||||
{
|
||||
switch(rc)
|
||||
{
|
||||
case PS_TITLE_SUCCESS:
|
||||
return "Success";
|
||||
|
||||
case PS_TITLE_NOT_AVAILABLE:
|
||||
return "Not available on this OS";
|
||||
|
||||
case PS_TITLE_NOT_INITIALIZED:
|
||||
return "Not initialized correctly";
|
||||
|
||||
case PS_TITLE_BUFFER_NOT_AVAILABLE:
|
||||
return "Buffer not contiguous";
|
||||
|
||||
#ifdef PS_USE_WIN32
|
||||
case PS_TITLE_WINDOWS_ERROR:
|
||||
sprintf(windows_error_details, "Windows error code: %d", GetLastError());
|
||||
return windows_error_details;
|
||||
#endif
|
||||
}
|
||||
|
||||
return "Unknown error code";
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a new process title.
|
||||
* Returns the appropriate error code if if there's an error
|
||||
* (like the functionality is compile time disabled, or the
|
||||
* save_ps_args() was not called.
|
||||
* Else returns 0 on success.
|
||||
*/
|
||||
int set_ps_title(const char* title)
|
||||
{
|
||||
int rc = is_ps_title_available();
|
||||
if (rc != PS_TITLE_SUCCESS)
|
||||
return rc;
|
||||
|
||||
strncpy(ps_buffer, title, ps_buffer_size);
|
||||
ps_buffer[ps_buffer_size - 1] = '\0';
|
||||
ps_buffer_cur_len = strlen(ps_buffer);
|
||||
|
||||
#ifdef PS_USE_SETPROCTITLE
|
||||
setproctitle("%s", ps_buffer);
|
||||
#endif
|
||||
|
||||
#ifdef PS_USE_PSTAT
|
||||
{
|
||||
union pstun pst;
|
||||
|
||||
pst.pst_command = ps_buffer;
|
||||
pstat(PSTAT_SETCMD, pst, ps_buffer_cur_len, 0, 0);
|
||||
}
|
||||
#endif /* PS_USE_PSTAT */
|
||||
|
||||
#ifdef PS_USE_PS_STRINGS
|
||||
PS_STRINGS->ps_nargvstr = 1;
|
||||
PS_STRINGS->ps_argvstr = ps_buffer;
|
||||
#endif /* PS_USE_PS_STRINGS */
|
||||
|
||||
#ifdef PS_USE_CLOBBER_ARGV
|
||||
/* pad unused memory */
|
||||
if (ps_buffer_cur_len < ps_buffer_size)
|
||||
{
|
||||
memset(ps_buffer + ps_buffer_cur_len, PS_PADDING,
|
||||
ps_buffer_size - ps_buffer_cur_len);
|
||||
}
|
||||
#endif /* PS_USE_CLOBBER_ARGV */
|
||||
|
||||
#ifdef PS_USE_WIN32
|
||||
{
|
||||
if (!SetConsoleTitle(ps_buffer))
|
||||
return PS_TITLE_WINDOWS_ERROR;
|
||||
}
|
||||
#endif /* PS_USE_WIN32 */
|
||||
|
||||
return PS_TITLE_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the current ps_buffer value into string. On some platforms
|
||||
* the string will not be null-terminated, so return the effective
|
||||
* length into *displen.
|
||||
* The return code indicates the error.
|
||||
*/
|
||||
int get_ps_title(int *displen, const char** string)
|
||||
{
|
||||
int rc = is_ps_title_available();
|
||||
if (rc != PS_TITLE_SUCCESS)
|
||||
return rc;
|
||||
|
||||
#ifdef PS_USE_WIN32
|
||||
if (!(ps_buffer_cur_len = GetConsoleTitle(ps_buffer, ps_buffer_size)))
|
||||
return PS_TITLE_WINDOWS_ERROR;
|
||||
#endif
|
||||
*displen = (int)ps_buffer_cur_len;
|
||||
*string = ps_buffer;
|
||||
return PS_TITLE_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the allocated argv and environ if applicable. Only call
|
||||
* this right before exiting.
|
||||
* This isn't needed per-se because the OS will clean-up anyway, but
|
||||
* having and calling this will ensure Valgrind doesn't output 'false
|
||||
* positives'.
|
||||
*/
|
||||
void cleanup_ps_args(char **argv)
|
||||
{
|
||||
#ifndef PS_USE_NONE
|
||||
if (save_argv)
|
||||
{
|
||||
save_argv = NULL;
|
||||
save_argc = 0;
|
||||
|
||||
#ifdef PS_USE_CLOBBER_ARGV
|
||||
{
|
||||
int i;
|
||||
for (i = 0; environ[i] != NULL; i++)
|
||||
free(environ[i]);
|
||||
free(environ);
|
||||
}
|
||||
#endif /* PS_USE_CLOBBER_ARGV */
|
||||
|
||||
#if defined(PS_USE_CHANGE_ARGV) || defined(PS_USE_CLOBBER_ARGV)
|
||||
{
|
||||
int i;
|
||||
for (i=0; argv[i] != NULL; i++)
|
||||
free(argv[i]);
|
||||
free(argv);
|
||||
}
|
||||
#endif /* PS_USE_CHANGE_ARGV or PS_USE_CLOBBER_ARGV */
|
||||
}
|
||||
#endif /* PS_USE_NONE */
|
||||
|
||||
return;
|
||||
}
|
42
sapi/cli/ps_title.h
Normal file
42
sapi/cli/ps_title.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2013 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Keyur Govande <kgovande@gmail.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef PS_TITLE_HEADER
|
||||
#define PS_TITLE_HEADER
|
||||
|
||||
#define PS_TITLE_SUCCESS 0
|
||||
#define PS_TITLE_NOT_AVAILABLE 1
|
||||
#define PS_TITLE_NOT_INITIALIZED 2
|
||||
#define PS_TITLE_BUFFER_NOT_AVAILABLE 3
|
||||
#define PS_TITLE_WINDOWS_ERROR 4
|
||||
|
||||
extern char** save_ps_args(int argc, char** argv);
|
||||
|
||||
extern int set_ps_title(const char* new_str);
|
||||
|
||||
extern int get_ps_title(int* displen, const char** string);
|
||||
|
||||
extern const char* ps_title_errno(int rc);
|
||||
|
||||
extern int is_ps_title_available();
|
||||
|
||||
extern void cleanup_ps_args(char **argv);
|
||||
|
||||
#endif // PS_TITLE_HEADER
|
49
sapi/cli/tests/cli_process_title_unix.phpt
Normal file
49
sapi/cli/tests/cli_process_title_unix.phpt
Normal file
@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
Check cli_process_title support on Unix
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
|
||||
die("skip");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
echo "*** Testing setting the process title ***\n";
|
||||
|
||||
$set_title = $original_title = uniqid("title", true);
|
||||
$pid = getmypid();
|
||||
|
||||
if (cli_set_process_title($original_title) === true)
|
||||
echo "Successfully set title\n";
|
||||
|
||||
$ps_output = shell_exec("ps -p $pid -o command | tail -n 1");
|
||||
|
||||
if ($ps_output === null)
|
||||
{
|
||||
echo "ps failed\n";
|
||||
die();
|
||||
}
|
||||
|
||||
$loaded_title = trim($ps_output);
|
||||
if (strpos(strtoupper(substr(PHP_OS, 0, 13)), "BSD") !== false)
|
||||
{
|
||||
// Fix up title for BSD
|
||||
$set_title = "php: $original_title (php)";
|
||||
}
|
||||
|
||||
if ($loaded_title == $set_title)
|
||||
echo "Successfully verified title using ps\n";
|
||||
else
|
||||
echo "Actually loaded from ps: $loaded_title\n";
|
||||
|
||||
$read_title = cli_get_process_title();
|
||||
if ($read_title == $original_title)
|
||||
echo "Successfully verified title using get\n";
|
||||
else
|
||||
echo "Actually loaded from get: $read_title\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
*** Testing setting the process title ***
|
||||
Successfully set title
|
||||
Successfully verified title using ps
|
||||
Successfully verified title using get
|
82
sapi/cli/tests/cli_process_title_windows.phpt
Normal file
82
sapi/cli/tests/cli_process_title_windows.phpt
Normal file
@ -0,0 +1,82 @@
|
||||
--TEST--
|
||||
Check cli_process_title support in Windows
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
|
||||
die("skip");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
// On Windows 8 and Server 2012, this test does not work the same way. When the PowerShell
|
||||
// command "get-process" is executed using shell_exec, it overwrites the ConsoleTitle with
|
||||
// "Windows PowerShell" and this title ONLY clears away when the php.exe process exits
|
||||
// i.e. the test finishes.
|
||||
// On older versions like Windows 7 though, running the command appends
|
||||
// "Windows PowerShell" to the ConsoleTitle temporarily and the title reverts
|
||||
// back to the original once shell_exec is done.
|
||||
// Hence on Windows 8, we don't verify that the title is actually set by
|
||||
// cli_set_process_title(). We're only making the API calls to ensure there are
|
||||
// no warnings/errors.
|
||||
|
||||
$is_windows8 = false;
|
||||
$ps_output = shell_exec("PowerShell \"(Get-Host).UI.RawUI.WindowTitle\"");
|
||||
if ($ps_output === null)
|
||||
{
|
||||
echo "Get-Host failed\n";
|
||||
die();
|
||||
}
|
||||
|
||||
$ps_output = trim($ps_output);
|
||||
if (($ps_output == "Windows PowerShell") || ($ps_output == "Administrator: Windows PowerShell"))
|
||||
$is_windows8 = true;
|
||||
|
||||
echo "*** Testing setting the process title ***\n";
|
||||
|
||||
$original_title = uniqid("title", true);
|
||||
$pid = getmypid();
|
||||
|
||||
if (cli_set_process_title($original_title) === true)
|
||||
echo "Successfully set title\n";
|
||||
|
||||
if ($is_windows8)
|
||||
{
|
||||
$loaded_title = $original_title;
|
||||
}
|
||||
else
|
||||
{
|
||||
$loaded_title = shell_exec("PowerShell \"get-process cmd*,powershell* | Select-Object mainWindowTitle | ft -hide\"");
|
||||
|
||||
if ($loaded_title === null)
|
||||
{
|
||||
echo "Reading title using get-process failed\n";
|
||||
die();
|
||||
}
|
||||
|
||||
// Kind of convoluted. So when the test is run on Windows 7 or older, the console where
|
||||
// the run-tests.php is executed forks a php.exe, which forks a cmd.exe, which then forks
|
||||
// a final php.exe to run the actual test. But the console title is set for the original console.
|
||||
// I couldn't figure out a good way to navigate this, so we're "grep'ing" all possible
|
||||
// console windows for our very unique title. It should occur exactly once in the grep
|
||||
// output.
|
||||
if (substr_count($loaded_title, $original_title, 0) == 1)
|
||||
$loaded_title = $original_title;
|
||||
}
|
||||
|
||||
if ($loaded_title == $original_title)
|
||||
echo "Successfully verified title using get-process\n";
|
||||
else
|
||||
echo "Actually loaded from get-process: $loaded_title\n";
|
||||
|
||||
$read_title = cli_get_process_title();
|
||||
if (substr_count($read_title, $original_title, 0) == 1)
|
||||
echo "Successfully verified title using get\n";
|
||||
else
|
||||
echo "Actually loaded from get: $read_title\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
*** Testing setting the process title ***
|
||||
Successfully set title
|
||||
Successfully verified title using get-process
|
||||
Successfully verified title using get
|
Loading…
Reference in New Issue
Block a user