Skip to content

Commit b7cb1ee

Browse files
feat: add cli_set_process_title() and cli_get_process_title()
1 parent 0f942c8 commit b7cb1ee

File tree

3 files changed

+201
-1
lines changed

3 files changed

+201
-1
lines changed

frankenphp.c

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,183 @@ PHP_FUNCTION(frankenphp_request_headers) {
360360
}
361361
/* }}} */
362362

363+
/* Process title implementation borrowed from sapi/cli/ps_title.c */
364+
#ifdef PHP_WIN32
365+
#include "win32/codepage.h"
366+
#include <process.h>
367+
#include <windows.h>
368+
#endif
369+
370+
#ifdef HAVE_SETPROCTITLE
371+
#define PS_USE_SETPROCTITLE
372+
#elif defined(__linux__) || defined(_AIX) || defined(__sgi) || \
373+
(defined(sun) && !defined(BSD)) || defined(ultrix) || defined(__osf__) || \
374+
defined(__APPLE__)
375+
#define PS_USE_CLOBBER_ARGV
376+
#elif defined(PHP_WIN32)
377+
#define PS_USE_WIN32
378+
#else
379+
#define PS_USE_NONE
380+
#endif
381+
382+
typedef enum {
383+
PS_TITLE_SUCCESS = 0,
384+
PS_TITLE_NOT_AVAILABLE = 1,
385+
PS_TITLE_NOT_INITIALIZED = 2,
386+
PS_TITLE_BUFFER_NOT_AVAILABLE = 3,
387+
PS_TITLE_WINDOWS_ERROR = 4,
388+
PS_TITLE_TOO_LONG = 5,
389+
} ps_title_status;
390+
391+
static char *ps_buffer = NULL;
392+
static size_t ps_buffer_size = 0;
393+
static size_t ps_buffer_cur_len = 0;
394+
395+
static ps_title_status is_ps_title_available(void) {
396+
#ifdef PS_USE_NONE
397+
return PS_TITLE_NOT_AVAILABLE;
398+
#else
399+
if (!ps_buffer) {
400+
return PS_TITLE_NOT_INITIALIZED;
401+
}
402+
return PS_TITLE_SUCCESS;
403+
#endif
404+
}
405+
406+
static const char *ps_title_errno(ps_title_status rc) {
407+
switch (rc) {
408+
case PS_TITLE_SUCCESS:
409+
return "Success";
410+
case PS_TITLE_NOT_AVAILABLE:
411+
return "Not available on this platform";
412+
case PS_TITLE_NOT_INITIALIZED:
413+
return "Not initialized";
414+
case PS_TITLE_BUFFER_NOT_AVAILABLE:
415+
return "Buffer not available";
416+
case PS_TITLE_WINDOWS_ERROR:
417+
return "Windows error";
418+
case PS_TITLE_TOO_LONG:
419+
return "Title too long";
420+
default:
421+
return "Unknown error";
422+
}
423+
}
424+
425+
static ps_title_status set_ps_title(const char *title, size_t title_len) {
426+
#ifdef PS_USE_NONE
427+
return PS_TITLE_NOT_AVAILABLE;
428+
#else
429+
if (title_len >= ps_buffer_size) {
430+
return PS_TITLE_TOO_LONG;
431+
}
432+
ps_title_status rc = is_ps_title_available();
433+
if (rc != PS_TITLE_SUCCESS)
434+
return rc;
435+
436+
memcpy(ps_buffer, title, title_len);
437+
ps_buffer[title_len] = '\0';
438+
ps_buffer_cur_len = title_len;
439+
440+
#ifdef PS_USE_SETPROCTITLE
441+
setproctitle("%s", ps_buffer);
442+
#endif
443+
#ifdef PS_USE_WIN32
444+
{
445+
wchar_t *ps_buffer_w = php_win32_cp_any_to_w(ps_buffer);
446+
if (!ps_buffer_w || !SetConsoleTitleW(ps_buffer_w)) {
447+
if (ps_buffer_w)
448+
free(ps_buffer_w);
449+
return PS_TITLE_WINDOWS_ERROR;
450+
}
451+
free(ps_buffer_w);
452+
}
453+
#endif
454+
return PS_TITLE_SUCCESS;
455+
#endif
456+
}
457+
458+
static ps_title_status get_ps_title(size_t *displen, const char **string) {
459+
ps_title_status rc = is_ps_title_available();
460+
if (rc != PS_TITLE_SUCCESS)
461+
return rc;
462+
463+
#ifdef PS_USE_WIN32
464+
{
465+
wchar_t ps_buffer_w[MAX_PATH];
466+
char *tmp;
467+
468+
if (!(ps_buffer_cur_len =
469+
GetConsoleTitleW(ps_buffer_w, (DWORD)sizeof(ps_buffer_w)))) {
470+
return PS_TITLE_WINDOWS_ERROR;
471+
}
472+
473+
tmp = php_win32_cp_conv_w_to_any(ps_buffer_w, PHP_WIN32_CP_IGNORE_LEN,
474+
&ps_buffer_cur_len);
475+
if (!tmp) {
476+
return PS_TITLE_WINDOWS_ERROR;
477+
}
478+
479+
ps_buffer_cur_len = ps_buffer_cur_len > ps_buffer_size - 1
480+
? ps_buffer_size - 1
481+
: ps_buffer_cur_len;
482+
memmove(ps_buffer, tmp, ps_buffer_cur_len);
483+
free(tmp);
484+
}
485+
#endif
486+
*displen = ps_buffer_cur_len;
487+
*string = ps_buffer;
488+
return PS_TITLE_SUCCESS;
489+
}
490+
491+
/* {{{ cli_set_process_title */
492+
PHP_FUNCTION(cli_set_process_title) {
493+
char *title;
494+
size_t title_len;
495+
ps_title_status rc;
496+
497+
ZEND_PARSE_PARAMETERS_START(1, 1)
498+
Z_PARAM_STRING(title, title_len)
499+
ZEND_PARSE_PARAMETERS_END();
500+
501+
if (!ps_buffer) {
502+
ps_buffer_size = 256; /* Reasonable default */
503+
ps_buffer = malloc(ps_buffer_size);
504+
if (ps_buffer) {
505+
ps_buffer[0] = '\0';
506+
ps_buffer_cur_len = 0;
507+
}
508+
}
509+
510+
rc = set_ps_title(title, title_len);
511+
if (rc != PS_TITLE_SUCCESS) {
512+
php_error_docref(NULL, E_WARNING, "cli_set_process_title had an error: %s",
513+
ps_title_errno(rc));
514+
RETURN_FALSE;
515+
}
516+
517+
RETURN_TRUE;
518+
}
519+
/* }}} */
520+
521+
/* {{{ cli_get_process_title */
522+
PHP_FUNCTION(cli_get_process_title) {
523+
const char *title = NULL;
524+
size_t length = 0;
525+
ps_title_status rc;
526+
527+
ZEND_PARSE_PARAMETERS_NONE();
528+
529+
rc = get_ps_title(&length, &title);
530+
if (rc != PS_TITLE_SUCCESS) {
531+
php_error_docref(NULL, E_WARNING, "cli_get_process_title had an error: %s",
532+
ps_title_errno(rc));
533+
RETURN_NULL();
534+
}
535+
536+
RETURN_STRINGL(title, length);
537+
}
538+
/* }}} */
539+
363540
/* add_response_header and apache_response_headers are copied from
364541
* https://github.com/php/php-src/blob/master/sapi/cli/php_cli_server.c
365542
* Copyright (c) The PHP Group
@@ -1119,6 +1296,13 @@ static void *execute_script_cli(void *arg) {
11191296
php_embed_init(cli_argc, cli_argv);
11201297

11211298
cli_register_file_handles(false);
1299+
1300+
#if PHP_VERSION_ID < 80400
1301+
zend_register_module(&frankenphp_module);
1302+
#else
1303+
zend_register_module_ex(&frankenphp_module, MODULE_PERSISTENT);
1304+
#endif
1305+
11221306
zend_first_try {
11231307
if (eval) {
11241308
/* evaluate the cli_script as literal PHP code (php-cli -r "...") */

frankenphp.stub.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,6 @@ function frankenphp_response_headers(): array|bool {}
3232
*/
3333
function apache_response_headers(): array|bool {}
3434

35+
function cli_set_process_title(string $title): bool {}
36+
37+
function cli_get_process_title(): ?string {}

frankenphp_arginfo.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 05ebde17137c559e891362fba6524fad1e0a2dfe */
2+
* Stub hash: 1b144396ea8609321ba7fc51b6c22f0d5635197d */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_frankenphp_handle_request, 0, 1,
55
_IS_BOOL, 0)
@@ -30,11 +30,22 @@ ZEND_END_ARG_INFO()
3030

3131
#define arginfo_apache_response_headers arginfo_frankenphp_response_headers
3232

33+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_cli_set_process_title, 0, 1,
34+
_IS_BOOL, 0)
35+
ZEND_ARG_TYPE_INFO(0, title, IS_STRING, 0)
36+
ZEND_END_ARG_INFO()
37+
38+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_cli_get_process_title, 0, 0,
39+
IS_STRING, 1)
40+
ZEND_END_ARG_INFO()
41+
3342
ZEND_FUNCTION(frankenphp_handle_request);
3443
ZEND_FUNCTION(headers_send);
3544
ZEND_FUNCTION(frankenphp_finish_request);
3645
ZEND_FUNCTION(frankenphp_request_headers);
3746
ZEND_FUNCTION(frankenphp_response_headers);
47+
ZEND_FUNCTION(cli_set_process_title);
48+
ZEND_FUNCTION(cli_get_process_title);
3849

3950
// clang-format off
4051
static const zend_function_entry ext_functions[] = {
@@ -47,6 +58,8 @@ static const zend_function_entry ext_functions[] = {
4758
ZEND_FALIAS(getallheaders, frankenphp_request_headers, arginfo_getallheaders)
4859
ZEND_FE(frankenphp_response_headers, arginfo_frankenphp_response_headers)
4960
ZEND_FALIAS(apache_response_headers, frankenphp_response_headers, arginfo_apache_response_headers)
61+
ZEND_FE(cli_set_process_title, arginfo_cli_set_process_title)
62+
ZEND_FE(cli_get_process_title, arginfo_cli_get_process_title)
5063
ZEND_FE_END
5164
};
5265
// clang-format on

0 commit comments

Comments
 (0)