xref: /unit/src/nxt_php_sapi.c (revision 2019:8fcb7e44c663)
10Sigor@sysoev.ru /*
286Smax.romanov@nginx.com  * Copyright (C) Max Romanov
30Sigor@sysoev.ru  * Copyright (C) Valentin V. Bartenev
40Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru  */
60Sigor@sysoev.ru 
70Sigor@sysoev.ru #include "php.h"
80Sigor@sysoev.ru #include "SAPI.h"
90Sigor@sysoev.ru #include "php_main.h"
100Sigor@sysoev.ru #include "php_variables.h"
111700Svbart@nginx.com #include "ext/standard/php_standard.h"
120Sigor@sysoev.ru 
130Sigor@sysoev.ru #include <nxt_main.h>
14446Sigor@sysoev.ru #include <nxt_router.h>
15743Smax.romanov@nginx.com #include <nxt_unit.h>
16743Smax.romanov@nginx.com #include <nxt_unit_request.h>
170Sigor@sysoev.ru 
180Sigor@sysoev.ru 
191369St.nateldemoura@f5.com #if PHP_VERSION_ID >= 50400
201369St.nateldemoura@f5.com #define NXT_HAVE_PHP_IGNORE_CWD 1
2186Smax.romanov@nginx.com #endif
220Sigor@sysoev.ru 
231369St.nateldemoura@f5.com #if PHP_VERSION_ID >= 70100
241369St.nateldemoura@f5.com #define NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 1
251369St.nateldemoura@f5.com #else
261369St.nateldemoura@f5.com #define NXT_HAVE_PHP_INTERRUPTS 1
271369St.nateldemoura@f5.com #endif
281369St.nateldemoura@f5.com 
291369St.nateldemoura@f5.com #if PHP_VERSION_ID >= 70000
301369St.nateldemoura@f5.com #define NXT_PHP7 1
311369St.nateldemoura@f5.com #endif
321562Sremi@remirepo.net #if PHP_VERSION_ID >= 80000
331562Sremi@remirepo.net #define NXT_PHP8 1
341562Sremi@remirepo.net #endif
35861Svbart@nginx.com 
361482Sremi@remirepo.net /* PHP 8 */
371482Sremi@remirepo.net #ifndef TSRMLS_CC
381482Sremi@remirepo.net #define TSRMLS_CC
391482Sremi@remirepo.net #define TSRMLS_DC
401482Sremi@remirepo.net #define TSRMLS_D  void
411482Sremi@remirepo.net #define TSRMLS_C
421482Sremi@remirepo.net #endif
431482Sremi@remirepo.net 
441473Svbart@nginx.com 
451473Svbart@nginx.com typedef struct {
461473Svbart@nginx.com     nxt_str_t  root;
471473Svbart@nginx.com     nxt_str_t  index;
481473Svbart@nginx.com     nxt_str_t  script_name;
491473Svbart@nginx.com     nxt_str_t  script_dirname;
501473Svbart@nginx.com     nxt_str_t  script_filename;
511473Svbart@nginx.com } nxt_php_target_t;
521473Svbart@nginx.com 
531473Svbart@nginx.com 
541376St.nateldemoura@f5.com typedef struct {
551376St.nateldemoura@f5.com     char                     *cookie;
561473Svbart@nginx.com     nxt_str_t                *root;
571473Svbart@nginx.com     nxt_str_t                *index;
581376St.nateldemoura@f5.com     nxt_str_t                path_info;
591376St.nateldemoura@f5.com     nxt_str_t                script_name;
601376St.nateldemoura@f5.com     nxt_str_t                script_filename;
611376St.nateldemoura@f5.com     nxt_str_t                script_dirname;
621376St.nateldemoura@f5.com     nxt_unit_request_info_t  *req;
631376St.nateldemoura@f5.com 
641376St.nateldemoura@f5.com     uint8_t                  chdir;  /* 1 bit */
651376St.nateldemoura@f5.com } nxt_php_run_ctx_t;
661376St.nateldemoura@f5.com 
67861Svbart@nginx.com 
681562Sremi@remirepo.net #if NXT_PHP8
691562Sremi@remirepo.net typedef int (*nxt_php_disable_t)(const char *p, size_t size);
701562Sremi@remirepo.net #elif NXT_PHP7
71861Svbart@nginx.com typedef int (*nxt_php_disable_t)(char *p, size_t size);
72861Svbart@nginx.com #else
73861Svbart@nginx.com typedef int (*nxt_php_disable_t)(char *p, uint TSRMLS_DC);
74861Svbart@nginx.com #endif
75861Svbart@nginx.com 
761376St.nateldemoura@f5.com #if PHP_VERSION_ID < 70200
771376St.nateldemoura@f5.com typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS);
781376St.nateldemoura@f5.com #endif
791376St.nateldemoura@f5.com 
80861Svbart@nginx.com 
811622St.nateldemoura@f5.com static nxt_int_t nxt_php_setup(nxt_task_t *task, nxt_process_t *process,
821622St.nateldemoura@f5.com     nxt_common_app_conf_t *conf);
831488St.nateldemoura@f5.com static nxt_int_t nxt_php_start(nxt_task_t *task, nxt_process_data_t *data);
841473Svbart@nginx.com static nxt_int_t nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target,
851473Svbart@nginx.com     nxt_conf_value_t *conf);
861622St.nateldemoura@f5.com static nxt_int_t nxt_php_set_ini_path(nxt_task_t *task, nxt_str_t *path,
871622St.nateldemoura@f5.com     char *workdir);
88688Svbart@nginx.com static void nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options,
89688Svbart@nginx.com     int type);
90713Svbart@nginx.com static nxt_int_t nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value,
91713Svbart@nginx.com     int type);
921636Svbart@nginx.com #ifdef NXT_PHP8
931636Svbart@nginx.com static void nxt_php_disable_functions(nxt_str_t *str);
941636Svbart@nginx.com #endif
95861Svbart@nginx.com static void nxt_php_disable(nxt_task_t *task, const char *type,
96861Svbart@nginx.com     nxt_str_t *value, char **ptr, nxt_php_disable_t disable);
971473Svbart@nginx.com 
981473Svbart@nginx.com static nxt_int_t nxt_php_dirname(const nxt_str_t *file, nxt_str_t *dir);
991473Svbart@nginx.com static void nxt_php_str_trim_trail(nxt_str_t *str, u_char t);
1001473Svbart@nginx.com static void nxt_php_str_trim_lead(nxt_str_t *str, u_char t);
1011473Svbart@nginx.com nxt_inline u_char *nxt_realpath(const void *c);
1021473Svbart@nginx.com 
1031473Svbart@nginx.com static void nxt_php_request_handler(nxt_unit_request_info_t *req);
1041473Svbart@nginx.com static void nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx,
1051473Svbart@nginx.com     nxt_unit_request_t *r);
1061473Svbart@nginx.com static void nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r);
1071473Svbart@nginx.com nxt_inline void nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir);
1081473Svbart@nginx.com 
1091473Svbart@nginx.com static int nxt_php_startup(sapi_module_struct *sapi_module);
110857Svbart@nginx.com static int nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC);
1111376St.nateldemoura@f5.com static void *nxt_php_hash_str_find_ptr(const HashTable *ht,
1121376St.nateldemoura@f5.com     const nxt_str_t *str);
113857Svbart@nginx.com static char *nxt_php_read_cookies(TSRMLS_D);
114743Smax.romanov@nginx.com static void nxt_php_set_sptr(nxt_unit_request_info_t *req, const char *name,
115743Smax.romanov@nginx.com     nxt_unit_sptr_t *v, uint32_t len, zval *track_vars_array TSRMLS_DC);
116743Smax.romanov@nginx.com nxt_inline void nxt_php_set_str(nxt_unit_request_info_t *req, const char *name,
117743Smax.romanov@nginx.com     nxt_str_t *s, zval *track_vars_array TSRMLS_DC);
118743Smax.romanov@nginx.com static void nxt_php_set_cstr(nxt_unit_request_info_t *req, const char *name,
119967Svbart@nginx.com     const char *str, uint32_t len, zval *track_vars_array TSRMLS_DC);
120857Svbart@nginx.com static void nxt_php_register_variables(zval *track_vars_array TSRMLS_DC);
1211562Sremi@remirepo.net #if NXT_PHP8
1221562Sremi@remirepo.net static void nxt_php_log_message(const char *message, int syslog_type_int);
1231562Sremi@remirepo.net #else
12486Smax.romanov@nginx.com #ifdef NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE
125579Svbart@nginx.com static void nxt_php_log_message(char *message, int syslog_type_int);
126579Svbart@nginx.com #else
127857Svbart@nginx.com static void nxt_php_log_message(char *message TSRMLS_DC);
12886Smax.romanov@nginx.com #endif
1291562Sremi@remirepo.net #endif
1300Sigor@sysoev.ru 
1310Sigor@sysoev.ru #ifdef NXT_PHP7
1320Sigor@sysoev.ru static size_t nxt_php_unbuffered_write(const char *str,
1330Sigor@sysoev.ru     size_t str_length TSRMLS_DC);
1340Sigor@sysoev.ru static size_t nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC);
1350Sigor@sysoev.ru #else
1360Sigor@sysoev.ru static int nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC);
1370Sigor@sysoev.ru static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC);
1380Sigor@sysoev.ru #endif
1390Sigor@sysoev.ru 
1400Sigor@sysoev.ru 
1411700Svbart@nginx.com #ifdef NXT_PHP7
1421700Svbart@nginx.com #if PHP_VERSION_ID < 70200
1431700Svbart@nginx.com ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fastcgi_finish_request, 0, 0,
1441700Svbart@nginx.com                                         _IS_BOOL, NULL, 0)
1451700Svbart@nginx.com #else
1461700Svbart@nginx.com ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fastcgi_finish_request, 0, 0,
1471700Svbart@nginx.com                                         _IS_BOOL, 0)
1481700Svbart@nginx.com #endif
1491700Svbart@nginx.com #else /* PHP5 */
1501700Svbart@nginx.com ZEND_BEGIN_ARG_INFO_EX(arginfo_fastcgi_finish_request, 0, 0, 0)
1511700Svbart@nginx.com #endif
1521700Svbart@nginx.com ZEND_END_ARG_INFO()
1531700Svbart@nginx.com 
1541700Svbart@nginx.com ZEND_FUNCTION(fastcgi_finish_request);
1551700Svbart@nginx.com 
1561376St.nateldemoura@f5.com PHP_MINIT_FUNCTION(nxt_php_ext);
1571376St.nateldemoura@f5.com ZEND_NAMED_FUNCTION(nxt_php_chdir);
1581376St.nateldemoura@f5.com 
1591700Svbart@nginx.com 
1601700Svbart@nginx.com static const zend_function_entry  nxt_php_ext_functions[] = {
1611700Svbart@nginx.com     ZEND_FE(fastcgi_finish_request, arginfo_fastcgi_finish_request)
1621700Svbart@nginx.com     ZEND_FE_END
1631700Svbart@nginx.com };
1641700Svbart@nginx.com 
1651700Svbart@nginx.com 
1661861Svbart@nginx.com zif_handler       nxt_php_chdir_handler;
1671861Svbart@nginx.com zend_auto_global  *nxt_php_server_ag;
1681376St.nateldemoura@f5.com 
1691376St.nateldemoura@f5.com 
1701376St.nateldemoura@f5.com static zend_module_entry  nxt_php_unit_module = {
1711376St.nateldemoura@f5.com     STANDARD_MODULE_HEADER,
1721376St.nateldemoura@f5.com     "unit",
1731700Svbart@nginx.com     nxt_php_ext_functions,       /* function table */
1741376St.nateldemoura@f5.com     PHP_MINIT(nxt_php_ext),      /* initialization */
1751376St.nateldemoura@f5.com     NULL,                        /* shutdown */
1761376St.nateldemoura@f5.com     NULL,                        /* request initialization */
1771376St.nateldemoura@f5.com     NULL,                        /* request shutdown */
1781376St.nateldemoura@f5.com     NULL,                        /* information */
1791376St.nateldemoura@f5.com     NXT_VERSION,
1801376St.nateldemoura@f5.com     STANDARD_MODULE_PROPERTIES
1811376St.nateldemoura@f5.com };
1821376St.nateldemoura@f5.com 
1831376St.nateldemoura@f5.com 
PHP_MINIT_FUNCTION(nxt_php_ext)1841376St.nateldemoura@f5.com PHP_MINIT_FUNCTION(nxt_php_ext)
1851376St.nateldemoura@f5.com {
1861376St.nateldemoura@f5.com     zend_function  *func;
1871376St.nateldemoura@f5.com 
1881376St.nateldemoura@f5.com     static const nxt_str_t  chdir = nxt_string("chdir");
1891376St.nateldemoura@f5.com 
1901376St.nateldemoura@f5.com     func = nxt_php_hash_str_find_ptr(CG(function_table), &chdir);
1911376St.nateldemoura@f5.com     if (nxt_slow_path(func == NULL)) {
1921376St.nateldemoura@f5.com         return FAILURE;
1931376St.nateldemoura@f5.com     }
1941376St.nateldemoura@f5.com 
1951376St.nateldemoura@f5.com     nxt_php_chdir_handler = func->internal_function.handler;
1961376St.nateldemoura@f5.com     func->internal_function.handler = nxt_php_chdir;
1971376St.nateldemoura@f5.com 
1981376St.nateldemoura@f5.com     return SUCCESS;
1991376St.nateldemoura@f5.com }
2001376St.nateldemoura@f5.com 
2011376St.nateldemoura@f5.com 
ZEND_NAMED_FUNCTION(nxt_php_chdir)2021376St.nateldemoura@f5.com ZEND_NAMED_FUNCTION(nxt_php_chdir)
2031376St.nateldemoura@f5.com {
2041376St.nateldemoura@f5.com     nxt_php_run_ctx_t  *ctx;
2051376St.nateldemoura@f5.com 
2061376St.nateldemoura@f5.com     ctx = SG(server_context);
207*2019Svbart@nginx.com 
208*2019Svbart@nginx.com     if (nxt_fast_path(ctx != NULL)) {
209*2019Svbart@nginx.com         ctx->chdir = 1;
210*2019Svbart@nginx.com     }
2111376St.nateldemoura@f5.com 
2121376St.nateldemoura@f5.com     nxt_php_chdir_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2131376St.nateldemoura@f5.com }
2141376St.nateldemoura@f5.com 
2151376St.nateldemoura@f5.com 
PHP_FUNCTION(fastcgi_finish_request)2161700Svbart@nginx.com PHP_FUNCTION(fastcgi_finish_request)
2171700Svbart@nginx.com {
2181861Svbart@nginx.com     zend_auto_global   *ag;
2191700Svbart@nginx.com     nxt_php_run_ctx_t  *ctx;
2201700Svbart@nginx.com 
2211700Svbart@nginx.com     if (nxt_slow_path(zend_parse_parameters_none() == FAILURE)) {
2221700Svbart@nginx.com #ifdef NXT_PHP8
2231700Svbart@nginx.com         RETURN_THROWS();
2241700Svbart@nginx.com #else
2251700Svbart@nginx.com         return;
2261700Svbart@nginx.com #endif
2271700Svbart@nginx.com     }
2281700Svbart@nginx.com 
2291700Svbart@nginx.com     ctx = SG(server_context);
2301700Svbart@nginx.com 
231*2019Svbart@nginx.com     if (nxt_slow_path(ctx == NULL || ctx->req == NULL)) {
2321700Svbart@nginx.com         RETURN_FALSE;
2331700Svbart@nginx.com     }
2341700Svbart@nginx.com 
2351700Svbart@nginx.com #ifdef NXT_PHP7
2361700Svbart@nginx.com     php_output_end_all();
2371700Svbart@nginx.com     php_header();
2381700Svbart@nginx.com #else
2391700Svbart@nginx.com #ifdef PHP_OUTPUT_NEWAPI
2401700Svbart@nginx.com     php_output_end_all(TSRMLS_C);
2411700Svbart@nginx.com #else
2421700Svbart@nginx.com     php_end_ob_buffers(1 TSRMLS_CC);
2431700Svbart@nginx.com #endif
2441700Svbart@nginx.com 
2451700Svbart@nginx.com     php_header(TSRMLS_C);
2461700Svbart@nginx.com #endif
2471700Svbart@nginx.com 
2481861Svbart@nginx.com     ag = nxt_php_server_ag;
2491861Svbart@nginx.com 
2501861Svbart@nginx.com     if (ag->armed) {
2511861Svbart@nginx.com #ifdef NXT_PHP7
2521861Svbart@nginx.com         ag->armed = ag->auto_global_callback(ag->name);
2531861Svbart@nginx.com #else
2541861Svbart@nginx.com         ag->armed = ag->auto_global_callback(ag->name, ag->name_len TSRMLS_CC);
2551861Svbart@nginx.com #endif
2561861Svbart@nginx.com     }
2571861Svbart@nginx.com 
2581700Svbart@nginx.com     nxt_unit_request_done(ctx->req, NXT_UNIT_OK);
2591700Svbart@nginx.com     ctx->req = NULL;
2601700Svbart@nginx.com 
2611700Svbart@nginx.com     PG(connection_status) = PHP_CONNECTION_ABORTED;
2621700Svbart@nginx.com #ifdef NXT_PHP7
2631700Svbart@nginx.com     php_output_set_status(PHP_OUTPUT_DISABLED);
2641700Svbart@nginx.com #else
2651700Svbart@nginx.com #ifdef PHP_OUTPUT_NEWAPI
2661700Svbart@nginx.com     php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC);
2671700Svbart@nginx.com #else
2681700Svbart@nginx.com     php_output_set_status(0 TSRMLS_CC);
2691700Svbart@nginx.com #endif
2701700Svbart@nginx.com #endif
2711700Svbart@nginx.com 
2721700Svbart@nginx.com     RETURN_TRUE;
2731700Svbart@nginx.com }
2741700Svbart@nginx.com 
2751700Svbart@nginx.com 
2760Sigor@sysoev.ru static sapi_module_struct  nxt_php_sapi_module =
2770Sigor@sysoev.ru {
2780Sigor@sysoev.ru     (char *) "cli-server",
279259Sigor@sysoev.ru     (char *) "unit",
2800Sigor@sysoev.ru 
2810Sigor@sysoev.ru     nxt_php_startup,             /* startup */
2820Sigor@sysoev.ru     php_module_shutdown_wrapper, /* shutdown */
2830Sigor@sysoev.ru 
2840Sigor@sysoev.ru     NULL,                        /* activate */
2850Sigor@sysoev.ru     NULL,                        /* deactivate */
2860Sigor@sysoev.ru 
2870Sigor@sysoev.ru     nxt_php_unbuffered_write,    /* unbuffered write */
288743Smax.romanov@nginx.com     NULL,                        /* flush */
2890Sigor@sysoev.ru     NULL,                        /* get uid */
2900Sigor@sysoev.ru     NULL,                        /* getenv */
2910Sigor@sysoev.ru 
2920Sigor@sysoev.ru     php_error,                   /* error handler */
2930Sigor@sysoev.ru 
2940Sigor@sysoev.ru     NULL,                        /* header handler */
2950Sigor@sysoev.ru     nxt_php_send_headers,        /* send headers handler */
2960Sigor@sysoev.ru     NULL,                        /* send header handler */
2970Sigor@sysoev.ru 
2980Sigor@sysoev.ru     nxt_php_read_post,           /* read POST data */
2990Sigor@sysoev.ru     nxt_php_read_cookies,        /* read Cookies */
3000Sigor@sysoev.ru 
3010Sigor@sysoev.ru     nxt_php_register_variables,  /* register server variables */
3020Sigor@sysoev.ru     nxt_php_log_message,         /* log message */
30386Smax.romanov@nginx.com     NULL,                        /* get request time */
30486Smax.romanov@nginx.com     NULL,                        /* terminate process */
3050Sigor@sysoev.ru 
30686Smax.romanov@nginx.com     NULL,                        /* php_ini_path_override */
30786Smax.romanov@nginx.com #ifdef NXT_HAVE_PHP_INTERRUPTS
30886Smax.romanov@nginx.com     NULL,                        /* block_interruptions */
30986Smax.romanov@nginx.com     NULL,                        /* unblock_interruptions */
31086Smax.romanov@nginx.com #endif
31186Smax.romanov@nginx.com     NULL,                        /* default_post_reader */
31286Smax.romanov@nginx.com     NULL,                        /* treat_data */
31386Smax.romanov@nginx.com     NULL,                        /* executable_location */
31486Smax.romanov@nginx.com 
31586Smax.romanov@nginx.com     0,                           /* php_ini_ignore */
31686Smax.romanov@nginx.com #ifdef NXT_HAVE_PHP_IGNORE_CWD
317687Svbart@nginx.com     1,                           /* php_ini_ignore_cwd */
31886Smax.romanov@nginx.com #endif
31986Smax.romanov@nginx.com     NULL,                        /* get_fd */
32086Smax.romanov@nginx.com 
32186Smax.romanov@nginx.com     NULL,                        /* force_http_10 */
32286Smax.romanov@nginx.com 
32386Smax.romanov@nginx.com     NULL,                        /* get_target_uid */
32486Smax.romanov@nginx.com     NULL,                        /* get_target_gid */
32586Smax.romanov@nginx.com 
32686Smax.romanov@nginx.com     NULL,                        /* input_filter */
32786Smax.romanov@nginx.com 
32886Smax.romanov@nginx.com     NULL,                        /* ini_defaults */
32986Smax.romanov@nginx.com     0,                           /* phpinfo_as_text */
33086Smax.romanov@nginx.com 
33186Smax.romanov@nginx.com     NULL,                        /* ini_entries */
33286Smax.romanov@nginx.com     NULL,                        /* additional_functions */
33386Smax.romanov@nginx.com     NULL                         /* input_filter_init */
3340Sigor@sysoev.ru };
3350Sigor@sysoev.ru 
336206Smax.romanov@nginx.com 
337258Sigor@sysoev.ru static uint32_t  compat[] = {
338360Sigor@sysoev.ru     NXT_VERNUM, NXT_DEBUG,
339258Sigor@sysoev.ru };
340258Sigor@sysoev.ru 
3410Sigor@sysoev.ru 
342743Smax.romanov@nginx.com NXT_EXPORT nxt_app_module_t  nxt_app_module = {
343258Sigor@sysoev.ru     sizeof(compat),
344258Sigor@sysoev.ru     compat,
345216Sigor@sysoev.ru     nxt_string("php"),
346612Salexander.borisov@nginx.com     PHP_VERSION,
3471489St.nateldemoura@f5.com     NULL,
3481622St.nateldemoura@f5.com     0,
3491622St.nateldemoura@f5.com     nxt_php_setup,
3501488St.nateldemoura@f5.com     nxt_php_start,
35186Smax.romanov@nginx.com };
3520Sigor@sysoev.ru 
3530Sigor@sysoev.ru 
3541473Svbart@nginx.com static nxt_php_target_t  *nxt_php_targets;
3551473Svbart@nginx.com static nxt_int_t         nxt_php_last_target = -1;
3561473Svbart@nginx.com 
3571513Svbart@nginx.com static nxt_unit_ctx_t    *nxt_php_unit_ctx;
3581369St.nateldemoura@f5.com #if defined(ZTS) && PHP_VERSION_ID < 70400
3591513Svbart@nginx.com static void              ***tsrm_ls;
360857Svbart@nginx.com #endif
361708Sigor@sysoev.ru 
362708Sigor@sysoev.ru 
36386Smax.romanov@nginx.com static nxt_int_t
nxt_php_setup(nxt_task_t * task,nxt_process_t * process,nxt_common_app_conf_t * conf)3641622St.nateldemoura@f5.com nxt_php_setup(nxt_task_t *task, nxt_process_t *process,
3651622St.nateldemoura@f5.com     nxt_common_app_conf_t *conf)
3661622St.nateldemoura@f5.com {
3671622St.nateldemoura@f5.com     nxt_str_t           ini_path;
3681622St.nateldemoura@f5.com     nxt_int_t           ret;
3691622St.nateldemoura@f5.com     nxt_conf_value_t    *value;
3701622St.nateldemoura@f5.com     nxt_php_app_conf_t  *c;
3711622St.nateldemoura@f5.com 
3721622St.nateldemoura@f5.com     static nxt_str_t  file_str = nxt_string("file");
3731622St.nateldemoura@f5.com     static nxt_str_t  user_str = nxt_string("user");
3741622St.nateldemoura@f5.com     static nxt_str_t  admin_str = nxt_string("admin");
3751622St.nateldemoura@f5.com 
3761622St.nateldemoura@f5.com     c = &conf->u.php;
3771622St.nateldemoura@f5.com 
3781622St.nateldemoura@f5.com #ifdef ZTS
3791622St.nateldemoura@f5.com 
3801622St.nateldemoura@f5.com #if PHP_VERSION_ID >= 70400
3811622St.nateldemoura@f5.com     php_tsrm_startup();
3821622St.nateldemoura@f5.com #else
3831622St.nateldemoura@f5.com     tsrm_startup(1, 1, 0, NULL);
3841622St.nateldemoura@f5.com     tsrm_ls = ts_resource(0);
3851622St.nateldemoura@f5.com #endif
3861622St.nateldemoura@f5.com 
3871622St.nateldemoura@f5.com #endif
3881622St.nateldemoura@f5.com 
3891622St.nateldemoura@f5.com #if defined(NXT_PHP7) && defined(ZEND_SIGNALS)
3901622St.nateldemoura@f5.com 
3911622St.nateldemoura@f5.com #if (NXT_ZEND_SIGNAL_STARTUP)
3921622St.nateldemoura@f5.com     zend_signal_startup();
3931622St.nateldemoura@f5.com #elif defined(ZTS)
3941622St.nateldemoura@f5.com #error PHP is built with thread safety and broken signals.
3951622St.nateldemoura@f5.com #endif
3961622St.nateldemoura@f5.com 
3971622St.nateldemoura@f5.com #endif
3981622St.nateldemoura@f5.com 
3991622St.nateldemoura@f5.com     sapi_startup(&nxt_php_sapi_module);
4001622St.nateldemoura@f5.com 
4011622St.nateldemoura@f5.com     if (c->options != NULL) {
4021622St.nateldemoura@f5.com         value = nxt_conf_get_object_member(c->options, &file_str, NULL);
4031622St.nateldemoura@f5.com 
4041622St.nateldemoura@f5.com         if (value != NULL) {
4051622St.nateldemoura@f5.com             nxt_conf_get_string(value, &ini_path);
4061622St.nateldemoura@f5.com 
4071622St.nateldemoura@f5.com             ret = nxt_php_set_ini_path(task, &ini_path,
4081622St.nateldemoura@f5.com                                        conf->working_directory);
4091622St.nateldemoura@f5.com 
4101622St.nateldemoura@f5.com             if (nxt_slow_path(ret != NXT_OK)) {
4111622St.nateldemoura@f5.com                 return NXT_ERROR;
4121622St.nateldemoura@f5.com             }
4131622St.nateldemoura@f5.com         }
4141622St.nateldemoura@f5.com     }
4151622St.nateldemoura@f5.com 
4161622St.nateldemoura@f5.com     if (nxt_slow_path(nxt_php_startup(&nxt_php_sapi_module) == FAILURE)) {
4171622St.nateldemoura@f5.com         nxt_alert(task, "failed to initialize SAPI module and extension");
4181622St.nateldemoura@f5.com         return NXT_ERROR;
4191622St.nateldemoura@f5.com     }
4201622St.nateldemoura@f5.com 
4211622St.nateldemoura@f5.com     if (c->options != NULL) {
4221622St.nateldemoura@f5.com         value = nxt_conf_get_object_member(c->options, &admin_str, NULL);
4231622St.nateldemoura@f5.com         nxt_php_set_options(task, value, ZEND_INI_SYSTEM);
4241622St.nateldemoura@f5.com 
4251622St.nateldemoura@f5.com         value = nxt_conf_get_object_member(c->options, &user_str, NULL);
4261622St.nateldemoura@f5.com         nxt_php_set_options(task, value, ZEND_INI_USER);
4271622St.nateldemoura@f5.com     }
4281622St.nateldemoura@f5.com 
4291861Svbart@nginx.com #ifdef NXT_PHP7
4301861Svbart@nginx.com     nxt_php_server_ag = zend_hash_str_find_ptr(CG(auto_globals), "_SERVER",
4311861Svbart@nginx.com                                                nxt_length("_SERVER"));
4321861Svbart@nginx.com #else
4331861Svbart@nginx.com     zend_hash_quick_find(CG(auto_globals), "_SERVER", sizeof("_SERVER"),
4341861Svbart@nginx.com                          zend_hash_func("_SERVER", sizeof("_SERVER")),
4351861Svbart@nginx.com                          (void **) &nxt_php_server_ag);
4361861Svbart@nginx.com #endif
4371861Svbart@nginx.com     if (nxt_slow_path(nxt_php_server_ag == NULL)) {
4381861Svbart@nginx.com         nxt_alert(task, "failed to find $_SERVER auto global");
4391861Svbart@nginx.com         return NXT_ERROR;
4401861Svbart@nginx.com     }
4411861Svbart@nginx.com 
4421622St.nateldemoura@f5.com     return NXT_OK;
4431622St.nateldemoura@f5.com }
4441622St.nateldemoura@f5.com 
4451622St.nateldemoura@f5.com 
4461622St.nateldemoura@f5.com static nxt_int_t
nxt_php_start(nxt_task_t * task,nxt_process_data_t * data)4471488St.nateldemoura@f5.com nxt_php_start(nxt_task_t *task, nxt_process_data_t *data)
4480Sigor@sysoev.ru {
4491488St.nateldemoura@f5.com     uint32_t               next;
4501488St.nateldemoura@f5.com     nxt_int_t              ret;
4511622St.nateldemoura@f5.com     nxt_str_t              name;
4521488St.nateldemoura@f5.com     nxt_uint_t             n;
4531488St.nateldemoura@f5.com     nxt_unit_ctx_t         *unit_ctx;
4541488St.nateldemoura@f5.com     nxt_unit_init_t        php_init;
4551488St.nateldemoura@f5.com     nxt_conf_value_t       *value;
4561488St.nateldemoura@f5.com     nxt_php_app_conf_t     *c;
4571488St.nateldemoura@f5.com     nxt_common_app_conf_t  *conf;
458142Smax.romanov@nginx.com 
4591488St.nateldemoura@f5.com     conf = data->app;
460142Smax.romanov@nginx.com     c = &conf->u.php;
461142Smax.romanov@nginx.com 
4621473Svbart@nginx.com     n = (c->targets != NULL) ? nxt_conf_object_members_count(c->targets) : 1;
463142Smax.romanov@nginx.com 
4641473Svbart@nginx.com     nxt_php_targets = nxt_zalloc(sizeof(nxt_php_target_t) * n);
4651473Svbart@nginx.com     if (nxt_slow_path(nxt_php_targets == NULL)) {
466462Smax.romanov@nginx.com         return NXT_ERROR;
467462Smax.romanov@nginx.com     }
468462Smax.romanov@nginx.com 
4691473Svbart@nginx.com     if (c->targets != NULL) {
4701473Svbart@nginx.com         next = 0;
471142Smax.romanov@nginx.com 
4721473Svbart@nginx.com         for (n = 0; /* void */; n++) {
4731473Svbart@nginx.com             value = nxt_conf_next_object_member(c->targets, &name, &next);
4741473Svbart@nginx.com             if (value == NULL) {
4751473Svbart@nginx.com                 break;
4761473Svbart@nginx.com             }
477142Smax.romanov@nginx.com 
4781473Svbart@nginx.com             ret = nxt_php_set_target(task, &nxt_php_targets[n], value);
4791473Svbart@nginx.com             if (nxt_slow_path(ret != NXT_OK)) {
4801473Svbart@nginx.com                 return NXT_ERROR;
4811473Svbart@nginx.com             }
482462Smax.romanov@nginx.com         }
483142Smax.romanov@nginx.com 
4841473Svbart@nginx.com     } else {
4851473Svbart@nginx.com         ret = nxt_php_set_target(task, &nxt_php_targets[0], conf->self);
4861376St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
4871376St.nateldemoura@f5.com             return NXT_ERROR;
4881376St.nateldemoura@f5.com         }
4891376St.nateldemoura@f5.com     }
4901376St.nateldemoura@f5.com 
4911980Smax.romanov@nginx.com     ret = nxt_unit_default_init(task, &php_init, conf);
4921519Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
4931519Smax.romanov@nginx.com         nxt_alert(task, "nxt_unit_default_init() failed");
4941519Smax.romanov@nginx.com         return ret;
495743Smax.romanov@nginx.com     }
496743Smax.romanov@nginx.com 
4971473Svbart@nginx.com     php_init.callbacks.request_handler = nxt_php_request_handler;
498743Smax.romanov@nginx.com 
499743Smax.romanov@nginx.com     unit_ctx = nxt_unit_init(&php_init);
500743Smax.romanov@nginx.com     if (nxt_slow_path(unit_ctx == NULL)) {
501743Smax.romanov@nginx.com         return NXT_ERROR;
502743Smax.romanov@nginx.com     }
503743Smax.romanov@nginx.com 
5041513Svbart@nginx.com     nxt_php_unit_ctx = unit_ctx;
5051513Svbart@nginx.com 
5061622St.nateldemoura@f5.com     nxt_unit_run(nxt_php_unit_ctx);
5071622St.nateldemoura@f5.com     nxt_unit_done(nxt_php_unit_ctx);
508743Smax.romanov@nginx.com 
509743Smax.romanov@nginx.com     exit(0);
510743Smax.romanov@nginx.com 
5110Sigor@sysoev.ru     return NXT_OK;
5120Sigor@sysoev.ru }
5130Sigor@sysoev.ru 
5140Sigor@sysoev.ru 
5151473Svbart@nginx.com static nxt_int_t
nxt_php_set_target(nxt_task_t * task,nxt_php_target_t * target,nxt_conf_value_t * conf)5161473Svbart@nginx.com nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target,
5171473Svbart@nginx.com     nxt_conf_value_t *conf)
5181473Svbart@nginx.com {
5191473Svbart@nginx.com     u_char            *tmp, *p;
5201473Svbart@nginx.com     nxt_str_t         str;
5211473Svbart@nginx.com     nxt_int_t         ret;
522