2001-06-12 16:54:25 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2001-12-11 23:32:16 +08:00
| PHP Version 4 |
2001-06-12 16:54:25 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2003-01-01 00:08:15 +08:00
| Copyright ( c ) 1997 - 2003 The PHP Group |
2001-06-12 16:54:25 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2003-06-11 04:04:29 +08:00
| This source file is subject to version 3.0 of the PHP license , |
2001-06-12 16:54:25 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-11 04:04:29 +08:00
| available through the world - wide - web at the following url : |
| http : //www.php.net/license/3_0.txt. |
2001-06-12 16:54:25 +08:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2002-02-28 16:29:35 +08:00
| Author : Jason Greene < jason @ inetgurus . net > |
2001-06-12 16:54:25 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2001-07-31 04:51:57 +08:00
/* $Id$ */
2001-06-20 05:42:57 +08:00
# define PCNTL_DEBUG 0
# if PCNTL_DEBUG
# define DEBUG_OUT printf("DEBUG: ");printf
2002-08-22 12:20:10 +08:00
# define IF_DEBUG(z) z
2001-06-20 05:42:57 +08:00
# else
2002-08-22 12:20:10 +08:00
# define IF_DEBUG(z)
2001-06-20 05:42:57 +08:00
# endif
2001-06-12 16:54:25 +08:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "php.h"
# include "php_ini.h"
2002-03-17 16:10:04 +08:00
# include "ext/standard/info.h"
2001-06-12 16:54:25 +08:00
# include "php_pcntl.h"
2003-02-18 09:41:06 +08:00
# if HAVE_GETPRIORITY || HAVE_SETPRIORITY
# include <sys/time.h>
# include <sys/resource.h>
# endif
2001-06-12 16:54:25 +08:00
ZEND_DECLARE_MODULE_GLOBALS ( pcntl )
function_entry pcntl_functions [ ] = {
2002-03-17 06:31:57 +08:00
PHP_FE ( pcntl_fork , NULL )
PHP_FE ( pcntl_waitpid , second_arg_force_ref )
PHP_FE ( pcntl_signal , NULL )
PHP_FE ( pcntl_wifexited , NULL )
PHP_FE ( pcntl_wifstopped , NULL )
PHP_FE ( pcntl_wifsignaled , NULL )
PHP_FE ( pcntl_wexitstatus , NULL )
PHP_FE ( pcntl_wtermsig , NULL )
PHP_FE ( pcntl_wstopsig , NULL )
PHP_FE ( pcntl_exec , NULL )
2002-06-04 23:51:25 +08:00
PHP_FE ( pcntl_alarm , NULL )
2003-02-18 09:41:06 +08:00
PHP_FE ( pcntl_getpriority , NULL )
PHP_FE ( pcntl_setpriority , NULL )
2001-06-12 16:54:25 +08:00
{ NULL , NULL , NULL }
} ;
zend_module_entry pcntl_module_entry = {
2001-10-12 07:33:59 +08:00
STANDARD_MODULE_HEADER ,
" pcntl " ,
pcntl_functions ,
2001-06-12 16:54:25 +08:00
PHP_MINIT ( pcntl ) ,
PHP_MSHUTDOWN ( pcntl ) ,
2002-08-22 12:20:10 +08:00
PHP_RINIT ( pcntl ) ,
PHP_RSHUTDOWN ( pcntl ) ,
2001-06-12 16:54:25 +08:00
PHP_MINFO ( pcntl ) ,
2001-10-12 07:33:59 +08:00
NO_VERSION_YET ,
2001-06-12 16:54:25 +08:00
STANDARD_MODULE_PROPERTIES
} ;
# ifdef COMPILE_DL_PCNTL
ZEND_GET_MODULE ( pcntl )
# endif
2003-05-30 07:39:41 +08:00
static void pcntl_signal_handler ( int ) ;
static void pcntl_tick_handler ( ) ;
2001-06-20 05:42:57 +08:00
2001-06-12 16:54:25 +08:00
void php_register_signal_constants ( INIT_FUNC_ARGS )
{
2002-03-17 06:31:57 +08:00
2001-07-06 13:48:52 +08:00
/* Wait Constants */
# ifdef WNOHANG
REGISTER_LONG_CONSTANT ( " WNOHANG " , ( long ) WNOHANG , CONST_CS | CONST_PERSISTENT ) ;
# endif
# ifdef WUNTRACED
REGISTER_LONG_CONSTANT ( " WUNTRACED " , ( long ) WUNTRACED , CONST_CS | CONST_PERSISTENT ) ;
# endif
/* Signal Constants */
2001-06-13 09:13:05 +08:00
REGISTER_LONG_CONSTANT ( " SIG_IGN " , ( long ) SIG_IGN , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIG_DFL " , ( long ) SIG_DFL , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIG_ERR " , ( long ) SIG_ERR , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGHUP " , ( long ) SIGHUP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGINT " , ( long ) SIGINT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGQUIT " , ( long ) SIGQUIT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGILL " , ( long ) SIGILL , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGTRAP " , ( long ) SIGTRAP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGABRT " , ( long ) SIGABRT , CONST_CS | CONST_PERSISTENT ) ;
2002-12-12 20:23:32 +08:00
# ifdef SIGIOT
2002-03-17 06:31:57 +08:00
REGISTER_LONG_CONSTANT ( " SIGIOT " , ( long ) SIGIOT , CONST_CS | CONST_PERSISTENT ) ;
2002-12-12 20:23:32 +08:00
# endif
2002-03-17 06:31:57 +08:00
REGISTER_LONG_CONSTANT ( " SIGBUS " , ( long ) SIGBUS , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGFPE " , ( long ) SIGFPE , CONST_CS | CONST_PERSISTENT ) ;
2001-06-13 09:13:05 +08:00
REGISTER_LONG_CONSTANT ( " SIGKILL " , ( long ) SIGKILL , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGUSR1 " , ( long ) SIGUSR1 , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGSEGV " , ( long ) SIGSEGV , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGUSR2 " , ( long ) SIGUSR2 , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGPIPE " , ( long ) SIGPIPE , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGALRM " , ( long ) SIGALRM , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGTERM " , ( long ) SIGTERM , CONST_CS | CONST_PERSISTENT ) ;
# ifdef SIGSTKFLT
REGISTER_LONG_CONSTANT ( " SIGSTKFLT " , ( long ) SIGSTKFLT , CONST_CS | CONST_PERSISTENT ) ;
# endif
# ifdef SIGCLD
REGISTER_LONG_CONSTANT ( " SIGCLD " , ( long ) SIGCLD , CONST_CS | CONST_PERSISTENT ) ;
# endif
# ifdef SIGCHLD
REGISTER_LONG_CONSTANT ( " SIGCHLD " , ( long ) SIGCHLD , CONST_CS | CONST_PERSISTENT ) ;
# endif
REGISTER_LONG_CONSTANT ( " SIGCONT " , ( long ) SIGCONT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGSTOP " , ( long ) SIGSTOP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGTSTP " , ( long ) SIGTSTP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGTTIN " , ( long ) SIGTTIN , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGTTOU " , ( long ) SIGTTOU , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGURG " , ( long ) SIGURG , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGXCPU " , ( long ) SIGXCPU , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGXFSZ " , ( long ) SIGXFSZ , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGVTALRM " , ( long ) SIGVTALRM , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGPROF " , ( long ) SIGPROF , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " SIGWINCH " , ( long ) SIGWINCH , CONST_CS | CONST_PERSISTENT ) ;
2001-06-26 12:54:47 +08:00
# ifdef SIGPOLL
2001-06-13 09:13:05 +08:00
REGISTER_LONG_CONSTANT ( " SIGPOLL " , ( long ) SIGPOLL , CONST_CS | CONST_PERSISTENT ) ;
2001-06-26 12:54:47 +08:00
# endif
2001-06-13 09:13:05 +08:00
REGISTER_LONG_CONSTANT ( " SIGIO " , ( long ) SIGIO , CONST_CS | CONST_PERSISTENT ) ;
2001-06-26 12:54:47 +08:00
# ifdef SIGPWR
2001-06-13 09:13:05 +08:00
REGISTER_LONG_CONSTANT ( " SIGPWR " , ( long ) SIGPWR , CONST_CS | CONST_PERSISTENT ) ;
2001-06-26 12:54:47 +08:00
# endif
2001-06-13 09:13:05 +08:00
REGISTER_LONG_CONSTANT ( " SIGSYS " , ( long ) SIGSYS , CONST_CS | CONST_PERSISTENT ) ;
2001-11-09 04:23:33 +08:00
REGISTER_LONG_CONSTANT ( " SIGBABY " , ( long ) SIGSYS , CONST_CS | CONST_PERSISTENT ) ;
2003-02-18 09:41:06 +08:00
# if HAVE_GETPRIORITY || HAVE_SETPRIORITY
REGISTER_LONG_CONSTANT ( " PRIO_PGRP " , PRIO_PGRP , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " PRIO_USER " , PRIO_USER , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " PRIO_PROCESS " , PRIO_PROCESS , CONST_CS | CONST_PERSISTENT ) ;
# endif
2001-06-12 16:54:25 +08:00
}
2001-06-20 05:42:57 +08:00
2002-03-17 06:31:57 +08:00
static void php_pcntl_init_globals ( zend_pcntl_globals * pcntl_globals )
2002-08-22 12:20:10 +08:00
{
2001-06-20 05:42:57 +08:00
/* Just in case ... */
2001-07-31 03:40:29 +08:00
memset ( & pcntl_globals - > php_signal_queue , 0 , sizeof ( pcntl_globals - > php_signal_queue ) ) ;
2001-06-20 05:42:57 +08:00
2001-07-31 03:40:29 +08:00
zend_llist_init ( & pcntl_globals - > php_signal_queue , sizeof ( long ) , NULL , 1 ) ;
2002-03-17 06:31:57 +08:00
pcntl_globals - > signal_queue_ready = 0 ;
pcntl_globals - > processing_signal_queue = 0 ;
2001-07-31 03:40:29 +08:00
}
2002-08-22 12:20:10 +08:00
PHP_RINIT_FUNCTION ( pcntl )
2001-07-31 03:40:29 +08:00
{
2002-08-22 12:20:10 +08:00
zend_hash_init ( & PCNTL_G ( php_signal_table ) , 16 , NULL , ZVAL_PTR_DTOR , 1 ) ;
return SUCCESS ;
2001-07-31 03:40:29 +08:00
}
PHP_MINIT_FUNCTION ( pcntl )
{
2002-03-17 06:31:57 +08:00
php_register_signal_constants ( INIT_FUNC_ARGS_PASSTHRU ) ;
2002-08-22 12:20:10 +08:00
ZEND_INIT_MODULE_GLOBALS ( pcntl , php_pcntl_init_globals , NULL ) ;
php_add_tick_function ( pcntl_tick_handler ) ;
2001-06-12 16:54:25 +08:00
return SUCCESS ;
}
2001-07-31 03:40:29 +08:00
2001-06-12 16:54:25 +08:00
PHP_MSHUTDOWN_FUNCTION ( pcntl )
{
2001-06-20 05:42:57 +08:00
zend_llist_destroy ( & PCNTL_G ( php_signal_queue ) ) ;
2001-06-12 16:54:25 +08:00
return SUCCESS ;
}
2002-08-22 12:20:10 +08:00
PHP_RSHUTDOWN_FUNCTION ( pcntl )
{
zend_hash_destroy ( & PCNTL_G ( php_signal_table ) ) ;
return SUCCESS ;
}
2001-07-31 03:40:29 +08:00
2001-06-12 16:54:25 +08:00
PHP_MINFO_FUNCTION ( pcntl )
{
php_info_print_table_start ( ) ;
php_info_print_table_header ( 2 , " pcntl support " , " enabled " ) ;
php_info_print_table_end ( ) ;
}
2001-07-06 13:48:52 +08:00
2001-11-09 06:11:41 +08:00
/* {{{ proto int pcntl_fork(void)
2001-06-12 16:54:25 +08:00
Forks the currently running process following the same behavior as the UNIX fork ( ) system call */
PHP_FUNCTION ( pcntl_fork )
{
pid_t id ;
2002-03-17 06:31:57 +08:00
id = fork ( ) ;
2001-06-12 16:54:25 +08:00
if ( id = = - 1 ) {
2002-12-12 21:08:59 +08:00
php_error_docref ( NULL TSRMLS_CC , E_ERROR , " Error %d " , errno ) ;
2001-06-12 16:54:25 +08:00
}
RETURN_LONG ( ( long ) id ) ;
}
/* }}} */
2002-06-04 23:51:25 +08:00
/* {{{ proto int pcntl_alarm(int seconds)
Set an alarm clock for delivery of a signal */
PHP_FUNCTION ( pcntl_alarm )
{
long seconds ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " l " , & seconds ) = = FAILURE )
return ;
RETURN_LONG ( ( long ) alarm ( seconds ) ) ;
}
/* }}} */
2001-11-09 04:23:33 +08:00
/* {{{ proto int pcntl_waitpid(long pid, long status, long options)
2001-11-09 06:11:41 +08:00
Waits on or returns the status of a forked child as defined by the waitpid ( ) system call */
2001-06-12 16:54:25 +08:00
PHP_FUNCTION ( pcntl_waitpid )
{
2002-04-24 05:21:41 +08:00
long pid , options = 0 ;
zval * z_status = NULL ;
int status ;
pid_t child_id ;
2001-06-12 16:54:25 +08:00
2002-04-24 05:21:41 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " lz|l " , & pid , & z_status , & options ) = = FAILURE )
return ;
2002-05-07 07:01:46 +08:00
convert_to_long_ex ( & z_status ) ;
2001-06-12 16:54:25 +08:00
2002-04-24 05:21:41 +08:00
status = Z_LVAL_P ( z_status ) ;
2001-06-12 16:54:25 +08:00
2002-04-24 05:21:41 +08:00
child_id = waitpid ( ( pid_t ) pid , & status , options ) ;
Z_LVAL_P ( z_status ) = status ;
RETURN_LONG ( ( long ) child_id ) ;
2001-06-12 16:54:25 +08:00
}
/* }}} */
2001-07-06 14:00:51 +08:00
/* {{{ proto bool pcntl_wifexited(long status)
2001-07-06 13:48:52 +08:00
Returns true if the child status code represents a successful exit */
PHP_FUNCTION ( pcntl_wifexited )
{
# ifdef WIFEXITED
zval * * status ;
int status_word ;
2002-03-17 06:31:57 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 1 | | zend_get_parameters_ex ( ZEND_NUM_ARGS ( ) , & status ) = = FAILURE ) {
2001-07-06 13:48:52 +08:00
WRONG_PARAM_COUNT ;
}
2002-03-17 06:31:57 +08:00
2001-07-06 13:48:52 +08:00
status_word = ( int ) Z_LVAL_PP ( status ) ;
2002-03-17 06:31:57 +08:00
if ( WIFEXITED ( status_word ) ) RETURN_TRUE ;
2001-07-06 13:48:52 +08:00
# endif
RETURN_FALSE ;
}
/* }}} */
2001-07-06 14:00:51 +08:00
/* {{{ proto bool pcntl_wifstopped(long status)
2001-11-09 06:11:41 +08:00
Returns true if the child status code represents a stopped process ( WUNTRACED must have been used with waitpid ) */
2001-07-06 13:48:52 +08:00
PHP_FUNCTION ( pcntl_wifstopped )
{
# ifdef WIFSTOPPED
zval * * status ;
int status_word ;
2002-03-17 06:31:57 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 1 | | zend_get_parameters_ex ( ZEND_NUM_ARGS ( ) , & status ) = = FAILURE ) {
2001-07-06 13:48:52 +08:00
WRONG_PARAM_COUNT ;
}
2002-03-17 06:31:57 +08:00
2001-07-06 13:48:52 +08:00
status_word = ( int ) Z_LVAL_PP ( status ) ;
2002-03-17 06:31:57 +08:00
if ( WIFSTOPPED ( status_word ) ) RETURN_TRUE ;
2001-07-06 13:48:52 +08:00
# endif
RETURN_FALSE ;
}
/* }}} */
2001-07-06 14:00:51 +08:00
/* {{{ proto bool pcntl_wifsignaled(long status)
2001-07-06 13:48:52 +08:00
Returns true if the child status code represents a process that was terminated due to a signal */
PHP_FUNCTION ( pcntl_wifsignaled )
{
# ifdef WIFSIGNALED
zval * * status ;
int status_word ;
2002-03-17 06:31:57 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 1 | | zend_get_parameters_ex ( ZEND_NUM_ARGS ( ) , & status ) = = FAILURE ) {
2001-07-06 13:48:52 +08:00
WRONG_PARAM_COUNT ;
}
2002-03-17 06:31:57 +08:00
2001-07-06 13:48:52 +08:00
status_word = ( int ) Z_LVAL_PP ( status ) ;
2002-03-17 06:31:57 +08:00
if ( WIFSIGNALED ( status_word ) ) RETURN_TRUE ;
2001-07-06 13:48:52 +08:00
# endif
RETURN_FALSE ;
}
/* }}} */
2001-11-09 04:23:33 +08:00
/* {{{ proto int pcntl_wexitstatus(long status)
2001-07-06 13:48:52 +08:00
Returns the status code of a child ' s exit */
PHP_FUNCTION ( pcntl_wexitstatus )
{
# ifdef WEXITSTATUS
zval * * status ;
int status_word ;
2002-03-17 06:31:57 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 1 | | zend_get_parameters_ex ( ZEND_NUM_ARGS ( ) , & status ) = = FAILURE ) {
2001-07-06 13:48:52 +08:00
WRONG_PARAM_COUNT ;
}
2002-03-17 06:31:57 +08:00
2001-07-06 13:48:52 +08:00
status_word = ( int ) Z_LVAL_PP ( status ) ;
/* WEXITSTATUS only returns 8 bits so we *MUST* cast this to signed char
if you want to have valid negative exit codes */
2002-03-17 06:31:57 +08:00
RETURN_LONG ( ( signed char ) WEXITSTATUS ( status_word ) ) ;
2001-07-06 13:48:52 +08:00
# else
RETURN_FALSE ;
# endif
}
/* }}} */
2001-11-09 04:23:33 +08:00
/* {{{ proto int pcntl_wtermsig(long status)
2001-07-06 13:48:52 +08:00
Returns the number of the signal that terminated the process who ' s status code is passed */
PHP_FUNCTION ( pcntl_wtermsig )
{
# ifdef WTERMSIG
zval * * status ;
int status_word ;
2002-03-17 06:31:57 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 1 | | zend_get_parameters_ex ( ZEND_NUM_ARGS ( ) , & status ) = = FAILURE ) {
2001-07-06 13:48:52 +08:00
WRONG_PARAM_COUNT ;
}
2002-03-17 06:31:57 +08:00
2001-07-06 13:48:52 +08:00
status_word = ( int ) Z_LVAL_PP ( status ) ;
2002-03-17 06:31:57 +08:00
RETURN_LONG ( WTERMSIG ( status_word ) ) ;
2001-07-06 13:48:52 +08:00
# else
RETURN_FALSE ;
# endif
}
/* }}} */
2001-11-09 04:23:33 +08:00
/* {{{ proto int pcntl_wstopsig(long status)
2001-11-09 06:11:41 +08:00
Returns the number of the signal that caused the process to stop who ' s status code is passed */
2001-07-06 13:48:52 +08:00
PHP_FUNCTION ( pcntl_wstopsig )
{
# ifdef WSTOPSIG
zval * * status ;
int status_word ;
2002-03-17 06:31:57 +08:00
if ( ZEND_NUM_ARGS ( ) ! = 1 | | zend_get_parameters_ex ( ZEND_NUM_ARGS ( ) , & status ) = = FAILURE ) {
2001-07-06 13:48:52 +08:00
WRONG_PARAM_COUNT ;
}
status_word = ( int ) Z_LVAL_PP ( status ) ;
RETURN_LONG ( WSTOPSIG ( status_word ) ) ;
# else
RETURN_FALSE ;
# endif
}
/* }}} */
2002-01-04 22:08:25 +08:00
/* {{{ proto bool pcntl_exec(string path [, array args [, array envs]])
2001-11-09 06:11:41 +08:00
Executes specified program in current process space as defined by exec ( 2 ) */
2001-09-30 14:59:12 +08:00
PHP_FUNCTION ( pcntl_exec )
{
zval * args , * envs ;
zval * * element ;
HashTable * args_hash , * envs_hash ;
2002-03-17 06:31:57 +08:00
int argc = 0 , argi = 0 ;
int envc = 0 , envi = 0 ;
int return_val = 0 ;
char * * argv = NULL , * * envp = NULL ;
char * * current_arg , * * pair ;
2001-09-30 14:59:12 +08:00
int pair_length ;
2002-03-17 06:31:57 +08:00
char * key ;
2001-09-30 14:59:12 +08:00
int key_length ;
char * path ;
int path_len ;
long key_num ;
2002-03-17 06:31:57 +08:00
2002-03-17 06:19:10 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " s|aa " , & path , & path_len , & args , & envs ) = = FAILURE ) {
2001-09-30 14:59:12 +08:00
return ;
}
2002-03-17 06:31:57 +08:00
if ( ZEND_NUM_ARGS ( ) > 1 ) {
2001-09-30 14:59:12 +08:00
/* Build argumnent list */
2002-03-17 06:31:57 +08:00
args_hash = HASH_OF ( args ) ;
argc = zend_hash_num_elements ( args_hash ) ;
argv = alloca ( ( argc + 2 ) * sizeof ( char * ) ) ;
* argv = path ;
for ( zend_hash_internal_pointer_reset ( args_hash ) , current_arg = argv + 1 ;
( argi < argc & & ( zend_hash_get_current_data ( args_hash , ( void * * ) & element ) = = SUCCESS ) ) ;
( argi + + , current_arg + + , zend_hash_move_forward ( args_hash ) ) ) {
2002-05-07 03:48:39 +08:00
convert_to_string_ex ( element ) ;
2002-03-17 06:31:57 +08:00
* current_arg = Z_STRVAL_PP ( element ) ;
2001-09-30 14:59:12 +08:00
}
2002-03-17 06:31:57 +08:00
* ( current_arg ) = NULL ;
2001-09-30 14:59:12 +08:00
} else {
2002-03-17 06:31:57 +08:00
argv = alloca ( 2 * sizeof ( char * ) ) ;
* argv = path ;
* ( argv + 1 ) = NULL ;
2001-09-30 14:59:12 +08:00
}
2002-03-17 06:31:57 +08:00
if ( ZEND_NUM_ARGS ( ) = = 3 ) {
2001-09-30 14:59:12 +08:00
/* Build environment pair list */
2002-03-17 06:31:57 +08:00
envs_hash = HASH_OF ( envs ) ;
envc = zend_hash_num_elements ( envs_hash ) ;
envp = alloca ( ( envc + 1 ) * sizeof ( char * ) ) ;
for ( zend_hash_internal_pointer_reset ( envs_hash ) , pair = envp ;
( envi < envc & & ( zend_hash_get_current_data ( envs_hash , ( void * * ) & element ) = = SUCCESS ) ) ;
( envi + + , pair + + , zend_hash_move_forward ( envs_hash ) ) ) {
switch ( return_val = zend_hash_get_current_key_ex ( envs_hash , & key , & key_length , & key_num , 0 , NULL ) ) {
2001-09-30 14:59:12 +08:00
case HASH_KEY_IS_LONG :
2002-03-17 06:31:57 +08:00
key = alloca ( 101 ) ;
2001-09-30 14:59:12 +08:00
snprintf ( key , 100 , " %ld " , key_num ) ;
2002-03-17 06:31:57 +08:00
key_length = strlen ( key ) ;
break ;
2001-09-30 14:59:12 +08:00
case HASH_KEY_NON_EXISTANT :
pair - - ;
continue ;
}
2002-05-07 03:48:39 +08:00
convert_to_string_ex ( element ) ;
2001-09-30 14:59:12 +08:00
/* Length of element + equal sign + length of key + null */
2002-03-17 06:31:57 +08:00
pair_length = Z_STRLEN_PP ( element ) + key_length + 2 ;
* pair = emalloc ( pair_length ) ;
strlcpy ( * pair , key , key_length ) ;
2001-09-30 14:59:12 +08:00
strlcat ( * pair , " = " , pair_length ) ;
strlcat ( * pair , Z_STRVAL_PP ( element ) , pair_length ) ;
2002-03-17 06:31:57 +08:00
2001-09-30 14:59:12 +08:00
/* Cleanup */
2001-10-03 11:48:27 +08:00
if ( return_val = = HASH_KEY_IS_LONG ) free_alloca ( key ) ;
2001-09-30 14:59:12 +08:00
}
2002-03-17 06:31:57 +08:00
* ( pair ) = NULL ;
2001-09-30 14:59:12 +08:00
}
2002-03-17 06:31:57 +08:00
2001-09-30 14:59:12 +08:00
if ( execve ( path , argv , envp ) = = - 1 ) {
2002-12-12 21:08:59 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error has occured: (errno %d) %s " , errno , strerror ( errno ) ) ;
2001-09-30 14:59:12 +08:00
}
2002-03-17 06:31:57 +08:00
2001-10-03 11:48:27 +08:00
/* Cleanup */
2002-05-07 03:48:39 +08:00
if ( envp ! = NULL ) {
for ( pair = envp ; * pair ! = NULL ; pair + + ) efree ( * pair ) ;
free_alloca ( envp ) ;
}
2001-10-03 11:48:27 +08:00
free_alloca ( argv ) ;
2002-03-17 06:31:57 +08:00
2001-09-30 14:59:12 +08:00
RETURN_FALSE ;
}
/* }}} */
2003-05-20 21:35:13 +08:00
/* {{{ proto bool pcntl_signal(long signo, callback handle, [bool restart_syscalls])
2001-11-09 06:11:41 +08:00
Assigns a system signal handler to a PHP function */
2001-06-12 16:54:25 +08:00
PHP_FUNCTION ( pcntl_signal )
{
2002-08-22 12:20:10 +08:00
zval * handle , * * dest_handle = NULL ;
2002-03-17 06:31:57 +08:00
char * func_name ;
2002-08-22 12:20:10 +08:00
long signo ;
zend_bool restart_syscalls = 1 ;
2001-06-12 16:54:25 +08:00
2002-08-22 12:20:10 +08:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " lz|b " , & signo , & handle , & restart_syscalls ) = = FAILURE ) {
return ;
2001-06-12 16:54:25 +08:00
}
/* Special long value case for SIG_DFL and SIG_IGN */
2002-08-22 12:20:10 +08:00
if ( Z_TYPE_P ( handle ) = = IS_LONG ) {
if ( Z_LVAL_P ( handle ) ! = ( long ) SIG_DFL & & Z_LVAL_P ( handle ) ! = ( long ) SIG_IGN ) {
2002-12-12 21:08:59 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Invalid value for handle argument specifEied " ) ;
2001-06-12 16:54:25 +08:00
}
2002-08-22 12:20:10 +08:00
if ( php_signal ( signo , ( Sigfunc * ) Z_LVAL_P ( handle ) , ( int ) restart_syscalls ) = = SIG_ERR ) {
2002-12-12 21:08:59 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error assigning singal " ) ;
2002-03-17 06:31:57 +08:00
RETURN_FALSE ;
2001-06-12 16:54:25 +08:00
}
RETURN_TRUE ;
2002-03-17 06:31:57 +08:00
}
2001-06-12 16:54:25 +08:00
2002-08-22 12:20:10 +08:00
if ( ! zend_is_callable ( handle , 0 , & func_name ) ) {
2002-12-12 21:08:59 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %s is not a callable function name error " , func_name ) ;
2002-03-17 06:31:57 +08:00
efree ( func_name ) ;
2001-06-12 16:54:25 +08:00
RETURN_FALSE ;
}
2002-03-17 06:31:57 +08:00
efree ( func_name ) ;
2001-06-12 16:54:25 +08:00
2002-08-22 12:20:10 +08:00
/* Add the function name to our signal table */
zend_hash_index_update ( & PCNTL_G ( php_signal_table ) , signo , ( void * * ) & handle , sizeof ( zval * ) , ( void * * ) & dest_handle ) ;
if ( dest_handle ) zval_add_ref ( dest_handle ) ;
if ( php_signal ( signo , pcntl_signal_handler , ( int ) restart_syscalls ) = = SIG_ERR ) {
2002-12-12 21:08:59 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error assigning singal " ) ;
2002-08-22 12:20:10 +08:00
RETURN_FALSE ;
2001-06-12 16:54:25 +08:00
}
2002-03-17 06:31:57 +08:00
RETURN_TRUE ;
2001-06-12 16:54:25 +08:00
}
/* }}} */
2003-02-18 09:41:06 +08:00
# ifdef HAVE_GETPRIORITY
/* {{{ proto int pcntl_getpriority(int pid, [int process_identifier]])
Get the priority of any process */
PHP_FUNCTION ( pcntl_getpriority )
{
long who = PRIO_PROCESS ;
long pid = getpid ( ) ;
int pri ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " |ll " , & pid , & who ) = = FAILURE ) {
RETURN_FALSE ;
}
/* needs to be cleared, since any returned value is valid */
errno = 0 ;
pri = getpriority ( who , pid ) ;
if ( errno ) {
switch ( errno ) {
case ESRCH :
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %l: No process was located using the given parameters. " , errno ) ;
break ;
case EINVAL :
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %l: Invalid identifier flag. " , errno ) ;
break ;
default :
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unknown error %l has occured. " , errno ) ;
break ;
}
RETURN_FALSE ;
}
RETURN_LONG ( pri ) ;
}
/* }}} */
# endif
# ifdef HAVE_SETPRIORITY
/* {{{ proto bool pcntl_setpriority(int priority, [int pid, [int process_identifier]])
Change the priority of any process */
PHP_FUNCTION ( pcntl_setpriority )
{
long who = PRIO_PROCESS ;
long pid = getpid ( ) ;
long pri ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " l|ll " , & pri , & pid , & who ) = = FAILURE ) {
RETURN_FALSE ;
}
if ( setpriority ( who , pid , pri ) ) {
switch ( errno ) {
case ESRCH :
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %l: No process was located using the given parameters. " , errno ) ;
break ;
case EINVAL :
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %l: Invalid identifier flag. " , errno ) ;
break ;
case EPERM :
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %l: A process was located, but neither its effective nor real user ID matched the effective user ID of the caller. " , errno ) ;
break ;
case EACCES :
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " %l: Only a super user may attempt to increase the process priority. " , errno ) ;
break ;
default :
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unknown error %l has occured. " , errno ) ;
break ;
}
RETURN_FALSE ;
}
RETURN_TRUE ;
}
/* }}} */
# endif
2001-06-26 01:56:23 +08:00
/* Our custom signal handler that calls the appropriate php_function */
2001-06-20 05:42:57 +08:00
static void pcntl_signal_handler ( int signo )
{
2002-03-17 06:31:57 +08:00
long signal_num = signo ;
2001-07-31 03:40:29 +08:00
TSRMLS_FETCH ( ) ;
2002-03-17 06:31:57 +08:00
2002-08-22 12:20:10 +08:00
IF_DEBUG ( DEBUG_OUT ( " Caught signo %d \n " , signo ) ) ;
if ( ! PCNTL_G ( processing_signal_queue ) ) {
2001-06-20 05:42:57 +08:00
zend_llist_add_element ( & PCNTL_G ( php_signal_queue ) , & signal_num ) ;
2002-03-17 06:31:57 +08:00
PCNTL_G ( signal_queue_ready ) = 1 ;
2002-08-22 12:20:10 +08:00
IF_DEBUG ( DEBUG_OUT ( " Added queue entry \n " ) ) ;
2001-06-20 05:42:57 +08:00
}
return ;
}
2002-08-22 12:20:10 +08:00
void pcntl_tick_handler ( )
2001-07-30 16:24:42 +08:00
{
2001-06-20 05:42:57 +08:00
zend_llist_element * element ;
2002-08-22 12:20:10 +08:00
zval * param , * * handle , * retval ;
2001-07-30 16:24:42 +08:00
TSRMLS_FETCH ( ) ;
2001-06-20 05:42:57 +08:00
/* Bail if the queue is empty or if we are already playing the queue*/
if ( ! PCNTL_G ( signal_queue_ready ) | | PCNTL_G ( processing_signal_queue ) )
return ;
2002-03-17 06:31:57 +08:00
/* Mark our queue empty */
PCNTL_G ( signal_queue_ready ) = 0 ;
2001-06-20 05:42:57 +08:00
/* If for some reason our signal queue is empty then return */
if ( zend_llist_count ( & PCNTL_G ( php_signal_queue ) ) < = 0 ) {
return ;
}
2002-03-17 06:31:57 +08:00
2002-08-22 12:20:10 +08:00
/* Prevent reentrant handler calls */
2002-03-17 06:31:57 +08:00
PCNTL_G ( processing_signal_queue ) = 1 ;
2001-06-20 05:42:57 +08:00
/* Allocate */
MAKE_STD_ZVAL ( param ) ;
MAKE_STD_ZVAL ( retval ) ;
/* Traverse through our signal queue and call the appropriate php functions */
2002-03-17 06:31:57 +08:00
for ( element = ( & PCNTL_G ( php_signal_queue ) ) - > head ; element ; element = element - > next ) {
long * signal_num = ( long * ) & element - > data ;
2002-08-22 12:20:10 +08:00
if ( zend_hash_index_find ( & PCNTL_G ( php_signal_table ) , * signal_num , ( void * * ) & handle ) = = FAILURE ) {
2001-06-20 05:42:57 +08:00
continue ;
}
2002-05-07 07:01:46 +08:00
2001-06-26 01:56:23 +08:00
ZVAL_LONG ( param , * signal_num ) ;
2002-03-17 06:31:57 +08:00
2003-05-20 21:35:13 +08:00
/* Call php singal handler - Note that we do not report errors, and we ignore the return value */
2002-08-22 12:20:10 +08:00
call_user_function ( EG ( function_table ) , NULL , * handle , retval , 1 , & param TSRMLS_CC ) ;
2001-06-20 05:42:57 +08:00
}
/* Clear */
zend_llist_clean ( & PCNTL_G ( php_signal_queue ) ) ;
/* Re-enable queue */
2002-03-17 06:31:57 +08:00
PCNTL_G ( processing_signal_queue ) = 0 ;
2001-06-20 05:42:57 +08:00
/* Clean up */
efree ( param ) ;
efree ( retval ) ;
}
2001-06-12 16:54:25 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* indent - tabs - mode : t
* End :
*/