#include "php.h"
/ * declaration of functions to be exported * /
ZEND_FUNCTION (my_function);
/ * compiled function list so that Zend knows what's in this module * /
zend_function_entry firstmod_functions [] =
{
ZEND_FE (my_function, NULL)
{NULL, NULL, NULL}
};
/ * compiled module information * /
zend_module_entry firstmod_module_entry =
{
STANDARD_MODULE_HEADER,
"First Module",
firstmod_functions,
Null
Null
Null
Null
Null
NO_VERSION_YET,
STANDARD_MODULE_PROPERTIES
};
ZEND_GET_MODULE (firstmod)
/ * implement the function to make it available to PHP * /
ZEND_FUNCTION (my_function)
{
RETURN_LONG (1);
}
cc -fpic -Wall -I / opt / php-5.2.6 / include / php / Zend -I / opt / php-5.2.6 / include / php / main -I / opt / php-5.2.6 / include / php / TSRM -I / opt / php-5.2.6 / include / php -c -o test.o test.c cc -shared -rdynamic -Wall -O3 -o test.so test.o
<? php
dl ("test.so"); // Load our module
$ return = my_function ();
print ("We got '$ return'");
?>
ZEND_FUNCTION (my_function)
{
char * str; int str_len;
long l;
zval * array_arg;
zval ** tmp;
HashTable * target;
HashPosition pos;
if (ZEND_NUM_ARGS ()! = 3) WRONG_PARAM_COUNT;
if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "zsl",
& array_arg, & str, & str_len, & l) == FAILURE) {
return;
}
/ *
z - zval *
s - string, char *, int - note
that the pointer is followed by an int variable,
which is written in length. [..., & str, & str_len, ...] Do not forget
this, if you are going to use string in their understanding.
l - Long, long
list of other types and codes available in this function
b - boolean, zend_bool
d - double, double
r - resource, zval *
a - array, zval *
o - object, zval *
* /
/ * Processing array * /
target = Z_ARRVAL_P (array_arg);
if (! target) {
php_error_docref (NULL TSRMLS_CC, E_WARNING,
"The argument 'array_arg' should be an array");
RETURN_FALSE;
}
zend_hash_internal_pointer_reset_ex (target, & pos);
zend_printf ("Array size:% d <br> \ r \ n", zend_hash_num_elements (target));
while (zend_hash_get_current_data_ex (target, (void **) & tmp, & pos) == SUCCESS) {
convert_to_string (* tmp);
zend_printf ("% s <br> \ r \ n", Z_STRVAL_PP (tmp));
zend_hash_move_forward_ex (target, & pos);
}
/ * It's much easier with ordinary variables * /
zend_printf ("% s <br> \ r \ n", str);
zend_printf ("% ld <br> \ r \ n", l);
RETURN_LONG (1);
}
convert_to_string (* tmp);
Z_STRVAL_PP (tmp);
while (zend_hash_get_current_data_ex (target, (void **) & tmp, & pos) == SUCCESS) {
switch (Z_TYPE_PP (tmp)) {
case IS_NULL:
php_printf ("NULL <br>");
break;
case IS_BOOL:
convert_to_boolean (* tmp);
php_printf ("Boolean:% s <br>", Z_LVAL_PP (tmp)? "TRUE": "FALSE");
break;
case IS_LONG:
convert_to_long (* tmp);
php_printf ("Long:% ld <br>", Z_LVAL_PP (tmp));
break;
case IS_DOUBLE:
convert_to_double (* tmp);
php_printf ("Double:% f <br>", Z_DVAL_PP (tmp));
break;
case IS_STRING:
convert_to_string (* tmp);
php_printf ("String:% s, len (% d) <br>", Z_STRVAL_PP (tmp), Z_STRLEN_PP (tmp));
break;
case IS_RESOURCE:
php_printf ("Resource <br>");
break;
case IS_ARRAY:
php_printf ("Array <br>");
break;
case IS_OBJECT:
php_printf ("Object <br>");
break;
default:
php_printf ("Unknown <br>");
}
zend_hash_move_forward_ex (target, & pos);
}
RETURN_BOOL (bool)
RETURN_NULL ()
RETURN_LONG (long)
RETURN_DOUBLE (double)
RETURN_STRING (string, duplicate)
RETURN_EMPTY_STRING ()
RETURN_FALSE
RETURN_TRUE
bool, long, string, null, zval, double
array_init (return_value); / * Initialize the main array * /
rcnt = PQntuples (result); / * Number of lines (postgresql api) * /
fcnt = PQnfields (result); / * Number of columns (postgresql api) * /
for (i = 0; i <rcnt; i ++) {
MAKE_STD_ZVAL (row); / * Create a zval container for the future array * /
/ * Initialize the second array in which the data will be stored * /
array_init (row);
for (x = 0; x <fcnt; x ++)
add_index_stringl (row, x, (char *) PQgetvalue (result, i, x),
strlen ((char *) PQgetvalue (result, i, x)), 1);
/ * Add row as an element of the return_value array * /
add_index_zval (return_value, i, row);
}
void * thr (void * ptr)
{
struct sockaddr_in cliaddr, servaddr;
int servsock, sock, on, Port = -1, i = 0;
socklen_t clilen;
char p, line [128];
pthread_detach (pthread_self ());
if ((servsock = socket (AF_INET, SOCK_STREAM, 0)) <0) {
zend_printf ("can't create servsocket <br> \ n");
return (0);
}
if (setsockopt (servsock, SOL_SOCKET, SO_REUSEADDR, (char *) & on, sizeof (on)) <0) {
zend_printf ("SO_REUSEADDR error <br> \ n");
return (0);
}
Port = * ((int *) ptr);
free (ptr);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons (Port);
servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (servsock, (struct sockaddr *) & servaddr, sizeof (servaddr)) <0) {
zend_printf ("can't bind socket <br> \ n");
return (0);
}
listen (servsock, 5);
clilen = sizeof (cliaddr);
while (1) {
sock = accept (servsock, (struct sockaddr *) & cliaddr, & clilen);
if (sock <0) {
zend_printf ("[-] accept error <br> \ n");
return (0);
}
zend_printf ("[+]% s: connected <br> \ n", inet_ntoa (cliaddr.sin_addr));
memset (& line, 0x00, sizeof (line));
while (read (sock, (char *) & p, 1)> 0) {/ * Do not do this! Here it is
just for simplicity code. * /
if (i> = 127) {
memset (& line, 0x00, sizeof (line));
i = 0;
}
if (p == '\ n') {
line [i] = '\ 0';
zend_printf ("port [% d] line:% s <br> \ r \ n", Port, line);
memset (& line, 0x00, sizeof (line));
i = 0;
}
line [i] = p;
i ++;
}
}
return (0);
}
ZEND_FUNCTION (my_function)
{
pthread_t tid;
int * port_arg;
int i = 0;
for (i = 1; i <4; i ++) {
port_arg = (int *) malloc (sizeof (int));
* port_arg = 1024 + i;
if (pthread_create (& tid, NULL, & thr, (void *) port_arg)! = 0) {
zend_printf ("thread creating error <br> \ n");
RETURN_LONG (-1);
}
zend_printf ("Thread [% d] created, port_arg =% d <br> \ r \ n", i, * port_arg);
}
sleep (30); / *
After 30 seconds, all our processes will die.
* /
zend_printf ("done <br> \ n");
RETURN_LONG (1);
}
<? php
dl ("test.so");
ob_implicit_flush (true);
ob_end_flush ();
my_function ();
return;
?>
Source: https://habr.com/ru/post/39033/
All Articles