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