diff options
author | Russ Allbery <eagle@eyrie.org> | 2016-04-25 21:32:42 -0700 |
---|---|---|
committer | Russ Allbery <eagle@eyrie.org> | 2016-04-25 21:32:42 -0700 |
commit | 7c468600907a6f07dc3cb847f03c3e02901a4994 (patch) | |
tree | 75234f5705ea46b4fcf0d9996286ae500a824ba1 /php | |
parent | f10b9e510510332867839712da4b13e60aa4de82 (diff) |
Port PHP extension to PHP 7
The PHP bindings have been ported to PHP 7, based on work by Nish
Aravamudan. The PHP 7 API is sufficiently different that this was
done by forking the PHP code and creating a new version for PHP 7 and
later, chosing which extension to compile based on the discovered
version of PHP. Currently, there is no functionality difference, but
the PHP 5 extension should be considered frozen and may not get any
new features. It will eventually be removed in a future version of
remctl when PHP 7 is sufficiently widespread.
Diffstat (limited to 'php')
-rw-r--r-- | php/config.m4.in | 8 | ||||
-rw-r--r-- | php/php5_remctl.c | 541 | ||||
-rw-r--r-- | php/php_remctl.c | 116 |
3 files changed, 601 insertions, 64 deletions
diff --git a/php/config.m4.in b/php/config.m4.in index 9132b1e..32f26a1 100644 --- a/php/config.m4.in +++ b/php/config.m4.in @@ -1,9 +1,11 @@ -dnl remctl PECL extension for PHP configuration -*- autoconf -*- +dnl remctl PECL extension for PHP configuration. +dnl -*- autoconf -*- dnl dnl Provides additional configuration hooks for the PHP module build system. dnl This file is used by the phpize frameowrk. dnl dnl Originally written by Andrew Mortensen <admorten@umich.edu>, 2008 +dnl Copyright 2015 Russ Allbery <eagle@eyrie.org> dnl Copyright 2008 Andrew Mortensen <admorten@umich.edu> dnl Copyright 2008 dnl The Board of Trustees of the Leland Stanford Junior University @@ -16,6 +18,8 @@ PHP_ARG_ENABLE([remctl], [whether to enable remctl PHP extension], dnl The @...@ variables are substituted by the top-level configure. Yes, this dnl is a little odd, but it seems to work. AS_IF([test "$PHP_REMCTL" != no], - [PHP_NEW_EXTENSION([remctl], [php_remctl.c], [$ext_shared]) + [AS_CASE([`$PHP_CONFIG --version`], + [5*], [PHP_NEW_EXTENSION([remctl], [php5_remctl.c], [$ext_shared])], + [*], [PHP_NEW_EXTENSION([remctl], [php_remctl.c], [$ext_shared])]) PHP_ADD_INCLUDE([@abs_top_srcdir@]) LDFLAGS="$LDFLAGS -L@abs_top_builddir@/client/.libs -lremctl"]) diff --git a/php/php5_remctl.c b/php/php5_remctl.c new file mode 100644 index 0000000..5fe6ce8 --- /dev/null +++ b/php/php5_remctl.c @@ -0,0 +1,541 @@ +/* + * remctl PECL extension for PHP 5 + * + * Provides bindings for PHP very similar to the libremctl library for C or + * the Net::Remctl bindings for Perl. This is an older version for PHP 5. + * See php_remctl.c for PHP 7 and later. + * + * This file is frozen and probably won't add any new features. It will be + * dropped in some future version of remctl when PHP 7 support is widespread + * enough. The API changes were sufficiently wide-ranging that trying to + * maintain one unified version with a ton of #ifdefs didn't seem practical. + * + * Originally written by Andrew Mortensen <admorten@umich.edu>, 2008 + * Copyirght 2016 Russ Allbery <eagle@eyrie.org> + * Copyright 2008 Andrew Mortensen <admorten@umich.edu> + * Copyright 2008, 2011, 2012, 2014 + * The Board of Trustees of the Leland Stanford Junior University + * + * See LICENSE for licensing terms. + */ + +#include <config.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <time.h> + +#include <client/remctl.h> + +#include <php.h> +#include <php_remctl.h> + +static int le_remctl_internal; + +static zend_function_entry remctl_functions[] = { + ZEND_FE(remctl, NULL) + ZEND_FE(remctl_new, NULL) + ZEND_FE(remctl_set_ccache, NULL) + ZEND_FE(remctl_set_source_ip, NULL) + ZEND_FE(remctl_set_timeout, NULL) + ZEND_FE(remctl_open, NULL) + ZEND_FE(remctl_close, NULL) + ZEND_FE(remctl_command, NULL) + ZEND_FE(remctl_output, NULL) + ZEND_FE(remctl_noop, NULL) + ZEND_FE(remctl_error, NULL) + { NULL, NULL, NULL, 0, 0 } +}; + +zend_module_entry remctl_module_entry = { + STANDARD_MODULE_HEADER, + PHP_REMCTL_EXTNAME, + remctl_functions, + PHP_MINIT(remctl), + NULL, + NULL, + NULL, + NULL, + PHP_REMCTL_VERSION, + STANDARD_MODULE_PROPERTIES +}; + +#ifdef COMPILE_DL_REMCTL +ZEND_GET_MODULE(remctl) +#endif + +/* + * Destructor for a remctl object. Close the underlying connection. + */ +static void +php_remctl_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) +{ + struct remctl *r = (struct remctl *) rsrc->ptr; + + if (r != NULL) + remctl_close(r); +} + + +/* + * Initialize the module and register the destructor. Stores the resource + * number of the module in le_remctl_internal. + */ +PHP_MINIT_FUNCTION(remctl) +{ + le_remctl_internal = + zend_register_list_destructors_ex(php_remctl_dtor, NULL, + PHP_REMCTL_RES_NAME, module_number); + return SUCCESS; +} + + +/* + * The simplified interface. Make a call and return the results as an + * object. + */ +ZEND_FUNCTION(remctl) +{ + zval *cmd_array, **data; + void **data_ref; + HashTable *hash; + HashPosition pos; + char *host, *principal = NULL; + const char **command = NULL; + long port; + int hlen, plen, count, i, status; + int success = 0; + struct remctl_result *result = NULL; + + /* + * Read the arguments (host, port, principal, and command) and check their + * validity. Host and command are required, so all arguments must be + * provided, but an empty string can be passed in as the principal. + */ + status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "slsa", &host, + &hlen, &port, &principal, &plen, &cmd_array); + if (status == FAILURE) { + zend_error(E_WARNING, "remctl: invalid parameters\n"); + RETURN_NULL(); + } + if (hlen == 0) { + zend_error(E_WARNING, "remctl: host must be a valid string\n"); + RETURN_NULL(); + } + if (plen == 0) + principal = NULL; + hash = Z_ARRVAL_P(cmd_array); + count = zend_hash_num_elements(hash); + if (count < 1) { + zend_error(E_WARNING, "remctl: command must not be empty\n"); + RETURN_NULL(); + } + + /* + * Convert the command array into the char ** needed by libremctl. This + * is less than ideal because we make another copy of all of the + * arguments. There should be some way to do this without making a copy. + */ + command = ecalloc(count + 1, sizeof(char *)); + if (command == NULL) { + zend_error(E_WARNING, "remctl: ecalloc failed\n"); + RETURN_NULL(); + } + i = 0; + zend_hash_internal_pointer_reset_ex(hash, &pos); + data_ref = (void **) &data; + while (zend_hash_get_current_data_ex(hash, data_ref, &pos) == SUCCESS) { + if (Z_TYPE_PP(data) != IS_STRING) { + zend_error(E_WARNING, "remctl: command contains non-string\n"); + goto cleanup; + } + if (i >= count) { + zend_error(E_WARNING, "remctl: internal error: incorrect count\n"); + goto cleanup; + } + command[i] = estrndup(Z_STRVAL_PP(data), Z_STRLEN_PP(data)); + if (command[i] == NULL) { + zend_error(E_WARNING, "remctl: estrndup failed\n"); + count = i; + goto cleanup; + } + i++; + zend_hash_move_forward_ex(hash, &pos); + } + command[count] = NULL; + + /* Run the actual remctl call. */ + result = remctl(host, port, principal, command); + if (result == NULL) { + zend_error(E_WARNING, "remctl: %s\n", strerror(errno)); + goto cleanup; + } + + /* + * Convert the remctl result to an object. return_value is defined for us + * by Zend. + */ + if (object_init(return_value) != SUCCESS) { + zend_error(E_WARNING, "remctl: object_init failed\n"); + goto cleanup; + } + if (result->error == NULL) + add_property_string(return_value, "error", "", 1); + else + add_property_string(return_value, "error", result->error, 1); + add_property_stringl(return_value, "stdout", result->stdout_buf, + result->stdout_len, 1); + add_property_long(return_value, "stdout_len", result->stdout_len); + add_property_stringl(return_value, "stderr", result->stderr_buf, + result->stderr_len, 1); + add_property_long(return_value, "stderr_len", result->stderr_len); + add_property_long(return_value, "status", result->status); + success = 1; + +cleanup: + if (command != NULL) { + for (i = 0; i < count; i++) + efree((char *) command[i]); + efree(command); + } + if (result != NULL) + remctl_result_free(result); + if (!success) + RETURN_NULL(); +} + + +/* + * Now the full interface. First, the constructor. + */ +ZEND_FUNCTION(remctl_new) +{ + struct remctl *r; + + r = remctl_new(); + if (r == NULL) { + zend_error(E_WARNING, "remctl_new: %s", strerror(errno)); + RETURN_NULL(); + } + ZEND_REGISTER_RESOURCE(return_value, r, le_remctl_internal); +} + + +/* + * Set the credential cache for subsequent connections with remctl_open. + */ +ZEND_FUNCTION(remctl_set_ccache) +{ + struct remctl *r; + zval *zrem; + char *ccache; + int clen, status; + + status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zrem, + &ccache, &clen); + if (status == FAILURE) { + zend_error(E_WARNING, "remctl_set_ccache: invalid parameters\n"); + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, + le_remctl_internal); + if (!remctl_set_ccache(r, ccache)) + RETURN_FALSE; + RETURN_TRUE; +} + + +/* + * Set the source IP for subsequent connections with remctl_open. + */ +ZEND_FUNCTION(remctl_set_source_ip) +{ + struct remctl *r; + zval *zrem; + char *source; + int slen, status; + + status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zrem, + &source, &slen); + if (status == FAILURE) { + zend_error(E_WARNING, "remctl_set_source_ip: invalid parameters\n"); + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, + le_remctl_internal); + if (!remctl_set_source_ip(r, source)) + RETURN_FALSE; + RETURN_TRUE; +} + + +/* + * Set the timeout for subsequent operations. + */ +ZEND_FUNCTION(remctl_set_timeout) +{ + struct remctl *r; + zval *zrem; + long timeout; + int status; + + status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zrem, + &timeout); + if (status == FAILURE) { + zend_error(E_WARNING, "remctl_set_timeout: invalid parameters\n"); + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, + le_remctl_internal); + if (!remctl_set_timeout(r, timeout)) + RETURN_FALSE; + RETURN_TRUE; +} + + +/* + * Open a connection to the remote host. Only the host parameter is required; + * the rest are optional. PHP may require something be passed in for + * principal, but the empty string is taken to mean "use the library default." + */ +ZEND_FUNCTION(remctl_open) +{ + struct remctl *r; + zval *zrem; + char *host; + char *principal = NULL; + long port = 0; + int hlen, plen, status; + + /* Parse and verify arguments. */ + status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|ls", &zrem, + &host, &hlen, &port, &principal, &plen); + if (status == FAILURE) { + zend_error(E_WARNING, "remctl_open: invalid parameters\n"); + RETURN_FALSE; + } + if (plen == 0) + principal = NULL; + ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, + le_remctl_internal); + + /* Now we have all the arguments and can do the real work. */ + if (!remctl_open(r, host, port, principal)) + RETURN_FALSE; + RETURN_TRUE; +} + + +/* + * Send a command to the remote server. + */ +ZEND_FUNCTION(remctl_command) +{ + struct remctl *r; + zval *zrem, *cmd_array, **data; + void **data_ref; + HashTable *hash; + HashPosition pos; + struct iovec *cmd_vec = NULL; + int i, count, status; + int success = 0; + + /* Parse and verify arguments. */ + status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra", &zrem, + &cmd_array); + if (status == FAILURE) { + zend_error(E_WARNING, "remctl_command: invalid parameters\n"); + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, + le_remctl_internal); + hash = Z_ARRVAL_P(cmd_array); + count = zend_hash_num_elements(hash); + if (count < 1) { + zend_error(E_WARNING, "remctl_command: command must not be empty\n"); + RETURN_NULL(); + } + + /* + * Transform the PHP array into an array of struct iovec. This is less + * than ideal because it makes another copy of all of the data. There + * should be some way to do this without copying. + */ + cmd_vec = ecalloc(count, sizeof(struct iovec)); + if (cmd_vec == NULL) { + zend_error(E_WARNING, "remctl_command: ecalloc failed\n"); + RETURN_FALSE; + } + i = 0; + zend_hash_internal_pointer_reset_ex(hash, &pos); + data_ref = (void **) &data; + while (zend_hash_get_current_data_ex(hash, data_ref, &pos) == SUCCESS) { + if (Z_TYPE_PP(data) != IS_STRING) { + zend_error(E_WARNING, + "remctl_command: command contains non-string\n"); + goto cleanup; + } + if (i >= count) { + zend_error(E_WARNING, + "remctl_command: internal error: incorrect count\n"); + goto cleanup; + } + cmd_vec[i].iov_base = emalloc(Z_STRLEN_PP(data) + 1); + if (cmd_vec[i].iov_base == NULL) { + zend_error(E_WARNING, "remctl_command: emalloc failed\n"); + count = i; + goto cleanup; + } + cmd_vec[i].iov_len = Z_STRLEN_PP(data); + memcpy(cmd_vec[i].iov_base, Z_STRVAL_PP(data), cmd_vec[i].iov_len); + i++; + zend_hash_move_forward_ex(hash, &pos); + } + + /* Finally, we can do the work. */ + if (!remctl_commandv(r, cmd_vec, count)) + goto cleanup; + success = 1; + +cleanup: + if (cmd_vec != NULL) { + for (i = 0; i < count; i++) + efree(cmd_vec[i].iov_base); + efree(cmd_vec); + } + if (!success) + RETURN_FALSE; + RETURN_TRUE; +} + + +/* + * Get an output token from the server and return it as an object. + */ +ZEND_FUNCTION(remctl_output) +{ + struct remctl *r; + struct remctl_output *output; + zval *zrem; + int status; + + /* Parse and verify arguments. */ + status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zrem); + if (status == FAILURE) { + zend_error(E_WARNING, "remctl_output: invalid parameters\n"); + RETURN_NULL(); + } + ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, + le_remctl_internal); + + /* Get the output token. */ + output = remctl_output(r); + if (output == NULL) + RETURN_NULL(); + + /* + * Populate an object with the output results. return_value is defined + * for us by Zend. + */ + if (object_init(return_value) != SUCCESS) { + zend_error(E_WARNING, "remctl_output: object_init failed\n"); + RETURN_NULL(); + } + switch (output->type) { + case REMCTL_OUT_OUTPUT: + add_property_string(return_value, "type", "output", 1); + add_property_stringl(return_value, "data", output->data, + output->length, 1); + add_property_long(return_value, "stream", output->stream); + break; + case REMCTL_OUT_ERROR: + add_property_string(return_value, "type", "error", 1); + add_property_stringl(return_value, "data", output->data, + output->length, 1); + add_property_long(return_value, "error", output->error); + break; + case REMCTL_OUT_STATUS: + add_property_string(return_value, "type", "status", 1); + add_property_long(return_value, "status", output->status); + break; + case REMCTL_OUT_DONE: + add_property_string(return_value, "type", "done", 1); + break; + } +} + + +/* + * Sends a NOOP message to the server and reads the reply. + */ +ZEND_FUNCTION(remctl_noop) +{ + struct remctl *r; + zval *zrem; + int status; + + status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zrem); + if (status == FAILURE) { + zend_error(E_WARNING, "remctl_noop: invalid parameters\n"); + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, + le_remctl_internal); + if (!remctl_noop(r)) + RETURN_FALSE; + RETURN_TRUE; +} + + +/* + * Returns the error message from a previously failed remctl call. + */ +ZEND_FUNCTION(remctl_error) +{ + struct remctl *r; + zval *zrem; + const char *error; + int status; + + /* Parse and verify arguments. */ + status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zrem); + if (status == FAILURE) { + zend_error(E_WARNING, "remctl_error: invalid parameters\n"); + RETURN_NULL(); + } + ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, + le_remctl_internal); + + /* Do the work. */ + error = remctl_error(r); + RETURN_STRING((char *) error, 1); +} + + +/* + * Close the connection. This isn't strictly necessary since the destructor + * will close the connection for us, but it's part of the interface. + */ +ZEND_FUNCTION(remctl_close) +{ + struct remctl *r; + zval *zrem; + int status; + + /* Parse and verify arguments. */ + status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zrem); + if (status == FAILURE) { + zend_error(E_WARNING, "remctl_error: invalid parameters\n"); + RETURN_NULL(); + } + ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, + le_remctl_internal); + + /* This delete invokes php_remctl_dtor, which calls remctl_close. */ + zend_list_delete(Z_LVAL_P(zrem)); + RETURN_TRUE; +} diff --git a/php/php_remctl.c b/php/php_remctl.c index 7e21f48..570ac13 100644 --- a/php/php_remctl.c +++ b/php/php_remctl.c @@ -1,10 +1,11 @@ /* - * remctl PECL extension for PHP + * remctl PECL extension for PHP 7 and later * * Provides bindings for PHP very similar to the libremctl library for C or * the Net::Remctl bindings for Perl. * * Originally written by Andrew Mortensen <admorten@umich.edu>, 2008 + * Copyirght 2016 Russ Allbery <eagle@eyrie.org> * Copyright 2008 Andrew Mortensen <admorten@umich.edu> * Copyright 2008, 2011, 2012, 2014 * The Board of Trustees of the Leland Stanford Junior University @@ -65,7 +66,7 @@ ZEND_GET_MODULE(remctl) * Destructor for a remctl object. Close the underlying connection. */ static void -php_remctl_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) +php_remctl_dtor(zend_resource *rsrc TSRMLS_DC) { struct remctl *r = (struct remctl *) rsrc->ptr; @@ -93,14 +94,13 @@ PHP_MINIT_FUNCTION(remctl) */ ZEND_FUNCTION(remctl) { - zval *cmd_array, **data; - void **data_ref; + zval *cmd_array, *data; HashTable *hash; - HashPosition pos; char *host, *principal = NULL; const char **command = NULL; long port; - int hlen, plen, count, i, status; + size_t hlen, plen; + int count, i, status; int success = 0; struct remctl_result *result = NULL; @@ -139,10 +139,8 @@ ZEND_FUNCTION(remctl) RETURN_NULL(); } i = 0; - zend_hash_internal_pointer_reset_ex(hash, &pos); - data_ref = (void **) &data; - while (zend_hash_get_current_data_ex(hash, data_ref, &pos) == SUCCESS) { - if (Z_TYPE_PP(data) != IS_STRING) { + ZEND_HASH_FOREACH_VAL(hash, data) { + if (Z_TYPE_P(data) != IS_STRING) { zend_error(E_WARNING, "remctl: command contains non-string\n"); goto cleanup; } @@ -150,15 +148,14 @@ ZEND_FUNCTION(remctl) zend_error(E_WARNING, "remctl: internal error: incorrect count\n"); goto cleanup; } - command[i] = estrndup(Z_STRVAL_PP(data), Z_STRLEN_PP(data)); + command[i] = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data)); if (command[i] == NULL) { zend_error(E_WARNING, "remctl: estrndup failed\n"); count = i; goto cleanup; } i++; - zend_hash_move_forward_ex(hash, &pos); - } + } ZEND_HASH_FOREACH_END(); command[count] = NULL; /* Run the actual remctl call. */ @@ -177,14 +174,14 @@ ZEND_FUNCTION(remctl) goto cleanup; } if (result->error == NULL) - add_property_string(return_value, "error", "", 1); + add_property_string(return_value, "error", ""); else - add_property_string(return_value, "error", result->error, 1); + add_property_string(return_value, "error", result->error); add_property_stringl(return_value, "stdout", result->stdout_buf, - result->stdout_len, 1); + result->stdout_len); add_property_long(return_value, "stdout_len", result->stdout_len); add_property_stringl(return_value, "stderr", result->stderr_buf, - result->stderr_len, 1); + result->stderr_len); add_property_long(return_value, "stderr_len", result->stderr_len); add_property_long(return_value, "status", result->status); success = 1; @@ -214,7 +211,7 @@ ZEND_FUNCTION(remctl_new) zend_error(E_WARNING, "remctl_new: %s", strerror(errno)); RETURN_NULL(); } - ZEND_REGISTER_RESOURCE(return_value, r, le_remctl_internal); + RETURN_RES(zend_register_resource(r, le_remctl_internal)); } @@ -226,7 +223,8 @@ ZEND_FUNCTION(remctl_set_ccache) struct remctl *r; zval *zrem; char *ccache; - int clen, status; + size_t clen; + int status; status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zrem, &ccache, &clen); @@ -234,8 +232,8 @@ ZEND_FUNCTION(remctl_set_ccache) zend_error(E_WARNING, "remctl_set_ccache: invalid parameters\n"); RETURN_FALSE; } - ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, - le_remctl_internal); + r = zend_fetch_resource(Z_RES_P(zrem), PHP_REMCTL_RES_NAME, + le_remctl_internal); if (!remctl_set_ccache(r, ccache)) RETURN_FALSE; RETURN_TRUE; @@ -250,7 +248,8 @@ ZEND_FUNCTION(remctl_set_source_ip) struct remctl *r; zval *zrem; char *source; - int slen, status; + size_t slen; + int status; status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zrem, &source, &slen); @@ -258,8 +257,8 @@ ZEND_FUNCTION(remctl_set_source_ip) zend_error(E_WARNING, "remctl_set_source_ip: invalid parameters\n"); RETURN_FALSE; } - ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, - le_remctl_internal); + r = zend_fetch_resource(Z_RES_P(zrem), PHP_REMCTL_RES_NAME, + le_remctl_internal); if (!remctl_set_source_ip(r, source)) RETURN_FALSE; RETURN_TRUE; @@ -273,7 +272,7 @@ ZEND_FUNCTION(remctl_set_timeout) { struct remctl *r; zval *zrem; - long timeout; + zend_long timeout; int status; status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zrem, @@ -282,8 +281,8 @@ ZEND_FUNCTION(remctl_set_timeout) zend_error(E_WARNING, "remctl_set_timeout: invalid parameters\n"); RETURN_FALSE; } - ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, - le_remctl_internal); + r = zend_fetch_resource(Z_RES_P(zrem), PHP_REMCTL_RES_NAME, + le_remctl_internal); if (!remctl_set_timeout(r, timeout)) RETURN_FALSE; RETURN_TRUE; @@ -301,8 +300,9 @@ ZEND_FUNCTION(remctl_open) zval *zrem; char *host; char *principal = NULL; - long port = 0; - int hlen, plen, status; + zend_long port = 0; + size_t hlen, plen; + int status; /* Parse and verify arguments. */ status = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|ls", &zrem, @@ -313,8 +313,8 @@ ZEND_FUNCTION(remctl_open) } if (plen == 0) principal = NULL; - ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, - le_remctl_internal); + r = zend_fetch_resource(Z_RES_P(zrem), PHP_REMCTL_RES_NAME, + le_remctl_internal); /* Now we have all the arguments and can do the real work. */ if (!remctl_open(r, host, port, principal)) @@ -329,10 +329,8 @@ ZEND_FUNCTION(remctl_open) ZEND_FUNCTION(remctl_command) { struct remctl *r; - zval *zrem, *cmd_array, **data; - void **data_ref; + zval *zrem, *cmd_array, *data; HashTable *hash; - HashPosition pos; struct iovec *cmd_vec = NULL; int i, count, status; int success = 0; @@ -344,8 +342,8 @@ ZEND_FUNCTION(remctl_command) zend_error(E_WARNING, "remctl_command: invalid parameters\n"); RETURN_FALSE; } - ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, - le_remctl_internal); + r = zend_fetch_resource(Z_RES_P(zrem), PHP_REMCTL_RES_NAME, + le_remctl_internal); hash = Z_ARRVAL_P(cmd_array); count = zend_hash_num_elements(hash); if (count < 1) { @@ -364,10 +362,8 @@ ZEND_FUNCTION(remctl_command) RETURN_FALSE; } i = 0; - zend_hash_internal_pointer_reset_ex(hash, &pos); - data_ref = (void **) &data; - while (zend_hash_get_current_data_ex(hash, data_ref, &pos) == SUCCESS) { - if (Z_TYPE_PP(data) != IS_STRING) { + ZEND_HASH_FOREACH_VAL(hash, data) { + if (Z_TYPE_P(data) != IS_STRING) { zend_error(E_WARNING, "remctl_command: command contains non-string\n"); goto cleanup; @@ -377,17 +373,16 @@ ZEND_FUNCTION(remctl_command) "remctl_command: internal error: incorrect count\n"); goto cleanup; } - cmd_vec[i].iov_base = emalloc(Z_STRLEN_PP(data) + 1); + cmd_vec[i].iov_base = emalloc(Z_STRLEN_P(data) + 1); if (cmd_vec[i].iov_base == NULL) { zend_error(E_WARNING, "remctl_command: emalloc failed\n"); count = i; goto cleanup; } - cmd_vec[i].iov_len = Z_STRLEN_PP(data); - memcpy(cmd_vec[i].iov_base, Z_STRVAL_PP(data), cmd_vec[i].iov_len); + cmd_vec[i].iov_len = Z_STRLEN_P(data); + memcpy(cmd_vec[i].iov_base, Z_STRVAL_P(data), cmd_vec[i].iov_len); i++; - zend_hash_move_forward_ex(hash, &pos); - } + } ZEND_HASH_FOREACH_END(); /* Finally, we can do the work. */ if (!remctl_commandv(r, cmd_vec, count)) @@ -422,8 +417,8 @@ ZEND_FUNCTION(remctl_output) zend_error(E_WARNING, "remctl_output: invalid parameters\n"); RETURN_NULL(); } - ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, - le_remctl_internal); + r = zend_fetch_resource(Z_RES_P(zrem), PHP_REMCTL_RES_NAME, + le_remctl_internal); /* Get the output token. */ output = remctl_output(r); @@ -440,23 +435,23 @@ ZEND_FUNCTION(remctl_output) } switch (output->type) { case REMCTL_OUT_OUTPUT: - add_property_string(return_value, "type", "output", 1); + add_property_string(return_value, "type", "output"); add_property_stringl(return_value, "data", output->data, - output->length, 1); + output->length); add_property_long(return_value, "stream", output->stream); break; case REMCTL_OUT_ERROR: - add_property_string(return_value, "type", "error", 1); + add_property_string(return_value, "type", "error"); add_property_stringl(return_value, "data", output->data, - output->length, 1); + output->length); add_property_long(return_value, "error", output->error); break; case REMCTL_OUT_STATUS: - add_property_string(return_value, "type", "status", 1); + add_property_string(return_value, "type", "status"); add_property_long(return_value, "status", output->status); break; case REMCTL_OUT_DONE: - add_property_string(return_value, "type", "done", 1); + add_property_string(return_value, "type", "done"); break; } } @@ -476,8 +471,8 @@ ZEND_FUNCTION(remctl_noop) zend_error(E_WARNING, "remctl_noop: invalid parameters\n"); RETURN_FALSE; } - ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, - le_remctl_internal); + r = zend_fetch_resource(Z_RES_P(zrem), PHP_REMCTL_RES_NAME, + le_remctl_internal); if (!remctl_noop(r)) RETURN_FALSE; RETURN_TRUE; @@ -500,12 +495,12 @@ ZEND_FUNCTION(remctl_error) zend_error(E_WARNING, "remctl_error: invalid parameters\n"); RETURN_NULL(); } - ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, - le_remctl_internal); + r = zend_fetch_resource(Z_RES_P(zrem), PHP_REMCTL_RES_NAME, + le_remctl_internal); /* Do the work. */ error = remctl_error(r); - RETURN_STRING((char *) error, 1); + RETURN_STRING((char *) error); } @@ -515,7 +510,6 @@ ZEND_FUNCTION(remctl_error) */ ZEND_FUNCTION(remctl_close) { - struct remctl *r; zval *zrem; int status; @@ -525,10 +519,8 @@ ZEND_FUNCTION(remctl_close) zend_error(E_WARNING, "remctl_error: invalid parameters\n"); RETURN_NULL(); } - ZEND_FETCH_RESOURCE(r, struct remctl *, &zrem, -1, PHP_REMCTL_RES_NAME, - le_remctl_internal); /* This delete invokes php_remctl_dtor, which calls remctl_close. */ - zend_list_delete(Z_LVAL_P(zrem)); + zend_list_delete(Z_RES_P(zrem)); RETURN_TRUE; } |