-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[WIP] an approach to embedding main() into sapi/embed from php code #19707
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if this is yes/empty we could use basename of |
||
fi | ||
], | ||
[PHP_EMBED_TYPE=]) | ||
|
||
AS_VAR_IF([PHP_EMBED_TYPE],, [AC_MSG_RESULT([no])], [ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
#include <fcntl.h> | ||
#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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not exactly sure why this is here, it doesn't look correct ... I moved to |
||
|
||
return SUCCESS; | ||
} | ||
|
@@ -264,3 +266,151 @@ EMBED_SAPI_API void php_embed_shutdown(void) | |
tsrm_shutdown(); | ||
#endif | ||
} | ||
#endif | ||
|
||
#ifdef HAVE_EMBED_MAIN | ||
# include <sys/mman.h> | ||
# 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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lifted from cli, possibly this should be exported API function in |
||
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 |