- 移除main.cc主程序文件及其PHP嵌入初始化代码 - 删除php_aot_helper.h头文件及其中的辅助函数声明 - 移除php_cli_process_title.c进程标题设置功能实现 - 删除php_cli_process_title.h头文件及函数声明 - 移除php_cli_process_title.stub.php存根文件 - 删除php_cli_process_title_arginfo.h参数信息文件 - 移除ps_title.c进程标题底层实现文件 - 删除ps_title.h头文件及状态枚举定义pull/1/head
parent
ccfef0f2b6
commit
b4d82a1bad
8 changed files with 0 additions and 805 deletions
@ -1,151 +0,0 @@ |
|||||||
#if PPROF_ON |
|
||||||
#include <gperftools/profiler.h> |
|
||||||
#endif |
|
||||||
|
|
||||||
#include <phpx.h> |
|
||||||
#include <php_aot_helper.h> |
|
||||||
#include "sapi/embed/php_embed.h" |
|
||||||
#include "ps_title.h" |
|
||||||
|
|
||||||
extern zend_module_entry *php_embed_get_module(); |
|
||||||
|
|
||||||
void module_init(zend_module_entry *module) { |
|
||||||
if (zend_register_module_ex(module, MODULE_PERSISTENT) == NULL) { |
|
||||||
zend_error(E_ERROR, "Failed to register module [%s]", module->name); |
|
||||||
exit(255); |
|
||||||
} |
|
||||||
if (zend_startup_module_ex(module) == FAILURE) { |
|
||||||
zend_error(E_ERROR, "Failed to startup module [%s]", module->name); |
|
||||||
exit(255); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const char *php_get_called_class(php::Object &this_) { |
|
||||||
auto ce = php_get_called_ce(this_); |
|
||||||
if (ce) { |
|
||||||
return ce->name->val; |
|
||||||
} else { |
|
||||||
return ""; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
zend_class_entry *php_get_called_ce(php::Object &this_) { |
|
||||||
if (this_.isObject()) { |
|
||||||
return this_.ce(); |
|
||||||
} else { |
|
||||||
return (zend_class_entry *) Z_PTR_P(this_.ptr()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static zend_execute_data *get_frame() { |
|
||||||
zend_execute_data *frame = EG(current_execute_data); |
|
||||||
while (frame && (!frame->func || !ZEND_USER_CODE(frame->func->type))) { |
|
||||||
frame = frame->prev_execute_data; |
|
||||||
} |
|
||||||
return frame; |
|
||||||
} |
|
||||||
|
|
||||||
php::Scope php_switch_scope(php::Object &this_) { |
|
||||||
php::Scope scope; |
|
||||||
scope.frame = get_frame(); |
|
||||||
scope.ce = scope.frame->func->common.scope; |
|
||||||
scope.frame->func->common.scope = php_get_called_ce(this_); |
|
||||||
return scope; |
|
||||||
} |
|
||||||
|
|
||||||
void php_restore_scope(php::Scope &ori_scope) { |
|
||||||
ori_scope.frame->func->common.scope = ori_scope.ce; |
|
||||||
} |
|
||||||
|
|
||||||
static php_stream *s_in_process = NULL; |
|
||||||
static void cli_register_file_handles(void) { |
|
||||||
php_stream *s_in, *s_out, *s_err; |
|
||||||
php_stream_context *sc_in = NULL, *sc_out = NULL, *sc_err = NULL; |
|
||||||
zend_constant ic, oc, ec; |
|
||||||
|
|
||||||
s_in = php_stream_open_wrapper_ex("php://stdin", "rb", 0, NULL, sc_in); |
|
||||||
s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out); |
|
||||||
s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err); |
|
||||||
|
|
||||||
/* Release stream resources, but don't free the underlying handles. Otherwise,
|
|
||||||
* extensions which write to stderr or company during mshutdown/gshutdown |
|
||||||
* won't have the expected functionality. |
|
||||||
*/ |
|
||||||
if (s_in) s_in->flags |= PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE; |
|
||||||
if (s_out) s_out->flags |= PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE; |
|
||||||
if (s_err) s_err->flags |= PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE; |
|
||||||
|
|
||||||
if (s_in == NULL || s_out == NULL || s_err == NULL) { |
|
||||||
if (s_in) php_stream_close(s_in); |
|
||||||
if (s_out) php_stream_close(s_out); |
|
||||||
if (s_err) php_stream_close(s_err); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
s_in_process = s_in; |
|
||||||
|
|
||||||
php_stream_to_zval(s_in, &ic.value); |
|
||||||
php_stream_to_zval(s_out, &oc.value); |
|
||||||
php_stream_to_zval(s_err, &ec.value); |
|
||||||
|
|
||||||
Z_CONSTANT_FLAGS(ic.value) = 0; |
|
||||||
ic.name = zend_string_init_interned("STDIN", sizeof("STDIN") - 1, 0); |
|
||||||
zend_register_constant(&ic); |
|
||||||
|
|
||||||
Z_CONSTANT_FLAGS(oc.value) = 0; |
|
||||||
oc.name = zend_string_init_interned("STDOUT", sizeof("STDOUT") - 1, 0); |
|
||||||
zend_register_constant(&oc); |
|
||||||
|
|
||||||
Z_CONSTANT_FLAGS(ec.value) = 0; |
|
||||||
ec.name = zend_string_init_interned("STDERR", sizeof("STDERR") - 1, 0); |
|
||||||
zend_register_constant(&ec); |
|
||||||
} |
|
||||||
|
|
||||||
void module_shutdown(zend_module_entry *module) { |
|
||||||
/**
|
|
||||||
* There is a bug in PHP's handling of internal strings. All interned strings are released in the request shutdown |
|
||||||
* function, but then released again in the php_embed_shutdown function, resulting in a use-after-free issue. These |
|
||||||
* must be manually removed from the module table to prevent double release. |
|
||||||
*/ |
|
||||||
auto name_len = strlen(module->name); |
|
||||||
auto lcname = zend_string_alloc(name_len, module->type == MODULE_PERSISTENT); |
|
||||||
zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len); |
|
||||||
zend_hash_del(&module_registry, lcname); |
|
||||||
} |
|
||||||
|
|
||||||
int main(int cpp_argc, char **cpp_argv) { |
|
||||||
php_embed_init(cpp_argc, cpp_argv); |
|
||||||
php::throw_impl = [](zend_object *ex) { throw ex; }; |
|
||||||
|
|
||||||
zend_module_entry *module = php_embed_get_module(); |
|
||||||
module_init(module); |
|
||||||
|
|
||||||
save_ps_args(cpp_argc, cpp_argv); |
|
||||||
|
|
||||||
int rc = 0; |
|
||||||
#if PPROF_ON |
|
||||||
ProfilerStart("profile.out"); |
|
||||||
#endif |
|
||||||
zend_first_try { |
|
||||||
try { |
|
||||||
char path_translated[] = "embed"; |
|
||||||
cli_register_file_handles(); |
|
||||||
SG(request_info).path_translated = path_translated; |
|
||||||
module->request_startup_func(module->type, module->module_number); |
|
||||||
} catch (zend_object *e) { |
|
||||||
rc = EG(exit_status); |
|
||||||
CG(unclean_shutdown) = 1; |
|
||||||
zend_exception_error(e, E_ERROR); |
|
||||||
} |
|
||||||
} |
|
||||||
zend_end_try(); |
|
||||||
#if PPROF_ON |
|
||||||
ProfilerStop(); |
|
||||||
#endif |
|
||||||
|
|
||||||
module->request_shutdown_func(module->type, module->module_number); |
|
||||||
module_shutdown(module); |
|
||||||
php_embed_shutdown(); |
|
||||||
|
|
||||||
return rc; |
|
||||||
} |
|
||||||
@ -1,34 +0,0 @@ |
|||||||
#include <phpx.h> |
|
||||||
#include <phpx_helper.h> |
|
||||||
|
|
||||||
#include <zend_attributes.h> |
|
||||||
|
|
||||||
extern zend_class_entry *php_get_class(int class_id, const php::Str &class_name); |
|
||||||
extern zend_function *php_get_func(int func_id, const php::Str &func_name); |
|
||||||
extern zend_function *php_get_method(int func_id, |
|
||||||
const php::Str &method_name, |
|
||||||
int class_id, |
|
||||||
const php::Str &class_name); |
|
||||||
extern uint32_t php_get_prop(int prop_id, const php::Str &prop_name, int class_id, const php::Str &class_name); |
|
||||||
|
|
||||||
namespace php { |
|
||||||
struct Scope { |
|
||||||
zend_class_entry *ce; |
|
||||||
zend_execute_data *frame; |
|
||||||
}; |
|
||||||
}; // namespace php
|
|
||||||
|
|
||||||
extern const char *php_get_called_class(php::Object &this_); |
|
||||||
extern zend_class_entry *php_get_called_ce(php::Object &this_); |
|
||||||
extern php::Scope php_switch_scope(php::Object &this_); |
|
||||||
extern void php_restore_scope(php::Scope &ori_scope); |
|
||||||
|
|
||||||
static inline auto php_std_create_object(zend_class_entry *ce) { |
|
||||||
auto obj = zend_objects_new(ce); |
|
||||||
object_properties_init(obj, ce); |
|
||||||
return obj; |
|
||||||
} |
|
||||||
|
|
||||||
static inline auto php_get_create_object_fn(zend_class_entry *ce) { |
|
||||||
return ce->create_object ? ce->create_object : php_std_create_object; |
|
||||||
} |
|
||||||
@ -1,63 +0,0 @@ |
|||||||
/*
|
|
||||||
+----------------------------------------------------------------------+ |
|
||||||
| Copyright (c) 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: | |
|
||||||
| https://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) | |
|
||||||
+----------------------------------------------------------------------+ |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H |
|
||||||
#include <config.h> |
|
||||||
#endif |
|
||||||
|
|
||||||
#include "php.h" |
|
||||||
#include "php_cli_process_title.h" |
|
||||||
#include "ps_title.h" |
|
||||||
|
|
||||||
/* {{{ Return a boolean to confirm if the process title was successfully changed or not */ |
|
||||||
PHP_FUNCTION(cli_set_process_title) |
|
||||||
{ |
|
||||||
char *title = NULL; |
|
||||||
size_t title_len; |
|
||||||
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &title, &title_len) == FAILURE) { |
|
||||||
RETURN_THROWS(); |
|
||||||
} |
|
||||||
|
|
||||||
ps_title_status rc = set_ps_title(title, title_len); |
|
||||||
if (rc == PS_TITLE_SUCCESS) { |
|
||||||
RETURN_TRUE; |
|
||||||
} |
|
||||||
|
|
||||||
php_error_docref(NULL, E_WARNING, "cli_set_process_title had an error: %s", ps_title_errno(rc)); |
|
||||||
RETURN_FALSE; |
|
||||||
} |
|
||||||
/* }}} */ |
|
||||||
|
|
||||||
/* {{{ Return a string with the current process title. NULL if error. */ |
|
||||||
PHP_FUNCTION(cli_get_process_title) |
|
||||||
{ |
|
||||||
size_t length = 0; |
|
||||||
const char* title = NULL; |
|
||||||
|
|
||||||
if (zend_parse_parameters_none() == FAILURE) { |
|
||||||
RETURN_THROWS(); |
|
||||||
} |
|
||||||
|
|
||||||
ps_title_status rc = get_ps_title(&length, &title); |
|
||||||
if (rc != PS_TITLE_SUCCESS) { |
|
||||||
php_error_docref(NULL, E_WARNING, "cli_get_process_title had an error: %s", ps_title_errno(rc)); |
|
||||||
RETURN_NULL(); |
|
||||||
} |
|
||||||
|
|
||||||
RETURN_STRINGL(title, length); |
|
||||||
} |
|
||||||
/* }}} */ |
|
||||||
@ -1,23 +0,0 @@ |
|||||||
/*
|
|
||||||
+----------------------------------------------------------------------+ |
|
||||||
| Copyright (c) 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: | |
|
||||||
| https://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) | |
|
||||||
+----------------------------------------------------------------------+ |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef PHP_PS_TITLE_HEADER |
|
||||||
#define PHP_PS_TITLE_HEADER |
|
||||||
|
|
||||||
PHP_FUNCTION(cli_set_process_title); |
|
||||||
PHP_FUNCTION(cli_get_process_title); |
|
||||||
|
|
||||||
#endif |
|
||||||
@ -1,5 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
function cli_set_process_title(string $title): bool {} |
|
||||||
|
|
||||||
function cli_get_process_title(): ?string {} |
|
||||||
@ -1,10 +0,0 @@ |
|||||||
/* This is a generated file, edit the .stub.php file instead.
|
|
||||||
* Stub hash: ee776e0c54fe4b66a98b3a0203af11c5f3082e38 */ |
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_cli_set_process_title, 0, 1, _IS_BOOL, 0) |
|
||||||
ZEND_ARG_TYPE_INFO(0, title, IS_STRING, 0) |
|
||||||
ZEND_END_ARG_INFO() |
|
||||||
|
|
||||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_cli_get_process_title, 0, 0, IS_STRING, 1) |
|
||||||
ZEND_END_ARG_INFO() |
|
||||||
|
|
||||||
@ -1,478 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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-2015, 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 <php.h> |
|
||||||
#ifdef PHP_WIN32 |
|
||||||
#include "config.w32.h" |
|
||||||
#include <windows.h> |
|
||||||
#include <process.h> |
|
||||||
#include "win32/codepage.h" |
|
||||||
#else |
|
||||||
#include <php_config.h> |
|
||||||
extern char** environ; |
|
||||||
#endif |
|
||||||
|
|
||||||
#include "ps_title.h" |
|
||||||
#include <stdio.h> |
|
||||||
|
|
||||||
#ifdef HAVE_UNISTD_H |
|
||||||
#include <sys/types.h> |
|
||||||
#include <unistd.h> |
|
||||||
#endif |
|
||||||
|
|
||||||
#include <stdbool.h> |
|
||||||
#include <string.h> |
|
||||||
#include <stdlib.h> |
|
||||||
|
|
||||||
#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(__APPLE__) |
|
||||||
#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(__APPLE__) |
|
||||||
#define PS_USE_CHANGE_ARGV |
|
||||||
#elif defined(__linux__) || defined(_AIX) || defined(__sgi) || (defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__osf__) || defined(__APPLE__) |
|
||||||
#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(__APPLE__) |
|
||||||
#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 */ |
|
||||||
static char *empty_environ[] = {0}; /* empty environment */ |
|
||||||
#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; |
|
||||||
|
|
||||||
/*
|
|
||||||
* This holds the 'locally' allocated environ from the save_ps_args method. |
|
||||||
* This is subsequently free'd at exit. |
|
||||||
*/ |
|
||||||
#if defined(PS_USE_CLOBBER_ARGV) |
|
||||||
static char** frozen_environ, **new_environ; |
|
||||||
#endif |
|
||||||
|
|
||||||
/*
|
|
||||||
* 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; |
|
||||||
bool is_contiguous_area = true; |
|
||||||
int i; |
|
||||||
|
|
||||||
/*
|
|
||||||
* check for contiguous argv strings |
|
||||||
*/ |
|
||||||
for (i = 0; is_contiguous_area && (i < argc); i++) |
|
||||||
{ |
|
||||||
if (i != 0 && end_of_area + 1 != argv[i]) { |
|
||||||
is_contiguous_area = false; |
|
||||||
} |
|
||||||
end_of_area = argv[i] + strlen(argv[i]); |
|
||||||
} |
|
||||||
|
|
||||||
if (!is_contiguous_area) { |
|
||||||
goto clobber_error; |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* check for contiguous environ strings following argv |
|
||||||
*/ |
|
||||||
for (i = 0; environ[i] != NULL; i++) |
|
||||||
{ |
|
||||||
if (end_of_area + 1 == environ[i]) { |
|
||||||
end_of_area = environ[i] + strlen(environ[i]); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
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 *)); |
|
||||||
frozen_environ = (char **) malloc((i + 1) * sizeof(char *)); |
|
||||||
if (!new_environ || !frozen_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; |
|
||||||
memcpy((char *)frozen_environ, (char *)new_environ, sizeof(char *) * (i + 1)); |
|
||||||
|
|
||||||
} |
|
||||||
#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]) { |
|
||||||
free(new_argv); |
|
||||||
goto clobber_error; |
|
||||||
} |
|
||||||
} |
|
||||||
new_argv[argc] = NULL; |
|
||||||
|
|
||||||
#if defined(__APPLE__) |
|
||||||
/*
|
|
||||||
* 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 |
|
||||||
*/ |
|
||||||
ps_title_status is_ps_title_available(void) |
|
||||||
{ |
|
||||||
#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(ps_title_status 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"; |
|
||||||
|
|
||||||
case PS_TITLE_TOO_LONG: |
|
||||||
// TODO Indicate max length?
|
|
||||||
return "Too long"; |
|
||||||
|
|
||||||
case PS_TITLE_WINDOWS_ERROR: |
|
||||||
#ifdef PS_USE_WIN32 |
|
||||||
snprintf(windows_error_details, sizeof(windows_error_details), "Windows error code: %lu", GetLastError()); |
|
||||||
return windows_error_details; |
|
||||||
#endif |
|
||||||
return "Windows error"; |
|
||||||
} |
|
||||||
|
|
||||||
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. |
|
||||||
*/ |
|
||||||
ps_title_status set_ps_title(const char *title, size_t title_len) |
|
||||||
{ |
|
||||||
if (title_len >= ps_buffer_size) { |
|
||||||
return PS_TITLE_TOO_LONG; |
|
||||||
} |
|
||||||
|
|
||||||
ps_title_status rc = is_ps_title_available(); |
|
||||||
if (rc != PS_TITLE_SUCCESS) |
|
||||||
return rc; |
|
||||||
|
|
||||||
/* Include final null byte */ |
|
||||||
memcpy(ps_buffer, title, title_len+1); |
|
||||||
ps_buffer_cur_len = title_len; |
|
||||||
|
|
||||||
#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 |
|
||||||
{ |
|
||||||
wchar_t *ps_buffer_w = php_win32_cp_any_to_w(ps_buffer); |
|
||||||
|
|
||||||
if (!ps_buffer_w || !SetConsoleTitleW(ps_buffer_w)) { |
|
||||||
return PS_TITLE_WINDOWS_ERROR; |
|
||||||
} |
|
||||||
|
|
||||||
free(ps_buffer_w); |
|
||||||
} |
|
||||||
#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. |
|
||||||
*/ |
|
||||||
ps_title_status get_ps_title(size_t *displen, const char** string) |
|
||||||
{ |
|
||||||
ps_title_status rc = is_ps_title_available(); |
|
||||||
if (rc != PS_TITLE_SUCCESS) |
|
||||||
return rc; |
|
||||||
|
|
||||||
#ifdef PS_USE_WIN32 |
|
||||||
{ |
|
||||||
wchar_t ps_buffer_w[MAX_PATH]; |
|
||||||
char *tmp; |
|
||||||
|
|
||||||
if (!(ps_buffer_cur_len = GetConsoleTitleW(ps_buffer_w, (DWORD)sizeof(ps_buffer_w)))) { |
|
||||||
return PS_TITLE_WINDOWS_ERROR; |
|
||||||
} |
|
||||||
|
|
||||||
tmp = php_win32_cp_conv_w_to_any(ps_buffer_w, PHP_WIN32_CP_IGNORE_LEN, &ps_buffer_cur_len); |
|
||||||
if (!tmp) { |
|
||||||
return PS_TITLE_WINDOWS_ERROR; |
|
||||||
} |
|
||||||
|
|
||||||
ps_buffer_cur_len = ps_buffer_cur_len > sizeof(ps_buffer)-1 ? sizeof(ps_buffer)-1 : ps_buffer_cur_len; |
|
||||||
|
|
||||||
memmove(ps_buffer, tmp, ps_buffer_cur_len); |
|
||||||
free(tmp); |
|
||||||
} |
|
||||||
#endif |
|
||||||
*displen = 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; frozen_environ[i] != NULL; i++) |
|
||||||
free(frozen_environ[i]); |
|
||||||
free(frozen_environ); |
|
||||||
free(new_environ); |
|
||||||
/* leave a sane environment behind since some atexit() handlers
|
|
||||||
call getenv(). */ |
|
||||||
environ = empty_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; |
|
||||||
} |
|
||||||
@ -1,41 +0,0 @@ |
|||||||
/*
|
|
||||||
+----------------------------------------------------------------------+ |
|
||||||
| Copyright (c) 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: | |
|
||||||
| https://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> | |
|
||||||
+----------------------------------------------------------------------+ |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef PS_TITLE_HEADER |
|
||||||
#define PS_TITLE_HEADER |
|
||||||
|
|
||||||
typedef enum { |
|
||||||
PS_TITLE_SUCCESS = 0, |
|
||||||
PS_TITLE_NOT_AVAILABLE = 1, |
|
||||||
PS_TITLE_NOT_INITIALIZED = 2, |
|
||||||
PS_TITLE_BUFFER_NOT_AVAILABLE = 3, |
|
||||||
PS_TITLE_WINDOWS_ERROR = 4, |
|
||||||
PS_TITLE_TOO_LONG = 5, |
|
||||||
} ps_title_status; |
|
||||||
|
|
||||||
extern char** save_ps_args(int argc, char** argv); |
|
||||||
|
|
||||||
extern ps_title_status set_ps_title(const char *title, size_t title_len); |
|
||||||
|
|
||||||
extern ps_title_status get_ps_title(size_t* displen, const char** string); |
|
||||||
|
|
||||||
extern const char* ps_title_errno(ps_title_status rc); |
|
||||||
|
|
||||||
extern ps_title_status is_ps_title_available(void); |
|
||||||
|
|
||||||
extern void cleanup_ps_args(char **argv); |
|
||||||
|
|
||||||
#endif // PS_TITLE_HEADER
|
|
||||||
Loading…
Reference in new issue