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, ¶m TSRMLS_CC);
! 1259: zval_ptr_dtor(¶m);
! 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>