From: Sterling Hughes Date: Sun, 20 Aug 2000 10:31:27 +0000 (+0000) Subject: A Whole buncha stuff, mostly bug fixing... X-Git-Tag: php-4.0.2RC1~35 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f75db1e3cbbdf5b5e7101dc393627f5241b41490;p=php A Whole buncha stuff, mostly bug fixing... - Make constants case-sensitive, conforming with the rest of PHP & the C API. - Make module compatible with thread safety features. - open_listen_sok() -> open_listen_sock() - Remove ext_skel comments - Get rid of the ZVAL macro and replace with the correct Z_*_* macros - declare all functions local to the file as static. - Remove empty PHP_MSHUTDOWN() function. - Removed confirm_sockets_compiled() - Changed RETVAL_* macro's to RETURN_* macro's eliminating errors with incorrect return values and a potential leak/crash or two. - functions that return void, actually return void - Replaced 'long' in the prototypes with 'int' - Fixed fd_zero() function, it gave a WRONG_PARAM_COUNT when you gave it the proper parameter count. - Changed the way an arbitrary number of parameters were accessed from build_iovec() to use the Zend API. - Added socketpair() and shutdown() functions. --- diff --git a/ext/sockets/php_sockets.h b/ext/sockets/php_sockets.h index 832ad01d7d..ba968b5195 100644 --- a/ext/sockets/php_sockets.h +++ b/ext/sockets/php_sockets.h @@ -12,8 +12,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: | - | | + | Authors: Chris Vandomelen | +----------------------------------------------------------------------+ */ @@ -22,9 +21,6 @@ /* $Id$ */ -/* You should tweak config.m4 so this symbol (or some else suitable) - gets defined. -*/ #if HAVE_SOCKETS extern zend_module_entry sockets_module_entry; @@ -37,12 +33,8 @@ extern zend_module_entry sockets_module_entry; #endif PHP_MINIT_FUNCTION(sockets); -PHP_MSHUTDOWN_FUNCTION(sockets); -PHP_RINIT_FUNCTION(sockets); -PHP_RSHUTDOWN_FUNCTION(sockets); PHP_MINFO_FUNCTION(sockets); -PHP_FUNCTION(confirm_sockets_compiled); PHP_FUNCTION(fd_alloc); PHP_FUNCTION(fd_dealloc); PHP_FUNCTION(fd_set); @@ -50,7 +42,7 @@ PHP_FUNCTION(fd_isset); PHP_FUNCTION(fd_clear); PHP_FUNCTION(fd_zero); PHP_FUNCTION(select); -PHP_FUNCTION(open_listen_sok); +PHP_FUNCTION(open_listen_sock); PHP_FUNCTION(accept_connect); PHP_FUNCTION(set_nonblock); PHP_FUNCTION(listen); @@ -79,29 +71,23 @@ PHP_FUNCTION(readv); PHP_FUNCTION(writev); PHP_FUNCTION(getsockopt); PHP_FUNCTION(setsockopt); +PHP_FUNCTION(socketpair); +PHP_FUNCTION(shutdown); + +typedef struct php_iovec { + struct iovec *iov_array; + unsigned int count; +} php_iovec_t; -/* Fill in this structure and use entries in it - for thread safety instead of using true globals. -*/ typedef struct { - /* You can use the next one as type if your module registers any - resources. Oh, you can of course rename it to something more - suitable, add list entry types or remove it if it not needed. - It's just an example. - */ - int le_sockets; + int le_destroy; + int le_iov; } php_sockets_globals; -/* In every function that needs to use variables in php_sockets_globals, - do call SOCKETSLS_FETCH(); after declaring other variables used by - that function, and always refer to them as SOCKETSG(variable). - You are encouraged to rename these macros something shorter, see - examples in any other php module directory. -*/ #ifdef ZTS #define SOCKETSG(v) (sockets_globals->v) -#define SOCKETSLS_FETCH() php_sockets_globals *sockets_globals = ts_resource(gd_sockets_id) +#define SOCKETSLS_FETCH() php_sockets_globals *sockets_globals = ts_resource(sockets_global_id) #else #define SOCKETSG(v) (sockets_globals.v) #define SOCKETSLS_FETCH() diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index bf6acf9cb6..759f2c7b0e 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -12,18 +12,20 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: | - | Chris Vandomelen | + | Authors: Chris Vandomelen | + | Sterling Hughes | +----------------------------------------------------------------------+ */ /* $Id$ */ #include "php.h" -#include "php_ini.h" -#include "php_sockets.h" -#include "../standard/info.h" + +#if HAVE_SOCKETS + +#include "ext/standard/info.h" +#include "php_sockets.h" #include #include @@ -39,24 +41,14 @@ #include #include -/* You should tweak config.m4 so this symbol (or some else suitable) - gets defined. - */ -#if HAVE_SOCKETS - #ifdef ZTS int sockets_globals_id; - #else php_sockets_globals sockets_globals; - #endif -#define ZVAL(arg, type) ((*(arg))->value.type) - /* Perform convert_to_long_ex on a list of items */ - -void v_convert_to_long_ex(int items,...) +static void v_convert_to_long_ex(int items,...) { va_list ap; zval **arg; @@ -71,7 +63,8 @@ void v_convert_to_long_ex(int items,...) va_end(ap); } -/* *INDENT-OFF* */ + + static unsigned char second_and_third_args_force_ref[] = {3, BYREF_NONE, BYREF_FORCE, BYREF_FORCE}; @@ -84,11 +77,7 @@ static unsigned char fourth_arg_force_ref[] = static unsigned char third_through_seventh_args_force_ref[] = {7, BYREF_NONE, BYREF_NONE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE}; -/* Every user visible function must have an entry in sockets_functions[]. - */ -function_entry sockets_functions[] = -{ - PHP_FE(confirm_sockets_compiled, NULL) /* For testing, remove later. */ +function_entry sockets_functions[] = { PHP_FE(fd_alloc, NULL) /* OK */ PHP_FE(fd_dealloc, NULL) /* OK */ PHP_FE(fd_set, NULL) /* OK */ @@ -96,7 +85,7 @@ function_entry sockets_functions[] = PHP_FE(fd_clear, NULL) /* OK */ PHP_FE(fd_zero, NULL) /* OK */ PHP_FE(select, NULL) /* OK */ - PHP_FE(open_listen_sok, NULL) /* OK */ + PHP_FE(open_listen_sock, NULL) /* OK */ PHP_FE(accept_connect, NULL) /* OK */ PHP_FE(set_nonblock, NULL) /* OK */ PHP_FE(listen, NULL) /* OK */ @@ -104,11 +93,17 @@ function_entry sockets_functions[] = PHP_FE(write, NULL) /* OK */ PHP_FE(read, second_arg_force_ref) /* OK */ #if 0 -/* If and when asynchronous context switching is avaliable, this will work. Otherwise, forget it. */ +/* + * If and when asynchronous context switching is avaliable, + * this will work. Otherwise, forget it. + */ PHP_FE(signal, NULL) #endif #if 0 -/* These are defined elsewhere.. would these be more appropriate? */ +/* + * These are defined elsewhere.. + * would these be more appropriate? + */ PHP_FE(gethostbyname, second_arg_force_ref) /* OK */ PHP_FE(gethostbyaddr, second_arg_force_ref) /* OK */ #endif @@ -126,7 +121,7 @@ function_entry sockets_functions[] = PHP_FE(fetch_iovec, NULL) PHP_FE(free_iovec, NULL) PHP_FE(add_iovec, NULL) - PHP_FE(delete_iovec, NULL) + PHP_FE(delete_iovec, NULL) PHP_FE(set_iovec, NULL) PHP_FE(recvmsg, third_through_seventh_args_force_ref) PHP_FE(sendmsg, NULL) @@ -134,49 +129,36 @@ function_entry sockets_functions[] = PHP_FE(writev, NULL) PHP_FE(getsockopt, fourth_arg_force_ref) PHP_FE(setsockopt, NULL) - {NULL, NULL, NULL} /* Must be the last line in sockets_functions[] */ + PHP_FE(socketpair, NULL) + PHP_FE(shutdown, NULL) + {NULL, NULL, NULL} }; -/* *INDENT-ON* */ - - - - -zend_module_entry sockets_module_entry = -{ +zend_module_entry sockets_module_entry = { "sockets", sockets_functions, PHP_MINIT(sockets), - PHP_MSHUTDOWN(sockets), + NULL, NULL, NULL, PHP_MINFO(sockets), STANDARD_MODULE_PROPERTIES }; -int le_destroy; -int le_iov; - #ifdef COMPILE_DL_SOCKETS ZEND_GET_MODULE(sockets) #endif -/* Remove comments and fill if you need to have entries in php.ini - PHP_INI_BEGIN() - PHP_INI_END() - */ +static void destroy_fd_sets(fd_set *set); +static void destroy_iovec(php_iovec_t *iov); -typedef struct php_iovec { - struct iovec *iov_array; - unsigned int count; -} php_iovec_t; -static void destroy_fd_sets(fd_set * set) +static void destroy_fd_sets(fd_set *set) { efree(set); } -static void destroy_iovec(php_iovec_t * iov) +static void destroy_iovec(php_iovec_t *iov) { int i; @@ -192,54 +174,51 @@ static void destroy_iovec(php_iovec_t * iov) PHP_MINIT_FUNCTION(sockets) { -/* Remove comments if you have entries in php.ini - REGISTER_INI_ENTRIES(); - */ - le_destroy = register_list_destructors(destroy_fd_sets, NULL); - le_iov = register_list_destructors(destroy_iovec, NULL); - - REGISTER_LONG_CONSTANT("AF_UNIX", AF_UNIX, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("AF_INET", AF_INET, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SOCK_STREAM", SOCK_STREAM, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SOCK_DGRAM", SOCK_DGRAM, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SOCK_RAW", SOCK_RAW, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SOCK_SEQPACKET", SOCK_SEQPACKET, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SOCK_RDM", SOCK_RDM, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MSG_OOB", MSG_OOB, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MSG_WAITALL", MSG_WAITALL, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MSG_PEEK", MSG_PEEK, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("MSG_DONTROUTE", MSG_DONTROUTE, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_DEBUG", SO_DEBUG, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_REUSEADDR", SO_REUSEADDR, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_KEEPALIVE", SO_KEEPALIVE, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_DONTROUTE", SO_DONTROUTE, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_LINGER", SO_LINGER, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_BROADCAST", SO_BROADCAST, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_OOBINLINE", SO_OOBINLINE, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_SNDBUF", SO_SNDBUF, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_RCVBUF", SO_RCVBUF, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_SNDLOWAT", SO_SNDLOWAT, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_RCVLOWAT", SO_RCVLOWAT, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_SNDTIMEO", SO_SNDTIMEO, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_RCVTIMEO", SO_RCVTIMEO, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_TYPE", SO_TYPE, CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SO_ERROR", SO_ERROR, CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("SOL_SOCKET", SOL_SOCKET, CONST_PERSISTENT); + SOCKETSLS_FETCH(); + SOCKETSG(le_destroy) = register_list_destructors(destroy_fd_sets, NULL); + SOCKETSG(le_iov) = register_list_destructors(destroy_iovec, NULL); + + REGISTER_LONG_CONSTANT("AF_UNIX", AF_UNIX, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("AF_INET", AF_INET, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOCK_STREAM", SOCK_STREAM, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOCK_DGRAM", SOCK_DGRAM, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOCK_RAW", SOCK_RAW, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOCK_SEQPACKET", SOCK_SEQPACKET, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOCK_RDM", SOCK_RDM, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MSG_OOB", MSG_OOB, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MSG_WAITALL", MSG_WAITALL, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MSG_PEEK", MSG_PEEK, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MSG_DONTROUTE", MSG_DONTROUTE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_DEBUG", SO_DEBUG, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_REUSEADDR", SO_REUSEADDR, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_KEEPALIVE", SO_KEEPALIVE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_DONTROUTE", SO_DONTROUTE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_LINGER", SO_LINGER, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_BROADCAST", SO_BROADCAST, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_OOBINLINE", SO_OOBINLINE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_SNDBUF", SO_SNDBUF, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_RCVBUF", SO_RCVBUF, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_SNDLOWAT", SO_SNDLOWAT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_RCVLOWAT", SO_RCVLOWAT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_SNDTIMEO", SO_SNDTIMEO, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_RCVTIMEO", SO_RCVTIMEO, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_TYPE", SO_TYPE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SO_ERROR", SO_ERROR, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOL_SOCKET", SOL_SOCKET, CONST_CS | CONST_PERSISTENT); + { struct protoent *pe; pe = getprotobyname("tcp"); - if (pe) - REGISTER_LONG_CONSTANT("SOL_TCP", pe->p_proto, CONST_PERSISTENT); + if (pe) { + REGISTER_LONG_CONSTANT("SOL_TCP", pe->p_proto, CONST_CS | CONST_PERSISTENT); + } + pe = getprotobyname("udp"); - if (pe) - REGISTER_LONG_CONSTANT("SOL_UDP", pe->p_proto, CONST_PERSISTENT); + if (pe) { + REGISTER_LONG_CONSTANT("SOL_UDP", pe->p_proto, CONST_CS | CONST_PERSISTENT); + } } - return SUCCESS; -} - -PHP_MSHUTDOWN_FUNCTION(sockets) -{ + return SUCCESS; } @@ -248,53 +227,22 @@ PHP_MINFO_FUNCTION(sockets) php_info_print_table_start(); php_info_print_table_header(2, "sockets support", "enabled"); php_info_print_table_end(); - - /* Remove comments if you have entries in php.ini - DISPLAY_INI_ENTRIES(); - */ -} - -/* Remove the following function when you have succesfully modified config.m4 - so that your module can be compiled into PHP, it exists only for testing - purposes. */ - -/* Every user-visible function in PHP should document itself in the source */ -/* {{{ proto string confirm_sockets_compiled(string arg) - Return a string to confirm that the module is compiled in */ -PHP_FUNCTION(confirm_sockets_compiled) -{ - zval **arg; - int len; - char string[256]; - - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) { - WRONG_PARAM_COUNT; - } - convert_to_string_ex(arg); - - len = sprintf(string, "Congratulations, you have successfully modified ext/sockets/config.m4, module %s is compiled in PHP", Z_STRVAL_PP(arg)); - RETVAL_STRINGL(string, len, 1); } -/* }}} */ -/* The previous line is meant for emacs, so it can correctly fold and unfold - functions in source code. See the corresponding marks just before function - definition, where the functions purpose is also documented. Please follow - this convention for the convenience of others editing your code. - */ /* {{{ proto resource fd_alloc(void) Allocate a file descriptor set */ PHP_FUNCTION(fd_alloc) { fd_set *set; - int ret; + SOCKETSLS_FETCH(); - set = emalloc(sizeof(fd_set)); + set = (fd_set *)emalloc(sizeof(fd_set)); if (!set) { - zend_error(E_ERROR, "Can't allocate memory for fd_set"); - RETVAL_FALSE; + php_error(E_WARNING, "Can't allocate memory for fd_set"); + RETURN_FALSE; } - ret = ZEND_REGISTER_RESOURCE(return_value, set, le_destroy); + + ZEND_REGISTER_RESOURCE(return_value, set, SOCKETSG(le_destroy)); } /* }}} */ @@ -303,30 +251,29 @@ PHP_FUNCTION(fd_alloc) /* ** BUG: This is currently a no-op! */ PHP_FUNCTION(fd_dealloc) { - RETVAL_TRUE; + RETURN_NULL(); } /* }}} */ -/* {{{ proto bool fd_set(long fd, resource set) +/* {{{ proto bool fd_set(int fd, resource set) Add a file descriptor to a set */ PHP_FUNCTION(fd_set) { zval **set, **fd; fd_set *the_set; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &fd, &set) == FAILURE) { + if (ZEND_NUM_ARGS() != 2 || + zend_get_parameters_ex(2, &fd, &set) == FAILURE) { WRONG_PARAM_COUNT; } - v_convert_to_long_ex(2, set, fd); + convert_to_long_ex(fd); - if ((*set)->type != IS_RESOURCE) { - (*set)->type = IS_RESOURCE; - } - ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", le_destroy); + ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", SOCKETSG(le_destroy)); - FD_SET((*fd)->value.lval, the_set); + FD_SET(Z_LVAL_PP(fd), the_set); - RETVAL_TRUE; + RETURN_TRUE; } /* }}} */ @@ -336,19 +283,19 @@ PHP_FUNCTION(fd_clear) { zval **set, **fd; fd_set *the_set; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &fd, &set) == FAILURE) { + if (ZEND_NUM_ARGS() != 2 || + zend_get_parameters_ex(2, &fd, &set) == FAILURE) { WRONG_PARAM_COUNT; } - v_convert_to_long_ex(2, set, fd); - - (*set)->type = IS_RESOURCE; + convert_to_long_ex(fd); - ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", le_destroy); + ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", SOCKETSG(le_destroy)); - FD_CLR((*fd)->value.lval, the_set); + FD_CLR(Z_LVAL_PP(fd), the_set); - RETVAL_TRUE; + RETURN_TRUE; } /* }}} */ @@ -358,20 +305,21 @@ PHP_FUNCTION(fd_isset) { zval **set, **fd; fd_set *the_set; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &fd, &set) == FAILURE) { + if (ZEND_NUM_ARGS() != 2 || + zend_get_parameters_ex(2, &fd, &set) == FAILURE) { WRONG_PARAM_COUNT; } - v_convert_to_long_ex(2, set, fd); - - (*set)->type = IS_RESOURCE; + convert_to_long_ex(fd); - ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", le_destroy); + ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", SOCKETSG(le_destroy)); - if (FD_ISSET((*fd)->value.lval, the_set)) { - RETVAL_TRUE; + if (FD_ISSET(Z_LVAL_PP(fd), the_set)) { + RETURN_TRUE; } - RETVAL_FALSE; + + RETURN_FALSE; } /* }}} */ @@ -381,19 +329,18 @@ PHP_FUNCTION(fd_zero) { zval **set; fd_set *the_set; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(2, &set) == FAILURE) { + if (ZEND_NUM_ARGS() != 1 || + zend_get_parameters_ex(1, &set) == FAILURE) { WRONG_PARAM_COUNT; } - convert_to_long_ex(set); - (*set)->type = IS_RESOURCE; - - ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", le_destroy); + ZEND_FETCH_RESOURCE(the_set, fd_set *, set, -1, "File descriptor set", SOCKETSG(le_destroy)); FD_ZERO(the_set); - RETVAL_TRUE; + RETURN_TRUE; } /* }}} */ @@ -417,57 +364,48 @@ PHP_FUNCTION(fd_zero) PHP_FUNCTION(select) { - zval **max_fd, **readfds, **writefds, **exceptfds, **tv_sec, - **tv_usec; + zval **max_fd, **readfds, **writefds, + **exceptfds, **tv_sec, **tv_usec; + struct timeval tv; fd_set *rfds, *wfds, *xfds; int ret = 0; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_ex(6, &max_fd, &readfds, &writefds, &exceptfds, - &tv_sec, &tv_usec) == FAILURE) { + if (ZEND_NUM_ARGS() != 6 || + zend_get_parameters_ex(6, &max_fd, &readfds, &writefds, &exceptfds, &tv_sec, &tv_usec) == FAILURE) { WRONG_PARAM_COUNT; } - v_convert_to_long_ex(6, max_fd, readfds, writefds, exceptfds, tv_sec, tv_usec); - - tv.tv_sec = ZVAL(tv_sec, lval); - tv.tv_usec = ZVAL(tv_usec, lval); + v_convert_to_long_ex(3, max_fd, tv_sec, tv_usec); - (*readfds)->type = IS_RESOURCE; - (*writefds)->type = IS_RESOURCE; - (*exceptfds)->type = IS_RESOURCE; + tv.tv_sec = Z_LVAL_PP(tv_sec); + tv.tv_usec = Z_LVAL_PP(tv_usec); - if (ZVAL(readfds, lval) == 0) { - rfds = NULL; + if (Z_LVAL_PP(readfds) != 0) { + ZEND_FETCH_RESOURCE(rfds, fd_set *, readfds, -1, "File descriptor set", SOCKETSG(le_destroy)); } else { - ZEND_FETCH_RESOURCE(rfds, fd_set *, readfds, -1, "File descriptor set", le_destroy); + rfds = NULL; } - - if (ZVAL(writefds, lval) == 0) { - wfds = NULL; + + if (Z_LVAL_PP(writefds) != 0) { + ZEND_FETCH_RESOURCE(wfds, fd_set *, writefds, -1, "File descriptor set", SOCKETSG(le_destroy)); } else { - ZEND_FETCH_RESOURCE(wfds, fd_set *, writefds, -1, "File descriptor set", le_destroy); + wfds = NULL; } - - if (ZVAL(exceptfds, lval) == 0) { - xfds = NULL; + + if (Z_LVAL_PP(exceptfds) != 0) { + ZEND_FETCH_RESOURCE(xfds, fd_set *, exceptfds, -1, "File descriptor set", SOCKETSG(le_destroy)); } else { - ZEND_FETCH_RESOURCE(xfds, fd_set *, exceptfds, -1, "File descriptor set", le_destroy); + xfds = NULL; } - ret = select(ZVAL(max_fd, lval), rfds, wfds, xfds, &tv); + ret = select(Z_LVAL_PP(max_fd), rfds, wfds, xfds, &tv); - if (ret < 0) { - RETVAL_LONG(-errno); - } else { - RETVAL_LONG(ret); - } + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto long open_listen_sok(long port) - Opens a socket on port to accept connections */ - -int open_listen_sok(int port) +static int open_listen_sock(int port) { int fd; struct sockaddr_in la; @@ -476,96 +414,91 @@ int open_listen_sok(int port) if ((hp = gethostbyname("0.0.0.0")) == NULL) { return -1; } - bcopy(hp->h_addr, (char *) &la.sin_addr, hp->h_length); + + bcopy(hp->h_addr, (char *)&la.sin_addr, hp->h_length); la.sin_family = hp->h_addrtype; la.sin_port = htons(port); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { return -1; } - if ((bind(fd, (struct sockaddr *) &la, sizeof(la)) < 0)) { + if ((bind(fd, (struct sockaddr *)&la, sizeof(la)) < 0)) { return -1; } listen(fd, 128); return fd; } -PHP_FUNCTION(open_listen_sok) +/* {{{ proto long open_listen_sock(long port) + Opens a socket on port to accept connections */ +PHP_FUNCTION(open_listen_sock) { zval **port; int ret; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &port) == FAILURE) { + if (ZEND_NUM_ARGS() != 1 || + zend_get_parameters_ex(1, &port) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long_ex(port); - ret = open_listen_sok(ZVAL(port, lval)); + ret = open_listen_sock(Z_LVAL_PP(port)); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto int accept_connect(long fd) - Accepts a connection on the listening socket fd */ -int accept_connect(int fd, struct sockaddr *la) +static int accept_connect(int fd, struct sockaddr *la) { - int foo, m; + int ret, m; m = sizeof(*la); - if ((foo = accept(fd, la, &m)) < 0) { + if ((ret = accept(fd, la, &m)) < 0) { return -1; } - return foo; + return ret; } +/* {{{ proto int accept_connect(int fd) + Accepts a connection on the listening socket fd */ PHP_FUNCTION(accept_connect) { zval **fd; int ret; struct sockaddr_in sa; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &fd) == FAILURE) { + if (ZEND_NUM_ARGS() != 1 || + zend_get_parameters_ex(1, &fd) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long_ex(fd); - ret = accept_connect(ZVAL(fd, lval), (struct sockaddr *) &sa); - - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } + ret = accept_connect(Z_LVAL_PP(fd), (struct sockaddr *)&sa); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto bool set_nonblock(long fd) +/* {{{ proto bool set_nonblock(int fd) Sets nonblocking mode for file descriptor fd */ PHP_FUNCTION(set_nonblock) { zval **fd; int ret; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &fd) == FAILURE) { + if (ZEND_NUM_ARGS() != 1 || + zend_get_parameters_ex(1, &fd) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_long_ex(fd); - ret = fcntl(ZVAL(fd, lval), F_SETFL, O_NONBLOCK); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } + ret = fcntl(Z_LVAL_PP(fd), F_SETFL, O_NONBLOCK); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto bool listen(long fd, long backlog) +/* {{{ proto bool listen(int fd, int backlog) Sets the maximum number of connections allowed to be waited for on the socket specified by fd */ PHP_FUNCTION(listen) { @@ -577,93 +510,94 @@ PHP_FUNCTION(listen) } v_convert_to_long_ex(2, fd, backlog); - ret = listen(ZVAL(fd, lval), ZVAL(backlog, lval)); - - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } + ret = listen(Z_LVAL_PP(fd), Z_LVAL_PP(backlog)); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto bool close(long fd) +/* {{{ proto bool close(int fd) Close a file descriptor */ PHP_FUNCTION(close) { - zval **arg; + zval **fd; int ret; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) { + if (ZEND_NUM_ARGS() != 1 || + zend_get_parameters_ex(1, &fd) == FAILURE) { WRONG_PARAM_COUNT; } - convert_to_long_ex(arg); - ret = close(ZVAL(arg, lval)); - + convert_to_long_ex(fd); + ret = close(Z_LVAL_PP(fd)); + if (ret == -1) { - zend_error(E_WARNING, "Invalid file descriptor"); - RETVAL_FALSE; + php_error(E_WARNING, "Invalid file descriptor"); + RETURN_FALSE; } - RETVAL_TRUE; + RETURN_TRUE; } /* }}} */ -/* {{{ proto long write(long fd, string buf, long length) +/* {{{ proto int write(int fd, string buf, int length) Writes length bytes of buf to the file descriptor fd */ PHP_FUNCTION(write) { zval **fd, **buf, **length; int ret; - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &fd, &buf, &length) == FAILURE) { + if (ZEND_NUM_ARGS() != 3 || + zend_get_parameters_ex(3, &fd, &buf, &length) == FAILURE) { WRONG_PARAM_COUNT; } + v_convert_to_long_ex(2, fd, length); convert_to_string_ex(buf); - if (ZVAL(buf, str.len) < ZVAL(length, lval)) { - ret = write(ZVAL(fd, lval), (void *) ZVAL(buf, str.val), ZVAL(buf, str.len)); + if (Z_STRLEN_PP(buf) < Z_LVAL_PP(length)) { + ret = write(Z_LVAL_PP(fd), (void *)Z_STRVAL_PP(buf), Z_STRLEN_PP(buf)); } else { - ret = write(ZVAL(fd, lval), (void *) ZVAL(buf, str.val), ZVAL(length, lval)); - } - - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); + ret = write(Z_LVAL_PP(fd), (void *)Z_STRVAL_PP(buf), Z_LVAL_PP(length)); } + + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto long read(long fd, string &buf, long length) +/* {{{ proto int read(int fd, string &buf, int length) Reads length bytes from fd into buf */ PHP_FUNCTION(read) { zval **fd, **buf, **length; - char *tmp; + char *tmpbuf; int ret; - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &fd, &buf, &length) == FAILURE) { + if (ZEND_NUM_ARGS() != 3 || + zend_get_parameters_ex(3, &fd, &buf, &length) == FAILURE) { WRONG_PARAM_COUNT; } v_convert_to_long_ex(2, fd, length); convert_to_string_ex(buf); - tmp = emalloc(ZVAL(length, lval)); - ret = read(ZVAL(fd, lval), tmp, ZVAL(length, lval)); - - if (ret < 0) { - RETURN_LONG(-errno); - } else { - ZVAL(buf, str.val) = tmp; - ZVAL(buf, str.len) = ret; - + tmpbuf = emalloc(Z_LVAL_PP(length)*sizeof(char)); + if (tmpbuf == NULL) { + php_error(E_WARNING, "Couldn't allocate memory from %s()", get_active_function_name()); + RETURN_FALSE; + } + + ret = read(Z_LVAL_PP(fd), tmpbuf, Z_LVAL_PP(length)); + + if (ret >= 0) { + Z_STRVAL_PP(buf) = tmpbuf; + Z_STRLEN_PP(buf) = ret; + RETURN_LONG(ret); + } else { + RETURN_LONG(-errno); } } /* }}} */ -/* {{{ proto long getsockname(long fd, string &addr, long &port) +/* {{{ proto int getsockname(int fd, string &addr, int &port) Given an fd, stores a string representing sa.sin_addr and the value of sa.sin_port into addr and port describing the local side of a socket */ /* A lock to prevent inet_ntoa() from causing problems in threading */ @@ -677,13 +611,14 @@ PHP_FUNCTION(getsockname) int salen = sizeof(struct sockaddr_in); int ret; - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &fd, &addr, &port) == FAILURE) { + if (ZEND_NUM_ARGS() != 3 || + zend_get_parameters_ex(3, &fd, &addr, &port) == FAILURE) { WRONG_PARAM_COUNT; } v_convert_to_long_ex(2, fd, port); convert_to_string_ex(addr); - ret = getsockname(ZVAL(fd, lval), &sa, &salen); + ret = getsockname(Z_LVAL_PP(fd), &sa, &salen); if (ret < 0) { RETURN_LONG(-errno); } else { @@ -696,10 +631,10 @@ PHP_FUNCTION(getsockname) bzero(tmp, strlen(addr_string) + 1); strncpy(tmp, addr_string, strlen(addr_string)); inet_ntoa_lock = 0; - - ZVAL(addr, str.val) = tmp; - ZVAL(addr, str.len) = strlen(tmp); - ZVAL(port, lval) = htons(sa.sin_port); + + Z_STRVAL_PP(addr) = tmp; + Z_STRLEN_PP(addr) = strlen(tmp); + Z_LVAL_PP(port) = htons(sa.sin_port); RETURN_LONG(ret); } @@ -707,7 +642,7 @@ PHP_FUNCTION(getsockname) /* }}} */ #if 0 -/* {{{ proto long gethostbyname(string name, string &addr) +/* {{{ proto int gethostbyname(string name, string &addr) Given a hostname, sets addr to be a human-readable version of the host's address */ /* Another lock to prevent multiple threads from grabbing gethostbyname() */ @@ -720,7 +655,8 @@ PHP_FUNCTION(gethostbyname) char *tmp, *addr_string; struct hostent *host_struct; - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &name, &addr) == FAILURE) { + if (ZEND_NUM_ARGS() != 2 || + zend_get_parameters_ex(2, &name, &addr) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(name); @@ -729,7 +665,7 @@ PHP_FUNCTION(gethostbyname) while (gethostbyname_lock == 1); gethostbyname_lock = 1; - host_struct = gethostbyname(ZVAL(name, str.val)); + host_struct = gethostbyname(Z_STRVAL_PP(name)); if (!host_struct) { gethostbyname_lock = 0; RETURN_LONG(-(h_errno) - 10000); /* return a value that is out of range for errno */ @@ -748,9 +684,9 @@ PHP_FUNCTION(gethostbyname) inet_ntoa_lock = 0; gethostbyname_lock = 0; - ZVAL(addr, str.val) = tmp; - ZVAL(addr, str.len) = strlen(tmp); - + Z_STRVAL_PP(addr) = tmp; + Z_STRLEN_PP(addr) = strlen(tmp); + RETURN_LONG(0); } @@ -769,13 +705,15 @@ PHP_FUNCTION(getpeername) int salen = sizeof(struct sockaddr_in); int ret; - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &fd, &addr, &port) == FAILURE) { + if (ZEND_NUM_ARGS() != 3 || + zend_get_parameters_ex(3, &fd, &addr, &port) == FAILURE) { WRONG_PARAM_COUNT; } v_convert_to_long_ex(2, fd, port); convert_to_string_ex(addr); - ret = getpeername(ZVAL(fd, lval), &sa, &salen); + ret = getpeername(Z_LVAL_PP(fd), &sa, &salen); + if (ret < 0) { RETURN_LONG(-errno); } else { @@ -788,10 +726,10 @@ PHP_FUNCTION(getpeername) bzero(tmp, strlen(addr_string) + 1); strncpy(tmp, addr_string, strlen(addr_string)); inet_ntoa_lock = 0; - - ZVAL(addr, str.val) = tmp; - ZVAL(addr, str.len) = strlen(tmp); - ZVAL(port, lval) = htons(sa.sin_port); + + Z_STRVAL_PP(addr) = tmp; + Z_STRLEN_PP(addr) = strlen(tmp); + Z_LVAL_PP(addr) = htons(sa.sin_port); RETURN_LONG(ret); } @@ -799,7 +737,7 @@ PHP_FUNCTION(getpeername) /* }}} */ #if 0 -/* {{{ proto long gethostbyaddr(string addr, string &name) +/* {{{ proto int gethostbyaddr(string addr, string &name) Given a human-readable address, sets name to be the host's name */ /* Another lock to prevent multiple threads from grabbing gethostbyname() */ @@ -813,20 +751,24 @@ PHP_FUNCTION(gethostbyaddr) struct hostent *host_struct; struct in_addr addr_buf; - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &addr, &name) == FAILURE) { + if (ZEND_NUM_ARGS() != 2 || + zend_get_parameters_ex(2, &addr, &name) == FAILURE) { WRONG_PARAM_COUNT; } - convert_to_string_ex(name); convert_to_string_ex(addr); + convert_to_string_ex(name); - ret = inet_aton(ZVAL(addr, str.val), &addr_buf); + ret = inet_aton(Z_STRVAL_PP(addr), &addr_buf); + if (ret < 0) { RETURN_LONG(-EINVAL); } + while (gethostbyaddr_lock == 1); gethostbyaddr_lock = 1; - host_struct = gethostbyname((char *) &addr_buf, sizeof(addr_buf), AF_INET); + host_struct = gethostbyname((char *)&addr_buf, sizeof(addr_buf), AF_INET); + if (!host_struct) { gethostbyaddr_lock = 0; RETURN_LONG(-(h_errno) - 10000); @@ -835,14 +777,15 @@ PHP_FUNCTION(gethostbyaddr) gethostbyaddr_lock = 0; RETURN_LONG(-EINVAL); } + addr_string = host_struct->h_name; tmp = emalloc(strlen(addr_string) + 1); strncpy(tmp, addr_string, strlen(addr_string)); gethostbyaddr_lock = 0; - ZVAL(addr, str.val) = tmp; - ZVAL(addr, str.len) = strlen(tmp); + Z_STRVAL_PP(addr) = tmp; + Z_STRLEN_PP(addr) = strlen(tmp); RETURN_LONG(0); } @@ -850,36 +793,36 @@ PHP_FUNCTION(gethostbyaddr) #endif -/* {{{ proto long socket(long domain, long type, long protocol) +/* {{{ proto int socket(int domain, int type, int protocol) Creates an endpoint for communication in the domain specified by domain, of type specified by type */ PHP_FUNCTION(socket) { zval **domain, **type, **protocol; int ret; - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &domain, &type, &protocol) == FAILURE) { + if (ZEND_NUM_ARGS() != 3 || + zend_get_parameters_ex(3, &domain, &type, &protocol) == FAILURE) { WRONG_PARAM_COUNT; } v_convert_to_long_ex(3, domain, type, protocol); - if (ZVAL(domain, lval) != AF_INET && ZVAL(domain, lval) != AF_UNIX) { - zend_error(E_WARNING, "invalid socket domain specified - assuming AF_INET"); - ZVAL(domain, lval) = AF_INET; + if (Z_LVAL_PP(domain) != AF_INET && Z_LVAL_PP(domain) != AF_UNIX) { + php_error(E_WARNING, "invalid socket domain specified - assuming AF_INET"); + Z_LVAL_PP(domain) = AF_INET; } - if (ZVAL(type, lval) > 10) { - zend_error(E_WARNING, "invalid socket type specified - assuming SOCK_STREAM"); - ZVAL(type, lval) = SOCK_STREAM; - } - ret = socket(ZVAL(domain, lval), ZVAL(type, lval), ZVAL(protocol, lval)); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); + + if (Z_LVAL_PP(type) > 10) { + php_error(E_WARNING, "invalid socket type specified - assuming SOCK_STREAM"); + Z_LVAL_PP(type) = SOCK_STREAM; } + + ret = socket(Z_LVAL_PP(domain), Z_LVAL_PP(type), Z_LVAL_PP(protocol)); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto long connect(long sockfd, string addr, long port) +/* {{{ proto int connect(int sockfd, string addr, int port) Opens a connection to addr:port on the socket specified by sockfd */ PHP_FUNCTION(connect) { @@ -890,35 +833,33 @@ PHP_FUNCTION(connect) struct in_addr addr_buf; struct hostent *host_struct; - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &sockfd, &addr, &port) == FAILURE) { + if (ZEND_NUM_ARGS() != 3 || + zend_get_parameters_ex(3, &sockfd, &addr, &port) == FAILURE) { WRONG_PARAM_COUNT; } v_convert_to_long_ex(2, sockfd, port); convert_to_string_ex(addr); bzero(&sa, sizeof(sa)); - sa.sin_port = ZVAL(port, lval); + sa.sin_port = Z_LVAL_PP(port); - if (inet_aton(ZVAL(addr, str.val), &addr_buf) == 0) { + if (inet_aton(Z_STRVAL_PP(addr), &addr_buf) == 0) { sa.sin_addr.s_addr = addr_buf.s_addr; } else { - host_struct = gethostbyname(ZVAL(addr, str.val)); + host_struct = gethostbyname(Z_STRVAL_PP(addr)); if (host_struct->h_addrtype != AF_INET) { RETURN_LONG(-EINVAL); } sa.sin_addr.s_addr = (int) *(host_struct->h_addr_list[0]); } - ret = connect(ZVAL(sockfd, lval), (struct sockaddr *) &sa, salen); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } + ret = connect(Z_LVAL_PP(sockfd), (struct sockaddr *)&sa, salen); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto string strerror(long errno) +/* {{{ proto string strerror(int errno) Returns a string describing an error */ PHP_FUNCTION(strerror) { @@ -926,24 +867,22 @@ PHP_FUNCTION(strerror) const char *buf; char *obuf; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &error) == FAILURE) { + if (ZEND_NUM_ARGS() != 1 || + zend_get_parameters_ex(1, &error) == FAILURE) { WRONG_PARAM_COUNT; } - if (ZVAL(error, lval) < -10000) { - ZVAL(error, lval) += 10000; - buf = hstrerror(-(ZVAL(error, lval))); + if (Z_LVAL_PP(error) < -10000) { + Z_LVAL_PP(error) += 10000; + buf = hstrerror(-(Z_LVAL_PP(error))); } else { - buf = strerror(-(ZVAL(error, lval))); + buf = strerror(-(Z_LVAL_PP(error))); } - - obuf = estrndup(buf, strlen(buf)); - ZVAL(&return_value, str.val) = obuf; - ZVAL(&return_value, str.len) = strlen(buf); - return_value->type = IS_STRING; + + RETURN_STRING((char *)buf, 1); } /* }}} */ -/* {{{ proto long bind(long sockfd, long addr [, long port]) +/* {{{ proto int bind(int sockfd, string addr [, int port]) Binds an open socket to a listening port */ /* Port is only specified if sockfd is in the AF_INET family. */ PHP_FUNCTION(bind) @@ -952,39 +891,33 @@ PHP_FUNCTION(bind) long ret; struct sockaddr sock_type; socklen_t length = sizeof(sock_type); - - if (ZEND_NUM_ARGS() < 2) { - WRONG_PARAM_COUNT; - } - switch (ZEND_NUM_ARGS()) { - case 2: - if (zend_get_parameters_ex(2, &arg0, &arg1) == FAILURE) { - WRONG_PARAM_COUNT; - } - break; - case 3: - if (zend_get_parameters_ex(3, &arg0, &arg1, &arg2) == FAILURE) { + + switch (ZEND_NUM_ARGS()) + { + case 2: + if (zend_get_parameters_ex(2, &arg0, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 3: + if (zend_get_parameters_ex(3, &arg0, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + default: WRONG_PARAM_COUNT; - } - break; - default: - WRONG_PARAM_COUNT; } convert_to_long_ex(arg0); - ret = getsockname(ZVAL(arg0, lval), &sock_type, &length); + ret = getsockname(Z_LVAL_PP(arg0), &sock_type, &length); if (ret < 0) { RETURN_LONG(-errno); } if (sock_type.sa_family == AF_UNIX) { struct sockaddr_un sa; - - if (ZEND_NUM_ARGS() < 2) { - WRONG_PARAM_COUNT; - } - snprintf(sa.sun_path, 108, "%s", ZVAL(arg1, str.val)); - ret = bind(ZVAL(arg0, lval), &sa, SUN_LEN(&sa)); + snprintf(sa.sun_path, 108, "%s", Z_STRVAL_PP(arg1)); + ret = bind(Z_LVAL_PP(arg0), &sa, SUN_LEN(&sa)); } else if (sock_type.sa_family == AF_INET) { struct sockaddr_in sa; struct in_addr addr_buf; @@ -992,27 +925,27 @@ PHP_FUNCTION(bind) if (ZEND_NUM_ARGS() != 3) { WRONG_PARAM_COUNT; } - sa.sin_port = htons(ZVAL(arg2, lval)); - if (inet_aton(ZVAL(arg1, str.val), &addr_buf) < 0) { - struct hostent *host_struct = gethostbyname(ZVAL(arg1, str.val)); + + sa.sin_port = htons(Z_LVAL_PP(arg2)); + + if (inet_aton(Z_STRVAL_PP(arg1), &addr_buf) < 0) { + struct hostent *host_struct; - if (host_struct == NULL) { + if ((host_struct = gethostbyname(Z_STRVAL_PP(arg1))) == NULL) { RETURN_LONG(-(h_errno) - 10000); } + sa.sin_addr.s_addr = (int) *(host_struct->h_addr_list[0]); } else { sa.sin_addr.s_addr = addr_buf.s_addr; } - ret = bind(ZVAL(arg0, lval), &sa, sizeof(sa)); - } else { - RETURN_LONG(-EPROTONOSUPPORT); - } - if (ret < 0) { - RETURN_LONG(-errno); + ret = bind(Z_LVAL_PP(arg0), &sa, sizeof(sa)); } else { - RETURN_LONG(ret); + RETURN_LONG(-EPROTONOSUPPORT); } + + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ @@ -1024,44 +957,38 @@ PHP_FUNCTION(bind) PHP_FUNCTION(build_iovec) { - zval **num_vectors, **vector_len; + zval ***args = (zval ***)NULL; php_iovec_t *vector; struct iovec *vector_array; - void **p; - int arg_count; - int i; - - ELS_FETCH(); - - if (ZEND_NUM_ARGS() < 1) { + int i, j, num_vectors, argcount = ZEND_NUM_ARGS(); + SOCKETSLS_FETCH(); + + args = emalloc(argcount * sizeof(zval *)); + + if (argcount < 1 || + zend_get_parameters_array_ex(argcount, args) == FAILURE) { + if (args) + efree(args); WRONG_PARAM_COUNT; } - p = EG(argument_stack).top_element - 2; - arg_count = (ulong) * p; - - num_vectors = (zval **) p - (arg_count--); - - convert_to_long_ex(num_vectors); - - vector_array = emalloc(sizeof(struct iovec) * (ZVAL(num_vectors, lval) + 1)); - - for (i = 0; i < ZVAL(num_vectors, lval); i++) { - if (arg_count < 1) { - WRONG_PARAM_COUNT; - } - vector_len = (zval **) p - (arg_count--); + + convert_to_long_ex(args[0]); + num_vectors = Z_LVAL_PP(args[0]); + + vector_array = emalloc(sizeof(struct iovec) * (num_vectors + 1)); - convert_to_long_ex(vector_len); - - vector_array[i].iov_base = emalloc(ZVAL(vector_len, lval)); - vector_array[i].iov_len = ZVAL(vector_len, lval); + for (i = 0, j = 1; i < num_vectors; i++, j++) { + convert_to_long_ex(args[j]); + + vector_array[i].iov_base = emalloc(Z_LVAL_PP(args[j])); + vector_array[i].iov_len = Z_LVAL_PP(args[j]); } vector = emalloc(sizeof(php_iovec_t)); vector->iov_array = vector_array; - vector->count = ZVAL(num_vectors, lval); + vector->count = num_vectors; - ZEND_REGISTER_RESOURCE(return_value, vector, le_iov); + ZEND_REGISTER_RESOURCE(return_value, vector, SOCKETSG(le_iov)); } /* }}} */ @@ -1071,20 +998,21 @@ PHP_FUNCTION(fetch_iovec) { zval **iovec_id, **iovec_position; php_iovec_t *vector; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &iovec_id, &iovec_position) == FAILURE) { + if (ZEND_NUM_ARGS() != 2 || + zend_get_parameters_ex(2, &iovec_id, &iovec_position) == FAILURE) { WRONG_PARAM_COUNT; } - (*iovec_id)->type = IS_RESOURCE; - ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov); + + ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", SOCKETSG(le_iov)); - if (ZVAL(iovec_position, lval) > vector->count) { - zend_error(E_WARNING, "Can't access a vector position past the amount of vectors set in the array"); + if (Z_LVAL_PP(iovec_position) > vector->count) { + php_error(E_WARNING, "Can't access a vector position past the amount of vectors set in the array"); RETURN_NULL(); } - RETURN_STRINGL(vector->iov_array[ZVAL(iovec_position, lval)].iov_base, - vector->iov_array[ZVAL(iovec_position, lval)].iov_len, - 1); + RETURN_STRINGL(vector->iov_array[Z_LVAL_PP(iovec_position)].iov_base, + vector->iov_array[Z_LVAL_PP(iovec_position)].iov_len, 1); } /* }}} */ @@ -1094,22 +1022,26 @@ PHP_FUNCTION(set_iovec) { zval **iovec_id, **iovec_position, **new_val; php_iovec_t *vector; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &iovec_id, &iovec_position, &new_val) == FAILURE) { + if (ZEND_NUM_ARGS() != 3 || + zend_get_parameters_ex(3, &iovec_id, &iovec_position, &new_val) == FAILURE) { WRONG_PARAM_COUNT; } - (*iovec_id)->type = IS_RESOURCE; - ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov); + + ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", SOCKETSG(le_iov)); - if (ZVAL(iovec_position, lval) > vector->count) { - zend_error(E_WARNING, "Can't access a vector position outside of the vector array bounds"); + if (Z_LVAL_PP(iovec_position) > vector->count) { + php_error(E_WARNING, "Can't access a vector position outside of the vector array bounds"); RETURN_FALSE; } - if (vector->iov_array[ZVAL(iovec_position, lval)].iov_base) { - efree(vector->iov_array[ZVAL(iovec_position, lval)].iov_base); + + if (vector->iov_array[Z_LVAL_PP(iovec_position)].iov_base) { + efree(vector->iov_array[Z_LVAL_PP(iovec_position)].iov_base); } - vector->iov_array[ZVAL(iovec_position, lval)].iov_base = estrdup(ZVAL(new_val, str.val)); - vector->iov_array[ZVAL(iovec_position, lval)].iov_len = strlen(ZVAL(new_val, str.val)); + + vector->iov_array[Z_LVAL_PP(iovec_position)].iov_base = estrdup(Z_STRVAL_PP(new_val)); + vector->iov_array[Z_LVAL_PP(iovec_position)].iov_len = strlen(Z_STRVAL_PP(new_val)); RETURN_TRUE; } @@ -1122,18 +1054,20 @@ PHP_FUNCTION(add_iovec) zval **iovec_id, **iov_len; php_iovec_t *vector; struct iovec *vector_array; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &iovec_id, &iov_len) == FAILURE) { + if (ZEND_NUM_ARGS() != 2 || + zend_get_parameters_ex(2, &iovec_id, &iov_len) == FAILURE) { WRONG_PARAM_COUNT; } - (*iovec_id)->type = IS_RESOURCE; - ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov); + + ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", SOCKETSG(le_iov)); vector_array = emalloc(sizeof(struct iovec) * (vector->count + 2)); bcopy(vector->iov_array, vector_array, sizeof(struct iovec) * vector->count); - vector_array[vector->count].iov_base = emalloc(ZVAL(iov_len, lval)); - vector_array[vector->count].iov_len = ZVAL(iov_len, lval); + vector_array[vector->count].iov_base = emalloc(Z_LVAL_PP(iov_len)); + vector_array[vector->count].iov_len = Z_LVAL_PP(iov_len); efree(vector->iov_array); vector->iov_array = vector_array; vector->count++; @@ -1151,23 +1085,25 @@ PHP_FUNCTION(delete_iovec) php_iovec_t *vector; struct iovec *vector_array; int i; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &iovec_id, &iov_pos) == FAILURE) { + if (ZEND_NUM_ARGS() != 2 || + zend_get_parameters_ex(2, &iovec_id, &iov_pos) == FAILURE) { WRONG_PARAM_COUNT; } - (*iovec_id)->type = IS_RESOURCE; - ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov); - if (ZVAL(iov_pos, lval) > vector->count) { - zend_error(E_WARNING, "Can't delete an IO vector that is out of array bounds"); + ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", SOCKETSG(le_iov)); + + if (Z_LVAL_PP(iov_pos) > vector->count) { + php_error(E_WARNING, "Can't delete an IO vector that is out of array bounds"); RETURN_FALSE; } vector_array = emalloc(vector->count * sizeof(struct iovec)); for (i = 0; i < vector->count; i++) { - if (i < ZVAL(iov_pos, lval)) { + if (i < Z_LVAL_PP(iov_pos)) { bcopy(&(vector_array[i]), &(vector->iov_array[i]), sizeof(struct iovec)); - } else if (i > ZVAL(iov_pos, lval)) { + } else if (i > Z_LVAL_PP(iov_pos)) { bcopy(&(vector_array[i - 1]), &(vector->iov_array[i]), sizeof(struct iovec)); } } @@ -1187,21 +1123,15 @@ PHP_FUNCTION(free_iovec) zval **iovec_id; php_iovec_t *vector; int pos; + SOCKETSLS_FETCH(); if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &iovec_id) == FAILURE) { WRONG_PARAM_COUNT; } - (*iovec_id)->type = IS_RESOURCE; - ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov); + + ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", SOCKETSG(le_iov)); - for (pos = 0; pos < vector->count; pos++) { - efree(vector->iov_array[pos].iov_base); - } - - efree(vector->iov_array); - - vector->iov_array = NULL; - vector->count = 0; + zend_list_delete(Z_LVAL_PP(iovec_id)); RETURN_TRUE; } @@ -1214,46 +1144,44 @@ PHP_FUNCTION(readv) zval **fd, **iovec_id; php_iovec_t *vector; int ret; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &fd, &iovec_id) == FAILURE) { + if (ZEND_NUM_ARGS() != 2 || + zend_get_parameters_ex(2, &fd, &iovec_id) == FAILURE) { WRONG_PARAM_COUNT; } - (*iovec_id)->type = IS_RESOURCE; - ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov); - ret = readv(ZVAL(fd, lval), vector->iov_array, vector->count); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } + ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", SOCKETSG(le_iov)); + + ret = readv(Z_LVAL_PP(fd), vector->iov_array, vector->count); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto long writev(long fd, resource iovec_id) - Writes to a fd, using the scatter-gather array defined by iovec_id */ +/* {{{ proto int writev(int fd, resource iovec_id) + Writes to a file descriptor, fd, using the scatter-gather array defined by iovec_id */ PHP_FUNCTION(writev) { zval **fd, **iovec_id; php_iovec_t *vector; int ret; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &fd, &iovec_id) == FAILURE) { + if (ZEND_NUM_ARGS() != 2 || + zend_get_parameters_ex(2, &fd, &iovec_id) == FAILURE) { WRONG_PARAM_COUNT; } - (*iovec_id)->type = IS_RESOURCE; - ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", le_iov); + + ZEND_FETCH_RESOURCE(vector, php_iovec_t *, iovec_id, -1, "IO vector table", SOCKETSG(le_iov)); - ret = writev(ZVAL(fd, lval), vector->iov_array, vector->count); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } + ret = writev(Z_LVAL_PP(fd), vector->iov_array, vector->count); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto long recv(long fd, string buf, long len, long flags) +/* {{{ proto int recv(int fd, string buf, int len, long flags) Receive data from a connected socket */ /* May be used with SOCK_DGRAM sockets. */ PHP_FUNCTION(recv) @@ -1262,25 +1190,27 @@ PHP_FUNCTION(recv) int ret; char *recv_buf; - if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &fd, &buf, &len, &flags) == FAILURE) { + if (ZEND_NUM_ARGS() != 4 || + zend_get_parameters_ex(4, &fd, &buf, &len, &flags) == FAILURE) { WRONG_PARAM_COUNT; } v_convert_to_long_ex(3, fd, len, flags); convert_to_string_ex(buf); - recv_buf = emalloc(ZVAL(len, lval) + 2); - bzero(recv_buf, ZVAL(len, lval) + 2); + recv_buf = emalloc(Z_LVAL_PP(len) + 2); + bzero(recv_buf, Z_LVAL_PP(len) + 2); - ret = recv(ZVAL(fd, lval), recv_buf, ZVAL(len, lval), ZVAL(flags, lval)); + ret = recv(Z_LVAL_PP(fd), recv_buf, Z_LVAL_PP(len), Z_LVAL_PP(flags)); + if (ret < 0) { efree(recv_buf); RETURN_LONG(-errno); } else { - if (ZVAL(buf, str.val) != NULL) { - efree(ZVAL(buf, str.val)); + if (Z_STRVAL_PP(buf) != NULL) { + efree(Z_STRVAL_PP(buf)); } - ZVAL(buf, str.val) = estrndup(recv_buf, strlen(recv_buf)); - ZVAL(buf, str.len) = strlen(recv_buf); + Z_STRVAL_PP(buf) = estrndup(recv_buf, strlen(recv_buf)); + Z_STRLEN_PP(buf) = strlen(recv_buf); efree(recv_buf); @@ -1289,7 +1219,7 @@ PHP_FUNCTION(recv) } /* }}} */ -/* {{{ proto long send(long fd, string buf, long len, long flags) +/* {{{ proto int send(int fd, string buf, int len, int flags) Send data to a connected socket */ /* May be used with SOCK_DGRAM sockets. */ PHP_FUNCTION(send) @@ -1297,24 +1227,22 @@ PHP_FUNCTION(send) zval **fd, **buf, **len, **flags; int ret; - if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &fd, &buf, &len, &flags) == FAILURE) { + if (ZEND_NUM_ARGS() != 4 || + zend_get_parameters_ex(4, &fd, &buf, &len, &flags) == FAILURE) { WRONG_PARAM_COUNT; } v_convert_to_long_ex(3, fd, len, flags); convert_to_string_ex(buf); - ret = send(ZVAL(fd, lval), ZVAL(buf, str.val), - (ZVAL(buf, str.len) < ZVAL(len, lval) ? ZVAL(buf, str.len) : ZVAL(len, lval)), - ZVAL(flags, lval)); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } + ret = send(Z_LVAL_PP(fd), Z_STRVAL_PP(buf), + (Z_STRLEN_PP(buf) < Z_LVAL_PP(len) ? Z_STRLEN_PP(buf) : Z_LVAL_PP(len)), + Z_LVAL_PP(flags)); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } /* }}} */ -/* {{{ proto long recvfrom(long fd, string &buf, long len, long flags, string &name [, long &port]) +/* {{{ proto int recvfrom(int fd, string &buf, int len, int flags, string &name [, int &port]) Receive data from a socket, connected or not */ PHP_FUNCTION(recvfrom) { @@ -1323,117 +1251,123 @@ PHP_FUNCTION(recvfrom) struct sockaddr sa; socklen_t salen; - if (ZEND_NUM_ARGS() < 5) { - WRONG_PARAM_COUNT; - } - switch (ZEND_NUM_ARGS()) { - case 5: - if (zend_get_parameters_ex(5, &fd, &buf, &len, &flags, &name) == FAILURE) { - WRONG_PARAM_COUNT; - } - break; - case 6: - if (zend_get_parameters_ex(6, &fd, &buf, &len, &flags, &name, &port) == FAILURE) { + switch (ZEND_NUM_ARGS()) + { + case 5: + if (zend_get_parameters_ex(5, &fd, &buf, &len, &flags, &name) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 6: + if (zend_get_parameters_ex(6, &fd, &buf, &len, &flags, &name, &port) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + default: WRONG_PARAM_COUNT; - } - break; - default: - WRONG_PARAM_COUNT; } salen = sizeof(sa); - ret = getsockname(ZVAL(fd, lval), &sa, &salen); + ret = getsockname(Z_LVAL_PP(fd), &sa, &salen); + if (ret < 0) { RETURN_LONG(-errno); } - switch (sa.sa_family) { - case AF_UNIX: - { - struct sockaddr_un sun; - char *recv_buf = emalloc(ZVAL(len, lval) + 2); - socklen_t sun_length = sizeof(sun); + + switch (sa.sa_family) + { + case AF_UNIX: + { + struct sockaddr_un sun; + char *recv_buf = emalloc(Z_LVAL_PP(len) + 2); + socklen_t sun_length = sizeof(sun); + + if (ZEND_NUM_ARGS() != 5) { + WRONG_PARAM_COUNT; + } + bzero(recv_buf, Z_LVAL_PP(len) + 2); - if (ZEND_NUM_ARGS() != 5) { - WRONG_PARAM_COUNT; - } - bzero(recv_buf, ZVAL(len, lval) + 2); + ret = recvfrom(Z_LVAL_PP(fd), recv_buf, Z_LVAL_PP(len), Z_LVAL_PP(flags), + (struct sockaddr *)&sun, (socklen_t *) & sun_length); - ret = recvfrom(ZVAL(fd, lval), recv_buf, ZVAL(len, lval), ZVAL(flags, lval), - (struct sockaddr *) &sun, (socklen_t *) & sun_length); + if (ret < 0) { + efree(recv_buf); + RETURN_LONG(-errno); + } + + if (Z_STRVAL_PP(buf) != NULL) { + efree(Z_STRVAL_PP(buf)); + } + + Z_STRVAL_PP(buf) = estrndup(recv_buf, strlen(recv_buf)); + Z_STRLEN_PP(buf) = strlen(recv_buf); + + if (Z_STRVAL_PP(name) != NULL) { + efree(Z_STRVAL_PP(name)); + } + + Z_STRVAL_PP(name) = estrdup(sun.sun_path); + Z_STRLEN_PP(name) = strlen(sun.sun_path); - if (ret < 0) { efree(recv_buf); - RETURN_LONG(-errno); - } - if (ZVAL(buf, str.val) != NULL) { - efree(ZVAL(buf, str.val)); - } - ZVAL(buf, str.val) = estrndup(recv_buf, strlen(recv_buf)); - ZVAL(buf, str.len) = strlen(recv_buf); - if (ZVAL(name, str.val) != NULL) { - efree(ZVAL(name, str.val)); + RETURN_LONG(ret); } - ZVAL(name, str.val) = estrdup(sun.sun_path); - ZVAL(name, str.len) = strlen(sun.sun_path); - - efree(recv_buf); - - RETURN_LONG(ret); - } - break; - case AF_INET: - { - struct sockaddr_in sin; - char *recv_buf = emalloc(ZVAL(len, lval) + 2); - socklen_t sin_length = sizeof(sin); - char *address; + break; + case AF_INET: + { + struct sockaddr_in sin; + char *recv_buf = emalloc(Z_LVAL_PP(len) + 2); + socklen_t sin_length = sizeof(sin); + char *address; - if (ZEND_NUM_ARGS() != 6) { - WRONG_PARAM_COUNT; - } - bzero(recv_buf, ZVAL(len, lval) + 2); + if (ZEND_NUM_ARGS() != 6) { + WRONG_PARAM_COUNT; + } + bzero(recv_buf, Z_LVAL_PP(len) + 2); - ret = recvfrom(ZVAL(fd, lval), recv_buf, ZVAL(len, lval), ZVAL(flags, lval), - (struct sockaddr *) &sin, (socklen_t *) & sin_length); + ret = recvfrom(Z_LVAL_PP(fd), recv_buf, Z_LVAL_PP(len), Z_LVAL_PP(flags), + (struct sockaddr *)&sin, (socklen_t *) & sin_length); + + if (ret < 0) { + efree(recv_buf); + RETURN_LONG(-errno); + } + + if (Z_STRVAL_PP(buf) != NULL) { + efree(Z_STRVAL_PP(buf)); + } + + if (Z_STRVAL_PP(name) != NULL) { + efree(Z_STRVAL_PP(name)); + } + + Z_STRVAL_PP(buf) = estrdup(recv_buf); + Z_STRLEN_PP(buf) = strlen(recv_buf); - if (ret < 0) { + address = inet_ntoa(sin.sin_addr); + if (address == NULL) { + Z_STRVAL_PP(name) = estrdup("0.0.0.0"); + Z_STRLEN_PP(name) = strlen(Z_STRVAL_PP(name)); + } else { + Z_STRVAL_PP(name) = estrdup(address); + Z_STRLEN_PP(name) = strlen(address); + } + + Z_LVAL_PP(port) = ntohs(sin.sin_port);; + efree(recv_buf); - RETURN_LONG(-errno); - } - if (ZVAL(buf, str.val) != NULL) { - efree(ZVAL(buf, str.val)); - } - if (ZVAL(name, str.val) != NULL) { - efree(ZVAL(name, str.val)); - } - ZVAL(buf, str.val) = estrdup(recv_buf); - ZVAL(buf, str.len) = strlen(recv_buf); - - address = inet_ntoa(sin.sin_addr); - if (address == NULL) { - ZVAL(name, str.val) = estrdup("0.0.0.0"); - ZVAL(name, str.len) = strlen(ZVAL(name, str.val)); - } else { - ZVAL(name, str.val) = estrdup(address); - ZVAL(name, str.len) = strlen(address); + RETURN_LONG(ret); } - - ZVAL(port, lval) = ntohs(sin.sin_port); - - efree(recv_buf); - RETURN_LONG(ret); - } - break; - default: - RETURN_LONG(-EPROTONOSUPPORT); - + break; + default: + RETURN_LONG(-EPROTONOSUPPORT); } } /* }}} */ -/* {{{ proto long sendto(long fd, string buf, long len, long flags, string addr [, long port]) +/* {{{ proto int sendto(int fd, string buf, int len, int flags, string addr [, int port]) Sends a message to a socket, whether it is connected or not */ PHP_FUNCTION(sendto) { @@ -1442,15 +1376,16 @@ PHP_FUNCTION(sendto) socklen_t salen = sizeof(sa); int ret; - switch (ZEND_NUM_ARGS()) { - case 5: - ret = zend_get_parameters_ex(5, &fd, &buf, &len, &flags, &addr); - break; - case 6: - ret = zend_get_parameters_ex(6, &fd, &buf, &len, &flags, &addr, &port); - break; - default: - ret = FAILURE; + switch (ZEND_NUM_ARGS()) + { + case 5: + ret = zend_get_parameters_ex(5, &fd, &buf, &len, &flags, &addr); + break; + case 6: + ret = zend_get_parameters_ex(6, &fd, &buf, &len, &flags, &addr, &port); + break; + default: + ret = FAILURE; } if (ret == FAILURE) { @@ -1462,72 +1397,69 @@ PHP_FUNCTION(sendto) if (ZEND_NUM_ARGS() == 6) { convert_to_long_ex(port); } - ret = getsockname(ZVAL(fd, lval), &sa, &salen); + + ret = getsockname(Z_LVAL_PP(fd), &sa, &salen); if (ret < 0) { RETURN_LONG(-errno); } - switch (sa.sa_family) { - case AF_UNIX: - { - struct sockaddr_un sun; - - if (ZEND_NUM_ARGS() != 5) { - WRONG_PARAM_COUNT; - } - bzero(&sun, sizeof(sun)); - sun.sun_family = AF_UNIX; - snprintf(sun.sun_path, 108, "%s", ZVAL(port, str.val)); - ret = sendto(ZVAL(fd, lval), ZVAL(buf, str.val), - (ZVAL(buf, str.len) > ZVAL(len, lval) ? ZVAL(len, lval) : ZVAL(buf, str.len)), - ZVAL(flags, lval), &sun, SUN_LEN(&sun)); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } - } - break; - case AF_INET: - { - struct sockaddr_in sin; - struct in_addr addr_buf; - if (ZEND_NUM_ARGS() != 6) { - WRONG_PARAM_COUNT; + switch (sa.sa_family) + { + case AF_UNIX: + { + struct sockaddr_un sun; + + if (ZEND_NUM_ARGS() != 5) { + WRONG_PARAM_COUNT; + } + bzero(&sun, sizeof(sun)); + sun.sun_family = AF_UNIX; + snprintf(sun.sun_path, 108, "%s", Z_STRVAL_PP(port)); + ret = sendto(Z_LVAL_PP(fd), Z_STRVAL_PP(buf), + (Z_STRLEN_PP(buf) > Z_LVAL_PP(len) ? Z_LVAL_PP(len) : Z_STRLEN_PP(buf)), + Z_LVAL_PP(flags), &sun, SUN_LEN(&sun)); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; + break; + case AF_INET: + { + struct sockaddr_in sin; + struct in_addr addr_buf; - if (inet_aton(ZVAL(addr, str.val), &addr_buf) == 0) { - sin.sin_addr.s_addr = addr_buf.s_addr; - } else { - struct hostent *he; + if (ZEND_NUM_ARGS() != 6) { + WRONG_PARAM_COUNT; + } + bzero(&sin, sizeof(sin)); + sin.sin_family = AF_INET; + + if (inet_aton(Z_STRVAL_PP(addr), &addr_buf) == 0) { + sin.sin_addr.s_addr = addr_buf.s_addr; + } else { + struct hostent *he; - he = gethostbyname(ZVAL(addr, str.val)); - if (he == NULL) { - RETURN_LONG(-(h_errno) - 10000); + he = gethostbyname(Z_STRVAL_PP(addr)); + if (he == NULL) { + RETURN_LONG(-(h_errno) - 10000); + } + sin.sin_addr.s_addr = *(int *) (he->h_addr_list[0]); } - sin.sin_addr.s_addr = *(int *) (he->h_addr_list[0]); - } - sin.sin_port = htons(ZVAL(port, lval)); - ret = sendto(ZVAL(fd, lval), ZVAL(buf, str.val), - (ZVAL(buf, str.len) > ZVAL(len, lval) ? ZVAL(len, lval) : ZVAL(buf, str.len)), - ZVAL(flags, lval), &sin, sizeof(sin)); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); + sin.sin_port = htons(Z_LVAL_PP(port)); + ret = sendto(Z_LVAL_PP(fd), Z_STRVAL_PP(buf), + (Z_STRLEN_PP(buf) > Z_LVAL_PP(len) ? Z_LVAL_PP(len) : Z_STRLEN_PP(buf)), + Z_LVAL_PP(flags), &sin, sizeof(sin)); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } - } - break; - default: - RETURN_LONG(-EPROTONOSUPPORT); - break; + break; + default: + RETURN_LONG(-EPROTONOSUPPORT); + break; } } /* }}} */ -/* {{{ proto long recvmsg(long fd, resource iovec, array &control, long &controllen, long &flags, string &addr [, long &port]) +/* {{{ proto int recvmsg(int fd, resource iovec, array &control, int &controllen, int &flags, string &addr [, int &port]) Used to receive messages on a socket, whether connection-oriented or not */ PHP_FUNCTION(recvmsg) { @@ -1541,94 +1473,105 @@ PHP_FUNCTION(recvmsg) struct cmsghdr *ctl_buf; socklen_t salen = sizeof(sa); int ret; + SOCKETSLS_FETCH(); - switch (ZEND_NUM_ARGS()) { - case 6: - ret = zend_get_parameters_ex(6, &fd, &iovec, &control, &controllen, &flags, &addr); - break; - case 7: - ret = zend_get_parameters_ex(7, &fd, &iovec, &control, &controllen, &flags, &addr, &port); - break; - default: - WRONG_PARAM_COUNT; + switch (ZEND_NUM_ARGS()) + { + case 6: + ret = zend_get_parameters_ex(6, &fd, &iovec, &control, &controllen, &flags, &addr); + break; + case 7: + ret = zend_get_parameters_ex(7, &fd, &iovec, &control, &controllen, &flags, &addr, &port); + break; + default: + WRONG_PARAM_COUNT; } if (ret == FAILURE) { WRONG_PARAM_COUNT; } - v_convert_to_long_ex(4, fd, iovec, controllen, flags); + + v_convert_to_long_ex(3, fd, controllen, flags); convert_to_string_ex(control); convert_to_string_ex(addr); if (ZEND_NUM_ARGS() == 7) { convert_to_long_ex(port); } - (*iovec)->type = IS_RESOURCE; - ZEND_FETCH_RESOURCE(iov, php_iovec_t *, iovec, -1, "IO vector table", le_iov); - ret = getsockname(ZVAL(fd, lval), &sa, &salen); + ZEND_FETCH_RESOURCE(iov, php_iovec_t *, iovec, -1, "IO vector table", SOCKETSG(le_iov)); + + ret = getsockname(Z_LVAL_PP(fd), &sa, &salen); if (ret < 0) { RETURN_LONG(-errno); } - if (ZVAL(controllen, lval) > sizeof(struct cmsghdr)) { - ctl_buf = emalloc(ZVAL(controllen, lval)); + + if (Z_LVAL_PP(controllen) > sizeof(struct cmsghdr)) { + ctl_buf = emalloc(Z_LVAL_PP(controllen)); } else { ctl_buf = NULL; } - switch (sa.sa_family) { - case AF_INET: - { - if (ZEND_NUM_ARGS() != 7) { - efree(ctl_buf); - WRONG_PARAM_COUNT; - } - bzero(&sa, sizeof(sa)); - hdr.msg_name = sin; - hdr.msg_namelen = sizeof(sa); - hdr.msg_iov = iov->iov_array; - hdr.msg_iovlen = iov->count; - - if (ctl_buf) { - hdr.msg_control = ctl_buf; - hdr.msg_controllen = ZVAL(controllen, lval); - } else { - hdr.msg_control = NULL; - hdr.msg_controllen = 0; - } + switch (sa.sa_family) + { + case AF_INET: + { + if (ZEND_NUM_ARGS() != 7) { + efree(ctl_buf); + WRONG_PARAM_COUNT; + } + bzero(&sa, sizeof(sa)); + hdr.msg_name = sin; + hdr.msg_namelen = sizeof(sa); + hdr.msg_iov = iov->iov_array; + hdr.msg_iovlen = iov->count; - hdr.msg_flags = 0; + if (ctl_buf) { + hdr.msg_control = ctl_buf; + hdr.msg_controllen = Z_LVAL_PP(controllen); + } else { + hdr.msg_control = NULL; + hdr.msg_controllen = 0; + } - ret = recvmsg(ZVAL(fd, lval), &hdr, ZVAL(flags, lval)); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - struct cmsghdr *mhdr = (struct cmsghdr *) hdr.msg_control; + hdr.msg_flags = 0; + + ret = recvmsg(Z_LVAL_PP(fd), &hdr, Z_LVAL_PP(flags)); + if (ret < 0) { + RETURN_LONG(-errno); + } else { + struct cmsghdr *mhdr = (struct cmsghdr *) hdr.msg_control; - /* copy values as appropriate... */ - array_init(control_array); - add_assoc_long(control_array, "cmsg_level", mhdr->cmsg_level); - add_assoc_long(control_array, "cmsg_type", mhdr->cmsg_type); - add_assoc_string(control_array, "cmsg_data", CMSG_DATA(mhdr), 1); - *control = control_array; - ZVAL(controllen, lval) = hdr.msg_controllen; - ZVAL(flags, lval) = hdr.msg_flags; - if (ZVAL(addr, str.val) != NULL) { - efree(ZVAL(addr, str.val)); - } { - char *tmp = inet_ntoa(sin->sin_addr); - - if (tmp == NULL) { - ZVAL(addr, str.val) = estrdup("0.0.0.0"); - } else { - ZVAL(addr, str.val) = estrdup(tmp); + /* copy values as appropriate... */ + if (array_init(control_array) == FAILURE) { + php_error(E_WARNING, "Cannot intialize array"); + RETURN_FALSE; + } + add_assoc_long(control_array, "cmsg_level", mhdr->cmsg_level); + add_assoc_long(control_array, "cmsg_type", mhdr->cmsg_type); + add_assoc_string(control_array, "cmsg_data", CMSG_DATA(mhdr), 1); + *control = control_array; + zval_copy_ctor(*control); + + Z_LVAL_PP(controllen) = hdr.msg_controllen; + Z_LVAL_PP(flags) = hdr.msg_flags; + if (Z_STRVAL_PP(addr) != NULL) { + efree(Z_STRVAL_PP(addr)); + } + { + char *tmp = inet_ntoa(sin->sin_addr); + + if (tmp == NULL) { + Z_STRVAL_PP(addr) = estrdup("0.0.0.0"); + } else { + Z_STRVAL_PP(addr) = estrdup(tmp); + } } + Z_STRLEN_PP(addr) = strlen(Z_STRVAL_PP(addr)); + Z_LVAL_PP(port) = ntohs(sin->sin_port); + RETURN_LONG(ret); } - ZVAL(addr, str.len) = strlen(ZVAL(addr, str.val)); - ZVAL(port, lval) = ntohs(sin->sin_port); - RETURN_LONG(ret); } - } - break; + break; case AF_UNIX: { if (ZEND_NUM_ARGS() != 6) { @@ -1643,7 +1586,7 @@ PHP_FUNCTION(recvmsg) if (ctl_buf) { hdr.msg_control = ctl_buf; - hdr.msg_controllen = ZVAL(controllen, lval); + hdr.msg_controllen = Z_LVAL_PP(controllen); } else { hdr.msg_control = NULL; hdr.msg_controllen = 0; @@ -1651,24 +1594,27 @@ PHP_FUNCTION(recvmsg) hdr.msg_flags = 0; - ret = recvmsg(ZVAL(fd, lval), &hdr, ZVAL(flags, lval)); + ret = recvmsg(Z_LVAL_PP(fd), &hdr, Z_LVAL_PP(flags)); if (ret < 0) { RETURN_LONG(-errno); } else { struct cmsghdr *mhdr = (struct cmsghdr *) hdr.msg_control; /* copy values as appropriate... */ - array_init(control_array); + if (array_init(control_array) == FAILURE) { + php_error(E_WARNING, "Cannot initialize return value from recvmsg()"); + RETURN_FALSE; + } add_assoc_long(control_array, "cmsg_level", mhdr->cmsg_level); add_assoc_long(control_array, "cmsg_type", mhdr->cmsg_type); add_assoc_string(control_array, "cmsg_data", CMSG_DATA(mhdr), 1); *control = control_array; - ZVAL(controllen, lval) = hdr.msg_controllen; - ZVAL(flags, lval) = hdr.msg_flags; - if (ZVAL(addr, str.val) != NULL) { - efree(ZVAL(addr, str.val)); + Z_LVAL_PP(controllen) = hdr.msg_controllen; + Z_LVAL_PP(flags) = hdr.msg_flags; + if (Z_STRVAL_PP(addr) != NULL) { + efree(Z_STRVAL_PP(addr)); } - ZVAL(addr, str.val) = estrdup(sun->sun_path); + Z_STRVAL_PP(addr) = estrdup(sun->sun_path); RETURN_LONG(ret); } } @@ -1679,34 +1625,29 @@ PHP_FUNCTION(recvmsg) } /* }}} */ -/* {{{ proto long sendmsg(long fd, resource iovec, long flags, string addr [, long port]) +/* {{{ proto int sendmsg(int fd, resource iovec, int flags, string addr [, int port]) Sends a message to a socket, regardless of whether it is connection-oriented or not */ PHP_FUNCTION(sendmsg) { zval **fd, **iovec, **flags, **addr, **port; php_iovec_t *iov; - int ret; + int ret, argc = ZEND_NUM_ARGS(); struct sockaddr sa; int salen; + SOCKETSLS_FETCH(); - if (ZEND_NUM_ARGS() == 4) { - ret = zend_get_parameters_ex(4, &fd, &iovec, &flags, &addr); - } else if (ZEND_NUM_ARGS() == 5) { - ret = zend_get_parameters_ex(5, &fd, &iovec, &flags, &addr, &port); - } - - if (ret == FAILURE) { + if (argc < 4 || argc > 5 || + zend_get_parameters_ex(argc, &fd, &iovec, &flags, &addr, &port) == FAILURE) { WRONG_PARAM_COUNT; } salen = sizeof(sa); - ret = getsockname(ZVAL(fd, lval), &sa, &salen); + ret = getsockname(Z_LVAL_PP(fd), &sa, &salen); if (ret < 0) { RETURN_LONG(-errno); } - (*iovec)->type = IS_RESOURCE; - ZEND_FETCH_RESOURCE(iov, php_iovec_t *, iovec, -1, "IO vector table", le_iov); + ZEND_FETCH_RESOURCE(iov, php_iovec_t *, iovec, -1, "IO vector table", SOCKETSG(le_iov)); switch(sa.sa_family) { @@ -1722,21 +1663,18 @@ PHP_FUNCTION(sendmsg) hdr.msg_iov = iov->iov_array; hdr.msg_iovlen = iov->count; - if (inet_aton(ZVAL(addr, str.val), &sin->sin_addr) != 0) { - struct hostent *he = gethostbyname(ZVAL(addr, str.val)); + if (inet_aton(Z_STRVAL_PP(addr), &sin->sin_addr) != 0) { + struct hostent *he = gethostbyname(Z_STRVAL_PP(addr)); if (!he) { RETURN_LONG(h_errno > 0 ? -(h_errno) - 10000 : -errno) } sin->sin_addr.s_addr = *(int *)(he->h_addr_list[0]); } - sin->sin_port = htons(ZVAL(port, lval)); - ret = sendmsg(ZVAL(fd, lval), &hdr, ZVAL(flags, lval)); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } + sin->sin_port = htons(Z_LVAL_PP(port)); + ret = sendmsg(Z_LVAL_PP(fd), &hdr, Z_LVAL_PP(flags)); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } break; case AF_UNIX: @@ -1748,16 +1686,13 @@ PHP_FUNCTION(sendmsg) hdr.msg_iov = iov->iov_array; hdr.msg_iovlen = iov->count; - snprintf(sun->sun_path, 108, "%s", ZVAL(addr, str.val)); + snprintf(sun->sun_path, 108, "%s", Z_STRVAL_PP(addr)); hdr.msg_namelen = SUN_LEN(sun); - ret = sendmsg(ZVAL(fd, lval), &hdr, ZVAL(flags, lval)); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); - } + ret = sendmsg(Z_LVAL_PP(fd), &hdr, Z_LVAL_PP(flags)); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } break; default: @@ -1766,7 +1701,7 @@ PHP_FUNCTION(sendmsg) } /* }}} */ -/* {{{ proto long getsockopt(long fd, long level, long optname, array|long &optval) +/* {{{ proto int getsockopt(int fd, int level, int optname, array|int &optval) Gets socket options for the socket */ /* If optname is SO_LINGER, optval is returned as an array with members "l_onoff" and "l_linger", otherwise it is an integer. @@ -1781,23 +1716,27 @@ PHP_FUNCTION(getsockopt) fd = level = optname = optval = NULL; - if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &fd, &level, &optname, &optval) == FAILURE) { + if (ZEND_NUM_ARGS() != 4 || + zend_get_parameters_ex(4, &fd, &level, &optname, &optval) == FAILURE) { WRONG_PARAM_COUNT; } v_convert_to_long_ex(3, fd, level, optname); /* optname is set on the way out .. */ - if (ZVAL(level, lval) == SO_LINGER) { + if (Z_LVAL_PP(level) == SO_LINGER) { zval *optval_array = NULL; optlen = sizeof(struct linger); - ret = getsockopt(ZVAL(fd, lval), ZVAL(level, lval), ZVAL(optname, lval), &linger_val, &optlen); + ret = getsockopt(Z_LVAL_PP(fd), Z_LVAL_PP(level), Z_LVAL_PP(optname), &linger_val, &optlen); if (ret < 0) { RETURN_LONG(-errno); } - array_init(optval_array); + if (array_init(optval_array) == FAILURE) { + php_error(E_WARNING, "Cannot initialize array from getsockopt()"); + RETURN_FALSE; + } add_assoc_long(optval_array, "l_onoff", linger_val.l_onoff); add_assoc_long(optval_array, "l_linger", linger_val.l_linger); @@ -1805,18 +1744,18 @@ PHP_FUNCTION(getsockopt) RETURN_LONG(ret); } else { optlen = sizeof(other_val); - ret = getsockopt(ZVAL(fd, lval), ZVAL(level, lval), ZVAL(optname, lval), &other_val, &optlen); + ret = getsockopt(Z_LVAL_PP(fd), Z_LVAL_PP(level), Z_LVAL_PP(optname), &other_val, &optlen); if (ret < 0) { RETURN_LONG(-errno); } - ZVAL_LONG(*optval, other_val); + Z_LVAL_PP(optval) = other_val; RETURN_LONG(ret); } } /* }}} */ -/* {{{ proto long setsockopt(long fd, long level, long optname, long|array optval) +/* {{{ proto int setsockopt(int fd, int level, int optname, int|array optval) Sets socket options for the socket */ /* If optname is SO_LINGER, optval is expected to be an array with members "l_onoff" and "l_linger", otherwise it should be an integer. */ @@ -1830,13 +1769,14 @@ PHP_FUNCTION(setsockopt) errno = 0; - if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &fd, &level, &optname, &optval) == FAILURE) { + if (ZEND_NUM_ARGS() != 4 || + zend_get_parameters_ex(4, &fd, &level, &optname, &optval) == FAILURE) { WRONG_PARAM_COUNT; } v_convert_to_long_ex(3, fd, level, optname); - if (ZVAL(optname, lval) == SO_LINGER) { + if (Z_LVAL_PP(optname) == SO_LINGER) { HashTable *ht; zval **l_onoff; zval **l_linger; @@ -1844,39 +1784,105 @@ PHP_FUNCTION(setsockopt) convert_to_array_ex(optval); ht = HASH_OF(*optval); - if (zend_hash_find(ht, "l_onoff", strlen("l_onoff") + 1, (void **) &l_onoff) == FAILURE) { - zend_error(E_ERROR, "No key \"l_onoff\" passed in optval"); - return; + if (zend_hash_find(ht, "l_onoff", strlen("l_onoff") + 1, (void **)&l_onoff) == FAILURE) { + php_error(E_WARNING, "No key \"l_onoff\" passed in optval"); + RETURN_FALSE; } if (zend_hash_find(ht, "l_linger", strlen("l_linger") + 1, (void **) &l_linger) == FAILURE) { - zend_error(E_ERROR, "No key \"l_linger\" passed in optval"); - return; + php_error(E_WARNING, "No key \"l_linger\" passed in optval"); + RETURN_FALSE; } convert_to_long_ex(l_onoff); convert_to_long_ex(l_linger); - lv.l_onoff = ZVAL(l_onoff, lval); - lv.l_linger = ZVAL(l_linger, lval); + lv.l_onoff = Z_LVAL_PP(l_onoff); + lv.l_linger = Z_LVAL_PP(l_linger); optlen = sizeof(lv); - ret = setsockopt(ZVAL(fd, lval), ZVAL(level, lval), ZVAL(optname, lval), &lv, optlen); + ret = setsockopt(Z_LVAL_PP(fd), Z_LVAL_PP(level), Z_LVAL_PP(optname), &lv, optlen); } else { convert_to_long_ex(optval); optlen = sizeof(ov); - ov = ZVAL(optval, lval); + ov = Z_LVAL_PP(optval); - ret = setsockopt(ZVAL(fd, lval), ZVAL(level, lval), ZVAL(optname, lval), &ov, optlen); + ret = setsockopt(Z_LVAL_PP(fd), Z_LVAL_PP(level), Z_LVAL_PP(optname), &ov, optlen); } - printf("returning: ret = %i, errno = %i\n", ret, errno); - if (ret < 0) { - RETURN_LONG(-errno); - } else { - RETURN_LONG(ret); + RETURN_LONG(((ret < 0) ? -errno : ret)); +} + +PHP_FUNCTION(socketpair) +{ + zval **domain, **type, **protocol, **fds, **fd; + int ret, fds_ar[2]; + HashTable *fd_ar; + + if (ZEND_NUM_ARGS() != 4 || + zend_get_parameters_ex(4, &domain, &type, &protocol, &fds) == FAILURE) { + WRONG_PARAM_COUNT; + } + v_convert_to_long_ex(3, domain, type, protocol); + + if (Z_LVAL_PP(domain) != AF_INET && Z_LVAL_PP(domain) != AF_UNIX) { + php_error(E_WARNING, "invalid socket domain specified -- assuming AF_INET"); + Z_LVAL_PP(domain) = AF_INET; + } + + if (Z_LVAL_PP(type) > 10) { + php_error(E_WARNING, "Invalid socket type specified - assuming SOCK_STREAM"); + Z_LVAL_PP(type) = SOCK_STREAM; + } + + fd_ar = HASH_OF(*fds); + zend_hash_internal_pointer_reset(fd_ar); + + if (zend_hash_get_current_data(fd_ar, (void **)&fd) == FAILURE) { + php_error(E_WARNING, "Can't access data from fds array"); + RETURN_FALSE; } + SEPARATE_ZVAL(fd); + + convert_to_long_ex(fd); + fds_ar[0] = Z_LVAL_PP(fd); + + zend_hash_move_forward(fd_ar); + if (zend_hash_get_current_data(fd_ar, (void **)&fd) == FAILURE) { + php_error(E_WARNING, "Can't access data from fds array"); + RETURN_FALSE; + } + SEPARATE_ZVAL(fd); + + convert_to_long_ex(fd); + fds_ar[1] = Z_LVAL_PP(fd); + + ret = socketpair(Z_LVAL_PP(domain), Z_LVAL_PP(type), Z_LVAL_PP(protocol), fds_ar); + + RETURN_LONG(((ret < 0) ? -errno : ret)); } + +PHP_FUNCTION(shutdown) +{ + zval **fd, **how; + int how_shutdown = 0, argc = ZEND_NUM_ARGS(), ret; + + if (argc < 1 || argc > 2 || + zend_get_parameters_ex(argc, &fd, &how) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long_ex(fd); + + if (argc > 1) { + convert_to_long_ex(how); + how_shutdown = Z_LVAL_PP(how); + } + + ret = shutdown(Z_LVAL_PP(fd), how_shutdown); + + RETURN_LONG(((ret < 0) ? -errno : ret)); +} + /* }}} */ #endif /* HAVE_SOCKETS */