From ab744a1855c06ee27633b80a35d37ada6833f1f3 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Thu, 4 Sep 2025 18:58:26 +0200 Subject: [PATCH] an approach to embedding main() into sapi/embed from php code --- sapi/embed/config.m4 | 67 +++++++++++++++++- sapi/embed/php_embed.c | 152 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 216 insertions(+), 3 deletions(-) diff --git a/sapi/embed/config.m4 b/sapi/embed/config.m4 index 2bb5ed4df4da4..cbed6bb3e374d 100644 --- a/sapi/embed/config.m4 +++ b/sapi/embed/config.m4 @@ -1,13 +1,36 @@ PHP_ARG_ENABLE([embed],, [AS_HELP_STRING([[--enable-embed[=TYPE]]], [Enable building of embedded SAPI library TYPE is either - 'shared' or 'static'. [TYPE=shared]])], + 'shared' or 'static' or 'main'. [TYPE=shared]])], + [no], + [no]) + +PHP_ARG_WITH([embed-main],, + [AS_HELP_STRING([[--enable-embed-main[=FILE]]], + [Enable building of embedded SAPI as a program with embedded main + [TYPE=no]])], + [no], + [no]) + +PHP_ARG_WITH([embed-link],, + [AS_HELP_STRING([[--enable-embed-link[=FILE]]], + [Enable creation of symlink to embedded code + [TYPE=no]])], [no], [no]) AC_MSG_CHECKING([for embedded SAPI library support]) -if test "$PHP_EMBED" != "no"; then +if test "$PHP_EMBED" != "no" || test "$PHP_EMBED_MAIN" != "no"; then + + if test "$PHP_EMBED" == "main"; then + if test "$PHP_EMBED_MAIN" == "no"; then + AC_MSG_ERROR([--with-embed-main is required for --enable-embed=main]) + fi + elif test "$PHP_EMBED_MAIN" != "no"; then + PHP_EMBED=main + fi + AS_CASE([$PHP_EMBED], [yes|shared], [ LIBPHP_CFLAGS="-shared" @@ -22,6 +45,46 @@ if test "$PHP_EMBED" != "no"; then PHP_EMBED_TYPE=static INSTALL_IT="\$(mkinstalldirs) \$(INSTALL_ROOT)\$(orig_libdir); \$(INSTALL) -m 0644 $SAPI_STATIC \$(INSTALL_ROOT)\$(orig_libdir)" ], + [main], [ + AC_MSG_RESULT([main]) + AC_PATH_PROG([XXD], [xxd]) + if test ! -x "$XXD"; then + AC_MSG_ERROR([xxd not found, required for --with-embed-main]) + fi + AC_MSG_CHECKING([for access to $PHP_EMBED_MAIN]) + if test ! -f "$PHP_EMBED_MAIN"; then + AC_MSG_ERROR([--with-embed-main argument "$PHP_EMBED_MAIN" not found]) + else + AC_MSG_RESULT([ok]) + fi + + AC_MSG_CHECKING([generating sapi/embed/php_embed_main.h]) + $XXD -i -n php_embed_main "$PHP_EMBED_MAIN" sapi/embed/php_embed_main.h + if test $? -ne 0; then + AC_MSG_ERROR([failed]) + else + AC_MSG_RESULT([ok]) + fi + + AC_MSG_CHECKING([proceeding to final configure of embed]) + LIBPHP_CFLAGS="-static" + PHP_EMBED_TYPE=static + INSTALL_IT="\ + \$(mkinstalldirs) \$(INSTALL_ROOT)\$(orig_libdir); \ + \$(INSTALL) -m 0644 \$(SAPI_STATIC) \$(INSTALL_ROOT)\$(orig_libdir); \ + \$(mkinstalldirs) \$(INSTALL_ROOT)\$(bindir); \ + \$(LIBTOOL) --tag=CC --mode=compile \$(CC) \ + \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(INCLUDES) -DHAVE_EMBED_MAIN \ + -c sapi/embed/php_embed.c -o sapi/embed/php_embed_main.lo; \ + \$(LIBTOOL) --tag=CC --mode=link \$(CC) \ + -export-dynamic \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \ + sapi/embed/php_embed_main.lo \ + \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) \ + -o \$(INSTALL_ROOT)\$(bindir)/php-embed-main" + if test "$PHP_EMBED_LINK" != "no"; then + AC_DEFINE_UNQUOTED([PHP_EMBED_LINK], ["$PHP_EMBED_LINK"], [PHP_EMBED_LINK]) + fi + ], [PHP_EMBED_TYPE=]) AS_VAR_IF([PHP_EMBED_TYPE],, [AC_MSG_RESULT([no])], [ diff --git a/sapi/embed/php_embed.c b/sapi/embed/php_embed.c index c18480d07d313..c5717efdb7fa4 100644 --- a/sapi/embed/php_embed.c +++ b/sapi/embed/php_embed.c @@ -23,6 +23,7 @@ #include #endif +#ifndef HAVE_EMBED_MAIN static const char HARDCODED_INI[] = "html_errors=0\n" "register_argc_argv=1\n" @@ -114,6 +115,8 @@ static void php_embed_log_message(const char *message, int syslog_type_int) static void php_embed_register_variables(zval *track_vars_array) { php_import_environment_variables(track_vars_array); + + php_register_variable("PHP_SELF", "-", track_vars_array); } /* Module initialization (MINIT) */ @@ -244,7 +247,6 @@ EMBED_SAPI_API int php_embed_init(int argc, char **argv) SG(headers_sent) = 1; SG(request_info).no_headers = 1; - php_register_variable("PHP_SELF", "-", NULL); return SUCCESS; } @@ -264,3 +266,151 @@ EMBED_SAPI_API void php_embed_shutdown(void) tsrm_shutdown(); #endif } +#endif + +#ifdef HAVE_EMBED_MAIN +# include +# include "php_embed_main.h" + +static char _php_embed_main_path_[MAXPATHLEN]; + +static php_stream *s_in_process = NULL; + +static int php_embed_main_streams(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); + + 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 FAILURE; + } + + 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); + + return SUCCESS; +} + +static void php_embed_main_variables(zval *track_vars_array) +{ + php_import_environment_variables(track_vars_array); + + php_register_variable("PHP_SELF", + _php_embed_main_path_, track_vars_array); +} + +static int php_embed_main_enter(void) { + int fd; + snprintf(_php_embed_main_path_, + MAXPATHLEN, "/tmp/php_embed_main.XXXXXX"); + fd = mkstemp(_php_embed_main_path_); + if (fd == FAILURE) { + fprintf(stderr, + "php_embed_main can not be initialized " + "at /tmp/php_embed_main.*: %d %s\n", + errno, strerror(errno)); + return FAILURE; + } + + if (write(fd, php_embed_main, php_embed_main_len) == FAILURE) { + fprintf(stderr, + "php_embed_main can not be written " + "at %s: %d %s\n", + _php_embed_main_path_, errno, strerror(errno)); + return FAILURE; + } + lseek(fd, 0, SEEK_SET); + close(fd); + +#ifdef PHP_EMBED_LINK + if (symlink(_php_embed_main_path_, PHP_EMBED_LINK) != SUCCESS) { + fprintf(stderr, + "php_embed_main link can not be initialized at %s: %d %s\n", + PHP_EMBED_LINK, + errno, strerror(errno)); + return FAILURE; + } + strcpy(_php_embed_main_path_, PHP_EMBED_LINK); +#endif + + php_embed_module.register_server_variables = php_embed_main_variables; + + return SUCCESS; +} + +static int php_embed_main_execute(void) { + int status = php_embed_main_streams(); + + if (status != SUCCESS) { + return 1; + } + + zend_file_handle fh; + zend_stream_init_filename(&fh, + _php_embed_main_path_); + if (!php_execute_script(&fh)) { + if (EG(exit_status) == SUCCESS) { + status = 1; + } + } + zend_destroy_file_handle(&fh); + + if (status == FAILURE) { + status = EG(exit_status); + } + + return status; +} + +static void php_embed_main_leave(void) { + unlink(_php_embed_main_path_); +#ifdef PHP_EMBED_LINK + unlink(PHP_EMBED_LINK); +#endif +} + +int main(int argc, char *argv[]) +{ + int status = FAILURE; + + if (php_embed_main_enter() != SUCCESS) { + return 1; + } + + PHP_EMBED_START_BLOCK(argc, argv) + + status = php_embed_main_execute(); + + PHP_EMBED_END_BLOCK() + + php_embed_main_leave(); + + return status; +} +#endif

AltStyle によって変換されたページ (->オリジナル) /