2001-06-12 16:54:25 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-01-08 16:18:22 +08:00
| PHP Version 5 |
2001-06-12 16:54:25 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2005-08-03 22:08:58 +08:00
| Copyright ( c ) 1997 - 2005 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-10-29 01:08:18 +08:00
# if HAVE_GETPRIORITY || HAVE_SETPRIORITY || HAVE_WAIT3
2003-02-18 09:41:06 +08:00
# include <sys/time.h>
# include <sys/resource.h>
# endif
2001-06-12 16:54:25 +08:00
ZEND_DECLARE_MODULE_GLOBALS ( pcntl )
2005-12-06 10:28:41 +08:00
zend_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 )
2003-10-29 01:08:18 +08:00
PHP_FE ( pcntl_wait , first_arg_force_ref )
2002-03-17 06:31:57 +08:00
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 )
2004-08-28 20:20:06 +08:00
# ifdef HAVE_GETPRIORITY
2003-02-18 09:41:06 +08:00
PHP_FE ( pcntl_getpriority , NULL )
2004-08-28 20:20:06 +08:00
# endif
# ifdef HAVE_SETPRIORITY
2003-02-18 09:41:06 +08:00
PHP_FE ( pcntl_setpriority , NULL )
2004-08-28 20:20:06 +08:00
# endif
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 )
2003-08-31 20:41:53 +08:00
# ifdef PHP_WIN32
# include "zend_arg_defs.c"
# endif
2001-06-12 16:54:25 +08:00
# 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
2004-12-14 22:01:06 +08:00
# ifdef SIGSYS
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 ) ;
2004-12-14 22:01:06 +08:00
# endif
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
{
2005-05-07 22:58:12 +08:00
memset ( pcntl_globals , 0 , sizeof ( * pcntl_globals ) ) ;
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
{
2005-05-07 22:58:12 +08:00
zend_hash_init ( & PCNTL_G ( php_signal_table ) , 16 , NULL , ZVAL_PTR_DTOR , 0 ) ;
PCNTL_G ( head ) = PCNTL_G ( tail ) = PCNTL_G ( spares ) = NULL ;
2002-08-22 12:20:10 +08:00
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 )
{
return SUCCESS ;
}
2002-08-22 12:20:10 +08:00
PHP_RSHUTDOWN_FUNCTION ( pcntl )
{
2005-05-07 22:58:12 +08:00
struct php_pcntl_pending_signal * sig ;
/* FIXME: if a signal is delivered after this point, things will go pear shaped;
* need to remove signal handlers */
2002-08-22 12:20:10 +08:00
zend_hash_destroy ( & PCNTL_G ( php_signal_table ) ) ;
2005-05-07 22:58:12 +08:00
while ( PCNTL_G ( head ) ) {
sig = PCNTL_G ( head ) ;
PCNTL_G ( head ) = sig - > next ;
efree ( sig ) ;
}
while ( PCNTL_G ( spares ) ) {
sig = PCNTL_G ( spares ) ;
PCNTL_G ( spares ) = sig - > next ;
efree ( sig ) ;
}
2002-08-22 12:20:10 +08:00
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 ) ) ;
}
/* }}} */
2003-06-22 22:33:09 +08:00
/* {{{ proto int pcntl_waitpid(int pid, int &status, int 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
}
/* }}} */
2003-10-29 01:08:18 +08:00
/* {{{ proto int pcntl_wait(int &status)
Waits on or returns the status of a forked child as defined by the waitpid ( ) system call */
PHP_FUNCTION ( pcntl_wait )
{
2003-11-06 07:44:09 +08:00
long options = 0 ;
2003-10-29 01:08:18 +08:00
zval * z_status = NULL ;
int status ;
pid_t child_id ;
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) TSRMLS_CC , " z|l " , & z_status , & options ) = = FAILURE )
return ;
convert_to_long_ex ( & z_status ) ;
status = Z_LVAL_P ( z_status ) ;
# ifdef HAVE_WAIT3
if ( options ) {
child_id = wait3 ( & status , options , NULL ) ;
}
else {
child_id = wait ( & status ) ;
}
# else
child_id = wait ( & status ) ;
# endif
Z_LVAL_P ( z_status ) = status ;
RETURN_LONG ( ( long ) child_id ) ;
}
/* }}} */
2003-06-22 22:33:09 +08:00
/* {{{ proto bool pcntl_wifexited(int 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 ;
}
/* }}} */
2003-06-22 22:33:09 +08:00
/* {{{ proto bool pcntl_wifstopped(int 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 ;
}
/* }}} */
2003-06-22 22:33:09 +08:00
/* {{{ proto bool pcntl_wifsignaled(int 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 ;
}
/* }}} */
2003-06-22 22:33:09 +08:00
/* {{{ proto int pcntl_wexitstatus(int 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
}
/* }}} */
2003-06-22 22:33:09 +08:00
/* {{{ proto int pcntl_wtermsig(int 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
}
/* }}} */
2003-06-22 22:33:09 +08:00
/* {{{ proto int pcntl_wstopsig(int 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 ) ;
2004-06-30 09:12:06 +08:00
argv = safe_emalloc ( ( argc + 2 ) , sizeof ( char * ) , 0 ) ;
2002-03-17 06:31:57 +08:00
* 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 {
2004-06-30 09:12:06 +08:00
argv = emalloc ( 2 * sizeof ( char * ) ) ;
2002-03-17 06:31:57 +08:00
* 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 ) ;
2004-06-30 09:12:06 +08:00
envp = safe_emalloc ( ( envc + 1 ) , sizeof ( char * ) , 0 ) ;
2002-03-17 06:31:57 +08:00
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 :
2004-06-30 09:12:06 +08:00
key = emalloc ( 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 */
2004-06-30 09:12:06 +08:00
if ( return_val = = HASH_KEY_IS_LONG ) efree ( 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 ) ;
2004-06-30 09:12:06 +08:00
efree ( envp ) ;
2002-05-07 03:48:39 +08:00
}
2004-06-30 09:12:06 +08:00
efree ( argv ) ;
2002-03-17 06:31:57 +08:00
2001-09-30 14:59:12 +08:00
RETURN_FALSE ;
}
/* }}} */
2003-06-22 22:33:09 +08:00
/* {{{ proto bool pcntl_signal(int 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
}
2005-05-07 22:58:12 +08:00
if ( ! PCNTL_G ( spares ) ) {
/* since calling malloc() from within a signal handler is not portable,
* pre - allocate a few records for recording signals */
int i ;
for ( i = 0 ; i < 32 ; i + + ) {
struct php_pcntl_pending_signal * psig ;
psig = emalloc ( sizeof ( * psig ) ) ;
psig - > next = PCNTL_G ( spares ) ;
PCNTL_G ( spares ) = psig ;
}
}
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 ) {
2004-01-23 15:02:15 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error assigning signal " ) ;
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 ) {
2004-01-23 15:02:15 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error assigning signal " ) ;
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
2003-06-22 22:33:09 +08:00
/* {{{ proto int pcntl_getpriority([int pid [, int process_identifier]])
2003-02-18 09:41:06 +08:00
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 :
2003-08-31 22:35:10 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error %d: No process was located using the given parameters " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
case EINVAL :
2003-08-31 22:35:10 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error %d: Invalid identifier flag " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
default :
2003-08-31 22:35:10 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unknown error %d has occured " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
}
RETURN_FALSE ;
}
RETURN_LONG ( pri ) ;
}
/* }}} */
# endif
# ifdef HAVE_SETPRIORITY
2003-06-22 22:33:09 +08:00
/* {{{ proto bool pcntl_setpriority(int priority [, int pid [, int process_identifier]])
2003-02-18 09:41:06 +08:00
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 :
2003-08-31 22:35:10 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error %d: No process was located using the given parameters " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
case EINVAL :
2003-08-31 22:35:10 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error %d: Invalid identifier flag " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
case EPERM :
2003-08-31 22:35:10 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error %d: A process was located, but neither its effective nor real user ID matched the effective user ID of the caller " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
case EACCES :
2003-08-31 22:35:10 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Error %d: Only a super user may attempt to increase the process priority " , errno ) ;
2003-02-18 09:41:06 +08:00
break ;
default :
2003-08-31 22:35:10 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unknown error %d has occured " , errno ) ;
2003-02-18 09:41:06 +08:00
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 )
{
2005-05-07 22:58:12 +08:00
struct php_pcntl_pending_signal * psig ;
2001-07-31 03:40:29 +08:00
TSRMLS_FETCH ( ) ;
2002-03-17 06:31:57 +08:00
2005-05-07 22:58:12 +08:00
psig = PCNTL_G ( spares ) ;
if ( ! psig ) {
/* oops, too many signals for us to track, so we'll forget about this one */
return ;
}
PCNTL_G ( spares ) = psig - > next ;
psig - > signo = signo ;
psig - > next = NULL ;
/* the head check is important, as the tick handler cannot atomically clear both
* the head and tail */
if ( PCNTL_G ( head ) & & PCNTL_G ( tail ) ) {
PCNTL_G ( tail ) - > next = psig ;
} else {
PCNTL_G ( head ) = psig ;
2001-06-20 05:42:57 +08:00
}
2005-05-07 22:58:12 +08:00
PCNTL_G ( tail ) = psig ;
2001-06-20 05:42:57 +08:00
}
2002-08-22 12:20:10 +08:00
void pcntl_tick_handler ( )
2001-07-30 16:24:42 +08:00
{
2002-08-22 12:20:10 +08:00
zval * param , * * handle , * retval ;
2005-05-07 22:58:12 +08:00
struct php_pcntl_pending_signal * queue , * next ;
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*/
2005-05-07 22:58:12 +08:00
if ( ! PCNTL_G ( head ) | | PCNTL_G ( processing_signal_queue ) )
2001-06-20 05:42:57 +08:00
return ;
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 ;
2005-05-07 22:58:12 +08:00
queue = PCNTL_G ( head ) ;
PCNTL_G ( head ) = NULL ; /* simple stores are atomic */
2001-06-20 05:42:57 +08:00
/* Allocate */
MAKE_STD_ZVAL ( param ) ;
MAKE_STD_ZVAL ( retval ) ;
2005-05-07 22:58:12 +08:00
while ( queue ) {
if ( zend_hash_index_find ( & PCNTL_G ( php_signal_table ) , queue - > signo , ( void * * ) & handle ) = = SUCCESS ) {
ZVAL_LONG ( param , queue - > signo ) ;
/* Call php signal handler - Note that we do not report errors, and we ignore the return value */
/* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
call_user_function ( EG ( function_table ) , NULL , * handle , retval , 1 , & param TSRMLS_CC ) ;
2001-06-20 05:42:57 +08:00
}
2002-05-07 07:01:46 +08:00
2005-05-07 22:58:12 +08:00
next = queue - > next ;
queue - > next = PCNTL_G ( spares ) ;
PCNTL_G ( spares ) = queue ;
queue = next ;
2001-06-20 05:42:57 +08:00
}
/* 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 ) ;
}
2005-05-07 22:58:12 +08:00
2001-06-12 16:54:25 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* indent - tabs - mode : t
* End :
*/