@@ -150,6 +150,25 @@ static void frankenphp_worker_request_shutdown() {
150150 SG (rfc1867_uploaded_files ) = NULL ;
151151}
152152
153+ PHPAPI void get_full_env (zval * track_vars_array ) {
154+ struct go_getfullenv_return full_env = go_getfullenv (thread_index );
155+
156+ for (int i = 0 ; i < full_env .r1 ; i ++ ) {
157+ go_string key = full_env .r0 [i * 2 ];
158+ go_string val = full_env .r0 [i * 2 + 1 ];
159+
160+ // create PHP strings for key and value
161+ zend_string * key_str = zend_string_init (key .data , key .len , 0 );
162+ zend_string * val_str = zend_string_init (val .data , val .len , 0 );
163+
164+ // add to the associative array
165+ add_assoc_str (track_vars_array , ZSTR_VAL (key_str ), val_str );
166+
167+ // release the key string
168+ zend_string_release (key_str );
169+ }
170+ }
171+
153172/* Adapted from php_request_startup() */
154173static int frankenphp_worker_request_startup () {
155174 int retval = SUCCESS ;
@@ -242,6 +261,60 @@ PHP_FUNCTION(frankenphp_finish_request) { /* {{{ */
242261 RETURN_TRUE ;
243262} /* }}} */
244263
264+ /* {{{ Call go's putenv to prevent race conditions */
265+ PHP_FUNCTION (frankenphp_putenv ) {
266+ char * setting ;
267+ size_t setting_len ;
268+
269+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
270+ Z_PARAM_STRING (setting , setting_len )
271+ ZEND_PARSE_PARAMETERS_END ();
272+
273+ // Cast str_len to int (ensure it fits in an int)
274+ if (setting_len > INT_MAX ) {
275+ php_error (E_WARNING , "String length exceeds maximum integer value" );
276+ RETURN_FALSE ;
277+ }
278+
279+ if (go_putenv (setting , (int )setting_len )) {
280+ RETURN_TRUE ;
281+ } else {
282+ RETURN_FALSE ;
283+ }
284+ } /* }}} */
285+
286+ /* {{{ Call go's getenv to prevent race conditions */
287+ PHP_FUNCTION (frankenphp_getenv ) {
288+ char * name = NULL ;
289+ size_t name_len = 0 ;
290+ bool local_only = 0 ;
291+
292+ ZEND_PARSE_PARAMETERS_START (0 , 2 )
293+ Z_PARAM_OPTIONAL
294+ Z_PARAM_STRING_OR_NULL (name , name_len )
295+ Z_PARAM_BOOL (local_only )
296+ ZEND_PARSE_PARAMETERS_END ();
297+
298+ if (!name ) {
299+ array_init (return_value );
300+ get_full_env (return_value );
301+
302+ return ;
303+ }
304+
305+ go_string gname = {name_len , name };
306+
307+ struct go_getenv_return result = go_getenv (thread_index , & gname );
308+
309+ if (result .r0 ) {
310+ // Return the single environment variable as a string
311+ RETVAL_STRINGL (result .r1 -> data , result .r1 -> len );
312+ } else {
313+ // Environment variable does not exist
314+ RETVAL_FALSE ;
315+ }
316+ } /* }}} */
317+
245318/* {{{ Fetch all HTTP request headers */
246319PHP_FUNCTION (frankenphp_request_headers ) {
247320 if (zend_parse_parameters_none () == FAILURE ) {
@@ -260,8 +333,6 @@ PHP_FUNCTION(frankenphp_request_headers) {
260333
261334 add_assoc_stringl_ex (return_value , key .data , key .len , val .data , val .len );
262335 }
263-
264- go_apache_request_cleanup (thread_index );
265336}
266337/* }}} */
267338
@@ -408,15 +479,39 @@ PHP_FUNCTION(headers_send) {
408479 RETURN_LONG (sapi_send_headers ());
409480}
410481
482+ PHP_MINIT_FUNCTION (frankenphp ) {
483+ zend_function * func ;
484+
485+ // Override putenv
486+ func = zend_hash_str_find_ptr (CG (function_table ), "putenv" ,
487+ sizeof ("putenv" ) - 1 );
488+ if (func != NULL && func -> type == ZEND_INTERNAL_FUNCTION ) {
489+ ((zend_internal_function * )func )-> handler = ZEND_FN (frankenphp_putenv );
490+ } else {
491+ php_error (E_WARNING , "Failed to find built-in putenv function" );
492+ }
493+
494+ // Override getenv
495+ func = zend_hash_str_find_ptr (CG (function_table ), "getenv" ,
496+ sizeof ("getenv" ) - 1 );
497+ if (func != NULL && func -> type == ZEND_INTERNAL_FUNCTION ) {
498+ ((zend_internal_function * )func )-> handler = ZEND_FN (frankenphp_getenv );
499+ } else {
500+ php_error (E_WARNING , "Failed to find built-in getenv function" );
501+ }
502+
503+ return SUCCESS ;
504+ }
505+
411506static zend_module_entry frankenphp_module = {
412507 STANDARD_MODULE_HEADER ,
413508 "frankenphp" ,
414- ext_functions , /* function table */
415- NULL , /* initialization */
416- NULL , /* shutdown */
417- NULL , /* request initialization */
418- NULL , /* request shutdown */
419- NULL , /* information */
509+ ext_functions , /* function table */
510+ PHP_MINIT ( frankenphp ), /* initialization */
511+ NULL , /* shutdown */
512+ NULL , /* request initialization */
513+ NULL , /* request shutdown */
514+ NULL , /* information */
420515 TOSTRING (FRANKENPHP_VERSION ),
421516 STANDARD_MODULE_PROPERTIES };
422517
@@ -473,6 +568,8 @@ int frankenphp_update_server_context(
473568}
474569
475570static int frankenphp_startup (sapi_module_struct * sapi_module ) {
571+ php_import_environment_variables = get_full_env ;
572+
476573 return php_module_startup (sapi_module , & frankenphp_module );
477574}
478575
@@ -662,14 +759,15 @@ static void frankenphp_register_variables(zval *track_vars_array) {
662759 /* https://www.php.net/manual/en/reserved.variables.server.php */
663760
664761 /* In CGI mode, we consider the environment to be a part of the server
665- * variables
762+ * variables.
666763 */
667764
668765 frankenphp_server_context * ctx = SG (server_context );
669766
670767 /* in non-worker mode we import the os environment regularly */
671768 if (!ctx -> has_main_request ) {
672- php_import_environment_variables (track_vars_array );
769+ get_full_env (track_vars_array );
770+ // php_import_environment_variables(track_vars_array);
673771 go_register_variables (thread_index , track_vars_array );
674772 return ;
675773 }
@@ -678,7 +776,8 @@ static void frankenphp_register_variables(zval *track_vars_array) {
678776 if (os_environment == NULL ) {
679777 os_environment = malloc (sizeof (zval ));
680778 array_init (os_environment );
681- php_import_environment_variables (os_environment );
779+ get_full_env (os_environment );
780+ // php_import_environment_variables(os_environment);
682781 }
683782 zend_hash_copy (Z_ARR_P (track_vars_array ), Z_ARR_P (os_environment ),
684783 (copy_ctor_func_t )zval_add_ref );
0 commit comments