Annotation of embedaddon/php/ext/pcntl/pcntl.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2012 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: pcntl.c 321634 2012-01-01 13:15:04Z felipe $ */
                     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: void php_register_signal_constants(INIT_FUNC_ARGS)
                    203: {
                    204: 
                    205:        /* Wait Constants */
                    206: #ifdef WNOHANG
                    207:        REGISTER_LONG_CONSTANT("WNOHANG",  (long) WNOHANG, CONST_CS | CONST_PERSISTENT);
                    208: #endif
                    209: #ifdef WUNTRACED
                    210:        REGISTER_LONG_CONSTANT("WUNTRACED",  (long) WUNTRACED, CONST_CS | CONST_PERSISTENT);
                    211: #endif
                    212: 
                    213:        /* Signal Constants */
                    214:        REGISTER_LONG_CONSTANT("SIG_IGN",  (long) SIG_IGN, CONST_CS | CONST_PERSISTENT);
                    215:        REGISTER_LONG_CONSTANT("SIG_DFL",  (long) SIG_DFL, CONST_CS | CONST_PERSISTENT);
                    216:        REGISTER_LONG_CONSTANT("SIG_ERR",  (long) SIG_ERR, CONST_CS | CONST_PERSISTENT);
                    217:        REGISTER_LONG_CONSTANT("SIGHUP",   (long) SIGHUP,  CONST_CS | CONST_PERSISTENT);
                    218:        REGISTER_LONG_CONSTANT("SIGINT",   (long) SIGINT,  CONST_CS | CONST_PERSISTENT);
                    219:        REGISTER_LONG_CONSTANT("SIGQUIT",  (long) SIGQUIT, CONST_CS | CONST_PERSISTENT);
                    220:        REGISTER_LONG_CONSTANT("SIGILL",   (long) SIGILL,  CONST_CS | CONST_PERSISTENT);
                    221:        REGISTER_LONG_CONSTANT("SIGTRAP",  (long) SIGTRAP, CONST_CS | CONST_PERSISTENT);
                    222:        REGISTER_LONG_CONSTANT("SIGABRT",  (long) SIGABRT, CONST_CS | CONST_PERSISTENT);
                    223: #ifdef SIGIOT
                    224:        REGISTER_LONG_CONSTANT("SIGIOT",   (long) SIGIOT,  CONST_CS | CONST_PERSISTENT);
                    225: #endif
                    226:        REGISTER_LONG_CONSTANT("SIGBUS",   (long) SIGBUS,  CONST_CS | CONST_PERSISTENT);
                    227:        REGISTER_LONG_CONSTANT("SIGFPE",   (long) SIGFPE,  CONST_CS | CONST_PERSISTENT);
                    228:        REGISTER_LONG_CONSTANT("SIGKILL",  (long) SIGKILL, CONST_CS | CONST_PERSISTENT);
                    229:        REGISTER_LONG_CONSTANT("SIGUSR1",  (long) SIGUSR1, CONST_CS | CONST_PERSISTENT);
                    230:        REGISTER_LONG_CONSTANT("SIGSEGV",  (long) SIGSEGV, CONST_CS | CONST_PERSISTENT);
                    231:        REGISTER_LONG_CONSTANT("SIGUSR2",  (long) SIGUSR2, CONST_CS | CONST_PERSISTENT);
                    232:        REGISTER_LONG_CONSTANT("SIGPIPE",  (long) SIGPIPE, CONST_CS | CONST_PERSISTENT);
                    233:        REGISTER_LONG_CONSTANT("SIGALRM",  (long) SIGALRM, CONST_CS | CONST_PERSISTENT);
                    234:        REGISTER_LONG_CONSTANT("SIGTERM",  (long) SIGTERM, CONST_CS | CONST_PERSISTENT);
                    235: #ifdef SIGSTKFLT
                    236:        REGISTER_LONG_CONSTANT("SIGSTKFLT",(long) SIGSTKFLT, CONST_CS | CONST_PERSISTENT);
                    237: #endif 
                    238: #ifdef SIGCLD
                    239:        REGISTER_LONG_CONSTANT("SIGCLD",   (long) SIGCLD, CONST_CS | CONST_PERSISTENT);
                    240: #endif
                    241: #ifdef SIGCHLD
                    242:        REGISTER_LONG_CONSTANT("SIGCHLD",  (long) SIGCHLD, CONST_CS | CONST_PERSISTENT);
                    243: #endif
                    244:        REGISTER_LONG_CONSTANT("SIGCONT",  (long) SIGCONT, CONST_CS | CONST_PERSISTENT);
                    245:        REGISTER_LONG_CONSTANT("SIGSTOP",  (long) SIGSTOP, CONST_CS | CONST_PERSISTENT);
                    246:        REGISTER_LONG_CONSTANT("SIGTSTP",  (long) SIGTSTP, CONST_CS | CONST_PERSISTENT);
                    247:        REGISTER_LONG_CONSTANT("SIGTTIN",  (long) SIGTTIN, CONST_CS | CONST_PERSISTENT);
                    248:        REGISTER_LONG_CONSTANT("SIGTTOU",  (long) SIGTTOU, CONST_CS | CONST_PERSISTENT);
                    249:        REGISTER_LONG_CONSTANT("SIGURG",   (long) SIGURG , CONST_CS | CONST_PERSISTENT);
                    250:        REGISTER_LONG_CONSTANT("SIGXCPU",  (long) SIGXCPU, CONST_CS | CONST_PERSISTENT);
                    251:        REGISTER_LONG_CONSTANT("SIGXFSZ",  (long) SIGXFSZ, CONST_CS | CONST_PERSISTENT);
                    252:        REGISTER_LONG_CONSTANT("SIGVTALRM",(long) SIGVTALRM, CONST_CS | CONST_PERSISTENT);
                    253:        REGISTER_LONG_CONSTANT("SIGPROF",  (long) SIGPROF, CONST_CS | CONST_PERSISTENT);
                    254:        REGISTER_LONG_CONSTANT("SIGWINCH", (long) SIGWINCH, CONST_CS | CONST_PERSISTENT);
                    255: #ifdef SIGPOLL
                    256:        REGISTER_LONG_CONSTANT("SIGPOLL",  (long) SIGPOLL, CONST_CS | CONST_PERSISTENT);
                    257: #endif
                    258:        REGISTER_LONG_CONSTANT("SIGIO",    (long) SIGIO, CONST_CS | CONST_PERSISTENT);
                    259: #ifdef SIGPWR
                    260:        REGISTER_LONG_CONSTANT("SIGPWR",   (long) SIGPWR, CONST_CS | CONST_PERSISTENT);
                    261: #endif
                    262: #ifdef SIGSYS
                    263:        REGISTER_LONG_CONSTANT("SIGSYS",   (long) SIGSYS, CONST_CS | CONST_PERSISTENT);
                    264:        REGISTER_LONG_CONSTANT("SIGBABY",  (long) SIGSYS, CONST_CS | CONST_PERSISTENT);
                    265: #endif
                    266: 
                    267: #if HAVE_GETPRIORITY || HAVE_SETPRIORITY
                    268:        REGISTER_LONG_CONSTANT("PRIO_PGRP", PRIO_PGRP, CONST_CS | CONST_PERSISTENT);
                    269:        REGISTER_LONG_CONSTANT("PRIO_USER", PRIO_USER, CONST_CS | CONST_PERSISTENT);
                    270:        REGISTER_LONG_CONSTANT("PRIO_PROCESS", PRIO_PROCESS, CONST_CS | CONST_PERSISTENT);
                    271: #endif
                    272: 
                    273:        /* {{{ "how" argument for sigprocmask */
                    274: #ifdef HAVE_SIGPROCMASK
                    275:        REGISTER_LONG_CONSTANT("SIG_BLOCK",   SIG_BLOCK, CONST_CS | CONST_PERSISTENT);
                    276:        REGISTER_LONG_CONSTANT("SIG_UNBLOCK", SIG_UNBLOCK, CONST_CS | CONST_PERSISTENT);
                    277:        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:        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:        REGISTER_LONG_CONSTANT("SI_KERNEL",  SI_KERNEL,  CONST_CS | CONST_PERSISTENT);
                    289: #endif
                    290:        REGISTER_LONG_CONSTANT("SI_QUEUE",   SI_QUEUE,   CONST_CS | CONST_PERSISTENT);
                    291:        REGISTER_LONG_CONSTANT("SI_TIMER",   SI_TIMER,   CONST_CS | CONST_PERSISTENT);
                    292:        REGISTER_LONG_CONSTANT("SI_MESGQ",   SI_MESGQ,   CONST_CS | CONST_PERSISTENT);
                    293:        REGISTER_LONG_CONSTANT("SI_ASYNCIO", SI_ASYNCIO, CONST_CS | CONST_PERSISTENT);
                    294: #ifdef SI_SIGIO
                    295:        REGISTER_LONG_CONSTANT("SI_SIGIO",   SI_SIGIO,   CONST_CS | CONST_PERSISTENT);
                    296: #endif
                    297: #ifdef SI_TKILL
                    298:        REGISTER_LONG_CONSTANT("SI_TKILL",   SI_TKILL,   CONST_CS | CONST_PERSISTENT);
                    299: #endif
                    300: 
                    301:        /* si_code for SIGCHILD */
                    302: #ifdef CLD_EXITED
                    303:        REGISTER_LONG_CONSTANT("CLD_EXITED",    CLD_EXITED,    CONST_CS | CONST_PERSISTENT);
                    304: #endif
                    305: #ifdef CLD_KILLED
                    306:        REGISTER_LONG_CONSTANT("CLD_KILLED",    CLD_KILLED,    CONST_CS | CONST_PERSISTENT);
                    307: #endif
                    308: #ifdef CLD_DUMPED
                    309:        REGISTER_LONG_CONSTANT("CLD_DUMPED",    CLD_DUMPED,    CONST_CS | CONST_PERSISTENT);
                    310: #endif
                    311: #ifdef CLD_TRAPPED
                    312:        REGISTER_LONG_CONSTANT("CLD_TRAPPED",   CLD_TRAPPED,   CONST_CS | CONST_PERSISTENT);
                    313: #endif
                    314: #ifdef CLD_STOPPED
                    315:        REGISTER_LONG_CONSTANT("CLD_STOPPED",   CLD_STOPPED,   CONST_CS | CONST_PERSISTENT);
                    316: #endif
                    317: #ifdef CLD_CONTINUED
                    318:        REGISTER_LONG_CONSTANT("CLD_CONTINUED", CLD_CONTINUED, CONST_CS | CONST_PERSISTENT);
                    319: #endif
                    320: 
                    321:        /* si_code for SIGTRAP */
                    322: #ifdef TRAP_BRKPT
                    323:        REGISTER_LONG_CONSTANT("TRAP_BRKPT", TRAP_BRKPT, CONST_CS | CONST_PERSISTENT);
                    324: #endif
                    325: #ifdef TRAP_TRACE
                    326:        REGISTER_LONG_CONSTANT("TRAP_TRACE", TRAP_TRACE, CONST_CS | CONST_PERSISTENT);
                    327: #endif
                    328: 
                    329:        /* si_code for SIGPOLL */
                    330: #ifdef POLL_IN
                    331:        REGISTER_LONG_CONSTANT("POLL_IN",  POLL_IN,  CONST_CS | CONST_PERSISTENT);
                    332: #endif
                    333: #ifdef POLL_OUT
                    334:        REGISTER_LONG_CONSTANT("POLL_OUT", POLL_OUT, CONST_CS | CONST_PERSISTENT);
                    335: #endif
                    336: #ifdef POLL_MSG
                    337:        REGISTER_LONG_CONSTANT("POLL_MSG", POLL_MSG, CONST_CS | CONST_PERSISTENT);
                    338: #endif
                    339: #ifdef POLL_ERR
                    340:        REGISTER_LONG_CONSTANT("POLL_ERR", POLL_ERR, CONST_CS | CONST_PERSISTENT);
                    341: #endif
                    342: #ifdef POLL_PRI
                    343:        REGISTER_LONG_CONSTANT("POLL_PRI", POLL_PRI, CONST_CS | CONST_PERSISTENT);
                    344: #endif
                    345: #ifdef POLL_HUP
                    346:        REGISTER_LONG_CONSTANT("POLL_HUP", POLL_HUP, CONST_CS | CONST_PERSISTENT);
                    347: #endif
                    348: 
                    349: #ifdef ILL_ILLOPC
                    350:        REGISTER_LONG_CONSTANT("ILL_ILLOPC", ILL_ILLOPC, CONST_CS | CONST_PERSISTENT);
                    351: #endif
                    352: #ifdef ILL_ILLOPN
                    353:        REGISTER_LONG_CONSTANT("ILL_ILLOPN", ILL_ILLOPN, CONST_CS | CONST_PERSISTENT);
                    354: #endif
                    355: #ifdef ILL_ILLADR
                    356:        REGISTER_LONG_CONSTANT("ILL_ILLADR", ILL_ILLADR, CONST_CS | CONST_PERSISTENT);
                    357: #endif
                    358: #ifdef ILL_ILLTRP
                    359:        REGISTER_LONG_CONSTANT("ILL_ILLTRP", ILL_ILLTRP, CONST_CS | CONST_PERSISTENT);
                    360: #endif
                    361: #ifdef ILL_PRVOPC
                    362:        REGISTER_LONG_CONSTANT("ILL_PRVOPC", ILL_PRVOPC, CONST_CS | CONST_PERSISTENT);
                    363: #endif
                    364: #ifdef ILL_PRVREG
                    365:        REGISTER_LONG_CONSTANT("ILL_PRVREG", ILL_PRVREG, CONST_CS | CONST_PERSISTENT);
                    366: #endif
                    367: #ifdef ILL_COPROC
                    368:        REGISTER_LONG_CONSTANT("ILL_COPROC", ILL_COPROC, CONST_CS | CONST_PERSISTENT);
                    369: #endif
                    370: #ifdef ILL_BADSTK
                    371:        REGISTER_LONG_CONSTANT("ILL_BADSTK", ILL_BADSTK, CONST_CS | CONST_PERSISTENT);
                    372: #endif
                    373: 
                    374: #ifdef FPE_INTDIV
                    375:        REGISTER_LONG_CONSTANT("FPE_INTDIV", FPE_INTDIV, CONST_CS | CONST_PERSISTENT);
                    376: #endif
                    377: #ifdef FPE_INTOVF
                    378:        REGISTER_LONG_CONSTANT("FPE_INTOVF", FPE_INTOVF, CONST_CS | CONST_PERSISTENT);
                    379: #endif
                    380: #ifdef FPE_FLTDIV
                    381:        REGISTER_LONG_CONSTANT("FPE_FLTDIV", FPE_FLTDIV, CONST_CS | CONST_PERSISTENT);
                    382: #endif
                    383: #ifdef FPE_FLTOVF
                    384:        REGISTER_LONG_CONSTANT("FPE_FLTOVF", FPE_FLTOVF, CONST_CS | CONST_PERSISTENT);
                    385: #endif
                    386: #ifdef FPE_FLTUND
                    387:        REGISTER_LONG_CONSTANT("FPE_FLTUND", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
                    388: #endif
                    389: #ifdef FPE_FLTRES
                    390:        REGISTER_LONG_CONSTANT("FPE_FLTRES", FPE_FLTRES, CONST_CS | CONST_PERSISTENT);
                    391: #endif
                    392: #ifdef FPE_FLTINV
                    393:        REGISTER_LONG_CONSTANT("FPE_FLTINV", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
                    394: #endif
                    395: #ifdef FPE_FLTSUB
                    396:        REGISTER_LONG_CONSTANT("FPE_FLTSUB", FPE_FLTSUB, CONST_CS | CONST_PERSISTENT);
                    397: #endif
                    398: 
                    399: #ifdef SEGV_MAPERR
                    400:        REGISTER_LONG_CONSTANT("SEGV_MAPERR", SEGV_MAPERR, CONST_CS | CONST_PERSISTENT);
                    401: #endif
                    402: #ifdef SEGV_ACCERR
                    403:        REGISTER_LONG_CONSTANT("SEGV_ACCERR", SEGV_ACCERR, CONST_CS | CONST_PERSISTENT);
                    404: #endif
                    405: 
                    406: #ifdef BUS_ADRALN
                    407:        REGISTER_LONG_CONSTANT("BUS_ADRALN", BUS_ADRALN, CONST_CS | CONST_PERSISTENT);
                    408: #endif
                    409: #ifdef BUS_ADRERR
                    410:        REGISTER_LONG_CONSTANT("BUS_ADRERR", BUS_ADRERR, CONST_CS | CONST_PERSISTENT);
                    411: #endif
                    412: #ifdef BUS_OBJERR
                    413:        REGISTER_LONG_CONSTANT("BUS_OBJERR", BUS_OBJERR, CONST_CS | CONST_PERSISTENT);
                    414: #endif
                    415: #endif /* HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT */
                    416:        /* }}} */
                    417: }
                    418: 
                    419: static void php_pcntl_register_errno_constants(INIT_FUNC_ARGS)
                    420: {
                    421: #ifdef EINTR
                    422:        REGISTER_PCNTL_ERRNO_CONSTANT(EINTR);
                    423: #endif
                    424: #ifdef ECHILD
                    425:        REGISTER_PCNTL_ERRNO_CONSTANT(ECHILD);
                    426: #endif
                    427: #ifdef EINVAL
                    428:        REGISTER_PCNTL_ERRNO_CONSTANT(EINVAL);
                    429: #endif
                    430: #ifdef EAGAIN
                    431:        REGISTER_PCNTL_ERRNO_CONSTANT(EAGAIN);
                    432: #endif
                    433: #ifdef ESRCH
                    434:        REGISTER_PCNTL_ERRNO_CONSTANT(ESRCH);
                    435: #endif
                    436: #ifdef EACCES
                    437:        REGISTER_PCNTL_ERRNO_CONSTANT(EACCES);
                    438: #endif
                    439: #ifdef EPERM
                    440:        REGISTER_PCNTL_ERRNO_CONSTANT(EPERM);
                    441: #endif
                    442: #ifdef ENOMEM
                    443:        REGISTER_PCNTL_ERRNO_CONSTANT(ENOMEM);
                    444: #endif
                    445: #ifdef E2BIG
                    446:        REGISTER_PCNTL_ERRNO_CONSTANT(E2BIG);
                    447: #endif
                    448: #ifdef EFAULT
                    449:        REGISTER_PCNTL_ERRNO_CONSTANT(EFAULT);
                    450: #endif
                    451: #ifdef EIO
                    452:        REGISTER_PCNTL_ERRNO_CONSTANT(EIO);
                    453: #endif
                    454: #ifdef EISDIR
                    455:        REGISTER_PCNTL_ERRNO_CONSTANT(EISDIR);
                    456: #endif
                    457: #ifdef ELIBBAD
                    458:        REGISTER_PCNTL_ERRNO_CONSTANT(ELIBBAD);
                    459: #endif
                    460: #ifdef ELOOP
                    461:        REGISTER_PCNTL_ERRNO_CONSTANT(ELOOP);
                    462: #endif
                    463: #ifdef EMFILE
                    464:        REGISTER_PCNTL_ERRNO_CONSTANT(EMFILE);
                    465: #endif
                    466: #ifdef ENAMETOOLONG
                    467:        REGISTER_PCNTL_ERRNO_CONSTANT(ENAMETOOLONG);
                    468: #endif
                    469: #ifdef ENFILE
                    470:        REGISTER_PCNTL_ERRNO_CONSTANT(ENFILE);
                    471: #endif
                    472: #ifdef ENOENT
                    473:        REGISTER_PCNTL_ERRNO_CONSTANT(ENOENT);
                    474: #endif
                    475: #ifdef ENOEXEC
                    476:        REGISTER_PCNTL_ERRNO_CONSTANT(ENOEXEC);
                    477: #endif
                    478: #ifdef ENOTDIR
                    479:        REGISTER_PCNTL_ERRNO_CONSTANT(ENOTDIR);
                    480: #endif
                    481: #ifdef ETXTBSY
                    482:        REGISTER_PCNTL_ERRNO_CONSTANT(ETXTBSY);
                    483: #endif
                    484: }
                    485: 
                    486: static PHP_GINIT_FUNCTION(pcntl)
                    487: { 
                    488:        memset(pcntl_globals, 0, sizeof(*pcntl_globals));
                    489: }
                    490: 
                    491: PHP_RINIT_FUNCTION(pcntl)
                    492: {
                    493:        zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0);
                    494:        PCNTL_G(head) = PCNTL_G(tail) = PCNTL_G(spares) = NULL;
                    495:        return SUCCESS;
                    496: }
                    497: 
                    498: PHP_MINIT_FUNCTION(pcntl)
                    499: {
                    500:        php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU);
                    501:        php_pcntl_register_errno_constants(INIT_FUNC_ARGS_PASSTHRU);
                    502:        php_add_tick_function(pcntl_signal_dispatch);
                    503: 
                    504:        return SUCCESS;
                    505: }
                    506: 
                    507: PHP_MSHUTDOWN_FUNCTION(pcntl)
                    508: {
                    509:        return SUCCESS;
                    510: }
                    511: 
                    512: 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:        zend_hash_destroy(&PCNTL_G(php_signal_table));
                    519:        while (PCNTL_G(head)) {
                    520:                sig = PCNTL_G(head);
                    521:                PCNTL_G(head) = sig->next;
                    522:                efree(sig);
                    523:        }
                    524:        while (PCNTL_G(spares)) {
                    525:                sig = PCNTL_G(spares);
                    526:                PCNTL_G(spares) = sig->next;
                    527:                efree(sig);
                    528:        }
                    529:        return SUCCESS;
                    530: }
                    531: 
                    532: PHP_MINFO_FUNCTION(pcntl)
                    533: {
                    534:        php_info_print_table_start();
                    535:        php_info_print_table_header(2, "pcntl support", "enabled");
                    536:        php_info_print_table_end();
                    537: }
                    538: 
                    539: /* {{{ proto int pcntl_fork(void)
                    540:    Forks the currently running process following the same behavior as the UNIX fork() system call*/
                    541: PHP_FUNCTION(pcntl_fork)
                    542: {
                    543:        pid_t id;
                    544: 
                    545:        id = fork();
                    546:        if (id == -1) {
                    547:                PCNTL_G(last_error) = errno;
                    548:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d", errno);
                    549:        }
                    550:        
                    551:        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: PHP_FUNCTION(pcntl_alarm)
                    558: {
                    559:        long seconds;
                    560: 
                    561:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &seconds) == FAILURE)
                    562:                return;
                    563:        
                    564:        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: PHP_FUNCTION(pcntl_waitpid)
                    571: {
                    572:        long pid, options = 0;
                    573:        zval *z_status = NULL;
                    574:        int status;
                    575:        pid_t child_id;
                    576: 
                    577:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|l", &pid, &z_status, &options) == FAILURE)
                    578:                return;
                    579:        
                    580:        convert_to_long_ex(&z_status);
                    581: 
                    582:        status = Z_LVAL_P(z_status);
                    583: 
                    584:        child_id = waitpid((pid_t) pid, &status, options);
                    585: 
                    586:        if (child_id < 0) {
                    587:                PCNTL_G(last_error) = errno;
                    588:        }
                    589: 
                    590:        Z_LVAL_P(z_status) = status;
                    591: 
                    592:        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: PHP_FUNCTION(pcntl_wait)
                    599: {
                    600:        long options = 0;
                    601:        zval *z_status = NULL;
                    602:        int status;
                    603:        pid_t child_id;
                    604: 
                    605:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &z_status, &options) == FAILURE)
                    606:                return;
                    607:        
                    608:        convert_to_long_ex(&z_status);
                    609: 
                    610:        status = Z_LVAL_P(z_status);
                    611: #ifdef HAVE_WAIT3
                    612:        if(options) {
                    613:                child_id = wait3(&status, options, NULL);
                    614:        }
                    615:        else {
                    616:                child_id = wait(&status);
                    617:        }
                    618: #else
                    619:        child_id = wait(&status);
                    620: #endif
                    621:        if (child_id < 0) {
                    622:                PCNTL_G(last_error) = errno;
                    623:        }
                    624: 
                    625:        Z_LVAL_P(z_status) = status;
                    626: 
                    627:        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: PHP_FUNCTION(pcntl_wifexited)
                    634: {
                    635: #ifdef WIFEXITED
                    636:        long status_word;
                    637: 
                    638:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
                    639:               return;
                    640:        }
                    641: 
                    642:        if (WIFEXITED(status_word))
                    643:                RETURN_TRUE;
                    644: #endif
                    645:        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: PHP_FUNCTION(pcntl_wifstopped)
                    652: {
                    653: #ifdef WIFSTOPPED
                    654:        long status_word;
                    655: 
                    656:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
                    657:               return;
                    658:        }
                    659: 
                    660:        if (WIFSTOPPED(status_word))
                    661:                RETURN_TRUE;
                    662: #endif
                    663:        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: PHP_FUNCTION(pcntl_wifsignaled)
                    670: {
                    671: #ifdef WIFSIGNALED
                    672:        long status_word;
                    673: 
                    674:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
                    675:               return;
                    676:        }
                    677: 
                    678:        if (WIFSIGNALED(status_word))
                    679:                RETURN_TRUE;
                    680: #endif
                    681:        RETURN_FALSE;
                    682: }
                    683: /* }}} */
                    684: 
                    685: /* {{{ proto int pcntl_wexitstatus(int status) 
                    686:    Returns the status code of a child's exit */
                    687: PHP_FUNCTION(pcntl_wexitstatus)
                    688: {
                    689: #ifdef WEXITSTATUS
                    690:        long status_word;
                    691: 
                    692:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
                    693:               return;
                    694:        }
                    695: 
                    696:        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: PHP_FUNCTION(pcntl_wtermsig)
                    706: {
                    707: #ifdef WTERMSIG
                    708:        long status_word;
                    709: 
                    710:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
                    711:               return;
                    712:        }
                    713: 
                    714:        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: PHP_FUNCTION(pcntl_wstopsig)
                    724: {
                    725: #ifdef WSTOPSIG
                    726:        long status_word;
                    727: 
                    728:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status_word) == FAILURE) {
                    729:               return;
                    730:        }
                    731: 
                    732:        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: PHP_FUNCTION(pcntl_exec)
                    742: {
                    743:        zval *args = NULL, *envs = NULL;
                    744:        zval **element;
                    745:        HashTable *args_hash, *envs_hash;
                    746:        int argc = 0, argi = 0;
                    747:        int envc = 0, envi = 0;
                    748:        int return_val = 0;
                    749:        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:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|aa", &path, &path_len, &args, &envs) == FAILURE) {
                    759:                return;
                    760:        }
                    761:        
                    762:        if (ZEND_NUM_ARGS() > 1) {
                    763:                /* Build argumnent list */
                    764:                args_hash = HASH_OF(args);
                    765:                argc = zend_hash_num_elements(args_hash);
                    766:                
                    767:                argv = safe_emalloc((argc + 2), sizeof(char *), 0);
                    768:                *argv = path;
                    769:                for ( zend_hash_internal_pointer_reset(args_hash), current_arg = argv+1; 
                    770:                        (argi < argc && (zend_hash_get_current_data(args_hash, (void **) &element) == SUCCESS));
                    771:                        (argi++, current_arg++, zend_hash_move_forward(args_hash)) ) {
                    772: 
                    773:                        convert_to_string_ex(element);
                    774:                        *current_arg = Z_STRVAL_PP(element);
                    775:                }
                    776:                *(current_arg) = NULL;
                    777:        } else {
                    778:                argv = emalloc(2 * sizeof(char *));
                    779:                *argv = path;
                    780:                *(argv+1) = NULL;
                    781:        }
                    782: 
                    783:        if ( ZEND_NUM_ARGS() == 3 ) {
                    784:                /* Build environment pair list */
                    785:                envs_hash = HASH_OF(envs);
                    786:                envc = zend_hash_num_elements(envs_hash);
                    787:                
                    788:                envp = safe_emalloc((envc + 1), sizeof(char *), 0);
                    789:                for ( zend_hash_internal_pointer_reset(envs_hash), pair = envp; 
                    790:                        (envi < envc && (zend_hash_get_current_data(envs_hash, (void **) &element) == SUCCESS));
                    791:                        (envi++, pair++, zend_hash_move_forward(envs_hash)) ) {
                    792:                        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:                                        key = emalloc(101);
                    795:                                        snprintf(key, 100, "%ld", key_num);
                    796:                                        key_length = strlen(key);
                    797:                                        break;
                    798:                                case HASH_KEY_NON_EXISTANT:
                    799:                                        pair--;
                    800:                                        continue;
                    801:                        }
                    802: 
                    803:                        convert_to_string_ex(element);
                    804: 
                    805:                        /* Length of element + equal sign + length of key + null */ 
                    806:                        pair_length = Z_STRLEN_PP(element) + key_length + 2;
                    807:                        *pair = emalloc(pair_length);
                    808:                        strlcpy(*pair, key, key_length); 
                    809:                        strlcat(*pair, "=", pair_length);
                    810:                        strlcat(*pair, Z_STRVAL_PP(element), pair_length);
                    811:                        
                    812:                        /* Cleanup */
                    813:                        if (return_val == HASH_KEY_IS_LONG) efree(key);
                    814:                }
                    815:                *(pair) = NULL;
                    816: 
                    817:                if (execve(path, argv, envp) == -1) {
                    818:                        PCNTL_G(last_error) = errno;
                    819:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occured: (errno %d) %s", errno, strerror(errno));
                    820:                }
                    821:        
                    822:                /* Cleanup */
                    823:                for (pair = envp; *pair != NULL; pair++) efree(*pair);
                    824:                efree(envp);
                    825:        } else {
                    826: 
                    827:                if (execv(path, argv) == -1) {
                    828:                        PCNTL_G(last_error) = errno;
                    829:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occured: (errno %d) %s", errno, strerror(errno));
                    830:                }
                    831:        }
                    832: 
                    833:        efree(argv);
                    834:        
                    835:        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: PHP_FUNCTION(pcntl_signal)
                    842: {
                    843:        zval *handle, **dest_handle = NULL;
                    844:        char *func_name;
                    845:        long signo;
                    846:        zend_bool restart_syscalls = 1;
                    847: 
                    848:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|b", &signo, &handle, &restart_syscalls) == FAILURE) {
                    849:                return;
                    850:        }
                    851: 
                    852:        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:                for (i = 0; i < 32; i++) {
                    857:                        struct php_pcntl_pending_signal *psig;
                    858: 
                    859:                        psig = emalloc(sizeof(*psig));
                    860:                        psig->next = PCNTL_G(spares);
                    861:                        PCNTL_G(spares) = psig;
                    862:                }
                    863:        }
                    864: 
                    865:        /* Special long value case for SIG_DFL and SIG_IGN */
                    866:        if (Z_TYPE_P(handle)==IS_LONG) {
                    867:                if (Z_LVAL_P(handle)!= (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) {
                    868:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for handle argument specified");
                    869:                }
                    870:                if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == SIG_ERR) {
                    871:                        PCNTL_G(last_error) = errno;
                    872:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
                    873:                        RETURN_FALSE;
                    874:                }
                    875:                RETURN_TRUE;
                    876:        }
                    877:        
                    878:        if (!zend_is_callable(handle, 0, &func_name TSRMLS_CC)) {
                    879:                PCNTL_G(last_error) = EINVAL;
                    880:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a callable function name error", func_name);
                    881:                efree(func_name);
                    882:                RETURN_FALSE;
                    883:        }
                    884:        efree(func_name);
                    885:        
                    886:        /* Add the function name to our signal table */
                    887:        zend_hash_index_update(&PCNTL_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle);
                    888:        if (dest_handle) zval_add_ref(dest_handle);
                    889:        
                    890:        if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == SIG_ERR) {
                    891:                PCNTL_G(last_error) = errno;
                    892:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
                    893:                RETURN_FALSE;
                    894:        }
                    895:        RETURN_TRUE;
                    896: }
                    897: /* }}} */
                    898: 
                    899: /* {{{ proto bool pcntl_signal_dispatch()
                    900:    Dispatch signals to signal handlers */
                    901: PHP_FUNCTION(pcntl_signal_dispatch)
                    902: {
                    903:        pcntl_signal_dispatch();
                    904:        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: PHP_FUNCTION(pcntl_sigprocmask)
                    912: {
                    913:        long          how, signo;
                    914:        zval         *user_set, *user_oldset = NULL, **user_signo;
                    915:        sigset_t      set, oldset;
                    916:        HashPosition  pos;
                    917: 
                    918:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "la|z", &how, &user_set, &user_oldset) == FAILURE) {
                    919:                return;
                    920:        }
                    921: 
                    922:        if (sigemptyset(&set) != 0 || sigemptyset(&oldset) != 0) {
                    923:                PCNTL_G(last_error) = errno;
                    924:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
                    925:                RETURN_FALSE;
                    926:        }
                    927: 
                    928:        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(user_set), &pos);
                    929:        while (zend_hash_get_current_data_ex(Z_ARRVAL_P(user_set), (void **)&user_signo, &pos) == SUCCESS)
                    930:        {
                    931:                if (Z_TYPE_PP(user_signo) != IS_LONG) {
                    932:                        SEPARATE_ZVAL(user_signo);
                    933:                        convert_to_long_ex(user_signo);
                    934:                }
                    935:                signo = Z_LVAL_PP(user_signo);
                    936:                if (sigaddset(&set, signo) != 0) {
                    937:                        PCNTL_G(last_error) = errno;
                    938:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
                    939:                        RETURN_FALSE;
                    940:                }
                    941:                zend_hash_move_forward_ex(Z_ARRVAL_P(user_set), &pos);
                    942:        }
                    943: 
                    944:        if (sigprocmask(how, &set, &oldset) != 0) {
                    945:                PCNTL_G(last_error) = errno;
                    946:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
                    947:                RETURN_FALSE;
                    948:        }
                    949: 
                    950:        if (user_oldset != NULL) {
                    951:                if (Z_TYPE_P(user_oldset) != IS_ARRAY) {
                    952:                        zval_dtor(user_oldset);
                    953:                        array_init(user_oldset);
                    954:                } else {
                    955:                        zend_hash_clean(Z_ARRVAL_P(user_oldset));
                    956:                }
                    957:                for (signo = 1; signo < MAX(NSIG-1, SIGRTMAX); ++signo) {
                    958:                        if (sigismember(&oldset, signo) != 1) {
                    959:                                continue;
                    960:                        }
                    961:                        add_next_index_long(user_oldset, signo);
                    962:                }
                    963:        }
                    964: 
                    965:        RETURN_TRUE;
                    966: }
                    967: /* }}} */
                    968: #endif
                    969: 
                    970: #if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
                    971: static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */
                    972: {
                    973:        zval            *user_set, **user_signo, *user_siginfo = NULL;
                    974:        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:        if (timedwait) {
                    982:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
                    983:                        return;
                    984:                }
                    985:        } else {
                    986:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &user_set, &user_siginfo) == FAILURE) {
                    987:                        return;
                    988:                }
                    989:        }
                    990: 
                    991:        if (sigemptyset(&set) != 0) {
                    992:                PCNTL_G(last_error) = errno;
                    993:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
                    994:                RETURN_FALSE;
                    995:        }
                    996: 
                    997:        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(user_set), &pos);
                    998:        while (zend_hash_get_current_data_ex(Z_ARRVAL_P(user_set), (void **)&user_signo, &pos) == SUCCESS)
                    999:        {
                   1000:                if (Z_TYPE_PP(user_signo) != IS_LONG) {
                   1001:                        SEPARATE_ZVAL(user_signo);
                   1002:                        convert_to_long_ex(user_signo);
                   1003:                }
                   1004:                signo = Z_LVAL_PP(user_signo);
                   1005:                if (sigaddset(&set, signo) != 0) {
                   1006:                        PCNTL_G(last_error) = errno;
                   1007:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
                   1008:                        RETURN_FALSE;
                   1009:                }
                   1010:                zend_hash_move_forward_ex(Z_ARRVAL_P(user_set), &pos);
                   1011:        }
                   1012: 
                   1013:        if (timedwait) {
                   1014:                timeout.tv_sec  = (time_t) tv_sec;
                   1015:                timeout.tv_nsec = tv_nsec;
                   1016:                signo = sigtimedwait(&set, &siginfo, &timeout);
                   1017:        } else {
                   1018:                signo = sigwaitinfo(&set, &siginfo);
                   1019:        }
                   1020:        if (signo == -1 && errno != EAGAIN) {
                   1021:                PCNTL_G(last_error) = errno;
                   1022:                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:        if (!signo && siginfo.si_signo) {
                   1030:                signo = siginfo.si_signo;
                   1031:        }
                   1032: 
                   1033:        if (signo > 0 && user_siginfo) {
                   1034:                if (Z_TYPE_P(user_siginfo) != IS_ARRAY) {
                   1035:                        zval_dtor(user_siginfo);
                   1036:                        array_init(user_siginfo);
                   1037:                } else {
                   1038:                        zend_hash_clean(Z_ARRVAL_P(user_siginfo));
                   1039:                }
                   1040:                add_assoc_long_ex(user_siginfo, "signo", sizeof("signo"), siginfo.si_signo);
                   1041:                add_assoc_long_ex(user_siginfo, "errno", sizeof("errno"), siginfo.si_errno);
                   1042:                add_assoc_long_ex(user_siginfo, "code",  sizeof("code"),  siginfo.si_code);
                   1043:                switch(signo) {
                   1044: #ifdef SIGCHLD
                   1045:                        case SIGCHLD:
                   1046:                                add_assoc_long_ex(user_siginfo,   "status", sizeof("status"), siginfo.si_status);
                   1047: # ifdef si_utime
                   1048:                                add_assoc_double_ex(user_siginfo, "utime",  sizeof("utime"),  siginfo.si_utime);
                   1049: # endif
                   1050: # ifdef si_stime
                   1051:                                add_assoc_double_ex(user_siginfo, "stime",  sizeof("stime"),  siginfo.si_stime);
                   1052: # endif
                   1053:                                add_assoc_long_ex(user_siginfo,   "pid",    sizeof("pid"),    siginfo.si_pid);
                   1054:                                add_assoc_long_ex(user_siginfo,   "uid",    sizeof("uid"),    siginfo.si_uid);
                   1055:                                break;
                   1056: #endif
                   1057:                        case SIGILL:
                   1058:                        case SIGFPE:
                   1059:                        case SIGSEGV:
                   1060:                        case SIGBUS:
                   1061:                                add_assoc_double_ex(user_siginfo, "addr", sizeof("addr"), (long)siginfo.si_addr);
                   1062:                                break;
                   1063: #ifdef SIGPOLL
                   1064:                        case SIGPOLL:
                   1065:                                add_assoc_long_ex(user_siginfo, "band", sizeof("band"), siginfo.si_band);
                   1066: # ifdef si_fd
                   1067:                                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:        RETURN_LONG(signo);
                   1076: }
                   1077: /* }}} */
                   1078: 
                   1079: /* {{{ proto int pcnlt_sigwaitinfo(array set[, array &siginfo])
                   1080:    Synchronously wait for queued signals */
                   1081: PHP_FUNCTION(pcntl_sigwaitinfo)
                   1082: {
                   1083:        pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                   1084: }
                   1085: /* }}} */
                   1086: 
                   1087: /* {{{ proto int pcntl_sigtimedwait(array set[, array &siginfo[, int seconds[, int nanoseconds]]])
                   1088:    Wait for queued signals */
                   1089: PHP_FUNCTION(pcntl_sigtimedwait)
                   1090: {
                   1091:        pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
                   1092: }
                   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: PHP_FUNCTION(pcntl_getpriority)
                   1100: {
                   1101:        long who = PRIO_PROCESS;
                   1102:        long pid = getpid();
                   1103:        int pri;
                   1104:        
                   1105:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &pid, &who) == FAILURE) {
                   1106:                RETURN_FALSE;
                   1107:        }
                   1108: 
                   1109:        /* needs to be cleared, since any returned value is valid */ 
                   1110:        errno = 0;
                   1111: 
                   1112:        pri = getpriority(who, pid);
                   1113: 
                   1114:        if (errno) {
                   1115:                PCNTL_G(last_error) = errno;
                   1116:                switch (errno) {
                   1117:                        case ESRCH:
                   1118:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
                   1119:                                break;
                   1120:                        case EINVAL:
                   1121:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
                   1122:                                break;
                   1123:                        default:
                   1124:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occured", errno);
                   1125:                                break;
                   1126:                }
                   1127:                RETURN_FALSE;
                   1128:        }
                   1129: 
                   1130:        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: PHP_FUNCTION(pcntl_setpriority)
                   1139: {
                   1140:        long who = PRIO_PROCESS;
                   1141:        long pid = getpid();
                   1142:        long pri;
                   1143: 
                   1144:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &pri, &pid, &who) == FAILURE) {
                   1145:                RETURN_FALSE;
                   1146:        }
                   1147: 
                   1148:        if (setpriority(who, pid, pri)) {
                   1149:                PCNTL_G(last_error) = errno;
                   1150:                switch (errno) {
                   1151:                        case ESRCH:
                   1152:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
                   1153:                                break;
                   1154:                        case EINVAL:
                   1155:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
                   1156:                                break;
                   1157:                        case EPERM:
                   1158:                                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:                                break;
                   1160:                        case EACCES:
                   1161:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Only a super user may attempt to increase the process priority", errno);
                   1162:                                break;
                   1163:                        default:
                   1164:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occured", errno);
                   1165:                                break;
                   1166:                }
                   1167:                RETURN_FALSE;
                   1168:        }
                   1169:        
                   1170:        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: PHP_FUNCTION(pcntl_get_last_error)
                   1178: {
                   1179:         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: PHP_FUNCTION(pcntl_strerror)
                   1186: {
                   1187:         long error;
                   1188: 
                   1189:         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &error) == FAILURE) {
                   1190:                 RETURN_FALSE;
                   1191:         }
                   1192: 
                   1193:         RETURN_STRING(strerror(error), 1);
                   1194: }
                   1195: /* }}} */
                   1196: 
                   1197: /* Our custom signal handler that calls the appropriate php_function */
                   1198: static void pcntl_signal_handler(int signo)
                   1199: {
                   1200:        struct php_pcntl_pending_signal *psig;
                   1201:        TSRMLS_FETCH();
                   1202:        
                   1203:        psig = PCNTL_G(spares);
                   1204:        if (!psig) {
                   1205:                /* oops, too many signals for us to track, so we'll forget about this one */
                   1206:                return;
                   1207:        }
                   1208:        PCNTL_G(spares) = psig->next;
                   1209: 
                   1210:        psig->signo = signo;
                   1211:        psig->next = NULL;
                   1212: 
                   1213:        /* the head check is important, as the tick handler cannot atomically clear both
                   1214:         * the head and tail */
                   1215:        if (PCNTL_G(head) && PCNTL_G(tail)) {
                   1216:                PCNTL_G(tail)->next = psig;
                   1217:        } else {
                   1218:                PCNTL_G(head) = psig;
                   1219:        }
                   1220:        PCNTL_G(tail) = psig;
                   1221: }
                   1222: 
                   1223: 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:        sigfillset(&mask);
                   1233:        sigprocmask(SIG_BLOCK, &mask, &old_mask);
                   1234: 
                   1235:        /* Bail if the queue is empty or if we are already playing the queue*/
                   1236:        if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue)) {
                   1237:                sigprocmask(SIG_SETMASK, &old_mask, NULL);
                   1238:                return;
                   1239:        }
                   1240: 
                   1241:        /* Prevent reentrant handler calls */
                   1242:        PCNTL_G(processing_signal_queue) = 1;
                   1243: 
                   1244:        queue = PCNTL_G(head);
                   1245:        PCNTL_G(head) = NULL; /* simple stores are atomic */
                   1246:        
                   1247:        /* Allocate */
                   1248: 
                   1249:        while (queue) {
                   1250:                if (zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo, (void **) &handle)==SUCCESS) {
                   1251:                        MAKE_STD_ZVAL(retval);
                   1252:                        MAKE_STD_ZVAL(param);
                   1253:                        ZVAL_NULL(retval);
                   1254:                        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:                        call_user_function(EG(function_table), NULL, *handle, retval, 1, &param TSRMLS_CC);
                   1259:                        zval_ptr_dtor(&param);
                   1260:                        zval_ptr_dtor(&retval);
                   1261:                }
                   1262: 
                   1263:                next = queue->next;
                   1264:                queue->next = PCNTL_G(spares);
                   1265:                PCNTL_G(spares) = queue;
                   1266:                queue = next;
                   1267:        }
                   1268: 
                   1269:        /* Re-enable queue */
                   1270:        PCNTL_G(processing_signal_queue) = 0;
                   1271:        
                   1272:        /* return signal mask to previous state */
                   1273:        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:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>