PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/pcntl - pcntl.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 394 471 83.7 %
Date: 2014-12-15 Functions: 28 31 90.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Author: Jason Greene <jason@inetgurus.net>                           |
      16             :    +----------------------------------------------------------------------+
      17             :  */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #define PCNTL_DEBUG 0
      22             : 
      23             : #if PCNTL_DEBUG
      24             : #define DEBUG_OUT printf("DEBUG: ");printf
      25             : #define IF_DEBUG(z) z
      26             : #else
      27             : #define IF_DEBUG(z)
      28             : #endif
      29             : 
      30             : #ifdef HAVE_CONFIG_H
      31             : #include "config.h"
      32             : #endif
      33             : 
      34             : #include "php.h"
      35             : #include "php_ini.h"
      36             : #include "ext/standard/info.h"
      37             : #include "php_pcntl.h"
      38             : #include "php_signal.h"
      39             : #include "php_ticks.h"
      40             : 
      41             : #if HAVE_GETPRIORITY || HAVE_SETPRIORITY || HAVE_WAIT3
      42             : #include <sys/wait.h>
      43             : #include <sys/time.h>
      44             : #include <sys/resource.h>
      45             : #endif
      46             : 
      47             : #include <errno.h>
      48             : 
      49             : ZEND_DECLARE_MODULE_GLOBALS(pcntl)
      50             : static PHP_GINIT_FUNCTION(pcntl);
      51             : 
      52             : /* {{{ arginfo */
      53             : ZEND_BEGIN_ARG_INFO(arginfo_pcntl_void, 0)
      54             : ZEND_END_ARG_INFO()
      55             : 
      56             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_waitpid, 0, 0, 2)
      57             :         ZEND_ARG_INFO(0, pid)
      58             :         ZEND_ARG_INFO(1, status)
      59             :         ZEND_ARG_INFO(0, options)
      60             : ZEND_END_ARG_INFO()
      61             : 
      62             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wait, 0, 0, 1)
      63             :         ZEND_ARG_INFO(1, status)
      64             :         ZEND_ARG_INFO(0, options)
      65             : ZEND_END_ARG_INFO()
      66             : 
      67             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_signal, 0, 0, 2)
      68             :         ZEND_ARG_INFO(0, signo)
      69             :         ZEND_ARG_INFO(0, handler)
      70             :         ZEND_ARG_INFO(0, restart_syscalls)
      71             : ZEND_END_ARG_INFO()
      72             : 
      73             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_sigprocmask, 0, 0, 2)
      74             :         ZEND_ARG_INFO(0, how)
      75             :         ZEND_ARG_INFO(0, set)
      76             :         ZEND_ARG_INFO(1, oldset)
      77             : ZEND_END_ARG_INFO()
      78             : 
      79             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_sigwaitinfo, 0, 0, 1)
      80             :         ZEND_ARG_INFO(0, set)
      81             :         ZEND_ARG_INFO(1, info)
      82             : ZEND_END_ARG_INFO()
      83             : 
      84             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_sigtimedwait, 0, 0, 1)
      85             :         ZEND_ARG_INFO(0, set)
      86             :         ZEND_ARG_INFO(1, info)
      87             :         ZEND_ARG_INFO(0, seconds)
      88             :         ZEND_ARG_INFO(0, nanoseconds)
      89             : ZEND_END_ARG_INFO()
      90             : 
      91             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifexited, 0, 0, 1)
      92             :         ZEND_ARG_INFO(0, status)
      93             : ZEND_END_ARG_INFO()
      94             : 
      95             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifstopped, 0, 0, 1)
      96             :         ZEND_ARG_INFO(0, status)
      97             : ZEND_END_ARG_INFO()
      98             : 
      99             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifsignaled, 0, 0, 1)
     100             :         ZEND_ARG_INFO(0, status)
     101             : ZEND_END_ARG_INFO()
     102             : 
     103             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifexitstatus, 0, 0, 1)
     104             :         ZEND_ARG_INFO(0, status)
     105             : ZEND_END_ARG_INFO()
     106             : 
     107             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wtermsig, 0, 0, 1)
     108             :         ZEND_ARG_INFO(0, status)
     109             : ZEND_END_ARG_INFO()
     110             : 
     111             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wstopsig, 0, 0, 1)
     112             :         ZEND_ARG_INFO(0, status)
     113             : ZEND_END_ARG_INFO()
     114             : 
     115             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_exec, 0, 0, 1)
     116             :         ZEND_ARG_INFO(0, path)
     117             :         ZEND_ARG_INFO(0, args)
     118             :         ZEND_ARG_INFO(0, envs)
     119             : ZEND_END_ARG_INFO()
     120             : 
     121             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_alarm, 0, 0, 1)
     122             :         ZEND_ARG_INFO(0, seconds)
     123             : ZEND_END_ARG_INFO()
     124             : 
     125             : #ifdef HAVE_GETPRIORITY
     126             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_getpriority, 0, 0, 0)
     127             :         ZEND_ARG_INFO(0, pid)
     128             :         ZEND_ARG_INFO(0, process_identifier)
     129             : ZEND_END_ARG_INFO()
     130             : #endif
     131             : 
     132             : #ifdef HAVE_SETPRIORITY
     133             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_setpriority, 0, 0, 1)
     134             :         ZEND_ARG_INFO(0, priority)
     135             :         ZEND_ARG_INFO(0, pid)
     136             :         ZEND_ARG_INFO(0, process_identifier)
     137             : ZEND_END_ARG_INFO()
     138             : #endif
     139             : 
     140             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_strerror, 0, 0, 1)
     141             :         ZEND_ARG_INFO(0, errno)
     142             : ZEND_END_ARG_INFO()
     143             : /* }}} */
     144             : 
     145             : const zend_function_entry pcntl_functions[] = {
     146             :         PHP_FE(pcntl_fork,                      arginfo_pcntl_void)
     147             :         PHP_FE(pcntl_waitpid,           arginfo_pcntl_waitpid)
     148             :         PHP_FE(pcntl_wait,                      arginfo_pcntl_wait)
     149             :         PHP_FE(pcntl_signal,            arginfo_pcntl_signal)
     150             :         PHP_FE(pcntl_signal_dispatch,   arginfo_pcntl_void)
     151             :         PHP_FE(pcntl_wifexited,         arginfo_pcntl_wifexited)
     152             :         PHP_FE(pcntl_wifstopped,        arginfo_pcntl_wifstopped)
     153             :         PHP_FE(pcntl_wifsignaled,       arginfo_pcntl_wifsignaled)
     154             :         PHP_FE(pcntl_wexitstatus,       arginfo_pcntl_wifexitstatus)
     155             :         PHP_FE(pcntl_wtermsig,          arginfo_pcntl_wtermsig)
     156             :         PHP_FE(pcntl_wstopsig,          arginfo_pcntl_wstopsig)
     157             :         PHP_FE(pcntl_exec,                      arginfo_pcntl_exec)
     158             :         PHP_FE(pcntl_alarm,                     arginfo_pcntl_alarm)
     159             :         PHP_FE(pcntl_get_last_error,    arginfo_pcntl_void)
     160             :         PHP_FALIAS(pcntl_errno, pcntl_get_last_error,   NULL)
     161             :         PHP_FE(pcntl_strerror,          arginfo_pcntl_strerror)
     162             : #ifdef HAVE_GETPRIORITY
     163             :         PHP_FE(pcntl_getpriority,       arginfo_pcntl_getpriority)
     164             : #endif
     165             : #ifdef HAVE_SETPRIORITY
     166             :         PHP_FE(pcntl_setpriority,       arginfo_pcntl_setpriority)
     167             : #endif
     168             : #ifdef HAVE_SIGPROCMASK
     169             :         PHP_FE(pcntl_sigprocmask,       arginfo_pcntl_sigprocmask)
     170             : #endif
     171             : #if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
     172             :         PHP_FE(pcntl_sigwaitinfo,       arginfo_pcntl_sigwaitinfo)
     173             :         PHP_FE(pcntl_sigtimedwait,      arginfo_pcntl_sigtimedwait)
     174             : #endif
     175             :         PHP_FE_END
     176             : };
     177             : 
     178             : zend_module_entry pcntl_module_entry = {
     179             :         STANDARD_MODULE_HEADER,
     180             :         "pcntl",
     181             :         pcntl_functions,
     182             :         PHP_MINIT(pcntl),
     183             :         PHP_MSHUTDOWN(pcntl),
     184             :         PHP_RINIT(pcntl),
     185             :         PHP_RSHUTDOWN(pcntl),
     186             :         PHP_MINFO(pcntl),
     187             :         NO_VERSION_YET,
     188             :         PHP_MODULE_GLOBALS(pcntl),
     189             :         PHP_GINIT(pcntl),
     190             :         NULL,
     191             :         NULL,
     192             :         STANDARD_MODULE_PROPERTIES_EX
     193             : };
     194             : 
     195             : #ifdef COMPILE_DL_PCNTL
     196             : ZEND_GET_MODULE(pcntl)
     197             : #endif
     198             : 
     199             : static void pcntl_signal_handler(int);
     200             : static void pcntl_signal_dispatch();
     201             :   
     202       20225 : void php_register_signal_constants(INIT_FUNC_ARGS)
     203             : {
     204             : 
     205             :         /* Wait Constants */
     206             : #ifdef WNOHANG
     207       20225 :         REGISTER_LONG_CONSTANT("WNOHANG",  (long) WNOHANG, CONST_CS | CONST_PERSISTENT);
     208             : #endif
     209             : #ifdef WUNTRACED
     210       20225 :         REGISTER_LONG_CONSTANT("WUNTRACED",  (long) WUNTRACED, CONST_CS | CONST_PERSISTENT);
     211             : #endif
     212             : 
     213             :         /* Signal Constants */
     214       20225 :         REGISTER_LONG_CONSTANT("SIG_IGN",  (long) SIG_IGN, CONST_CS | CONST_PERSISTENT);
     215       20225 :         REGISTER_LONG_CONSTANT("SIG_DFL",  (long) SIG_DFL, CONST_CS | CONST_PERSISTENT);
     216       20225 :         REGISTER_LONG_CONSTANT("SIG_ERR",  (long) SIG_ERR, CONST_CS | CONST_PERSISTENT);
     217       20225 :         REGISTER_LONG_CONSTANT("SIGHUP",   (long) SIGHUP,  CONST_CS | CONST_PERSISTENT);
     218       20225 :         REGISTER_LONG_CONSTANT("SIGINT",   (long) SIGINT,  CONST_CS | CONST_PERSISTENT);
     219       20225 :         REGISTER_LONG_CONSTANT("SIGQUIT",  (long) SIGQUIT, CONST_CS | CONST_PERSISTENT);
     220       20225 :         REGISTER_LONG_CONSTANT("SIGILL",   (long) SIGILL,  CONST_CS | CONST_PERSISTENT);
     221       20225 :         REGISTER_LONG_CONSTANT("SIGTRAP",  (long) SIGTRAP, CONST_CS | CONST_PERSISTENT);
     222       20225 :         REGISTER_LONG_CONSTANT("SIGABRT",  (long) SIGABRT, CONST_CS | CONST_PERSISTENT);
     223             : #ifdef SIGIOT
     224       20225 :         REGISTER_LONG_CONSTANT("SIGIOT",   (long) SIGIOT,  CONST_CS | CONST_PERSISTENT);
     225             : #endif
     226       20225 :         REGISTER_LONG_CONSTANT("SIGBUS",   (long) SIGBUS,  CONST_CS | CONST_PERSISTENT);
     227       20225 :         REGISTER_LONG_CONSTANT("SIGFPE",   (long) SIGFPE,  CONST_CS | CONST_PERSISTENT);
     228       20225 :         REGISTER_LONG_CONSTANT("SIGKILL",  (long) SIGKILL, CONST_CS | CONST_PERSISTENT);
     229       20225 :         REGISTER_LONG_CONSTANT("SIGUSR1",  (long) SIGUSR1, CONST_CS | CONST_PERSISTENT);
     230       20225 :         REGISTER_LONG_CONSTANT("SIGSEGV",  (long) SIGSEGV, CONST_CS | CONST_PERSISTENT);
     231       20225 :         REGISTER_LONG_CONSTANT("SIGUSR2",  (long) SIGUSR2, CONST_CS | CONST_PERSISTENT);
     232       20225 :         REGISTER_LONG_CONSTANT("SIGPIPE",  (long) SIGPIPE, CONST_CS | CONST_PERSISTENT);
     233       20225 :         REGISTER_LONG_CONSTANT("SIGALRM",  (long) SIGALRM, CONST_CS | CONST_PERSISTENT);
     234       20225 :         REGISTER_LONG_CONSTANT("SIGTERM",  (long) SIGTERM, CONST_CS | CONST_PERSISTENT);
     235             : #ifdef SIGSTKFLT
     236       20225 :         REGISTER_LONG_CONSTANT("SIGSTKFLT",(long) SIGSTKFLT, CONST_CS | CONST_PERSISTENT);
     237             : #endif 
     238             : #ifdef SIGCLD
     239       20225 :         REGISTER_LONG_CONSTANT("SIGCLD",   (long) SIGCLD, CONST_CS | CONST_PERSISTENT);
     240             : #endif
     241             : #ifdef SIGCHLD
     242       20225 :         REGISTER_LONG_CONSTANT("SIGCHLD",  (long) SIGCHLD, CONST_CS | CONST_PERSISTENT);
     243             : #endif
     244       20225 :         REGISTER_LONG_CONSTANT("SIGCONT",  (long) SIGCONT, CONST_CS | CONST_PERSISTENT);
     245       20225 :         REGISTER_LONG_CONSTANT("SIGSTOP",  (long) SIGSTOP, CONST_CS | CONST_PERSISTENT);
     246       20225 :         REGISTER_LONG_CONSTANT("SIGTSTP",  (long) SIGTSTP, CONST_CS | CONST_PERSISTENT);
     247       20225 :         REGISTER_LONG_CONSTANT("SIGTTIN",  (long) SIGTTIN, CONST_CS | CONST_PERSISTENT);
     248       20225 :         REGISTER_LONG_CONSTANT("SIGTTOU",  (long) SIGTTOU, CONST_CS | CONST_PERSISTENT);
     249       20225 :         REGISTER_LONG_CONSTANT("SIGURG",   (long) SIGURG , CONST_CS | CONST_PERSISTENT);
     250       20225 :         REGISTER_LONG_CONSTANT("SIGXCPU",  (long) SIGXCPU, CONST_CS | CONST_PERSISTENT);
     251       20225 :         REGISTER_LONG_CONSTANT("SIGXFSZ",  (long) SIGXFSZ, CONST_CS | CONST_PERSISTENT);
     252       20225 :         REGISTER_LONG_CONSTANT("SIGVTALRM",(long) SIGVTALRM, CONST_CS | CONST_PERSISTENT);
     253       20225 :         REGISTER_LONG_CONSTANT("SIGPROF",  (long) SIGPROF, CONST_CS | CONST_PERSISTENT);
     254       20225 :         REGISTER_LONG_CONSTANT("SIGWINCH", (long) SIGWINCH, CONST_CS | CONST_PERSISTENT);
     255             : #ifdef SIGPOLL
     256       20225 :         REGISTER_LONG_CONSTANT("SIGPOLL",  (long) SIGPOLL, CONST_CS | CONST_PERSISTENT);
     257             : #endif
     258       20225 :         REGISTER_LONG_CONSTANT("SIGIO",    (long) SIGIO, CONST_CS | CONST_PERSISTENT);
     259             : #ifdef SIGPWR
     260       20225 :         REGISTER_LONG_CONSTANT("SIGPWR",   (long) SIGPWR, CONST_CS | CONST_PERSISTENT);
     261             : #endif
     262             : #ifdef SIGSYS
     263       20225 :         REGISTER_LONG_CONSTANT("SIGSYS",   (long) SIGSYS, CONST_CS | CONST_PERSISTENT);
     264       20225 :         REGISTER_LONG_CONSTANT("SIGBABY",  (long) SIGSYS, CONST_CS | CONST_PERSISTENT);
     265             : #endif
     266             : 
     267             : #if HAVE_GETPRIORITY || HAVE_SETPRIORITY
     268       20225 :         REGISTER_LONG_CONSTANT("PRIO_PGRP", PRIO_PGRP, CONST_CS | CONST_PERSISTENT);
     269       20225 :         REGISTER_LONG_CONSTANT("PRIO_USER", PRIO_USER, CONST_CS | CONST_PERSISTENT);
     270       20225 :         REGISTER_LONG_CONSTANT("PRIO_PROCESS", PRIO_PROCESS, CONST_CS | CONST_PERSISTENT);
     271             : #endif
     272             : 
     273             :         /* {{{ "how" argument for sigprocmask */
     274             : #ifdef HAVE_SIGPROCMASK
     275       20225 :         REGISTER_LONG_CONSTANT("SIG_BLOCK",   SIG_BLOCK, CONST_CS | CONST_PERSISTENT);
     276       20225 :         REGISTER_LONG_CONSTANT("SIG_UNBLOCK", SIG_UNBLOCK, CONST_CS | CONST_PERSISTENT);
     277       20225 :         REGISTER_LONG_CONSTANT("SIG_SETMASK", SIG_SETMASK, CONST_CS | CONST_PERSISTENT);
     278             : #endif
     279             :         /* }}} */
     280             : 
     281             :         /* {{{ si_code */
     282             : #if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
     283       20225 :         REGISTER_LONG_CONSTANT("SI_USER",    SI_USER,    CONST_CS | CONST_PERSISTENT);
     284             : #ifdef SI_NOINFO
     285             :         REGISTER_LONG_CONSTANT("SI_NOINFO",  SI_NOINFO,  CONST_CS | CONST_PERSISTENT);
     286             : #endif
     287             : #ifdef SI_KERNEL
     288       20225 :         REGISTER_LONG_CONSTANT("SI_KERNEL",  SI_KERNEL,  CONST_CS | CONST_PERSISTENT);
     289             : #endif
     290       20225 :         REGISTER_LONG_CONSTANT("SI_QUEUE",   SI_QUEUE,   CONST_CS | CONST_PERSISTENT);
     291       20225 :         REGISTER_LONG_CONSTANT("SI_TIMER",   SI_TIMER,   CONST_CS | CONST_PERSISTENT);
     292       20225 :         REGISTER_LONG_CONSTANT("SI_MESGQ",   SI_MESGQ,   CONST_CS | CONST_PERSISTENT);
     293       20225 :         REGISTER_LONG_CONSTANT("SI_ASYNCIO", SI_ASYNCIO, CONST_CS | CONST_PERSISTENT);
     294             : #ifdef SI_SIGIO
     295       20225 :         REGISTER_LONG_CONSTANT("SI_SIGIO",   SI_SIGIO,   CONST_CS | CONST_PERSISTENT);
     296             : #endif
     297             : #ifdef SI_TKILL
     298       20225 :         REGISTER_LONG_CONSTANT("SI_TKILL",   SI_TKILL,   CONST_CS | CONST_PERSISTENT);
     299             : #endif
     300             : 
     301             :         /* si_code for SIGCHILD */
     302             : #ifdef CLD_EXITED
     303       20225 :         REGISTER_LONG_CONSTANT("CLD_EXITED",    CLD_EXITED,    CONST_CS | CONST_PERSISTENT);
     304             : #endif
     305             : #ifdef CLD_KILLED
     306       20225 :         REGISTER_LONG_CONSTANT("CLD_KILLED",    CLD_KILLED,    CONST_CS | CONST_PERSISTENT);
     307             : #endif
     308             : #ifdef CLD_DUMPED
     309       20225 :         REGISTER_LONG_CONSTANT("CLD_DUMPED",    CLD_DUMPED,    CONST_CS | CONST_PERSISTENT);
     310             : #endif
     311             : #ifdef CLD_TRAPPED
     312       20225 :         REGISTER_LONG_CONSTANT("CLD_TRAPPED",   CLD_TRAPPED,   CONST_CS | CONST_PERSISTENT);
     313             : #endif
     314             : #ifdef CLD_STOPPED
     315       20225 :         REGISTER_LONG_CONSTANT("CLD_STOPPED",   CLD_STOPPED,   CONST_CS | CONST_PERSISTENT);
     316             : #endif
     317             : #ifdef CLD_CONTINUED
     318       20225 :         REGISTER_LONG_CONSTANT("CLD_CONTINUED", CLD_CONTINUED, CONST_CS | CONST_PERSISTENT);
     319             : #endif
     320             : 
     321             :         /* si_code for SIGTRAP */
     322             : #ifdef TRAP_BRKPT
     323       20225 :         REGISTER_LONG_CONSTANT("TRAP_BRKPT", TRAP_BRKPT, CONST_CS | CONST_PERSISTENT);
     324             : #endif
     325             : #ifdef TRAP_TRACE
     326       20225 :         REGISTER_LONG_CONSTANT("TRAP_TRACE", TRAP_TRACE, CONST_CS | CONST_PERSISTENT);
     327             : #endif
     328             : 
     329             :         /* si_code for SIGPOLL */
     330             : #ifdef POLL_IN
     331       20225 :         REGISTER_LONG_CONSTANT("POLL_IN",  POLL_IN,  CONST_CS | CONST_PERSISTENT);
     332             : #endif
     333             : #ifdef POLL_OUT
     334       20225 :         REGISTER_LONG_CONSTANT("POLL_OUT", POLL_OUT, CONST_CS | CONST_PERSISTENT);
     335             : #endif
     336             : #ifdef POLL_MSG
     337       20225 :         REGISTER_LONG_CONSTANT("POLL_MSG", POLL_MSG, CONST_CS | CONST_PERSISTENT);
     338             : #endif
     339             : #ifdef POLL_ERR
     340       20225 :         REGISTER_LONG_CONSTANT("POLL_ERR", POLL_ERR, CONST_CS | CONST_PERSISTENT);
     341             : #endif
     342             : #ifdef POLL_PRI
     343       20225 :         REGISTER_LONG_CONSTANT("POLL_PRI", POLL_PRI, CONST_CS | CONST_PERSISTENT);
     344             : #endif
     345             : #ifdef POLL_HUP
     346       20225 :         REGISTER_LONG_CONSTANT("POLL_HUP", POLL_HUP, CONST_CS | CONST_PERSISTENT);
     347             : #endif
     348             : 
     349             : #ifdef ILL_ILLOPC
     350       20225 :         REGISTER_LONG_CONSTANT("ILL_ILLOPC", ILL_ILLOPC, CONST_CS | CONST_PERSISTENT);
     351             : #endif
     352             : #ifdef ILL_ILLOPN
     353       20225 :         REGISTER_LONG_CONSTANT("ILL_ILLOPN", ILL_ILLOPN, CONST_CS | CONST_PERSISTENT);
     354             : #endif
     355             : #ifdef ILL_ILLADR
     356       20225 :         REGISTER_LONG_CONSTANT("ILL_ILLADR", ILL_ILLADR, CONST_CS | CONST_PERSISTENT);
     357             : #endif
     358             : #ifdef ILL_ILLTRP
     359       20225 :         REGISTER_LONG_CONSTANT("ILL_ILLTRP", ILL_ILLTRP, CONST_CS | CONST_PERSISTENT);
     360             : #endif
     361             : #ifdef ILL_PRVOPC
     362       20225 :         REGISTER_LONG_CONSTANT("ILL_PRVOPC", ILL_PRVOPC, CONST_CS | CONST_PERSISTENT);
     363             : #endif
     364             : #ifdef ILL_PRVREG
     365       20225 :         REGISTER_LONG_CONSTANT("ILL_PRVREG", ILL_PRVREG, CONST_CS | CONST_PERSISTENT);
     366             : #endif
     367             : #ifdef ILL_COPROC
     368       20225 :         REGISTER_LONG_CONSTANT("ILL_COPROC", ILL_COPROC, CONST_CS | CONST_PERSISTENT);
     369             : #endif
     370             : #ifdef ILL_BADSTK
     371       20225 :         REGISTER_LONG_CONSTANT("ILL_BADSTK", ILL_BADSTK, CONST_CS | CONST_PERSISTENT);
     372             : #endif
     373             : 
     374             : #ifdef FPE_INTDIV
     375       20225 :         REGISTER_LONG_CONSTANT("FPE_INTDIV", FPE_INTDIV, CONST_CS | CONST_PERSISTENT);
     376             : #endif
     377             : #ifdef FPE_INTOVF
     378       20225 :         REGISTER_LONG_CONSTANT("FPE_INTOVF", FPE_INTOVF, CONST_CS | CONST_PERSISTENT);
     379             : #endif
     380             : #ifdef FPE_FLTDIV
     381       20225 :         REGISTER_LONG_CONSTANT("FPE_FLTDIV", FPE_FLTDIV, CONST_CS | CONST_PERSISTENT);
     382             : #endif
     383             : #ifdef FPE_FLTOVF
     384       20225 :         REGISTER_LONG_CONSTANT("FPE_FLTOVF", FPE_FLTOVF, CONST_CS | CONST_PERSISTENT);
     385             : #endif
     386             : #ifdef FPE_FLTUND
     387       20225 :         REGISTER_LONG_CONSTANT("FPE_FLTUND", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
     388             : #endif
     389             : #ifdef FPE_FLTRES
     390       20225 :         REGISTER_LONG_CONSTANT("FPE_FLTRES", FPE_FLTRES, CONST_CS | CONST_PERSISTENT);
     391             : #endif
     392             : #ifdef FPE_FLTINV
     393       20225 :         REGISTER_LONG_CONSTANT("FPE_FLTINV", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
     394             : #endif
     395             : #ifdef FPE_FLTSUB
     396       20225 :         REGISTER_LONG_CONSTANT("FPE_FLTSUB", FPE_FLTSUB, CONST_CS | CONST_PERSISTENT);
     397             : #endif
     398             : 
     399             : #ifdef SEGV_MAPERR
     400       20225 :         REGISTER_LONG_CONSTANT("SEGV_MAPERR", SEGV_MAPERR, CONST_CS | CONST_PERSISTENT);
     401             : #endif
     402             : #ifdef SEGV_ACCERR
     403       20225 :         REGISTER_LONG_CONSTANT("SEGV_ACCERR", SEGV_ACCERR, CONST_CS | CONST_PERSISTENT);
     404             : #endif
     405             : 
     406             : #ifdef BUS_ADRALN
     407       20225 :         REGISTER_LONG_CONSTANT("BUS_ADRALN", BUS_ADRALN, CONST_CS | CONST_PERSISTENT);
     408             : #endif
     409             : #ifdef BUS_ADRERR
     410       20225 :         REGISTER_LONG_CONSTANT("BUS_ADRERR", BUS_ADRERR, CONST_CS | CONST_PERSISTENT);
     411             : #endif
     412             : #ifdef BUS_OBJERR
     413       20225 :         REGISTER_LONG_CONSTANT("BUS_OBJERR", BUS_OBJERR, CONST_CS | CONST_PERSISTENT);
     414             : #endif
     415             : #endif /* HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT */
     416             :         /* }}} */
     417       20225 : }
     418             : 
     419       20225 : static void php_pcntl_register_errno_constants(INIT_FUNC_ARGS)
     420             : {
     421             : #ifdef EINTR
     422       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(EINTR);
     423             : #endif
     424             : #ifdef ECHILD
     425       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ECHILD);
     426             : #endif
     427             : #ifdef EINVAL
     428       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(EINVAL);
     429             : #endif
     430             : #ifdef EAGAIN
     431       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(EAGAIN);
     432             : #endif
     433             : #ifdef ESRCH
     434       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ESRCH);
     435             : #endif
     436             : #ifdef EACCES
     437       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(EACCES);
     438             : #endif
     439             : #ifdef EPERM
     440       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(EPERM);
     441             : #endif
     442             : #ifdef ENOMEM
     443       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOMEM);
     444             : #endif
     445             : #ifdef E2BIG
     446       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(E2BIG);
     447             : #endif
     448             : #ifdef EFAULT
     449       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(EFAULT);
     450             : #endif
     451             : #ifdef EIO
     452       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(EIO);
     453             : #endif
     454             : #ifdef EISDIR
     455       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(EISDIR);
     456             : #endif
     457             : #ifdef ELIBBAD
     458       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ELIBBAD);
     459             : #endif
     460             : #ifdef ELOOP
     461       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ELOOP);
     462             : #endif
     463             : #ifdef EMFILE
     464       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(EMFILE);
     465             : #endif
     466             : #ifdef ENAMETOOLONG
     467       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENAMETOOLONG);
     468             : #endif
     469             : #ifdef ENFILE
     470       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENFILE);
     471             : #endif
     472             : #ifdef ENOENT
     473       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOENT);
     474             : #endif
     475             : #ifdef ENOEXEC
     476       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOEXEC);
     477             : #endif
     478             : #ifdef ENOTDIR
     479       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOTDIR);
     480             : #endif
     481             : #ifdef ETXTBSY
     482       20225 :         REGISTER_PCNTL_ERRNO_CONSTANT(ETXTBSY);
     483             : #endif
     484       20225 : }
     485             : 
     486       20225 : static PHP_GINIT_FUNCTION(pcntl)
     487             : { 
     488       20225 :         memset(pcntl_globals, 0, sizeof(*pcntl_globals));
     489       20225 : }
     490             : 
     491       20182 : PHP_RINIT_FUNCTION(pcntl)
     492             : {
     493       20182 :         zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0);
     494       20182 :         PCNTL_G(head) = PCNTL_G(tail) = PCNTL_G(spares) = NULL;
     495       20182 :         return SUCCESS;
     496             : }
     497             : 
     498       20225 : PHP_MINIT_FUNCTION(pcntl)
     499             : {
     500       20225 :         php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU);
     501       20225 :         php_pcntl_register_errno_constants(INIT_FUNC_ARGS_PASSTHRU);
     502       20225 :         php_add_tick_function(pcntl_signal_dispatch);
     503             : 
     504       20225 :         return SUCCESS;
     505             : }
     506             : 
     507       20261 : PHP_MSHUTDOWN_FUNCTION(pcntl)
     508             : {
     509       20261 :         return SUCCESS;
     510             : }
     511             : 
     512       20220 : PHP_RSHUTDOWN_FUNCTION(pcntl)
     513             : {
     514             :         struct php_pcntl_pending_signal *sig;
     515             : 
     516             :         /* FIXME: if a signal is delivered after this point, things will go pear shaped;
     517             :          * need to remove signal handlers */
     518       20220 :         zend_hash_destroy(&PCNTL_G(php_signal_table));
     519       40441 :         while (PCNTL_G(head)) {
     520           1 :                 sig = PCNTL_G(head);
     521           1 :                 PCNTL_G(head) = sig->next;
     522           1 :                 efree(sig);
     523             :         }
     524       40599 :         while (PCNTL_G(spares)) {
     525         159 :                 sig = PCNTL_G(spares);
     526         159 :                 PCNTL_G(spares) = sig->next;
     527         159 :                 efree(sig);
     528             :         }
     529       20220 :         return SUCCESS;
     530             : }
     531             : 
     532         148 : PHP_MINFO_FUNCTION(pcntl)
     533             : {
     534         148 :         php_info_print_table_start();
     535         148 :         php_info_print_table_header(2, "pcntl support", "enabled");
     536         148 :         php_info_print_table_end();
     537         148 : }
     538             : 
     539             : /* {{{ proto int pcntl_fork(void)
     540             :    Forks the currently running process following the same behavior as the UNIX fork() system call*/
     541          69 : PHP_FUNCTION(pcntl_fork)
     542             : {
     543             :         pid_t id;
     544             : 
     545          69 :         id = fork();
     546         112 :         if (id == -1) {
     547           0 :                 PCNTL_G(last_error) = errno;
     548           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d", errno);
     549             :         }
     550             :         
     551         112 :         RETURN_LONG((long) id);
     552             : }
     553             : /* }}} */
     554             : 
     555             : /* {{{ proto int pcntl_alarm(int seconds)
     556             :    Set an alarm clock for delivery of a signal*/
     557          28 : PHP_FUNCTION(pcntl_alarm)
     558             : {
     559             :         long seconds;
     560             : 
     561          28 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &seconds) == FAILURE)
     562           1 :                 return;
     563             :         
     564          27 :         RETURN_LONG ((long) alarm(seconds));
     565             : }
     566             : /* }}} */
     567             : 
     568             : /* {{{ proto int pcntl_waitpid(int pid, int &status, int options)
     569             :    Waits on or returns the status of a forked child as defined by the waitpid() system call */
     570          67 : PHP_FUNCTION(pcntl_waitpid)
     571             : {
     572          67 :         long pid, options = 0;
     573          67 :         zval *z_status = NULL;
     574             :         int status;
     575             :         pid_t child_id;
     576             : 
     577          67 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|l", &pid, &z_status, &options) == FAILURE)
     578           1 :                 return;
     579             :         
     580         132 :         convert_to_long_ex(&z_status);
     581             : 
     582          66 :         status = Z_LVAL_P(z_status);
     583             : 
     584          66 :         child_id = waitpid((pid_t) pid, &status, options);
     585             : 
     586          66 :         if (child_id < 0) {
     587           0 :                 PCNTL_G(last_error) = errno;
     588             :         }
     589             : 
     590          66 :         Z_LVAL_P(z_status) = status;
     591             : 
     592          66 :         RETURN_LONG((long) child_id);
     593             : }
     594             : /* }}} */
     595             : 
     596             : /* {{{ proto int pcntl_wait(int &status)
     597             :    Waits on or returns the status of a forked child as defined by the waitpid() system call */
     598           9 : PHP_FUNCTION(pcntl_wait)
     599             : {
     600           9 :         long options = 0;
     601           9 :         zval *z_status = NULL;
     602             :         int status;
     603             :         pid_t child_id;
     604             : 
     605           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &z_status, &options) == FAILURE)
     606           1 :                 return;
     607             :         
     608          18 :         convert_to_long_ex(&z_status);
     609             : 
     610           8 :         status = Z_LVAL_P(z_status);
     611             : #ifdef HAVE_WAIT3
     612           8 :         if(options) {
     613           2 :                 child_id = wait3(&status, options, NULL);
     614             :         }
     615             :         else {
     616           6 :                 child_id = wait(&status);
     617             :         }
     618             : #else
     619             :         child_id = wait(&status);
     620             : #endif
     621           8 :         if (child_id < 0) {
     622           3 :                 PCNTL_G(last_error) = errno;
     623             :         }
     624             : 
     625           8 :         Z_LVAL_P(z_status) = status;
     626             : 
     627           8 :         RETURN_LONG((long) child_id);
     628             : }
     629             : /* }}} */
     630             : 
     631             : /* {{{ proto bool pcntl_wifexited(int status) 
     632             :    Returns true if the child status code represents a successful exit */
     633           5 : PHP_FUNCTION(pcntl_wifexited)
     634             : {
     635             : #ifdef WIFEXITED
     636             :         long status_word;
     637             : 
     638           5 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
     639           1 :                return;
     640             :         }
     641             : 
     642           4 :         if (WIFEXITED(status_word))
     643           3 :                 RETURN_TRUE;
     644             : #endif
     645           1 :         RETURN_FALSE;
     646             : }
     647             : /* }}} */
     648             : 
     649             : /* {{{ proto bool pcntl_wifstopped(int status) 
     650             :    Returns true if the child status code represents a stopped process (WUNTRACED must have been used with waitpid) */
     651           3 : PHP_FUNCTION(pcntl_wifstopped)
     652             : {
     653             : #ifdef WIFSTOPPED
     654             :         long status_word;
     655             : 
     656           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
     657           1 :                return;
     658             :         }
     659             : 
     660           2 :         if (WIFSTOPPED(status_word))
     661           1 :                 RETURN_TRUE;
     662             : #endif
     663           1 :         RETURN_FALSE;
     664             : }
     665             : /* }}} */
     666             : 
     667             : /* {{{ proto bool pcntl_wifsignaled(int status) 
     668             :    Returns true if the child status code represents a process that was terminated due to a signal */
     669           3 : PHP_FUNCTION(pcntl_wifsignaled)
     670             : {
     671             : #ifdef WIFSIGNALED
     672             :         long status_word;
     673             : 
     674           3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
     675           1 :                return;
     676             :         }
     677             : 
     678           2 :         if (WIFSIGNALED(status_word))
     679           1 :                 RETURN_TRUE;
     680             : #endif
     681           1 :         RETURN_FALSE;
     682             : }
     683             : /* }}} */
     684             : 
     685             : /* {{{ proto int pcntl_wexitstatus(int status) 
     686             :    Returns the status code of a child's exit */
     687           6 : PHP_FUNCTION(pcntl_wexitstatus)
     688             : {
     689             : #ifdef WEXITSTATUS
     690             :         long status_word;
     691             : 
     692           6 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
     693           1 :                return;
     694             :         }
     695             : 
     696           5 :         RETURN_LONG(WEXITSTATUS(status_word));
     697             : #else
     698             :         RETURN_FALSE;
     699             : #endif
     700             : }
     701             : /* }}} */
     702             : 
     703             : /* {{{ proto int pcntl_wtermsig(int status) 
     704             :    Returns the number of the signal that terminated the process who's status code is passed  */
     705           2 : PHP_FUNCTION(pcntl_wtermsig)
     706             : {
     707             : #ifdef WTERMSIG
     708             :         long status_word;
     709             : 
     710           2 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
     711           1 :                return;
     712             :         }
     713             : 
     714           1 :         RETURN_LONG(WTERMSIG(status_word));
     715             : #else
     716             :         RETURN_FALSE;
     717             : #endif
     718             : }
     719             : /* }}} */
     720             : 
     721             : /* {{{ proto int pcntl_wstopsig(int status) 
     722             :    Returns the number of the signal that caused the process to stop who's status code is passed */
     723           2 : PHP_FUNCTION(pcntl_wstopsig)
     724             : {
     725             : #ifdef WSTOPSIG
     726             :         long status_word;
     727             : 
     728           2 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
     729           1 :                return;
     730             :         }
     731             : 
     732           1 :         RETURN_LONG(WSTOPSIG(status_word));
     733             : #else
     734             :         RETURN_FALSE;
     735             : #endif
     736             : }
     737             : /* }}} */
     738             : 
     739             : /* {{{ proto bool pcntl_exec(string path [, array args [, array envs]])
     740             :    Executes specified program in current process space as defined by exec(2) */
     741           4 : PHP_FUNCTION(pcntl_exec)
     742             : {
     743           4 :         zval *args = NULL, *envs = NULL;
     744             :         zval **element;
     745             :         HashTable *args_hash, *envs_hash;
     746           4 :         int argc = 0, argi = 0;
     747           4 :         int envc = 0, envi = 0;
     748           4 :         int return_val = 0;
     749           4 :         char **argv = NULL, **envp = NULL;
     750             :         char **current_arg, **pair;
     751             :         int pair_length;
     752             :         char *key;
     753             :         uint key_length;
     754             :         char *path;
     755             :         int path_len;
     756             :         ulong key_num;
     757             :                 
     758           4 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|aa", &path, &path_len, &args, &envs) == FAILURE) {
     759           1 :                 return;
     760             :         }
     761             :         
     762           3 :         if (ZEND_NUM_ARGS() > 1) {
     763             :                 /* Build argument list */
     764           3 :                 args_hash = HASH_OF(args);
     765           3 :                 argc = zend_hash_num_elements(args_hash);
     766             :                 
     767           3 :                 argv = safe_emalloc((argc + 2), sizeof(char *), 0);
     768           3 :                 *argv = path;
     769          16 :                 for ( zend_hash_internal_pointer_reset(args_hash), current_arg = argv+1; 
     770           5 :                         (argi < argc && (zend_hash_get_current_data(args_hash, (void **) &element) == SUCCESS));
     771           5 :                         (argi++, current_arg++, zend_hash_move_forward(args_hash)) ) {
     772             : 
     773           5 :                         convert_to_string_ex(element);
     774           5 :                         *current_arg = Z_STRVAL_PP(element);
     775             :                 }
     776           3 :                 *(current_arg) = NULL;
     777             :         } else {
     778           0 :                 argv = emalloc(2 * sizeof(char *));
     779           0 :                 *argv = path;
     780           0 :                 *(argv+1) = NULL;
     781             :         }
     782             : 
     783           3 :         if ( ZEND_NUM_ARGS() == 3 ) {
     784             :                 /* Build environment pair list */
     785           2 :                 envs_hash = HASH_OF(envs);
     786           2 :                 envc = zend_hash_num_elements(envs_hash);
     787             :                 
     788           2 :                 envp = safe_emalloc((envc + 1), sizeof(char *), 0);
     789          11 :                 for ( zend_hash_internal_pointer_reset(envs_hash), pair = envp; 
     790           4 :                         (envi < envc && (zend_hash_get_current_data(envs_hash, (void **) &element) == SUCCESS));
     791           4 :                         (envi++, pair++, zend_hash_move_forward(envs_hash)) ) {
     792           4 :                         switch (return_val = zend_hash_get_current_key_ex(envs_hash, &key, &key_length, &key_num, 0, NULL)) {
     793             :                                 case HASH_KEY_IS_LONG:
     794           1 :                                         key = emalloc(101);
     795           1 :                                         snprintf(key, 100, "%ld", key_num);
     796           1 :                                         key_length = strlen(key);
     797           1 :                                         break;
     798             :                                 case HASH_KEY_NON_EXISTANT:
     799           0 :                                         pair--;
     800           0 :                                         continue;
     801             :                         }
     802             : 
     803           4 :                         convert_to_string_ex(element);
     804             : 
     805             :                         /* Length of element + equal sign + length of key + null */ 
     806           4 :                         pair_length = Z_STRLEN_PP(element) + key_length + 2;
     807           4 :                         *pair = emalloc(pair_length);
     808           4 :                         strlcpy(*pair, key, key_length); 
     809           4 :                         strlcat(*pair, "=", pair_length);
     810           4 :                         strlcat(*pair, Z_STRVAL_PP(element), pair_length);
     811             :                         
     812             :                         /* Cleanup */
     813           4 :                         if (return_val == HASH_KEY_IS_LONG) efree(key);
     814             :                 }
     815           1 :                 *(pair) = NULL;
     816             : 
     817           1 :                 if (execve(path, argv, envp) == -1) {
     818           1 :                         PCNTL_G(last_error) = errno;
     819           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
     820             :                 }
     821             :         
     822             :                 /* Cleanup */
     823           1 :                 for (pair = envp; *pair != NULL; pair++) efree(*pair);
     824           1 :                 efree(envp);
     825             :         } else {
     826             : 
     827           1 :                 if (execv(path, argv) == -1) {
     828           0 :                         PCNTL_G(last_error) = errno;
     829           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
     830             :                 }
     831             :         }
     832             : 
     833           2 :         efree(argv);
     834             :         
     835           1 :         RETURN_FALSE;
     836             : }
     837             : /* }}} */
     838             : 
     839             : /* {{{ proto bool pcntl_signal(int signo, callback handle [, bool restart_syscalls])
     840             :    Assigns a system signal handler to a PHP function */
     841          10 : PHP_FUNCTION(pcntl_signal)
     842             : {
     843          10 :         zval *handle, **dest_handle = NULL;
     844             :         char *func_name;
     845             :         long signo;
     846          10 :         zend_bool restart_syscalls = 1;
     847             : 
     848          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|b", &signo, &handle, &restart_syscalls) == FAILURE) {
     849           1 :                 return;
     850             :         }
     851             : 
     852           9 :         if (signo < 1 || signo > 32) {
     853           2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid signal");
     854           2 :                 RETURN_FALSE;
     855             :         }
     856             : 
     857           7 :         if (!PCNTL_G(spares)) {
     858             :                 /* since calling malloc() from within a signal handler is not portable,
     859             :                  * pre-allocate a few records for recording signals */
     860             :                 int i;
     861         165 :                 for (i = 0; i < 32; i++) {
     862             :                         struct php_pcntl_pending_signal *psig;
     863             : 
     864         160 :                         psig = emalloc(sizeof(*psig));
     865         160 :                         psig->next = PCNTL_G(spares);
     866         160 :                         PCNTL_G(spares) = psig;
     867             :                 }
     868             :         }
     869             : 
     870             :         /* Special long value case for SIG_DFL and SIG_IGN */
     871           7 :         if (Z_TYPE_P(handle)==IS_LONG) {
     872           1 :                 if (Z_LVAL_P(handle) != (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) {
     873           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for handle argument specified");
     874           0 :                         RETURN_FALSE;
     875             :                 }
     876           1 :                 if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == SIG_ERR) {
     877           0 :                         PCNTL_G(last_error) = errno;
     878           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
     879           0 :                         RETURN_FALSE;
     880             :                 }
     881           1 :                 RETURN_TRUE;
     882             :         }
     883             :         
     884           6 :         if (!zend_is_callable(handle, 0, &func_name TSRMLS_CC)) {
     885           1 :                 PCNTL_G(last_error) = EINVAL;
     886           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a callable function name error", func_name);
     887           1 :                 efree(func_name);
     888           1 :                 RETURN_FALSE;
     889             :         }
     890           5 :         efree(func_name);
     891             :         
     892             :         /* Add the function name to our signal table */
     893           5 :         zend_hash_index_update(&PCNTL_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle);
     894           5 :         if (dest_handle) zval_add_ref(dest_handle);
     895             :         
     896           5 :         if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == SIG_ERR) {
     897           0 :                 PCNTL_G(last_error) = errno;
     898           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
     899           0 :                 RETURN_FALSE;
     900             :         }
     901           5 :         RETURN_TRUE;
     902             : }
     903             : /* }}} */
     904             : 
     905             : /* {{{ proto bool pcntl_signal_dispatch()
     906             :    Dispatch signals to signal handlers */
     907           2 : PHP_FUNCTION(pcntl_signal_dispatch)
     908             : {
     909           2 :         pcntl_signal_dispatch();
     910           2 :         RETURN_TRUE;
     911             : }
     912             : /* }}} */
     913             : 
     914             : #ifdef HAVE_SIGPROCMASK
     915             : /* {{{ proto bool pcntl_sigprocmask(int how, array set[, array &oldset])
     916             :    Examine and change blocked signals */
     917           9 : PHP_FUNCTION(pcntl_sigprocmask)
     918             : {
     919             :         long          how, signo;
     920           9 :         zval         *user_set, *user_oldset = NULL, **user_signo;
     921             :         sigset_t      set, oldset;
     922             :         HashPosition  pos;
     923             : 
     924           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "la|z", &how, &user_set, &user_oldset) == FAILURE) {
     925           0 :                 return;
     926             :         }
     927             : 
     928           9 :         if (sigemptyset(&set) != 0 || sigemptyset(&oldset) != 0) {
     929           0 :                 PCNTL_G(last_error) = errno;
     930           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     931           0 :                 RETURN_FALSE;
     932             :         }
     933             : 
     934           9 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(user_set), &pos);
     935          25 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(user_set), (void **)&user_signo, &pos) == SUCCESS)
     936             :         {
     937           8 :                 if (Z_TYPE_PP(user_signo) != IS_LONG) {
     938           2 :                         SEPARATE_ZVAL(user_signo);
     939           4 :                         convert_to_long_ex(user_signo);
     940             :                 }
     941           8 :                 signo = Z_LVAL_PP(user_signo);
     942           8 :                 if (sigaddset(&set, signo) != 0) {
     943           1 :                         PCNTL_G(last_error) = errno;
     944           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     945           1 :                         RETURN_FALSE;
     946             :                 }
     947           7 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(user_set), &pos);
     948             :         }
     949             : 
     950           8 :         if (sigprocmask(how, &set, &oldset) != 0) {
     951           0 :                 PCNTL_G(last_error) = errno;
     952           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     953           0 :                 RETURN_FALSE;
     954             :         }
     955             : 
     956           8 :         if (user_oldset != NULL) {
     957           7 :                 if (Z_TYPE_P(user_oldset) != IS_ARRAY) {
     958           1 :                         zval_dtor(user_oldset);
     959           1 :                         array_init(user_oldset);
     960             :                 } else {
     961           6 :                         zend_hash_clean(Z_ARRVAL_P(user_oldset));
     962             :                 }
     963         448 :                 for (signo = 1; signo < MAX(NSIG-1, SIGRTMAX); ++signo) {
     964         441 :                         if (sigismember(&oldset, signo) != 1) {
     965         431 :                                 continue;
     966             :                         }
     967          10 :                         add_next_index_long(user_oldset, signo);
     968             :                 }
     969             :         }
     970             : 
     971           8 :         RETURN_TRUE;
     972             : }
     973             : /* }}} */
     974             : #endif
     975             : 
     976             : #if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
     977           5 : static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */
     978             : {
     979           5 :         zval            *user_set, **user_signo, *user_siginfo = NULL;
     980           5 :         long             tv_sec = 0, tv_nsec = 0;
     981             :         sigset_t         set;
     982             :         HashPosition     pos;
     983             :         int              signo;
     984             :         siginfo_t        siginfo;
     985             :         struct timespec  timeout;
     986             : 
     987           5 :         if (timedwait) {
     988           2 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
     989           0 :                         return;
     990             :                 }
     991             :         } else {
     992           3 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &user_set, &user_siginfo) == FAILURE) {
     993           0 :                         return;
     994             :                 }
     995             :         }
     996             : 
     997           5 :         if (sigemptyset(&set) != 0) {
     998           0 :                 PCNTL_G(last_error) = errno;
     999           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
    1000           0 :                 RETURN_FALSE;
    1001             :         }
    1002             : 
    1003           5 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(user_set), &pos);
    1004          14 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(user_set), (void **)&user_signo, &pos) == SUCCESS)
    1005             :         {
    1006           5 :                 if (Z_TYPE_PP(user_signo) != IS_LONG) {
    1007           2 :                         SEPARATE_ZVAL(user_signo);
    1008           4 :                         convert_to_long_ex(user_signo);
    1009             :                 }
    1010           5 :                 signo = Z_LVAL_PP(user_signo);
    1011           5 :                 if (sigaddset(&set, signo) != 0) {
    1012           1 :                         PCNTL_G(last_error) = errno;
    1013           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
    1014           1 :                         RETURN_FALSE;
    1015             :                 }
    1016           4 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(user_set), &pos);
    1017             :         }
    1018             : 
    1019           4 :         if (timedwait) {
    1020           2 :                 timeout.tv_sec  = (time_t) tv_sec;
    1021           2 :                 timeout.tv_nsec = tv_nsec;
    1022           2 :                 signo = sigtimedwait(&set, &siginfo, &timeout);
    1023             :         } else {
    1024           2 :                 signo = sigwaitinfo(&set, &siginfo);
    1025             :         }
    1026           4 :         if (signo == -1 && errno != EAGAIN) {
    1027           1 :                 PCNTL_G(last_error) = errno;
    1028           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
    1029             :         }
    1030             : 
    1031             :         /*
    1032             :          * sigtimedwait and sigwaitinfo can return 0 on success on some 
    1033             :          * platforms, e.g. NetBSD
    1034             :          */
    1035           4 :         if (!signo && siginfo.si_signo) {
    1036           0 :                 signo = siginfo.si_signo;
    1037             :         }
    1038             : 
    1039           4 :         if (signo > 0 && user_siginfo) {
    1040           3 :                 if (Z_TYPE_P(user_siginfo) != IS_ARRAY) {
    1041           1 :                         zval_dtor(user_siginfo);
    1042           1 :                         array_init(user_siginfo);
    1043             :                 } else {
    1044           2 :                         zend_hash_clean(Z_ARRVAL_P(user_siginfo));
    1045             :                 }
    1046           3 :                 add_assoc_long_ex(user_siginfo, "signo", sizeof("signo"), siginfo.si_signo);
    1047           3 :                 add_assoc_long_ex(user_siginfo, "errno", sizeof("errno"), siginfo.si_errno);
    1048           3 :                 add_assoc_long_ex(user_siginfo, "code",  sizeof("code"),  siginfo.si_code);
    1049           3 :                 switch(signo) {
    1050             : #ifdef SIGCHLD
    1051             :                         case SIGCHLD:
    1052           1 :                                 add_assoc_long_ex(user_siginfo,   "status", sizeof("status"), siginfo.si_status);
    1053             : # ifdef si_utime
    1054           1 :                                 add_assoc_double_ex(user_siginfo, "utime",  sizeof("utime"),  siginfo.si_utime);
    1055             : # endif
    1056             : # ifdef si_stime
    1057           1 :                                 add_assoc_double_ex(user_siginfo, "stime",  sizeof("stime"),  siginfo.si_stime);
    1058             : # endif
    1059           1 :                                 add_assoc_long_ex(user_siginfo,   "pid",    sizeof("pid"),    siginfo.si_pid);
    1060           1 :                                 add_assoc_long_ex(user_siginfo,   "uid",    sizeof("uid"),    siginfo.si_uid);
    1061           1 :                                 break;
    1062             : #endif
    1063             :                         case SIGILL:
    1064             :                         case SIGFPE:
    1065             :                         case SIGSEGV:
    1066             :                         case SIGBUS:
    1067           0 :                                 add_assoc_double_ex(user_siginfo, "addr", sizeof("addr"), (long)siginfo.si_addr);
    1068           0 :                                 break;
    1069             : #ifdef SIGPOLL
    1070             :                         case SIGPOLL:
    1071           0 :                                 add_assoc_long_ex(user_siginfo, "band", sizeof("band"), siginfo.si_band);
    1072             : # ifdef si_fd
    1073           0 :                                 add_assoc_long_ex(user_siginfo, "fd",   sizeof("fd"),   siginfo.si_fd);
    1074             : # endif
    1075             :                                 break;
    1076             : #endif
    1077             :                         EMPTY_SWITCH_DEFAULT_CASE();
    1078             :                 }
    1079             :         }
    1080             :         
    1081           4 :         RETURN_LONG(signo);
    1082             : }
    1083             : /* }}} */
    1084             : 
    1085             : /* {{{ proto int pcnlt_sigwaitinfo(array set[, array &siginfo])
    1086             :    Synchronously wait for queued signals */
    1087           3 : PHP_FUNCTION(pcntl_sigwaitinfo)
    1088             : {
    1089           3 :         pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    1090           3 : }
    1091             : /* }}} */
    1092             : 
    1093             : /* {{{ proto int pcntl_sigtimedwait(array set[, array &siginfo[, int seconds[, int nanoseconds]]])
    1094             :    Wait for queued signals */
    1095           2 : PHP_FUNCTION(pcntl_sigtimedwait)
    1096             : {
    1097           2 :         pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    1098           2 : }
    1099             : /* }}} */
    1100             : #endif
    1101             : 
    1102             : #ifdef HAVE_GETPRIORITY
    1103             : /* {{{ proto int pcntl_getpriority([int pid [, int process_identifier]])
    1104             :    Get the priority of any process */
    1105           0 : PHP_FUNCTION(pcntl_getpriority)
    1106             : {
    1107           0 :         long who = PRIO_PROCESS;
    1108           0 :         long pid = getpid();
    1109             :         int pri;
    1110             :         
    1111           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &pid, &who) == FAILURE) {
    1112           0 :                 RETURN_FALSE;
    1113             :         }
    1114             : 
    1115             :         /* needs to be cleared, since any returned value is valid */ 
    1116           0 :         errno = 0;
    1117             : 
    1118           0 :         pri = getpriority(who, pid);
    1119             : 
    1120           0 :         if (errno) {
    1121           0 :                 PCNTL_G(last_error) = errno;
    1122           0 :                 switch (errno) {
    1123             :                         case ESRCH:
    1124           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
    1125           0 :                                 break;
    1126             :                         case EINVAL:
    1127           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
    1128           0 :                                 break;
    1129             :                         default:
    1130           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occurred", errno);
    1131             :                                 break;
    1132             :                 }
    1133           0 :                 RETURN_FALSE;
    1134             :         }
    1135             : 
    1136           0 :         RETURN_LONG(pri);
    1137             : }
    1138             : /* }}} */
    1139             : #endif
    1140             : 
    1141             : #ifdef HAVE_SETPRIORITY
    1142             : /* {{{ proto bool pcntl_setpriority(int priority [, int pid [, int process_identifier]])
    1143             :    Change the priority of any process */
    1144           0 : PHP_FUNCTION(pcntl_setpriority)
    1145             : {
    1146           0 :         long who = PRIO_PROCESS;
    1147           0 :         long pid = getpid();
    1148             :         long pri;
    1149             : 
    1150           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &pri, &pid, &who) == FAILURE) {
    1151           0 :                 RETURN_FALSE;
    1152             :         }
    1153             : 
    1154           0 :         if (setpriority(who, pid, pri)) {
    1155           0 :                 PCNTL_G(last_error) = errno;
    1156           0 :                 switch (errno) {
    1157             :                         case ESRCH:
    1158           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
    1159           0 :                                 break;
    1160             :                         case EINVAL:
    1161           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
    1162           0 :                                 break;
    1163             :                         case EPERM:
    1164           0 :                                 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);
    1165           0 :                                 break;
    1166             :                         case EACCES:
    1167           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Only a super user may attempt to increase the process priority", errno);
    1168           0 :                                 break;
    1169             :                         default:
    1170           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occurred", errno);
    1171             :                                 break;
    1172             :                 }
    1173           0 :                 RETURN_FALSE;
    1174             :         }
    1175             :         
    1176           0 :         RETURN_TRUE;
    1177             : }
    1178             : /* }}} */
    1179             : #endif
    1180             : 
    1181             : /* {{{ proto int pcntl_get_last_error(void)
    1182             :    Retrieve the error number set by the last pcntl function which failed. */
    1183           2 : PHP_FUNCTION(pcntl_get_last_error)
    1184             : {
    1185           2 :         RETURN_LONG(PCNTL_G(last_error));
    1186             : }
    1187             : /* }}} */
    1188             : 
    1189             : /* {{{ proto string pcntl_strerror(int errno)
    1190             :    Retrieve the system error message associated with the given errno. */
    1191           0 : PHP_FUNCTION(pcntl_strerror)
    1192             : {
    1193             :         long error;
    1194             : 
    1195           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &error) == FAILURE) {
    1196           0 :                 RETURN_FALSE;
    1197             :         }
    1198             : 
    1199           0 :         RETURN_STRING(strerror(error), 1);
    1200             : }
    1201             : /* }}} */
    1202             : 
    1203             : /* Our custom signal handler that calls the appropriate php_function */
    1204           4 : static void pcntl_signal_handler(int signo)
    1205             : {
    1206             :         struct php_pcntl_pending_signal *psig;
    1207             :         TSRMLS_FETCH();
    1208             :         
    1209           4 :         psig = PCNTL_G(spares);
    1210           4 :         if (!psig) {
    1211             :                 /* oops, too many signals for us to track, so we'll forget about this one */
    1212           0 :                 return;
    1213             :         }
    1214           4 :         PCNTL_G(spares) = psig->next;
    1215             : 
    1216           4 :         psig->signo = signo;
    1217           4 :         psig->next = NULL;
    1218             : 
    1219             :         /* the head check is important, as the tick handler cannot atomically clear both
    1220             :          * the head and tail */
    1221           4 :         if (PCNTL_G(head) && PCNTL_G(tail)) {
    1222           0 :                 PCNTL_G(tail)->next = psig;
    1223             :         } else {
    1224           4 :                 PCNTL_G(head) = psig;
    1225             :         }
    1226           4 :         PCNTL_G(tail) = psig;
    1227             : }
    1228             : 
    1229          47 : void pcntl_signal_dispatch()
    1230             : {
    1231             :         zval *param, **handle, *retval;
    1232             :         struct php_pcntl_pending_signal *queue, *next;
    1233             :         sigset_t mask;
    1234             :         sigset_t old_mask;
    1235             :         TSRMLS_FETCH();
    1236             :                 
    1237             :         /* Mask all signals */
    1238          47 :         sigfillset(&mask);
    1239          47 :         sigprocmask(SIG_BLOCK, &mask, &old_mask);
    1240             : 
    1241             :         /* Bail if the queue is empty or if we are already playing the queue*/
    1242          47 :         if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue)) {
    1243          44 :                 sigprocmask(SIG_SETMASK, &old_mask, NULL);
    1244          44 :                 return;
    1245             :         }
    1246             : 
    1247             :         /* Prevent reentrant handler calls */
    1248           3 :         PCNTL_G(processing_signal_queue) = 1;
    1249             : 
    1250           3 :         queue = PCNTL_G(head);
    1251           3 :         PCNTL_G(head) = NULL; /* simple stores are atomic */
    1252             :         
    1253             :         /* Allocate */
    1254             : 
    1255           9 :         while (queue) {
    1256           3 :                 if (zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo, (void **) &handle)==SUCCESS) {
    1257           3 :                         MAKE_STD_ZVAL(retval);
    1258           3 :                         MAKE_STD_ZVAL(param);
    1259           3 :                         ZVAL_NULL(retval);
    1260           3 :                         ZVAL_LONG(param, queue->signo);
    1261             : 
    1262             :                         /* Call php signal handler - Note that we do not report errors, and we ignore the return value */
    1263             :                         /* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
    1264           3 :                         call_user_function(EG(function_table), NULL, *handle, retval, 1, &param TSRMLS_CC);
    1265           3 :                         zval_ptr_dtor(&param);
    1266           3 :                         zval_ptr_dtor(&retval);
    1267             :                 }
    1268             : 
    1269           3 :                 next = queue->next;
    1270           3 :                 queue->next = PCNTL_G(spares);
    1271           3 :                 PCNTL_G(spares) = queue;
    1272           3 :                 queue = next;
    1273             :         }
    1274             : 
    1275             :         /* Re-enable queue */
    1276           3 :         PCNTL_G(processing_signal_queue) = 0;
    1277             :         
    1278             :         /* return signal mask to previous state */
    1279           3 :         sigprocmask(SIG_SETMASK, &old_mask, NULL);
    1280             : }
    1281             : 
    1282             : 
    1283             : 
    1284             : /*
    1285             :  * Local variables:
    1286             :  * tab-width: 4
    1287             :  * c-basic-offset: 4
    1288             :  * indent-tabs-mode: t
    1289             :  * End:
    1290             :  */

Generated by: LCOV version 1.10

Generated at Mon, 15 Dec 2014 17:02:46 +0000 (3 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.