-
Notifications
You must be signed in to change notification settings - Fork 424
implement getenv and putenv in go #1086
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 21 commits
e03b78e
d46938d
59ab1ef
969ceea
098c795
660dc99
0c795b9
e6031cd
7b4c8ab
4ef55f9
41ff6b2
929a2c0
71279ff
2518bbb
61e4e20
a3cec5b
7d64751
67a547c
02e8545
d2bf2d9
f97a34b
1e5abb2
b68cf50
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 |
|---|---|---|
|
|
@@ -242,6 +242,75 @@ PHP_FUNCTION(frankenphp_finish_request) { /* {{{ */ | |
| RETURN_TRUE; | ||
| } /* }}} */ | ||
|
|
||
| /* {{{ Call go's putenv to prevent race conditions */ | ||
| PHP_FUNCTION(frankenphp_putenv) { | ||
| char *setting; | ||
| size_t setting_len; | ||
|
|
||
| ZEND_PARSE_PARAMETERS_START(1, 1) | ||
| Z_PARAM_STRING(setting, setting_len) | ||
| ZEND_PARSE_PARAMETERS_END(); | ||
|
|
||
| // Cast str_len to int (ensure it fits in an int) | ||
| if (setting_len > INT_MAX) { | ||
| php_error(E_WARNING, "String length exceeds maximum integer value"); | ||
| RETURN_FALSE; | ||
| } | ||
|
|
||
| if (go_putenv(setting, (int)setting_len)) { | ||
| RETURN_TRUE; | ||
| } else { | ||
| RETURN_FALSE; | ||
| } | ||
| } /* }}} */ | ||
|
|
||
| /* {{{ Call go's getenv to prevent race conditions */ | ||
| PHP_FUNCTION(frankenphp_getenv) { | ||
| char *name = NULL; | ||
| size_t name_len = 0; | ||
| bool local_only = 0; | ||
|
|
||
| ZEND_PARSE_PARAMETERS_START(0, 2) | ||
| Z_PARAM_OPTIONAL | ||
| Z_PARAM_STRING_OR_NULL(name, name_len) | ||
| Z_PARAM_BOOL(local_only) | ||
| ZEND_PARSE_PARAMETERS_END(); | ||
|
|
||
| if (!name) { | ||
| struct go_getfullenv_return full_env = go_getfullenv(thread_index); | ||
|
|
||
| array_init(return_value); | ||
| for (int i = 0; i < full_env.r1; i++) { | ||
| go_string key = full_env.r0[i * 2]; | ||
| go_string val = full_env.r0[i * 2 + 1]; | ||
|
|
||
| // create PHP strings for key and value | ||
| zend_string *key_str = zend_string_init(key.data, key.len, 0); | ||
| zend_string *val_str = zend_string_init(val.data, val.len, 0); | ||
|
|
||
| // add to the associative array | ||
| add_assoc_str(return_value, ZSTR_VAL(key_str), val_str); | ||
|
|
||
| // release the key string | ||
| zend_string_release(key_str); | ||
| } | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| go_string gname = {name_len, name}; | ||
|
|
||
| struct go_getenv_return result = go_getenv(thread_index, &gname); | ||
|
|
||
| if (result.r0) { | ||
| // Return the single environment variable as a string | ||
| RETVAL_STRINGL(result.r1->data, result.r1->len); | ||
| } else { | ||
| // Environment variable does not exist | ||
| RETVAL_FALSE; | ||
| } | ||
| } /* }}} */ | ||
|
|
||
| /* {{{ Fetch all HTTP request headers */ | ||
| PHP_FUNCTION(frankenphp_request_headers) { | ||
| if (zend_parse_parameters_none() == FAILURE) { | ||
|
|
@@ -260,8 +329,6 @@ PHP_FUNCTION(frankenphp_request_headers) { | |
|
|
||
| add_assoc_stringl_ex(return_value, key.data, key.len, val.data, val.len); | ||
| } | ||
|
|
||
| go_apache_request_cleanup(thread_index); | ||
| } | ||
| /* }}} */ | ||
|
|
||
|
|
@@ -408,15 +475,39 @@ PHP_FUNCTION(headers_send) { | |
| RETURN_LONG(sapi_send_headers()); | ||
| } | ||
|
|
||
| PHP_MINIT_FUNCTION(frankenphp) { | ||
| zend_function *func; | ||
|
|
||
| // Override putenv | ||
| func = zend_hash_str_find_ptr(CG(function_table), "putenv", | ||
| sizeof("putenv") - 1); | ||
| if (func != NULL && func->type == ZEND_INTERNAL_FUNCTION) { | ||
| ((zend_internal_function *)func)->handler = ZEND_FN(frankenphp_putenv); | ||
| } else { | ||
| php_error(E_WARNING, "Failed to find built-in putenv function"); | ||
| } | ||
|
|
||
| // Override getenv | ||
| func = zend_hash_str_find_ptr(CG(function_table), "getenv", | ||
| sizeof("getenv") - 1); | ||
| if (func != NULL && func->type == ZEND_INTERNAL_FUNCTION) { | ||
| ((zend_internal_function *)func)->handler = ZEND_FN(frankenphp_getenv); | ||
| } else { | ||
| php_error(E_WARNING, "Failed to find built-in getenv function"); | ||
| } | ||
|
|
||
| return SUCCESS; | ||
| } | ||
|
|
||
| static zend_module_entry frankenphp_module = { | ||
| STANDARD_MODULE_HEADER, | ||
| "frankenphp", | ||
| ext_functions, /* function table */ | ||
| NULL, /* initialization */ | ||
| NULL, /* shutdown */ | ||
| NULL, /* request initialization */ | ||
| NULL, /* request shutdown */ | ||
| NULL, /* information */ | ||
| ext_functions, /* function table */ | ||
| PHP_MINIT(frankenphp), /* initialization */ | ||
| NULL, /* shutdown */ | ||
| NULL, /* request initialization */ | ||
| NULL, /* request shutdown */ | ||
| NULL, /* information */ | ||
| TOSTRING(FRANKENPHP_VERSION), | ||
| STANDARD_MODULE_PROPERTIES}; | ||
|
|
||
|
|
@@ -472,7 +563,28 @@ int frankenphp_update_server_context( | |
| return SUCCESS; | ||
| } | ||
|
|
||
| PHPAPI void get_full_env(zval *track_vars_array) { | ||
| struct go_getfullenv_return full_env = go_getfullenv(thread_index); | ||
|
||
|
|
||
| for (int i = 0; i < full_env.r1; i++) { | ||
| go_string key = full_env.r0[i * 2]; | ||
| go_string val = full_env.r0[i * 2 + 1]; | ||
|
|
||
| // create PHP strings for key and value | ||
| zend_string *key_str = zend_string_init(key.data, key.len, 0); | ||
| zend_string *val_str = zend_string_init(val.data, val.len, 0); | ||
|
|
||
| // add to the associative array | ||
| add_assoc_str(track_vars_array, ZSTR_VAL(key_str), val_str); | ||
|
|
||
| // release the key string | ||
| zend_string_release(key_str); | ||
| } | ||
| } | ||
|
|
||
| static int frankenphp_startup(sapi_module_struct *sapi_module) { | ||
| php_import_environment_variables = get_full_env; | ||
|
|
||
| return php_module_startup(sapi_module, &frankenphp_module); | ||
| } | ||
|
|
||
|
|
@@ -662,14 +774,15 @@ static void frankenphp_register_variables(zval *track_vars_array) { | |
| /* https://www.php.net/manual/en/reserved.variables.server.php */ | ||
|
|
||
| /* In CGI mode, we consider the environment to be a part of the server | ||
| * variables | ||
| * variables. | ||
| */ | ||
|
|
||
| frankenphp_server_context *ctx = SG(server_context); | ||
|
|
||
| /* in non-worker mode we import the os environment regularly */ | ||
| if (!ctx->has_main_request) { | ||
| php_import_environment_variables(track_vars_array); | ||
| get_full_env(track_vars_array); | ||
| // php_import_environment_variables(track_vars_array); | ||
| go_register_variables(thread_index, track_vars_array); | ||
| return; | ||
| } | ||
|
|
@@ -678,7 +791,8 @@ static void frankenphp_register_variables(zval *track_vars_array) { | |
| if (os_environment == NULL) { | ||
| os_environment = malloc(sizeof(zval)); | ||
| array_init(os_environment); | ||
| php_import_environment_variables(os_environment); | ||
| get_full_env(os_environment); | ||
| // php_import_environment_variables(os_environment); | ||
| } | ||
| zend_hash_copy(Z_ARR_P(track_vars_array), Z_ARR_P(os_environment), | ||
| (copy_ctor_func_t)zval_add_ref); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| <?php | ||
|
|
||
| require_once __DIR__.'/_executor.php'; | ||
|
|
||
| return function() { | ||
| $var = 'MY_VAR_' . ($_GET['var'] ?? ''); | ||
| // Setting an environment variable | ||
| $result = putenv("$var=HelloWorld"); | ||
| if ($result) { | ||
| echo "Set MY_VAR successfully.\n"; | ||
| echo "MY_VAR = " . getenv($var) . "\n"; | ||
| } else { | ||
| echo "Failed to set MY_VAR.\n"; | ||
| } | ||
|
|
||
| // Unsetting the environment variable | ||
| $result = putenv($var); | ||
| if ($result) { | ||
| echo "Unset MY_VAR successfully.\n"; | ||
| $value = getenv($var); | ||
| if ($value === false) { | ||
| echo "MY_VAR is unset.\n"; | ||
| } else { | ||
| echo "MY_VAR = " . $value . "\n"; | ||
| } | ||
| } else { | ||
| echo "Failed to unset MY_VAR.\n"; | ||
| } | ||
|
|
||
| $result = putenv("$var="); | ||
| if ($result) { | ||
| echo "MY_VAR set to empty successfully.\n"; | ||
| $value = getenv($var); | ||
| if ($value === false) { | ||
| echo "MY_VAR is unset.\n"; | ||
| } else { | ||
| echo "MY_VAR = " . $value . "\n"; | ||
| } | ||
| } else { | ||
| echo "Failed to set MY_VAR.\n"; | ||
| } | ||
|
|
||
| // Attempt to unset a non-existing variable | ||
| $result = putenv('NON_EXISTING_VAR' . ($_GET['var'] ?? '')); | ||
| if ($result) { | ||
| echo "Unset NON_EXISTING_VAR successfully.\n"; | ||
| } else { | ||
| echo "Failed to unset NON_EXISTING_VAR.\n"; | ||
| } | ||
| }; |
Uh oh!
There was an error while loading. Please reload this page.