Annotation of embedaddon/php/ext/pcntl/pcntl.c, revision 1.1.1.3
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 ! misho 5: | Copyright (c) 1997-2013 The PHP Group |
1.1 misho 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:
1.1.1.2 misho 19: /* $Id$ */
1.1 misho 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) {
1.1.1.2 misho 763: /* Build argument list */
1.1 misho 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;
1.1.1.3 ! misho 819: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
1.1 misho 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;
1.1.1.3 ! misho 829: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
1.1 misho 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:
1.1.1.2 misho 852: if (signo < 1 || signo > 32) {
853: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid signal");
854: RETURN_FALSE;
855: }
856:
1.1 misho 857: if (!PCNTL_G(spares)) {
858: /* since calling malloc() from within a signal handler is not portable,
859: * pre-allocate a few records for recording signals */
860: int i;
861: for (i = 0; i < 32; i++) {
862: struct php_pcntl_pending_signal *psig;
863:
864: psig = emalloc(sizeof(*psig));
865: psig->next = PCNTL_G(spares);
866: PCNTL_G(spares) = psig;
867: }
868: }
869:
870: /* Special long value case for SIG_DFL and SIG_IGN */
871: if (Z_TYPE_P(handle)==IS_LONG) {
1.1.1.2 misho 872: if (Z_LVAL_P(handle) != (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) {
1.1 misho 873: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for handle argument specified");
1.1.1.2 misho 874: RETURN_FALSE;
1.1 misho 875: }
876: if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == SIG_ERR) {
877: PCNTL_G(last_error) = errno;
878: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
879: RETURN_FALSE;
880: }
881: RETURN_TRUE;
882: }
883:
884: if (!zend_is_callable(handle, 0, &func_name TSRMLS_CC)) {
885: PCNTL_G(last_error) = EINVAL;
886: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a callable function name error", func_name);
887: efree(func_name);
888: RETURN_FALSE;
889: }
890: efree(func_name);
891:
892: /* Add the function name to our signal table */
893: zend_hash_index_update(&PCNTL_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle);
894: if (dest_handle) zval_add_ref(dest_handle);
895:
896: if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == SIG_ERR) {
897: PCNTL_G(last_error) = errno;
898: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
899: RETURN_FALSE;
900: }
901: RETURN_TRUE;
902: }
903: /* }}} */
904:
905: /* {{{ proto bool pcntl_signal_dispatch()
906: Dispatch signals to signal handlers */
907: PHP_FUNCTION(pcntl_signal_dispatch)
908: {
909: pcntl_signal_dispatch();
910: RETURN_TRUE;
911: }
912: /* }}} */
913:
914: #ifdef HAVE_SIGPROCMASK
915: /* {{{ proto bool pcntl_sigprocmask(int how, array set[, array &oldset])
916: Examine and change blocked signals */
917: PHP_FUNCTION(pcntl_sigprocmask)
918: {
919: long how, signo;
920: zval *user_set, *user_oldset = NULL, **user_signo;
921: sigset_t set, oldset;
922: HashPosition pos;
923:
924: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "la|z", &how, &user_set, &user_oldset) == FAILURE) {
925: return;
926: }
927:
928: if (sigemptyset(&set) != 0 || sigemptyset(&oldset) != 0) {
929: PCNTL_G(last_error) = errno;
930: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
931: RETURN_FALSE;
932: }
933:
934: zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(user_set), &pos);
935: while (zend_hash_get_current_data_ex(Z_ARRVAL_P(user_set), (void **)&user_signo, &pos) == SUCCESS)
936: {
937: if (Z_TYPE_PP(user_signo) != IS_LONG) {
938: SEPARATE_ZVAL(user_signo);
939: convert_to_long_ex(user_signo);
940: }
941: signo = Z_LVAL_PP(user_signo);
942: if (sigaddset(&set, signo) != 0) {
943: PCNTL_G(last_error) = errno;
944: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
945: RETURN_FALSE;
946: }
947: zend_hash_move_forward_ex(Z_ARRVAL_P(user_set), &pos);
948: }
949:
950: if (sigprocmask(how, &set, &oldset) != 0) {
951: PCNTL_G(last_error) = errno;
952: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
953: RETURN_FALSE;
954: }
955:
956: if (user_oldset != NULL) {
957: if (Z_TYPE_P(user_oldset) != IS_ARRAY) {
958: zval_dtor(user_oldset);
959: array_init(user_oldset);
960: } else {
961: zend_hash_clean(Z_ARRVAL_P(user_oldset));
962: }
963: for (signo = 1; signo < MAX(NSIG-1, SIGRTMAX); ++signo) {
964: if (sigismember(&oldset, signo) != 1) {
965: continue;
966: }
967: add_next_index_long(user_oldset, signo);
968: }
969: }
970:
971: RETURN_TRUE;
972: }
973: /* }}} */
974: #endif
975:
976: #if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
977: static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */
978: {
979: zval *user_set, **user_signo, *user_siginfo = NULL;
980: long tv_sec = 0, tv_nsec = 0;
981: sigset_t set;
982: HashPosition pos;
983: int signo;
984: siginfo_t siginfo;
985: struct timespec timeout;
986:
987: if (timedwait) {
988: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
989: return;
990: }
991: } else {
992: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &user_set, &user_siginfo) == FAILURE) {
993: return;
994: }
995: }
996:
997: if (sigemptyset(&set) != 0) {
998: PCNTL_G(last_error) = errno;
999: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
1000: RETURN_FALSE;
1001: }
1002:
1003: zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(user_set), &pos);
1004: while (zend_hash_get_current_data_ex(Z_ARRVAL_P(user_set), (void **)&user_signo, &pos) == SUCCESS)
1005: {
1006: if (Z_TYPE_PP(user_signo) != IS_LONG) {
1007: SEPARATE_ZVAL(user_signo);
1008: convert_to_long_ex(user_signo);
1009: }
1010: signo = Z_LVAL_PP(user_signo);
1011: if (sigaddset(&set, signo) != 0) {
1012: PCNTL_G(last_error) = errno;
1013: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
1014: RETURN_FALSE;
1015: }
1016: zend_hash_move_forward_ex(Z_ARRVAL_P(user_set), &pos);
1017: }
1018:
1019: if (timedwait) {
1020: timeout.tv_sec = (time_t) tv_sec;
1021: timeout.tv_nsec = tv_nsec;
1022: signo = sigtimedwait(&set, &siginfo, &timeout);
1023: } else {
1024: signo = sigwaitinfo(&set, &siginfo);
1025: }
1026: if (signo == -1 && errno != EAGAIN) {
1027: PCNTL_G(last_error) = errno;
1028: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
1029: }
1030:
1031: /*
1032: * sigtimedwait and sigwaitinfo can return 0 on success on some
1033: * platforms, e.g. NetBSD
1034: */
1035: if (!signo && siginfo.si_signo) {
1036: signo = siginfo.si_signo;
1037: }
1038:
1039: if (signo > 0 && user_siginfo) {
1040: if (Z_TYPE_P(user_siginfo) != IS_ARRAY) {
1041: zval_dtor(user_siginfo);
1042: array_init(user_siginfo);
1043: } else {
1044: zend_hash_clean(Z_ARRVAL_P(user_siginfo));
1045: }
1046: add_assoc_long_ex(user_siginfo, "signo", sizeof("signo"), siginfo.si_signo);
1047: add_assoc_long_ex(user_siginfo, "errno", sizeof("errno"), siginfo.si_errno);
1048: add_assoc_long_ex(user_siginfo, "code", sizeof("code"), siginfo.si_code);
1049: switch(signo) {
1050: #ifdef SIGCHLD
1051: case SIGCHLD:
1052: add_assoc_long_ex(user_siginfo, "status", sizeof("status"), siginfo.si_status);
1053: # ifdef si_utime
1054: add_assoc_double_ex(user_siginfo, "utime", sizeof("utime"), siginfo.si_utime);
1055: # endif
1056: # ifdef si_stime
1057: add_assoc_double_ex(user_siginfo, "stime", sizeof("stime"), siginfo.si_stime);
1058: # endif
1059: add_assoc_long_ex(user_siginfo, "pid", sizeof("pid"), siginfo.si_pid);
1060: add_assoc_long_ex(user_siginfo, "uid", sizeof("uid"), siginfo.si_uid);
1061: break;
1062: #endif
1063: case SIGILL:
1064: case SIGFPE:
1065: case SIGSEGV:
1066: case SIGBUS:
1067: add_assoc_double_ex(user_siginfo, "addr", sizeof("addr"), (long)siginfo.si_addr);
1068: break;
1069: #ifdef SIGPOLL
1070: case SIGPOLL:
1071: add_assoc_long_ex(user_siginfo, "band", sizeof("band"), siginfo.si_band);
1072: # ifdef si_fd
1073: add_assoc_long_ex(user_siginfo, "fd", sizeof("fd"), siginfo.si_fd);
1074: # endif
1075: break;
1076: #endif
1077: EMPTY_SWITCH_DEFAULT_CASE();
1078: }
1079: }
1080:
1081: RETURN_LONG(signo);
1082: }
1083: /* }}} */
1084:
1085: /* {{{ proto int pcnlt_sigwaitinfo(array set[, array &siginfo])
1086: Synchronously wait for queued signals */
1087: PHP_FUNCTION(pcntl_sigwaitinfo)
1088: {
1089: pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1090: }
1091: /* }}} */
1092:
1093: /* {{{ proto int pcntl_sigtimedwait(array set[, array &siginfo[, int seconds[, int nanoseconds]]])
1094: Wait for queued signals */
1095: PHP_FUNCTION(pcntl_sigtimedwait)
1096: {
1097: pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1098: }
1099: /* }}} */
1100: #endif
1101:
1102: #ifdef HAVE_GETPRIORITY
1103: /* {{{ proto int pcntl_getpriority([int pid [, int process_identifier]])
1104: Get the priority of any process */
1105: PHP_FUNCTION(pcntl_getpriority)
1106: {
1107: long who = PRIO_PROCESS;
1108: long pid = getpid();
1109: int pri;
1110:
1111: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &pid, &who) == FAILURE) {
1112: RETURN_FALSE;
1113: }
1114:
1115: /* needs to be cleared, since any returned value is valid */
1116: errno = 0;
1117:
1118: pri = getpriority(who, pid);
1119:
1120: if (errno) {
1121: PCNTL_G(last_error) = errno;
1122: switch (errno) {
1123: case ESRCH:
1124: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
1125: break;
1126: case EINVAL:
1127: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
1128: break;
1129: default:
1.1.1.3 ! misho 1130: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occurred", errno);
1.1 misho 1131: break;
1132: }
1133: RETURN_FALSE;
1134: }
1135:
1136: RETURN_LONG(pri);
1137: }
1138: /* }}} */
1139: #endif
1140:
1141: #ifdef HAVE_SETPRIORITY
1142: /* {{{ proto bool pcntl_setpriority(int priority [, int pid [, int process_identifier]])
1143: Change the priority of any process */
1144: PHP_FUNCTION(pcntl_setpriority)
1145: {
1146: long who = PRIO_PROCESS;
1147: long pid = getpid();
1148: long pri;
1149:
1150: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &pri, &pid, &who) == FAILURE) {
1151: RETURN_FALSE;
1152: }
1153:
1154: if (setpriority(who, pid, pri)) {
1155: PCNTL_G(last_error) = errno;
1156: switch (errno) {
1157: case ESRCH:
1158: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: No process was located using the given parameters", errno);
1159: break;
1160: case EINVAL:
1161: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Invalid identifier flag", errno);
1162: break;
1163: case EPERM:
1164: 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);
1165: break;
1166: case EACCES:
1167: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d: Only a super user may attempt to increase the process priority", errno);
1168: break;
1169: default:
1.1.1.3 ! misho 1170: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error %d has occurred", errno);
1.1 misho 1171: break;
1172: }
1173: RETURN_FALSE;
1174: }
1175:
1176: RETURN_TRUE;
1177: }
1178: /* }}} */
1179: #endif
1180:
1181: /* {{{ proto int pcntl_get_last_error(void)
1182: Retrieve the error number set by the last pcntl function which failed. */
1183: PHP_FUNCTION(pcntl_get_last_error)
1184: {
1185: RETURN_LONG(PCNTL_G(last_error));
1186: }
1187: /* }}} */
1188:
1189: /* {{{ proto string pcntl_strerror(int errno)
1190: Retrieve the system error message associated with the given errno. */
1191: PHP_FUNCTION(pcntl_strerror)
1192: {
1193: long error;
1194:
1195: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &error) == FAILURE) {
1196: RETURN_FALSE;
1197: }
1198:
1199: RETURN_STRING(strerror(error), 1);
1200: }
1201: /* }}} */
1202:
1203: /* Our custom signal handler that calls the appropriate php_function */
1204: static void pcntl_signal_handler(int signo)
1205: {
1206: struct php_pcntl_pending_signal *psig;
1207: TSRMLS_FETCH();
1208:
1209: psig = PCNTL_G(spares);
1210: if (!psig) {
1211: /* oops, too many signals for us to track, so we'll forget about this one */
1212: return;
1213: }
1214: PCNTL_G(spares) = psig->next;
1215:
1216: psig->signo = signo;
1217: psig->next = NULL;
1218:
1219: /* the head check is important, as the tick handler cannot atomically clear both
1220: * the head and tail */
1221: if (PCNTL_G(head) && PCNTL_G(tail)) {
1222: PCNTL_G(tail)->next = psig;
1223: } else {
1224: PCNTL_G(head) = psig;
1225: }
1226: PCNTL_G(tail) = psig;
1227: }
1228:
1229: void pcntl_signal_dispatch()
1230: {
1231: zval *param, **handle, *retval;
1232: struct php_pcntl_pending_signal *queue, *next;
1233: sigset_t mask;
1234: sigset_t old_mask;
1235: TSRMLS_FETCH();
1236:
1237: /* Mask all signals */
1238: sigfillset(&mask);
1239: sigprocmask(SIG_BLOCK, &mask, &old_mask);
1240:
1241: /* Bail if the queue is empty or if we are already playing the queue*/
1242: if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue)) {
1243: sigprocmask(SIG_SETMASK, &old_mask, NULL);
1244: return;
1245: }
1246:
1247: /* Prevent reentrant handler calls */
1248: PCNTL_G(processing_signal_queue) = 1;
1249:
1250: queue = PCNTL_G(head);
1251: PCNTL_G(head) = NULL; /* simple stores are atomic */
1252:
1253: /* Allocate */
1254:
1255: while (queue) {
1256: if (zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo, (void **) &handle)==SUCCESS) {
1257: MAKE_STD_ZVAL(retval);
1258: MAKE_STD_ZVAL(param);
1259: ZVAL_NULL(retval);
1260: ZVAL_LONG(param, queue->signo);
1261:
1262: /* Call php signal handler - Note that we do not report errors, and we ignore the return value */
1263: /* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
1264: call_user_function(EG(function_table), NULL, *handle, retval, 1, ¶m TSRMLS_CC);
1265: zval_ptr_dtor(¶m);
1266: zval_ptr_dtor(&retval);
1267: }
1268:
1269: next = queue->next;
1270: queue->next = PCNTL_G(spares);
1271: PCNTL_G(spares) = queue;
1272: queue = next;
1273: }
1274:
1275: /* Re-enable queue */
1276: PCNTL_G(processing_signal_queue) = 0;
1277:
1278: /* return signal mask to previous state */
1279: sigprocmask(SIG_SETMASK, &old_mask, NULL);
1280: }
1281:
1282:
1283:
1284: /*
1285: * Local variables:
1286: * tab-width: 4
1287: * c-basic-offset: 4
1288: * indent-tabs-mode: t
1289: * End:
1290: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>