Annotation of embedaddon/php/ext/pcntl/pcntl.c, revision 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>