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: 401 467 85.9 %
Date: 2014-04-18 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-2013 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       19341 : void php_register_signal_constants(INIT_FUNC_ARGS)
     203             : {
     204             : 
     205             :         /* Wait Constants */
     206             : #ifdef WNOHANG
     207       19341 :         REGISTER_LONG_CONSTANT("WNOHANG",  (long) WNOHANG, CONST_CS | CONST_PERSISTENT);
     208             : #endif
     209             : #ifdef WUNTRACED
     210       19341 :         REGISTER_LONG_CONSTANT("WUNTRACED",  (long) WUNTRACED, CONST_CS | CONST_PERSISTENT);
     211             : #endif
     212             : 
     213             :         /* Signal Constants */
     214       19341 :         REGISTER_LONG_CONSTANT("SIG_IGN",  (long) SIG_IGN, CONST_CS | CONST_PERSISTENT);
     215       19341 :         REGISTER_LONG_CONSTANT("SIG_DFL",  (long) SIG_DFL, CONST_CS | CONST_PERSISTENT);
     216       19341 :         REGISTER_LONG_CONSTANT("SIG_ERR",  (long) SIG_ERR, CONST_CS | CONST_PERSISTENT);
     217       19341 :         REGISTER_LONG_CONSTANT("SIGHUP",   (long) SIGHUP,  CONST_CS | CONST_PERSISTENT);
     218       19341 :         REGISTER_LONG_CONSTANT("SIGINT",   (long) SIGINT,  CONST_CS | CONST_PERSISTENT);
     219       19341 :         REGISTER_LONG_CONSTANT("SIGQUIT",  (long) SIGQUIT, CONST_CS | CONST_PERSISTENT);
     220       19341 :         REGISTER_LONG_CONSTANT("SIGILL",   (long) SIGILL,  CONST_CS | CONST_PERSISTENT);
     221       19341 :         REGISTER_LONG_CONSTANT("SIGTRAP",  (long) SIGTRAP, CONST_CS | CONST_PERSISTENT);
     222       19341 :         REGISTER_LONG_CONSTANT("SIGABRT",  (long) SIGABRT, CONST_CS | CONST_PERSISTENT);
     223             : #ifdef SIGIOT
     224       19341 :         REGISTER_LONG_CONSTANT("SIGIOT",   (long) SIGIOT,  CONST_CS | CONST_PERSISTENT);
     225             : #endif
     226       19341 :         REGISTER_LONG_CONSTANT("SIGBUS",   (long) SIGBUS,  CONST_CS | CONST_PERSISTENT);
     227       19341 :         REGISTER_LONG_CONSTANT("SIGFPE",   (long) SIGFPE,  CONST_CS | CONST_PERSISTENT);
     228       19341 :         REGISTER_LONG_CONSTANT("SIGKILL",  (long) SIGKILL, CONST_CS | CONST_PERSISTENT);
     229       19341 :         REGISTER_LONG_CONSTANT("SIGUSR1",  (long) SIGUSR1, CONST_CS | CONST_PERSISTENT);
     230       19341 :         REGISTER_LONG_CONSTANT("SIGSEGV",  (long) SIGSEGV, CONST_CS | CONST_PERSISTENT);
     231       19341 :         REGISTER_LONG_CONSTANT("SIGUSR2",  (long) SIGUSR2, CONST_CS | CONST_PERSISTENT);
     232       19341 :         REGISTER_LONG_CONSTANT("SIGPIPE",  (long) SIGPIPE, CONST_CS | CONST_PERSISTENT);
     233       19341 :         REGISTER_LONG_CONSTANT("SIGALRM",  (long) SIGALRM, CONST_CS | CONST_PERSISTENT);
     234       19341 :         REGISTER_LONG_CONSTANT("SIGTERM",  (long) SIGTERM, CONST_CS | CONST_PERSISTENT);
     235             : #ifdef SIGSTKFLT
     236       19341 :         REGISTER_LONG_CONSTANT("SIGSTKFLT",(long) SIGSTKFLT, CONST_CS | CONST_PERSISTENT);
     237             : #endif 
     238             : #ifdef SIGCLD
     239       19341 :         REGISTER_LONG_CONSTANT("SIGCLD",   (long) SIGCLD, CONST_CS | CONST_PERSISTENT);
     240             : #endif
     241             : #ifdef SIGCHLD
     242       19341 :         REGISTER_LONG_CONSTANT("SIGCHLD",  (long) SIGCHLD, CONST_CS | CONST_PERSISTENT);
     243             : #endif
     244       19341 :         REGISTER_LONG_CONSTANT("SIGCONT",  (long) SIGCONT, CONST_CS | CONST_PERSISTENT);
     245       19341 :         REGISTER_LONG_CONSTANT("SIGSTOP",  (long) SIGSTOP, CONST_CS | CONST_PERSISTENT);
     246       19341 :         REGISTER_LONG_CONSTANT("SIGTSTP",  (long) SIGTSTP, CONST_CS | CONST_PERSISTENT);
     247       19341 :         REGISTER_LONG_CONSTANT("SIGTTIN",  (long) SIGTTIN, CONST_CS | CONST_PERSISTENT);
     248       19341 :         REGISTER_LONG_CONSTANT("SIGTTOU",  (long) SIGTTOU, CONST_CS | CONST_PERSISTENT);
     249       19341 :         REGISTER_LONG_CONSTANT("SIGURG",   (long) SIGURG , CONST_CS | CONST_PERSISTENT);
     250       19341 :         REGISTER_LONG_CONSTANT("SIGXCPU",  (long) SIGXCPU, CONST_CS | CONST_PERSISTENT);
     251       19341 :         REGISTER_LONG_CONSTANT("SIGXFSZ",  (long) SIGXFSZ, CONST_CS | CONST_PERSISTENT);
     252       19341 :         REGISTER_LONG_CONSTANT("SIGVTALRM",(long) SIGVTALRM, CONST_CS | CONST_PERSISTENT);
     253       19341 :         REGISTER_LONG_CONSTANT("SIGPROF",  (long) SIGPROF, CONST_CS | CONST_PERSISTENT);
     254       19341 :         REGISTER_LONG_CONSTANT("SIGWINCH", (long) SIGWINCH, CONST_CS | CONST_PERSISTENT);
     255             : #ifdef SIGPOLL
     256       19341 :         REGISTER_LONG_CONSTANT("SIGPOLL",  (long) SIGPOLL, CONST_CS | CONST_PERSISTENT);
     257             : #endif
     258       19341 :         REGISTER_LONG_CONSTANT("SIGIO",    (long) SIGIO, CONST_CS | CONST_PERSISTENT);
     259             : #ifdef SIGPWR
     260       19341 :         REGISTER_LONG_CONSTANT("SIGPWR",   (long) SIGPWR, CONST_CS | CONST_PERSISTENT);
     261             : #endif
     262             : #ifdef SIGSYS
     263       19341 :         REGISTER_LONG_CONSTANT("SIGSYS",   (long) SIGSYS, CONST_CS | CONST_PERSISTENT);
     264       19341 :         REGISTER_LONG_CONSTANT("SIGBABY",  (long) SIGSYS, CONST_CS | CONST_PERSISTENT);
     265             : #endif
     266             : 
     267             : #if HAVE_GETPRIORITY || HAVE_SETPRIORITY
     268       19341 :         REGISTER_LONG_CONSTANT("PRIO_PGRP", PRIO_PGRP, CONST_CS | CONST_PERSISTENT);
     269       19341 :         REGISTER_LONG_CONSTANT("PRIO_USER", PRIO_USER, CONST_CS | CONST_PERSISTENT);
     270       19341 :         REGISTER_LONG_CONSTANT("PRIO_PROCESS", PRIO_PROCESS, CONST_CS | CONST_PERSISTENT);
     271             : #endif
     272             : 
     273             :         /* {{{ "how" argument for sigprocmask */
     274             : #ifdef HAVE_SIGPROCMASK
     275       19341 :         REGISTER_LONG_CONSTANT("SIG_BLOCK",   SIG_BLOCK, CONST_CS | CONST_PERSISTENT);
     276       19341 :         REGISTER_LONG_CONSTANT("SIG_UNBLOCK", SIG_UNBLOCK, CONST_CS | CONST_PERSISTENT);
     277       19341 :         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       19341 :         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       19341 :         REGISTER_LONG_CONSTANT("SI_KERNEL",  SI_KERNEL,  CONST_CS | CONST_PERSISTENT);
     289             : #endif
     290       19341 :         REGISTER_LONG_CONSTANT("SI_QUEUE",   SI_QUEUE,   CONST_CS | CONST_PERSISTENT);
     291       19341 :         REGISTER_LONG_CONSTANT("SI_TIMER",   SI_TIMER,   CONST_CS | CONST_PERSISTENT);
     292       19341 :         REGISTER_LONG_CONSTANT("SI_MESGQ",   SI_MESGQ,   CONST_CS | CONST_PERSISTENT);
     293       19341 :         REGISTER_LONG_CONSTANT("SI_ASYNCIO", SI_ASYNCIO, CONST_CS | CONST_PERSISTENT);
     294             : #ifdef SI_SIGIO
     295       19341 :         REGISTER_LONG_CONSTANT("SI_SIGIO",   SI_SIGIO,   CONST_CS | CONST_PERSISTENT);
     296             : #endif
     297             : #ifdef SI_TKILL
     298       19341 :         REGISTER_LONG_CONSTANT("SI_TKILL",   SI_TKILL,   CONST_CS | CONST_PERSISTENT);
     299             : #endif
     300             : 
     301             :         /* si_code for SIGCHILD */
     302             : #ifdef CLD_EXITED
     303       19341 :         REGISTER_LONG_CONSTANT("CLD_EXITED",    CLD_EXITED,    CONST_CS | CONST_PERSISTENT);
     304             : #endif
     305             : #ifdef CLD_KILLED
     306       19341 :         REGISTER_LONG_CONSTANT("CLD_KILLED",    CLD_KILLED,    CONST_CS | CONST_PERSISTENT);
     307             : #endif
     308             : #ifdef CLD_DUMPED
     309       19341 :         REGISTER_LONG_CONSTANT("CLD_DUMPED",    CLD_DUMPED,    CONST_CS | CONST_PERSISTENT);
     310             : #endif
     311             : #ifdef CLD_TRAPPED
     312       19341 :         REGISTER_LONG_CONSTANT("CLD_TRAPPED",   CLD_TRAPPED,   CONST_CS | CONST_PERSISTENT);
     313             : #endif
     314             : #ifdef CLD_STOPPED
     315       19341 :         REGISTER_LONG_CONSTANT("CLD_STOPPED",   CLD_STOPPED,   CONST_CS | CONST_PERSISTENT);
     316             : #endif
     317             : #ifdef CLD_CONTINUED
     318       19341 :         REGISTER_LONG_CONSTANT("CLD_CONTINUED", CLD_CONTINUED, CONST_CS | CONST_PERSISTENT);
     319             : #endif
     320             : 
     321             :         /* si_code for SIGTRAP */
     322             : #ifdef TRAP_BRKPT
     323       19341 :         REGISTER_LONG_CONSTANT("TRAP_BRKPT", TRAP_BRKPT, CONST_CS | CONST_PERSISTENT);
     324             : #endif
     325             : #ifdef TRAP_TRACE
     326       19341 :         REGISTER_LONG_CONSTANT("TRAP_TRACE", TRAP_TRACE, CONST_CS | CONST_PERSISTENT);
     327             : #endif
     328             : 
     329             :         /* si_code for SIGPOLL */
     330             : #ifdef POLL_IN
     331       19341 :         REGISTER_LONG_CONSTANT("POLL_IN",  POLL_IN,  CONST_CS | CONST_PERSISTENT);
     332             : #endif
     333             : #ifdef POLL_OUT
     334       19341 :         REGISTER_LONG_CONSTANT("POLL_OUT", POLL_OUT, CONST_CS | CONST_PERSISTENT);
     335             : #endif
     336             : #ifdef POLL_MSG
     337       19341 :         REGISTER_LONG_CONSTANT("POLL_MSG", POLL_MSG, CONST_CS | CONST_PERSISTENT);
     338             : #endif
     339             : #ifdef POLL_ERR
     340       19341 :         REGISTER_LONG_CONSTANT("POLL_ERR", POLL_ERR, CONST_CS | CONST_PERSISTENT);
     341             : #endif
     342             : #ifdef POLL_PRI
     343       19341 :         REGISTER_LONG_CONSTANT("POLL_PRI", POLL_PRI, CONST_CS | CONST_PERSISTENT);
     344             : #endif
     345             : #ifdef POLL_HUP
     346       19341 :         REGISTER_LONG_CONSTANT("POLL_HUP", POLL_HUP, CONST_CS | CONST_PERSISTENT);
     347             : #endif
     348             : 
     349             : #ifdef ILL_ILLOPC
     350       19341 :         REGISTER_LONG_CONSTANT("ILL_ILLOPC", ILL_ILLOPC, CONST_CS | CONST_PERSISTENT);
     351             : #endif
     352             : #ifdef ILL_ILLOPN
     353       19341 :         REGISTER_LONG_CONSTANT("ILL_ILLOPN", ILL_ILLOPN, CONST_CS | CONST_PERSISTENT);
     354             : #endif
     355             : #ifdef ILL_ILLADR
     356       19341 :         REGISTER_LONG_CONSTANT("ILL_ILLADR", ILL_ILLADR, CONST_CS | CONST_PERSISTENT);
     357             : #endif
     358             : #ifdef ILL_ILLTRP
     359       19341 :         REGISTER_LONG_CONSTANT("ILL_ILLTRP", ILL_ILLTRP, CONST_CS | CONST_PERSISTENT);
     360             : #endif
     361             : #ifdef ILL_PRVOPC
     362       19341 :         REGISTER_LONG_CONSTANT("ILL_PRVOPC", ILL_PRVOPC, CONST_CS | CONST_PERSISTENT);
     363             : #endif
     364             : #ifdef ILL_PRVREG
     365       19341 :         REGISTER_LONG_CONSTANT("ILL_PRVREG", ILL_PRVREG, CONST_CS | CONST_PERSISTENT);
     366             : #endif
     367             : #ifdef ILL_COPROC
     368       19341 :         REGISTER_LONG_CONSTANT("ILL_COPROC", ILL_COPROC, CONST_CS | CONST_PERSISTENT);
     369             : #endif
     370             : #ifdef ILL_BADSTK
     371       19341 :         REGISTER_LONG_CONSTANT("ILL_BADSTK", ILL_BADSTK, CONST_CS | CONST_PERSISTENT);
     372             : #endif
     373             : 
     374             : #ifdef FPE_INTDIV
     375       19341 :         REGISTER_LONG_CONSTANT("FPE_INTDIV", FPE_INTDIV, CONST_CS | CONST_PERSISTENT);
     376             : #endif
     377             : #ifdef FPE_INTOVF
     378       19341 :         REGISTER_LONG_CONSTANT("FPE_INTOVF", FPE_INTOVF, CONST_CS | CONST_PERSISTENT);
     379             : #endif
     380             : #ifdef FPE_FLTDIV
     381       19341 :         REGISTER_LONG_CONSTANT("FPE_FLTDIV", FPE_FLTDIV, CONST_CS | CONST_PERSISTENT);
     382             : #endif
     383             : #ifdef FPE_FLTOVF
     384       19341 :         REGISTER_LONG_CONSTANT("FPE_FLTOVF", FPE_FLTOVF, CONST_CS | CONST_PERSISTENT);
     385             : #endif
     386             : #ifdef FPE_FLTUND
     387       19341 :         REGISTER_LONG_CONSTANT("FPE_FLTUND", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
     388             : #endif
     389             : #ifdef FPE_FLTRES
     390       19341 :         REGISTER_LONG_CONSTANT("FPE_FLTRES", FPE_FLTRES, CONST_CS | CONST_PERSISTENT);
     391             : #endif
     392             : #ifdef FPE_FLTINV
     393       19341 :         REGISTER_LONG_CONSTANT("FPE_FLTINV", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
     394             : #endif
     395             : #ifdef FPE_FLTSUB
     396       19341 :         REGISTER_LONG_CONSTANT("FPE_FLTSUB", FPE_FLTSUB, CONST_CS | CONST_PERSISTENT);
     397             : #endif
     398             : 
     399             : #ifdef SEGV_MAPERR
     400       19341 :         REGISTER_LONG_CONSTANT("SEGV_MAPERR", SEGV_MAPERR, CONST_CS | CONST_PERSISTENT);
     401             : #endif
     402             : #ifdef SEGV_ACCERR
     403       19341 :         REGISTER_LONG_CONSTANT("SEGV_ACCERR", SEGV_ACCERR, CONST_CS | CONST_PERSISTENT);
     404             : #endif
     405             : 
     406             : #ifdef BUS_ADRALN
     407       19341 :         REGISTER_LONG_CONSTANT("BUS_ADRALN", BUS_ADRALN, CONST_CS | CONST_PERSISTENT);
     408             : #endif
     409             : #ifdef BUS_ADRERR
     410       19341 :         REGISTER_LONG_CONSTANT("BUS_ADRERR", BUS_ADRERR, CONST_CS | CONST_PERSISTENT);
     411             : #endif
     412             : #ifdef BUS_OBJERR
     413       19341 :         REGISTER_LONG_CONSTANT("BUS_OBJERR", BUS_OBJERR, CONST_CS | CONST_PERSISTENT);
     414             : #endif
     415             : #endif /* HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT */
     416             :         /* }}} */
     417       19341 : }
     418             : 
     419       19341 : static void php_pcntl_register_errno_constants(INIT_FUNC_ARGS)
     420             : {
     421             : #ifdef EINTR
     422       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(EINTR);
     423             : #endif
     424             : #ifdef ECHILD
     425       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ECHILD);
     426             : #endif
     427             : #ifdef EINVAL
     428       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(EINVAL);
     429             : #endif
     430             : #ifdef EAGAIN
     431       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(EAGAIN);
     432             : #endif
     433             : #ifdef ESRCH
     434       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ESRCH);
     435             : #endif
     436             : #ifdef EACCES
     437       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(EACCES);
     438             : #endif
     439             : #ifdef EPERM
     440       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(EPERM);
     441             : #endif
     442             : #ifdef ENOMEM
     443       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOMEM);
     444             : #endif
     445             : #ifdef E2BIG
     446       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(E2BIG);
     447             : #endif
     448             : #ifdef EFAULT
     449       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(EFAULT);
     450             : #endif
     451             : #ifdef EIO
     452       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(EIO);
     453             : #endif
     454             : #ifdef EISDIR
     455       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(EISDIR);
     456             : #endif
     457             : #ifdef ELIBBAD
     458       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ELIBBAD);
     459             : #endif
     460             : #ifdef ELOOP
     461       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ELOOP);
     462             : #endif
     463             : #ifdef EMFILE
     464       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(EMFILE);
     465             : #endif
     466             : #ifdef ENAMETOOLONG
     467       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENAMETOOLONG);
     468             : #endif
     469             : #ifdef ENFILE
     470       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENFILE);
     471             : #endif
     472             : #ifdef ENOENT
     473       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOENT);
     474             : #endif
     475             : #ifdef ENOEXEC
     476       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOEXEC);
     477             : #endif
     478             : #ifdef ENOTDIR
     479       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ENOTDIR);
     480             : #endif
     481             : #ifdef ETXTBSY
     482       19341 :         REGISTER_PCNTL_ERRNO_CONSTANT(ETXTBSY);
     483             : #endif
     484       19341 : }
     485             : 
     486       19341 : static PHP_GINIT_FUNCTION(pcntl)
     487             : { 
     488       19341 :         memset(pcntl_globals, 0, sizeof(*pcntl_globals));
     489       19341 : }
     490             : 
     491       19327 : PHP_RINIT_FUNCTION(pcntl)
     492             : {
     493       19327 :         zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0);
     494       19327 :         PCNTL_G(head) = PCNTL_G(tail) = PCNTL_G(spares) = NULL;
     495       19327 :         return SUCCESS;
     496             : }
     497             : 
     498       19341 : PHP_MINIT_FUNCTION(pcntl)
     499             : {
     500       19341 :         php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU);
     501       19341 :         php_pcntl_register_errno_constants(INIT_FUNC_ARGS_PASSTHRU);
     502       19341 :         php_add_tick_function(pcntl_signal_dispatch);
     503             : 
     504       19341 :         return SUCCESS;
     505             : }
     506             : 
     507       19376 : PHP_MSHUTDOWN_FUNCTION(pcntl)
     508             : {
     509       19376 :         return SUCCESS;
     510             : }
     511             : 
     512       19362 : 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       19362 :         zend_hash_destroy(&PCNTL_G(php_signal_table));
     519       38725 :         while (PCNTL_G(head)) {
     520           1 :                 sig = PCNTL_G(head);
     521           1 :                 PCNTL_G(head) = sig->next;
     522           1 :                 efree(sig);
     523             :         }
     524       38883 :         while (PCNTL_G(spares)) {
     525         159 :                 sig = PCNTL_G(spares);
     526         159 :                 PCNTL_G(spares) = sig->next;
     527         159 :                 efree(sig);
     528             :         }
     529       19362 :         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          58 : PHP_FUNCTION(pcntl_fork)
     542             : {
     543             :         pid_t id;
     544             : 
     545          58 :         id = fork();
     546          98 :         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          98 :         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          20 : PHP_FUNCTION(pcntl_alarm)
     558             : {
     559             :         long seconds;
     560             : 
     561          20 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &seconds) == FAILURE)
     562           1 :                 return;
     563             :         
     564          19 :         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          44 : PHP_FUNCTION(pcntl_waitpid)
     571             : {
     572          44 :         long pid, options = 0;
     573          44 :         zval *z_status = NULL;
     574             :         int status;
     575             :         pid_t child_id;
     576             : 
     577          44 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|l", &pid, &z_status, &options) == FAILURE)
     578           1 :                 return;
     579             :         
     580          93 :         convert_to_long_ex(&z_status);
     581             : 
     582          43 :         status = Z_LVAL_P(z_status);
     583             : 
     584          43 :         child_id = waitpid((pid_t) pid, &status, options);
     585             : 
     586          43 :         if (child_id < 0) {
     587           0 :                 PCNTL_G(last_error) = errno;
     588             :         }
     589             : 
     590          43 :         Z_LVAL_P(z_status) = status;
     591             : 
     592          43 :         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           2 :                 args_hash = HASH_OF(args);
     765           2 :                 argc = zend_hash_num_elements(args_hash);
     766             :                 
     767           2 :                 argv = safe_emalloc((argc + 2), sizeof(char *), 0);
     768           2 :                 *argv = path;
     769          10 :                 for ( zend_hash_internal_pointer_reset(args_hash), current_arg = argv+1; 
     770           3 :                         (argi < argc && (zend_hash_get_current_data(args_hash, (void **) &element) == SUCCESS));
     771           3 :                         (argi++, current_arg++, zend_hash_move_forward(args_hash)) ) {
     772             : 
     773           3 :                         convert_to_string_ex(element);
     774           3 :                         *current_arg = Z_STRVAL_PP(element);
     775             :                 }
     776           2 :                 *(current_arg) = NULL;
     777             :         } else {
     778           1 :                 argv = emalloc(2 * sizeof(char *));
     779           1 :                 *argv = path;
     780           1 :                 *(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 occured: (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 occured: (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 (!PCNTL_G(spares)) {
     853             :                 /* since calling malloc() from within a signal handler is not portable,
     854             :                  * pre-allocate a few records for recording signals */
     855             :                 int i;
     856         165 :                 for (i = 0; i < 32; i++) {
     857             :                         struct php_pcntl_pending_signal *psig;
     858             : 
     859         160 :                         psig = emalloc(sizeof(*psig));
     860         160 :                         psig->next = PCNTL_G(spares);
     861         160 :                         PCNTL_G(spares) = psig;
     862             :                 }
     863             :         }
     864             : 
     865             :         /* Special long value case for SIG_DFL and SIG_IGN */
     866           9 :         if (Z_TYPE_P(handle)==IS_LONG) {
     867           2 :                 if (Z_LVAL_P(handle)!= (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) {
     868           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for handle argument specified");
     869             :                 }
     870           2 :                 if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == SIG_ERR) {
     871           1 :                         PCNTL_G(last_error) = errno;
     872           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
     873           1 :                         RETURN_FALSE;
     874             :                 }
     875           1 :                 RETURN_TRUE;
     876             :         }
     877             :         
     878           7 :         if (!zend_is_callable(handle, 0, &func_name TSRMLS_CC)) {
     879           1 :                 PCNTL_G(last_error) = EINVAL;
     880           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a callable function name error", func_name);
     881           1 :                 efree(func_name);
     882           1 :                 RETURN_FALSE;
     883             :         }
     884           6 :         efree(func_name);
     885             :         
     886             :         /* Add the function name to our signal table */
     887           6 :         zend_hash_index_update(&PCNTL_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle);
     888           6 :         if (dest_handle) zval_add_ref(dest_handle);
     889             :         
     890           6 :         if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == SIG_ERR) {
     891           1 :                 PCNTL_G(last_error) = errno;
     892           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
     893           1 :                 RETURN_FALSE;
     894             :         }
     895           5 :         RETURN_TRUE;
     896             : }
     897             : /* }}} */
     898             : 
     899             : /* {{{ proto bool pcntl_signal_dispatch()
     900             :    Dispatch signals to signal handlers */
     901           2 : PHP_FUNCTION(pcntl_signal_dispatch)
     902             : {
     903           2 :         pcntl_signal_dispatch();
     904           2 :         RETURN_TRUE;
     905             : }
     906             : /* }}} */
     907             : 
     908             : #ifdef HAVE_SIGPROCMASK
     909             : /* {{{ proto bool pcntl_sigprocmask(int how, array set[, array &oldset])
     910             :    Examine and change blocked signals */
     911           9 : PHP_FUNCTION(pcntl_sigprocmask)
     912             : {
     913             :         long          how, signo;
     914           9 :         zval         *user_set, *user_oldset = NULL, **user_signo;
     915             :         sigset_t      set, oldset;
     916             :         HashPosition  pos;
     917             : 
     918           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "la|z", &how, &user_set, &user_oldset) == FAILURE) {
     919           0 :                 return;
     920             :         }
     921             : 
     922           9 :         if (sigemptyset(&set) != 0 || sigemptyset(&oldset) != 0) {
     923           0 :                 PCNTL_G(last_error) = errno;
     924           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     925           0 :                 RETURN_FALSE;
     926             :         }
     927             : 
     928           9 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(user_set), &pos);
     929          25 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(user_set), (void **)&user_signo, &pos) == SUCCESS)
     930             :         {
     931           8 :                 if (Z_TYPE_PP(user_signo) != IS_LONG) {
     932           2 :                         SEPARATE_ZVAL(user_signo);
     933           4 :                         convert_to_long_ex(user_signo);
     934             :                 }
     935           8 :                 signo = Z_LVAL_PP(user_signo);
     936           8 :                 if (sigaddset(&set, signo) != 0) {
     937           1 :                         PCNTL_G(last_error) = errno;
     938           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     939           1 :                         RETURN_FALSE;
     940             :                 }
     941           7 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(user_set), &pos);
     942             :         }
     943             : 
     944           8 :         if (sigprocmask(how, &set, &oldset) != 0) {
     945           0 :                 PCNTL_G(last_error) = errno;
     946           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     947           0 :                 RETURN_FALSE;
     948             :         }
     949             : 
     950           8 :         if (user_oldset != NULL) {
     951           7 :                 if (Z_TYPE_P(user_oldset) != IS_ARRAY) {
     952           1 :                         zval_dtor(user_oldset);
     953           1 :                         array_init(user_oldset);
     954             :                 } else {
     955           6 :                         zend_hash_clean(Z_ARRVAL_P(user_oldset));
     956             :                 }
     957         448 :                 for (signo = 1; signo < MAX(NSIG-1, SIGRTMAX); ++signo) {
     958         441 :                         if (sigismember(&oldset, signo) != 1) {
     959         431 :                                 continue;
     960             :                         }
     961          10 :                         add_next_index_long(user_oldset, signo);
     962             :                 }
     963             :         }
     964             : 
     965           8 :         RETURN_TRUE;
     966             : }
     967             : /* }}} */
     968             : #endif
     969             : 
     970             : #if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
     971           5 : static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */
     972             : {
     973           5 :         zval            *user_set, **user_signo, *user_siginfo = NULL;
     974           5 :         long             tv_sec = 0, tv_nsec = 0;
     975             :         sigset_t         set;
     976             :         HashPosition     pos;
     977             :         int              signo;
     978             :         siginfo_t        siginfo;
     979             :         struct timespec  timeout;
     980             : 
     981           5 :         if (timedwait) {
     982           2 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
     983           0 :                         return;
     984             :                 }
     985             :         } else {
     986           3 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &user_set, &user_siginfo) == FAILURE) {
     987           0 :                         return;
     988             :                 }
     989             :         }
     990             : 
     991           5 :         if (sigemptyset(&set) != 0) {
     992           0 :                 PCNTL_G(last_error) = errno;
     993           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
     994           0 :                 RETURN_FALSE;
     995             :         }
     996             : 
     997           5 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(user_set), &pos);
     998          14 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(user_set), (void **)&user_signo, &pos) == SUCCESS)
     999             :         {
    1000           5 :                 if (Z_TYPE_PP(user_signo) != IS_LONG) {
    1001           2 :                         SEPARATE_ZVAL(user_signo);
    1002           4 :                         convert_to_long_ex(user_signo);
    1003             :                 }
    1004           5 :                 signo = Z_LVAL_PP(user_signo);
    1005           5 :                 if (sigaddset(&set, signo) != 0) {
    1006           1 :                         PCNTL_G(last_error) = errno;
    1007           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
    1008           1 :                         RETURN_FALSE;
    1009             :                 }
    1010           4 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(user_set), &pos);
    1011             :         }
    1012             : 
    1013           4 :         if (timedwait) {
    1014           2 :                 timeout.tv_sec  = (time_t) tv_sec;
    1015           2 :                 timeout.tv_nsec = tv_nsec;
    1016           2 :                 signo = sigtimedwait(&set, &siginfo, &timeout);
    1017             :         } else {
    1018           2 :                 signo = sigwaitinfo(&set, &siginfo);
    1019             :         }
    1020           4 :         if (signo == -1 && errno != EAGAIN) {
    1021           1 :                 PCNTL_G(last_error) = errno;
    1022           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
    1023             :         }
    1024             : 
    1025             :         /*
    1026             :          * sigtimedwait and sigwaitinfo can return 0 on success on some 
    1027             :          * platforms, e.g. NetBSD
    1028             :          */
    1029           4 :         if (!signo && siginfo.si_signo) {
    1030           0 :                 signo = siginfo.si_signo;
    1031             :         }
    1032             : 
    1033           4 :         if (signo > 0 && user_siginfo) {
    1034           3 :                 if (Z_TYPE_P(user_siginfo) != IS_ARRAY) {
    1035           1 :                         zval_dtor(user_siginfo);
    1036           1 :                         array_init(user_siginfo);
    1037             :                 } else {
    1038           2 :                         zend_hash_clean(Z_ARRVAL_P(user_siginfo));
    1039             :                 }
    1040           3 :                 add_assoc_long_ex(user_siginfo, "signo", sizeof("signo"), siginfo.si_signo);
    1041           3 :                 add_assoc_long_ex(user_siginfo, "errno", sizeof("errno"), siginfo.si_errno);
    1042           3 :                 add_assoc_long_ex(user_siginfo, "code",  sizeof("code"),  siginfo.si_code);
    1043           3 :                 switch(signo) {
    1044             : #ifdef SIGCHLD
    1045             :                         case SIGCHLD:
    1046           1 :                                 add_assoc_long_ex(user_siginfo,   "status", sizeof("status"), siginfo.si_status);
    1047             : # ifdef si_utime
    1048           1 :                                 add_assoc_double_ex(user_siginfo, "utime",  sizeof("utime"),  siginfo.si_utime);
    1049             : # endif
    1050             : # ifdef si_stime
    1051           1 :                                 add_assoc_double_ex(user_siginfo, "stime",  sizeof("stime"),  siginfo.si_stime);
    1052             : # endif
    1053           1 :                                 add_assoc_long_ex(user_siginfo,   "pid",    sizeof("pid"),    siginfo.si_pid);
    1054           1 :                                 add_assoc_long_ex(user_siginfo,   "uid",    sizeof("uid"),    siginfo.si_uid);
    1055           1 :                                 break;
    1056             : #endif
    1057             :                         case SIGILL:
    1058             :                         case SIGFPE:
    1059             :                         case SIGSEGV:
    1060             :                         case SIGBUS:
    1061           0 :                                 add_assoc_double_ex(user_siginfo, "addr", sizeof("addr"), (long)siginfo.si_addr);
    1062           0 :                                 break;
    1063             : #ifdef SIGPOLL
    1064             :                         case SIGPOLL:
    1065           0 :                                 add_assoc_long_ex(user_siginfo, "band", sizeof("band"), siginfo.si_band);
    1066             : # ifdef si_fd
    1067           0 :                                 add_assoc_long_ex(user_siginfo, "fd",   sizeof("fd"),   siginfo.si_fd);
    1068             : # endif
    1069             :                                 break;
    1070             : #endif
    1071             :                         EMPTY_SWITCH_DEFAULT_CASE();
    1072             :                 }
    1073             :         }
    1074             :         
    1075           4 :         RETURN_LONG(signo);
    1076             : }
    1077             : /* }}} */
    1078             : 
    1079             : /* {{{ proto int pcnlt_sigwaitinfo(array set[, array &siginfo])
    1080             :    Synchronously wait for queued signals */
    1081           3 : PHP_FUNCTION(pcntl_sigwaitinfo)
    1082             : {
    1083           3 :         pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    1084           3 : }
    1085             : /* }}} */
    1086             : 
    1087             : /* {{{ proto int pcntl_sigtimedwait(array set[, array &siginfo[, int seconds[, int nanoseconds]]])
    1088             :    Wait for queued signals */
    1089           2 : PHP_FUNCTION(pcntl_sigtimedwait)
    1090             : {
    1091           2 :         pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    1092           2 : }
    1093             : /* }}} */
    1094             : #endif
    1095             : 
    1096             : #ifdef HAVE_GETPRIORITY
    1097             : /* {{{ proto int pcntl_getpriority([int pid [, int process_identifier]])
    1098             :    Get the priority of any process */
    1099           0 : PHP_FUNCTION(pcntl_getpriority)
    1100             : {
    1101           0 :         long who = PRIO_PROCESS;
    1102           0 :         long pid = getpid();
    1103             :         int pri;
    1104             :         
    1105           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &pid, &who) == FAILURE) {
    1106           0 :                 RETURN_FALSE;
    1107             :         }
    1108             : 
    1109             :         /* needs to be cleared, since any returned value is valid */ 
    1110           0 :         errno = 0;
    1111             : 
    1112           0 :         pri = getpriority(who, pid);
    1113             : 
    1114           0 :         if (errno) {
    1115           0 :                 PCNTL_G(last_error) = errno;
    1116           0 :                 switch (errno) {
    1117             :                         case ESRCH:
    1118           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
    1119           0 :                                 break;
    1120             :                         case EINVAL:
    1121           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
    1122           0 :                                 break;
    1123             :                         default:
    1124           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occured", errno);
    1125             :                                 break;
    1126             :                 }
    1127           0 :                 RETURN_FALSE;
    1128             :         }
    1129             : 
    1130           0 :         RETURN_LONG(pri);
    1131             : }
    1132             : /* }}} */
    1133             : #endif
    1134             : 
    1135             : #ifdef HAVE_SETPRIORITY
    1136             : /* {{{ proto bool pcntl_setpriority(int priority [, int pid [, int process_identifier]])
    1137             :    Change the priority of any process */
    1138           0 : PHP_FUNCTION(pcntl_setpriority)
    1139             : {
    1140           0 :         long who = PRIO_PROCESS;
    1141           0 :         long pid = getpid();
    1142             :         long pri;
    1143             : 
    1144           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &pri, &pid, &who) == FAILURE) {
    1145           0 :                 RETURN_FALSE;
    1146             :         }
    1147             : 
    1148           0 :         if (setpriority(who, pid, pri)) {
    1149           0 :                 PCNTL_G(last_error) = errno;
    1150           0 :                 switch (errno) {
    1151             :                         case ESRCH:
    1152           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
    1153           0 :                                 break;
    1154             :                         case EINVAL:
    1155           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
    1156           0 :                                 break;
    1157             :                         case EPERM:
    1158           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);
    1159           0 :                                 break;
    1160             :                         case EACCES:
    1161           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Only a super user may attempt to increase the process priority", errno);
    1162           0 :                                 break;
    1163             :                         default:
    1164           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occured", errno);
    1165             :                                 break;
    1166             :                 }
    1167           0 :                 RETURN_FALSE;
    1168             :         }
    1169             :         
    1170           0 :         RETURN_TRUE;
    1171             : }
    1172             : /* }}} */
    1173             : #endif
    1174             : 
    1175             : /* {{{ proto int pcntl_get_last_error(void)
    1176             :    Retrieve the error number set by the last pcntl function which failed. */
    1177           2 : PHP_FUNCTION(pcntl_get_last_error)
    1178             : {
    1179           2 :         RETURN_LONG(PCNTL_G(last_error));
    1180             : }
    1181             : /* }}} */
    1182             : 
    1183             : /* {{{ proto string pcntl_strerror(int errno)
    1184             :    Retrieve the system error message associated with the given errno. */
    1185           0 : PHP_FUNCTION(pcntl_strerror)
    1186             : {
    1187             :         long error;
    1188             : 
    1189           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &error) == FAILURE) {
    1190           0 :                 RETURN_FALSE;
    1191             :         }
    1192             : 
    1193           0 :         RETURN_STRING(strerror(error), 1);
    1194             : }
    1195             : /* }}} */
    1196             : 
    1197             : /* Our custom signal handler that calls the appropriate php_function */
    1198           4 : static void pcntl_signal_handler(int signo)
    1199             : {
    1200             :         struct php_pcntl_pending_signal *psig;
    1201             :         TSRMLS_FETCH();
    1202             :         
    1203           4 :         psig = PCNTL_G(spares);
    1204           4 :         if (!psig) {
    1205             :                 /* oops, too many signals for us to track, so we'll forget about this one */
    1206           0 :                 return;
    1207             :         }
    1208           4 :         PCNTL_G(spares) = psig->next;
    1209             : 
    1210           4 :         psig->signo = signo;
    1211           4 :         psig->next = NULL;
    1212             : 
    1213             :         /* the head check is important, as the tick handler cannot atomically clear both
    1214             :          * the head and tail */
    1215           4 :         if (PCNTL_G(head) && PCNTL_G(tail)) {
    1216           0 :                 PCNTL_G(tail)->next = psig;
    1217             :         } else {
    1218           4 :                 PCNTL_G(head) = psig;
    1219             :         }
    1220           4 :         PCNTL_G(tail) = psig;
    1221             : }
    1222             : 
    1223          40 : void pcntl_signal_dispatch()
    1224             : {
    1225             :         zval *param, **handle, *retval;
    1226             :         struct php_pcntl_pending_signal *queue, *next;
    1227             :         sigset_t mask;
    1228             :         sigset_t old_mask;
    1229             :         TSRMLS_FETCH();
    1230             :                 
    1231             :         /* Mask all signals */
    1232          40 :         sigfillset(&mask);
    1233          40 :         sigprocmask(SIG_BLOCK, &mask, &old_mask);
    1234             : 
    1235             :         /* Bail if the queue is empty or if we are already playing the queue*/
    1236          40 :         if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue)) {
    1237          37 :                 sigprocmask(SIG_SETMASK, &old_mask, NULL);
    1238          37 :                 return;
    1239             :         }
    1240             : 
    1241             :         /* Prevent reentrant handler calls */
    1242           3 :         PCNTL_G(processing_signal_queue) = 1;
    1243             : 
    1244           3 :         queue = PCNTL_G(head);
    1245           3 :         PCNTL_G(head) = NULL; /* simple stores are atomic */
    1246             :         
    1247             :         /* Allocate */
    1248             : 
    1249           9 :         while (queue) {
    1250           3 :                 if (zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo, (void **) &handle)==SUCCESS) {
    1251           3 :                         MAKE_STD_ZVAL(retval);
    1252           3 :                         MAKE_STD_ZVAL(param);
    1253           3 :                         ZVAL_NULL(retval);
    1254           3 :                         ZVAL_LONG(param, queue->signo);
    1255             : 
    1256             :                         /* Call php signal handler - Note that we do not report errors, and we ignore the return value */
    1257             :                         /* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
    1258           3 :                         call_user_function(EG(function_table), NULL, *handle, retval, 1, &param TSRMLS_CC);
    1259           3 :                         zval_ptr_dtor(&param);
    1260           3 :                         zval_ptr_dtor(&retval);
    1261             :                 }
    1262             : 
    1263           3 :                 next = queue->next;
    1264           3 :                 queue->next = PCNTL_G(spares);
    1265           3 :                 PCNTL_G(spares) = queue;
    1266           3 :                 queue = next;
    1267             :         }
    1268             : 
    1269             :         /* Re-enable queue */
    1270           3 :         PCNTL_G(processing_signal_queue) = 0;
    1271             :         
    1272             :         /* return signal mask to previous state */
    1273           3 :         sigprocmask(SIG_SETMASK, &old_mask, NULL);
    1274             : }
    1275             : 
    1276             : 
    1277             : 
    1278             : /*
    1279             :  * Local variables:
    1280             :  * tab-width: 4
    1281             :  * c-basic-offset: 4
    1282             :  * indent-tabs-mode: t
    1283             :  * End:
    1284             :  */

Generated by: LCOV version 1.10

Generated at Fri, 18 Apr 2014 07:01:31 +0000 (2 days ago)

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