1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 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 #define PCNTL_DEBUG 0
20 
21 #if PCNTL_DEBUG
22 #define DEBUG_OUT printf("DEBUG: ");printf
23 #define IF_DEBUG(z) z
24 #else
25 #define IF_DEBUG(z)
26 #endif
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #include "php.h"
33 #include "php_ini.h"
34 #include "ext/standard/info.h"
35 #include "php_pcntl.h"
36 #include "php_signal.h"
37 #include "php_ticks.h"
38 
39 #if HAVE_GETPRIORITY || HAVE_SETPRIORITY || HAVE_WAIT3
40 #include <sys/wait.h>
41 #include <sys/time.h>
42 #include <sys/resource.h>
43 #endif
44 
45 #include <errno.h>
46 #ifdef HAVE_UNSHARE
47 #include <sched.h>
48 #endif
49 
50 #ifndef NSIG
51 # ifdef SIGRTMAX
52 #  define NSIG (SIGRTMAX + 1)
53 # else
54 #  define NSIG 32
55 # endif
56 #endif
57 
58 ZEND_DECLARE_MODULE_GLOBALS(pcntl)
59 static PHP_GINIT_FUNCTION(pcntl);
60 
61 /* {{{ arginfo */
62 ZEND_BEGIN_ARG_INFO(arginfo_pcntl_void, 0)
63 ZEND_END_ARG_INFO()
64 
65 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_waitpid, 0, 0, 2)
66 	ZEND_ARG_INFO(0, pid)
67 	ZEND_ARG_INFO(1, status)
68 	ZEND_ARG_INFO(0, options)
69 	ZEND_ARG_INFO(1, rusage)
70 ZEND_END_ARG_INFO()
71 
72 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wait, 0, 0, 1)
73 	ZEND_ARG_INFO(1, status)
74 	ZEND_ARG_INFO(0, options)
75 	ZEND_ARG_INFO(1, rusage)
76 ZEND_END_ARG_INFO()
77 
78 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_signal, 0, 0, 2)
79 	ZEND_ARG_INFO(0, signo)
80 	ZEND_ARG_INFO(0, handler)
81 	ZEND_ARG_INFO(0, restart_syscalls)
82 ZEND_END_ARG_INFO()
83 
84 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_signal_get_handler, 0, 0, 1)
85 	ZEND_ARG_INFO(0, signo)
86 ZEND_END_ARG_INFO()
87 
88 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_sigprocmask, 0, 0, 2)
89 	ZEND_ARG_INFO(0, how)
90 	ZEND_ARG_INFO(0, set)
91 	ZEND_ARG_INFO(1, oldset)
92 ZEND_END_ARG_INFO()
93 
94 #ifdef HAVE_STRUCT_SIGINFO_T
95 # if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
96 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_sigwaitinfo, 0, 0, 1)
97 	ZEND_ARG_INFO(0, set)
98 	ZEND_ARG_INFO(1, info)
99 ZEND_END_ARG_INFO()
100 
101 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_sigtimedwait, 0, 0, 1)
102 	ZEND_ARG_INFO(0, set)
103 	ZEND_ARG_INFO(1, info)
104 	ZEND_ARG_INFO(0, seconds)
105 	ZEND_ARG_INFO(0, nanoseconds)
106 ZEND_END_ARG_INFO()
107 # endif
108 #endif
109 
110 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifexited, 0, 0, 1)
111 	ZEND_ARG_INFO(0, status)
112 ZEND_END_ARG_INFO()
113 
114 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifstopped, 0, 0, 1)
115 	ZEND_ARG_INFO(0, status)
116 ZEND_END_ARG_INFO()
117 
118 #ifdef HAVE_WCONTINUED
119 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifcontinued, 0, 0, 1)
120 	ZEND_ARG_INFO(0, status)
121 ZEND_END_ARG_INFO()
122 #endif
123 
124 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifsignaled, 0, 0, 1)
125 	ZEND_ARG_INFO(0, status)
126 ZEND_END_ARG_INFO()
127 
128 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wifexitstatus, 0, 0, 1)
129 	ZEND_ARG_INFO(0, status)
130 ZEND_END_ARG_INFO()
131 
132 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wtermsig, 0, 0, 1)
133 	ZEND_ARG_INFO(0, status)
134 ZEND_END_ARG_INFO()
135 
136 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wstopsig, 0, 0, 1)
137 	ZEND_ARG_INFO(0, status)
138 ZEND_END_ARG_INFO()
139 
140 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_exec, 0, 0, 1)
141 	ZEND_ARG_INFO(0, path)
142 	ZEND_ARG_INFO(0, args)
143 	ZEND_ARG_INFO(0, envs)
144 ZEND_END_ARG_INFO()
145 
146 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_alarm, 0, 0, 1)
147 	ZEND_ARG_INFO(0, seconds)
148 ZEND_END_ARG_INFO()
149 
150 #ifdef HAVE_GETPRIORITY
151 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_getpriority, 0, 0, 0)
152 	ZEND_ARG_INFO(0, pid)
153 	ZEND_ARG_INFO(0, process_identifier)
154 ZEND_END_ARG_INFO()
155 #endif
156 
157 #ifdef HAVE_SETPRIORITY
158 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_setpriority, 0, 0, 1)
159 	ZEND_ARG_INFO(0, priority)
160 	ZEND_ARG_INFO(0, pid)
161 	ZEND_ARG_INFO(0, process_identifier)
162 ZEND_END_ARG_INFO()
163 #endif
164 
165 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_strerror, 0, 0, 1)
166         ZEND_ARG_INFO(0, errno)
167 ZEND_END_ARG_INFO()
168 
169 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_async_signals, 0, 0, 1)
170         ZEND_ARG_INFO(0, on)
171 ZEND_END_ARG_INFO()
172 
173 #ifdef HAVE_UNSHARE
174 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_unshare, 0, 0, 1)
175 	ZEND_ARG_INFO(0, flags)
176 ZEND_END_ARG_INFO()
177 #endif
178 /* }}} */
179 
180 static const zend_function_entry pcntl_functions[] = {
181 	PHP_FE(pcntl_fork,			arginfo_pcntl_void)
182 	PHP_FE(pcntl_waitpid,		arginfo_pcntl_waitpid)
183 	PHP_FE(pcntl_wait,			arginfo_pcntl_wait)
184 	PHP_FE(pcntl_signal,		arginfo_pcntl_signal)
185 	PHP_FE(pcntl_signal_get_handler,		arginfo_pcntl_signal_get_handler)
186 	PHP_FE(pcntl_signal_dispatch,	arginfo_pcntl_void)
187 	PHP_FE(pcntl_wifexited,		arginfo_pcntl_wifexited)
188 	PHP_FE(pcntl_wifstopped,	arginfo_pcntl_wifstopped)
189 	PHP_FE(pcntl_wifsignaled,	arginfo_pcntl_wifsignaled)
190 	PHP_FE(pcntl_wexitstatus,	arginfo_pcntl_wifexitstatus)
191 	PHP_FE(pcntl_wtermsig,		arginfo_pcntl_wtermsig)
192 	PHP_FE(pcntl_wstopsig,		arginfo_pcntl_wstopsig)
193 	PHP_FE(pcntl_exec,			arginfo_pcntl_exec)
194 	PHP_FE(pcntl_alarm,			arginfo_pcntl_alarm)
195 	PHP_FE(pcntl_get_last_error,	arginfo_pcntl_void)
196 	PHP_FALIAS(pcntl_errno, pcntl_get_last_error,	NULL)
197 	PHP_FE(pcntl_strerror,		arginfo_pcntl_strerror)
198 #ifdef HAVE_GETPRIORITY
199 	PHP_FE(pcntl_getpriority,	arginfo_pcntl_getpriority)
200 #endif
201 #ifdef HAVE_SETPRIORITY
202 	PHP_FE(pcntl_setpriority,	arginfo_pcntl_setpriority)
203 #endif
204 #ifdef HAVE_SIGPROCMASK
205 	PHP_FE(pcntl_sigprocmask,	arginfo_pcntl_sigprocmask)
206 #endif
207 #ifdef HAVE_STRUCT_SIGINFO_T
208 # if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
209 	PHP_FE(pcntl_sigwaitinfo,	arginfo_pcntl_sigwaitinfo)
210 	PHP_FE(pcntl_sigtimedwait,	arginfo_pcntl_sigtimedwait)
211 # endif
212 #endif
213 #ifdef HAVE_WCONTINUED
214 	PHP_FE(pcntl_wifcontinued,	arginfo_pcntl_wifcontinued)
215 #endif
216 	PHP_FE(pcntl_async_signals,	arginfo_pcntl_async_signals)
217 #ifdef HAVE_UNSHARE
218 	PHP_FE(pcntl_unshare,		arginfo_pcntl_unshare)
219 #endif
220 	PHP_FE_END
221 };
222 
223 zend_module_entry pcntl_module_entry = {
224 	STANDARD_MODULE_HEADER,
225 	"pcntl",
226 	pcntl_functions,
227 	PHP_MINIT(pcntl),
228 	PHP_MSHUTDOWN(pcntl),
229 	PHP_RINIT(pcntl),
230 	PHP_RSHUTDOWN(pcntl),
231 	PHP_MINFO(pcntl),
232 	PHP_PCNTL_VERSION,
233 	PHP_MODULE_GLOBALS(pcntl),
234 	PHP_GINIT(pcntl),
235 	NULL,
236 	NULL,
237 	STANDARD_MODULE_PROPERTIES_EX
238 };
239 
240 #ifdef COMPILE_DL_PCNTL
241 #ifdef ZTS
242 ZEND_TSRMLS_CACHE_DEFINE()
243 #endif
244 ZEND_GET_MODULE(pcntl)
245 #endif
246 
247 static void (*orig_interrupt_function)(zend_execute_data *execute_data);
248 
249 #ifdef HAVE_STRUCT_SIGINFO_T
250 static void pcntl_signal_handler(int, siginfo_t*, void*);
251 static void pcntl_siginfo_to_zval(int, siginfo_t*, zval*);
252 #else
253 static void pcntl_signal_handler(int);
254 #endif
255 static void pcntl_signal_dispatch();
256 static void pcntl_interrupt_function(zend_execute_data *execute_data);
257 
php_register_signal_constantsnull258 void php_register_signal_constants(INIT_FUNC_ARGS)
259 {
260 
261 	/* Wait Constants */
262 #ifdef WNOHANG
263 	REGISTER_LONG_CONSTANT("WNOHANG",  (zend_long) WNOHANG, CONST_CS | CONST_PERSISTENT);
264 #endif
265 #ifdef WUNTRACED
266 	REGISTER_LONG_CONSTANT("WUNTRACED",  (zend_long) WUNTRACED, CONST_CS | CONST_PERSISTENT);
267 #endif
268 #ifdef HAVE_WCONTINUED
269 	REGISTER_LONG_CONSTANT("WCONTINUED",  (zend_long) WCONTINUED, CONST_CS | CONST_PERSISTENT);
270 #endif
271 
272 	/* Signal Constants */
273 	REGISTER_LONG_CONSTANT("SIG_IGN",  (zend_long) SIG_IGN, CONST_CS | CONST_PERSISTENT);
274 	REGISTER_LONG_CONSTANT("SIG_DFL",  (zend_long) SIG_DFL, CONST_CS | CONST_PERSISTENT);
275 	REGISTER_LONG_CONSTANT("SIG_ERR",  (zend_long) SIG_ERR, CONST_CS | CONST_PERSISTENT);
276 	REGISTER_LONG_CONSTANT("SIGHUP",   (zend_long) SIGHUP,  CONST_CS | CONST_PERSISTENT);
277 	REGISTER_LONG_CONSTANT("SIGINT",   (zend_long) SIGINT,  CONST_CS | CONST_PERSISTENT);
278 	REGISTER_LONG_CONSTANT("SIGQUIT",  (zend_long) SIGQUIT, CONST_CS | CONST_PERSISTENT);
279 	REGISTER_LONG_CONSTANT("SIGILL",   (zend_long) SIGILL,  CONST_CS | CONST_PERSISTENT);
280 	REGISTER_LONG_CONSTANT("SIGTRAP",  (zend_long) SIGTRAP, CONST_CS | CONST_PERSISTENT);
281 	REGISTER_LONG_CONSTANT("SIGABRT",  (zend_long) SIGABRT, CONST_CS | CONST_PERSISTENT);
282 #ifdef SIGIOT
283 	REGISTER_LONG_CONSTANT("SIGIOT",   (zend_long) SIGIOT,  CONST_CS | CONST_PERSISTENT);
284 #endif
285 	REGISTER_LONG_CONSTANT("SIGBUS",   (zend_long) SIGBUS,  CONST_CS | CONST_PERSISTENT);
286 	REGISTER_LONG_CONSTANT("SIGFPE",   (zend_long) SIGFPE,  CONST_CS | CONST_PERSISTENT);
287 	REGISTER_LONG_CONSTANT("SIGKILL",  (zend_long) SIGKILL, CONST_CS | CONST_PERSISTENT);
288 	REGISTER_LONG_CONSTANT("SIGUSR1",  (zend_long) SIGUSR1, CONST_CS | CONST_PERSISTENT);
289 	REGISTER_LONG_CONSTANT("SIGSEGV",  (zend_long) SIGSEGV, CONST_CS | CONST_PERSISTENT);
290 	REGISTER_LONG_CONSTANT("SIGUSR2",  (zend_long) SIGUSR2, CONST_CS | CONST_PERSISTENT);
291 	REGISTER_LONG_CONSTANT("SIGPIPE",  (zend_long) SIGPIPE, CONST_CS | CONST_PERSISTENT);
292 	REGISTER_LONG_CONSTANT("SIGALRM",  (zend_long) SIGALRM, CONST_CS | CONST_PERSISTENT);
293 	REGISTER_LONG_CONSTANT("SIGTERM",  (zend_long) SIGTERM, CONST_CS | CONST_PERSISTENT);
294 #ifdef SIGSTKFLT
295 	REGISTER_LONG_CONSTANT("SIGSTKFLT",(zend_long) SIGSTKFLT, CONST_CS | CONST_PERSISTENT);
296 #endif
297 #ifdef SIGCLD
298 	REGISTER_LONG_CONSTANT("SIGCLD",   (zend_long) SIGCLD, CONST_CS | CONST_PERSISTENT);
299 #endif
300 #ifdef SIGCHLD
301 	REGISTER_LONG_CONSTANT("SIGCHLD",  (zend_long) SIGCHLD, CONST_CS | CONST_PERSISTENT);
302 #endif
303 	REGISTER_LONG_CONSTANT("SIGCONT",  (zend_long) SIGCONT, CONST_CS | CONST_PERSISTENT);
304 	REGISTER_LONG_CONSTANT("SIGSTOP",  (zend_long) SIGSTOP, CONST_CS | CONST_PERSISTENT);
305 	REGISTER_LONG_CONSTANT("SIGTSTP",  (zend_long) SIGTSTP, CONST_CS | CONST_PERSISTENT);
306 	REGISTER_LONG_CONSTANT("SIGTTIN",  (zend_long) SIGTTIN, CONST_CS | CONST_PERSISTENT);
307 	REGISTER_LONG_CONSTANT("SIGTTOU",  (zend_long) SIGTTOU, CONST_CS | CONST_PERSISTENT);
308 	REGISTER_LONG_CONSTANT("SIGURG",   (zend_long) SIGURG , CONST_CS | CONST_PERSISTENT);
309 	REGISTER_LONG_CONSTANT("SIGXCPU",  (zend_long) SIGXCPU, CONST_CS | CONST_PERSISTENT);
310 	REGISTER_LONG_CONSTANT("SIGXFSZ",  (zend_long) SIGXFSZ, CONST_CS | CONST_PERSISTENT);
311 	REGISTER_LONG_CONSTANT("SIGVTALRM",(zend_long) SIGVTALRM, CONST_CS | CONST_PERSISTENT);
312 	REGISTER_LONG_CONSTANT("SIGPROF",  (zend_long) SIGPROF, CONST_CS | CONST_PERSISTENT);
313 	REGISTER_LONG_CONSTANT("SIGWINCH", (zend_long) SIGWINCH, CONST_CS | CONST_PERSISTENT);
314 #ifdef SIGPOLL
315 	REGISTER_LONG_CONSTANT("SIGPOLL",  (zend_long) SIGPOLL, CONST_CS | CONST_PERSISTENT);
316 #endif
317 	REGISTER_LONG_CONSTANT("SIGIO",    (zend_long) SIGIO, CONST_CS | CONST_PERSISTENT);
318 #ifdef SIGPWR
319 	REGISTER_LONG_CONSTANT("SIGPWR",   (zend_long) SIGPWR, CONST_CS | CONST_PERSISTENT);
320 #endif
321 #ifdef SIGSYS
322 	REGISTER_LONG_CONSTANT("SIGSYS",   (zend_long) SIGSYS, CONST_CS | CONST_PERSISTENT);
323 	REGISTER_LONG_CONSTANT("SIGBABY",  (zend_long) SIGSYS, CONST_CS | CONST_PERSISTENT);
324 #endif
325 #ifdef SIGRTMIN
326 	REGISTER_LONG_CONSTANT("SIGRTMIN", (zend_long) SIGRTMIN, CONST_CS | CONST_PERSISTENT);
327 #endif
328 #ifdef SIGRTMAX
329 	REGISTER_LONG_CONSTANT("SIGRTMAX", (zend_long) SIGRTMAX, CONST_CS | CONST_PERSISTENT);
330 #endif
331 
332 #if HAVE_GETPRIORITY || HAVE_SETPRIORITY
333 	REGISTER_LONG_CONSTANT("PRIO_PGRP", PRIO_PGRP, CONST_CS | CONST_PERSISTENT);
334 	REGISTER_LONG_CONSTANT("PRIO_USER", PRIO_USER, CONST_CS | CONST_PERSISTENT);
335 	REGISTER_LONG_CONSTANT("PRIO_PROCESS", PRIO_PROCESS, CONST_CS | CONST_PERSISTENT);
336 #endif
337 
338 	/* {{{ "how" argument for sigprocmask */
339 #ifdef HAVE_SIGPROCMASK
340 	REGISTER_LONG_CONSTANT("SIG_BLOCK",   SIG_BLOCK, CONST_CS | CONST_PERSISTENT);
341 	REGISTER_LONG_CONSTANT("SIG_UNBLOCK", SIG_UNBLOCK, CONST_CS | CONST_PERSISTENT);
342 	REGISTER_LONG_CONSTANT("SIG_SETMASK", SIG_SETMASK, CONST_CS | CONST_PERSISTENT);
343 #endif
344 	/* }}} */
345 
346 	/* {{{ si_code */
347 #if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
348 	REGISTER_LONG_CONSTANT("SI_USER",    SI_USER,    CONST_CS | CONST_PERSISTENT);
349 #ifdef SI_NOINFO
350 	REGISTER_LONG_CONSTANT("SI_NOINFO",  SI_NOINFO,  CONST_CS | CONST_PERSISTENT);
351 #endif
352 #ifdef SI_KERNEL
353 	REGISTER_LONG_CONSTANT("SI_KERNEL",  SI_KERNEL,  CONST_CS | CONST_PERSISTENT);
354 #endif
355 	REGISTER_LONG_CONSTANT("SI_QUEUE",   SI_QUEUE,   CONST_CS | CONST_PERSISTENT);
356 	REGISTER_LONG_CONSTANT("SI_TIMER",   SI_TIMER,   CONST_CS | CONST_PERSISTENT);
357 	REGISTER_LONG_CONSTANT("SI_MESGQ",   SI_MESGQ,   CONST_CS | CONST_PERSISTENT);
358 	REGISTER_LONG_CONSTANT("SI_ASYNCIO", SI_ASYNCIO, CONST_CS | CONST_PERSISTENT);
359 #ifdef SI_SIGIO
360 	REGISTER_LONG_CONSTANT("SI_SIGIO",   SI_SIGIO,   CONST_CS | CONST_PERSISTENT);
361 #endif
362 #ifdef SI_TKILL
363 	REGISTER_LONG_CONSTANT("SI_TKILL",   SI_TKILL,   CONST_CS | CONST_PERSISTENT);
364 #endif
365 
366 	/* si_code for SIGCHILD */
367 #ifdef CLD_EXITED
368 	REGISTER_LONG_CONSTANT("CLD_EXITED",    CLD_EXITED,    CONST_CS | CONST_PERSISTENT);
369 #endif
370 #ifdef CLD_KILLED
371 	REGISTER_LONG_CONSTANT("CLD_KILLED",    CLD_KILLED,    CONST_CS | CONST_PERSISTENT);
372 #endif
373 #ifdef CLD_DUMPED
374 	REGISTER_LONG_CONSTANT("CLD_DUMPED",    CLD_DUMPED,    CONST_CS | CONST_PERSISTENT);
375 #endif
376 #ifdef CLD_TRAPPED
377 	REGISTER_LONG_CONSTANT("CLD_TRAPPED",   CLD_TRAPPED,   CONST_CS | CONST_PERSISTENT);
378 #endif
379 #ifdef CLD_STOPPED
380 	REGISTER_LONG_CONSTANT("CLD_STOPPED",   CLD_STOPPED,   CONST_CS | CONST_PERSISTENT);
381 #endif
382 #ifdef CLD_CONTINUED
383 	REGISTER_LONG_CONSTANT("CLD_CONTINUED", CLD_CONTINUED, CONST_CS | CONST_PERSISTENT);
384 #endif
385 
386 	/* si_code for SIGTRAP */
387 #ifdef TRAP_BRKPT
388 	REGISTER_LONG_CONSTANT("TRAP_BRKPT", TRAP_BRKPT, CONST_CS | CONST_PERSISTENT);
389 #endif
390 #ifdef TRAP_TRACE
391 	REGISTER_LONG_CONSTANT("TRAP_TRACE", TRAP_TRACE, CONST_CS | CONST_PERSISTENT);
392 #endif
393 
394 	/* si_code for SIGPOLL */
395 #ifdef POLL_IN
396 	REGISTER_LONG_CONSTANT("POLL_IN",  POLL_IN,  CONST_CS | CONST_PERSISTENT);
397 #endif
398 #ifdef POLL_OUT
399 	REGISTER_LONG_CONSTANT("POLL_OUT", POLL_OUT, CONST_CS | CONST_PERSISTENT);
400 #endif
401 #ifdef POLL_MSG
402 	REGISTER_LONG_CONSTANT("POLL_MSG", POLL_MSG, CONST_CS | CONST_PERSISTENT);
403 #endif
404 #ifdef POLL_ERR
405 	REGISTER_LONG_CONSTANT("POLL_ERR", POLL_ERR, CONST_CS | CONST_PERSISTENT);
406 #endif
407 #ifdef POLL_PRI
408 	REGISTER_LONG_CONSTANT("POLL_PRI", POLL_PRI, CONST_CS | CONST_PERSISTENT);
409 #endif
410 #ifdef POLL_HUP
411 	REGISTER_LONG_CONSTANT("POLL_HUP", POLL_HUP, CONST_CS | CONST_PERSISTENT);
412 #endif
413 
414 #ifdef ILL_ILLOPC
415 	REGISTER_LONG_CONSTANT("ILL_ILLOPC", ILL_ILLOPC, CONST_CS | CONST_PERSISTENT);
416 #endif
417 #ifdef ILL_ILLOPN
418 	REGISTER_LONG_CONSTANT("ILL_ILLOPN", ILL_ILLOPN, CONST_CS | CONST_PERSISTENT);
419 #endif
420 #ifdef ILL_ILLADR
421 	REGISTER_LONG_CONSTANT("ILL_ILLADR", ILL_ILLADR, CONST_CS | CONST_PERSISTENT);
422 #endif
423 #ifdef ILL_ILLTRP
424 	REGISTER_LONG_CONSTANT("ILL_ILLTRP", ILL_ILLTRP, CONST_CS | CONST_PERSISTENT);
425 #endif
426 #ifdef ILL_PRVOPC
427 	REGISTER_LONG_CONSTANT("ILL_PRVOPC", ILL_PRVOPC, CONST_CS | CONST_PERSISTENT);
428 #endif
429 #ifdef ILL_PRVREG
430 	REGISTER_LONG_CONSTANT("ILL_PRVREG", ILL_PRVREG, CONST_CS | CONST_PERSISTENT);
431 #endif
432 #ifdef ILL_COPROC
433 	REGISTER_LONG_CONSTANT("ILL_COPROC", ILL_COPROC, CONST_CS | CONST_PERSISTENT);
434 #endif
435 #ifdef ILL_BADSTK
436 	REGISTER_LONG_CONSTANT("ILL_BADSTK", ILL_BADSTK, CONST_CS | CONST_PERSISTENT);
437 #endif
438 
439 #ifdef FPE_INTDIV
440 	REGISTER_LONG_CONSTANT("FPE_INTDIV", FPE_INTDIV, CONST_CS | CONST_PERSISTENT);
441 #endif
442 #ifdef FPE_INTOVF
443 	REGISTER_LONG_CONSTANT("FPE_INTOVF", FPE_INTOVF, CONST_CS | CONST_PERSISTENT);
444 #endif
445 #ifdef FPE_FLTDIV
446 	REGISTER_LONG_CONSTANT("FPE_FLTDIV", FPE_FLTDIV, CONST_CS | CONST_PERSISTENT);
447 #endif
448 #ifdef FPE_FLTOVF
449 	REGISTER_LONG_CONSTANT("FPE_FLTOVF", FPE_FLTOVF, CONST_CS | CONST_PERSISTENT);
450 #endif
451 #ifdef FPE_FLTUND
452 	REGISTER_LONG_CONSTANT("FPE_FLTUND", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
453 #endif
454 #ifdef FPE_FLTRES
455 	REGISTER_LONG_CONSTANT("FPE_FLTRES", FPE_FLTRES, CONST_CS | CONST_PERSISTENT);
456 #endif
457 #ifdef FPE_FLTINV
458 	REGISTER_LONG_CONSTANT("FPE_FLTINV", FPE_FLTINV, CONST_CS | CONST_PERSISTENT);
459 #endif
460 #ifdef FPE_FLTSUB
461 	REGISTER_LONG_CONSTANT("FPE_FLTSUB", FPE_FLTSUB, CONST_CS | CONST_PERSISTENT);
462 #endif
463 
464 #ifdef SEGV_MAPERR
465 	REGISTER_LONG_CONSTANT("SEGV_MAPERR", SEGV_MAPERR, CONST_CS | CONST_PERSISTENT);
466 #endif
467 #ifdef SEGV_ACCERR
468 	REGISTER_LONG_CONSTANT("SEGV_ACCERR", SEGV_ACCERR, CONST_CS | CONST_PERSISTENT);
469 #endif
470 
471 #ifdef BUS_ADRALN
472 	REGISTER_LONG_CONSTANT("BUS_ADRALN", BUS_ADRALN, CONST_CS | CONST_PERSISTENT);
473 #endif
474 #ifdef BUS_ADRERR
475 	REGISTER_LONG_CONSTANT("BUS_ADRERR", BUS_ADRERR, CONST_CS | CONST_PERSISTENT);
476 #endif
477 #ifdef BUS_OBJERR
478 	REGISTER_LONG_CONSTANT("BUS_OBJERR", BUS_OBJERR, CONST_CS | CONST_PERSISTENT);
479 #endif
480 #endif /* HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT */
481 	/* }}} */
482 
483 	/* unshare(/clone) constants */
484 #ifdef HAVE_UNSHARE
485 	REGISTER_LONG_CONSTANT("CLONE_NEWNS",		CLONE_NEWNS, CONST_CS | CONST_PERSISTENT);
486 #ifdef CLONE_NEWIPC
487 	REGISTER_LONG_CONSTANT("CLONE_NEWIPC",		CLONE_NEWIPC, CONST_CS | CONST_PERSISTENT);
488 #endif
489 #ifdef CLONE_NEWUTS
490 	REGISTER_LONG_CONSTANT("CLONE_NEWUTS",		CLONE_NEWUTS, CONST_CS | CONST_PERSISTENT);
491 #endif
492 #ifdef CLONE_NEWNET
493 	REGISTER_LONG_CONSTANT("CLONE_NEWNET",		CLONE_NEWNET, CONST_CS | CONST_PERSISTENT);
494 #endif
495 #ifdef CLONE_NEWPID
496 	REGISTER_LONG_CONSTANT("CLONE_NEWPID",		CLONE_NEWPID, CONST_CS | CONST_PERSISTENT);
497 #endif
498 #ifdef CLONE_NEWUSER
499 	REGISTER_LONG_CONSTANT("CLONE_NEWUSER",		CLONE_NEWUSER, CONST_CS | CONST_PERSISTENT);
500 #endif
501 #ifdef CLONE_NEWCGROUP
502 	REGISTER_LONG_CONSTANT("CLONE_NEWCGROUP",	CLONE_NEWCGROUP, CONST_CS | CONST_PERSISTENT);
503 #endif
504 #endif
505 }
506 
php_pcntl_register_errno_constantsnull507 static void php_pcntl_register_errno_constants(INIT_FUNC_ARGS)
508 {
509 #ifdef EINTR
510 	REGISTER_PCNTL_ERRNO_CONSTANT(EINTR);
511 #endif
512 #ifdef ECHILD
513 	REGISTER_PCNTL_ERRNO_CONSTANT(ECHILD);
514 #endif
515 #ifdef EINVAL
516 	REGISTER_PCNTL_ERRNO_CONSTANT(EINVAL);
517 #endif
518 #ifdef EAGAIN
519 	REGISTER_PCNTL_ERRNO_CONSTANT(EAGAIN);
520 #endif
521 #ifdef ESRCH
522 	REGISTER_PCNTL_ERRNO_CONSTANT(ESRCH);
523 #endif
524 #ifdef EACCES
525 	REGISTER_PCNTL_ERRNO_CONSTANT(EACCES);
526 #endif
527 #ifdef EPERM
528 	REGISTER_PCNTL_ERRNO_CONSTANT(EPERM);
529 #endif
530 #ifdef ENOMEM
531 	REGISTER_PCNTL_ERRNO_CONSTANT(ENOMEM);
532 #endif
533 #ifdef E2BIG
534 	REGISTER_PCNTL_ERRNO_CONSTANT(E2BIG);
535 #endif
536 #ifdef EFAULT
537 	REGISTER_PCNTL_ERRNO_CONSTANT(EFAULT);
538 #endif
539 #ifdef EIO
540 	REGISTER_PCNTL_ERRNO_CONSTANT(EIO);
541 #endif
542 #ifdef EISDIR
543 	REGISTER_PCNTL_ERRNO_CONSTANT(EISDIR);
544 #endif
545 #ifdef ELIBBAD
546 	REGISTER_PCNTL_ERRNO_CONSTANT(ELIBBAD);
547 #endif
548 #ifdef ELOOP
549 	REGISTER_PCNTL_ERRNO_CONSTANT(ELOOP);
550 #endif
551 #ifdef EMFILE
552 	REGISTER_PCNTL_ERRNO_CONSTANT(EMFILE);
553 #endif
554 #ifdef ENAMETOOLONG
555 	REGISTER_PCNTL_ERRNO_CONSTANT(ENAMETOOLONG);
556 #endif
557 #ifdef ENFILE
558 	REGISTER_PCNTL_ERRNO_CONSTANT(ENFILE);
559 #endif
560 #ifdef ENOENT
561 	REGISTER_PCNTL_ERRNO_CONSTANT(ENOENT);
562 #endif
563 #ifdef ENOEXEC
564 	REGISTER_PCNTL_ERRNO_CONSTANT(ENOEXEC);
565 #endif
566 #ifdef ENOTDIR
567 	REGISTER_PCNTL_ERRNO_CONSTANT(ENOTDIR);
568 #endif
569 #ifdef ETXTBSY
570 	REGISTER_PCNTL_ERRNO_CONSTANT(ETXTBSY);
571 #endif
572 #ifdef ENOSPC
573 	REGISTER_PCNTL_ERRNO_CONSTANT(ENOSPC);
574 #endif
575 #ifdef EUSERS
576 	REGISTER_PCNTL_ERRNO_CONSTANT(EUSERS);
577 #endif
578 }
579 
PHP_GINIT_FUNCTIONnull580 static PHP_GINIT_FUNCTION(pcntl)
581 {
582 #if defined(COMPILE_DL_PCNTL) && defined(ZTS)
583 	ZEND_TSRMLS_CACHE_UPDATE();
584 #endif
585 	memset(pcntl_globals, 0, sizeof(*pcntl_globals));
586 }
587 
PHP_RINIT_FUNCTIONnull588 PHP_RINIT_FUNCTION(pcntl)
589 {
590 	php_add_tick_function(pcntl_signal_dispatch, NULL);
591 	zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0);
592 	PCNTL_G(head) = PCNTL_G(tail) = PCNTL_G(spares) = NULL;
593 	PCNTL_G(async_signals) = 0;
594 	return SUCCESS;
595 }
596 
PHP_MINIT_FUNCTIONnull597 PHP_MINIT_FUNCTION(pcntl)
598 {
599 	php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU);
600 	php_pcntl_register_errno_constants(INIT_FUNC_ARGS_PASSTHRU);
601 	orig_interrupt_function = zend_interrupt_function;
602 	zend_interrupt_function = pcntl_interrupt_function;
603 
604 	return SUCCESS;
605 }
606 
PHP_MSHUTDOWN_FUNCTIONnull607 PHP_MSHUTDOWN_FUNCTION(pcntl)
608 {
609 	return SUCCESS;
610 }
611 
PHP_RSHUTDOWN_FUNCTIONnull612 PHP_RSHUTDOWN_FUNCTION(pcntl)
613 {
614 	struct php_pcntl_pending_signal *sig;
615 
616 	/* FIXME: if a signal is delivered after this point, things will go pear shaped;
617 	 * need to remove signal handlers */
618 	zend_hash_destroy(&PCNTL_G(php_signal_table));
619 	while (PCNTL_G(head)) {
620 		sig = PCNTL_G(head);
621 		PCNTL_G(head) = sig->next;
622 		efree(sig);
623 	}
624 	while (PCNTL_G(spares)) {
625 		sig = PCNTL_G(spares);
626 		PCNTL_G(spares) = sig->next;
627 		efree(sig);
628 	}
629 	return SUCCESS;
630 }
631 
PHP_MINFO_FUNCTIONnull632 PHP_MINFO_FUNCTION(pcntl)
633 {
634 	php_info_print_table_start();
635 	php_info_print_table_header(2, "pcntl support", "enabled");
636 	php_info_print_table_end();
637 }
638 
639 /* {{{ proto int pcntl_fork(void)
640    Forks the currently running process following the same behavior as the UNIX fork() system call*/
PHP_FUNCTIONnull641 PHP_FUNCTION(pcntl_fork)
642 {
643 	pid_t id;
644 
645 	id = fork();
646 	if (id == -1) {
647 		PCNTL_G(last_error) = errno;
648 		php_error_docref(NULL, E_WARNING, "Error %d", errno);
649 	}
650 
651 	RETURN_LONG((zend_long) id);
652 }
653 /* }}} */
654 
655 /* {{{ proto int pcntl_alarm(int seconds)
656    Set an alarm clock for delivery of a signal*/
PHP_FUNCTIONnull657 PHP_FUNCTION(pcntl_alarm)
658 {
659 	zend_long seconds;
660 
661 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &seconds) == FAILURE)
662 		return;
663 
664 	RETURN_LONG ((zend_long) alarm(seconds));
665 }
666 /* }}} */
667 
668 #define PHP_RUSAGE_PARA(from, to, field) \
669 	add_assoc_long(to, #field, from.field)
670 #ifndef _OSD_POSIX
671 	#define PHP_RUSAGE_SPECIAL(from, to) \
672 		PHP_RUSAGE_PARA(from, to, ru_oublock); \
673 		PHP_RUSAGE_PARA(from, to, ru_inblock); \
674 		PHP_RUSAGE_PARA(from, to, ru_msgsnd); \
675 		PHP_RUSAGE_PARA(from, to, ru_msgrcv); \
676 		PHP_RUSAGE_PARA(from, to, ru_maxrss); \
677 		PHP_RUSAGE_PARA(from, to, ru_ixrss); \
678 		PHP_RUSAGE_PARA(from, to, ru_idrss); \
679 		PHP_RUSAGE_PARA(from, to, ru_minflt); \
680 		PHP_RUSAGE_PARA(from, to, ru_majflt); \
681 		PHP_RUSAGE_PARA(from, to, ru_nsignals); \
682 		PHP_RUSAGE_PARA(from, to, ru_nvcsw); \
683 		PHP_RUSAGE_PARA(from, to, ru_nivcsw); \
684 		PHP_RUSAGE_PARA(from, to, ru_nswap);
685 #else /*_OSD_POSIX*/
686 	#define PHP_RUSAGE_SPECIAL(from, to)
687 #endif
688 
689 #define PHP_RUSAGE_COMMON(from ,to) \
690 	PHP_RUSAGE_PARA(from, to, ru_utime.tv_usec); \
691 	PHP_RUSAGE_PARA(from, to, ru_utime.tv_sec); \
692 	PHP_RUSAGE_PARA(from, to, ru_stime.tv_usec); \
693 	PHP_RUSAGE_PARA(from, to, ru_stime.tv_sec);
694 
695 #define PHP_RUSAGE_TO_ARRAY(from, to) \
696 	if (to) { \
697 		PHP_RUSAGE_SPECIAL(from, to) \
698 		PHP_RUSAGE_COMMON(from, to); \
699 	}
700 
701 /* {{{ proto int pcntl_waitpid(int pid, int &status, int options, array &$rusage)
702    Waits on or returns the status of a forked child as defined by the waitpid() system call */
PHP_FUNCTIONnull703 PHP_FUNCTION(pcntl_waitpid)
704 {
705 	zend_long pid, options = 0;
706 	zval *z_status = NULL, *z_rusage = NULL;
707 	int status;
708 	pid_t child_id;
709 #ifdef HAVE_WAIT4
710 	struct rusage rusage;
711 #endif
712 
713 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz|lz", &pid, &z_status, &options, &z_rusage) == FAILURE) {
714 		return;
715 	}
716 
717 	status = zval_get_long(z_status);
718 
719 #ifdef HAVE_WAIT4
720 	if (z_rusage) {
721 		z_rusage = zend_try_array_init(z_rusage);
722 		if (!z_rusage) {
723 			return;
724 		}
725 
726 		memset(&rusage, 0, sizeof(struct rusage));
727 		child_id = wait4((pid_t) pid, &status, options, &rusage);
728 	} else {
729 		child_id = waitpid((pid_t) pid, &status, options);
730 	}
731 #else
732 	child_id = waitpid((pid_t) pid, &status, options);
733 #endif
734 
735 	if (child_id < 0) {
736 		PCNTL_G(last_error) = errno;
737 	}
738 
739 #ifdef HAVE_WAIT4
740 	if (child_id > 0) {
741 		PHP_RUSAGE_TO_ARRAY(rusage, z_rusage);
742 	}
743 #endif
744 
745 	ZEND_TRY_ASSIGN_REF_LONG(z_status, status);
746 
747 	RETURN_LONG((zend_long) child_id);
748 }
749 /* }}} */
750 
751 /* {{{ proto int pcntl_wait(int &status, int $options, array &$rusage)
752    Waits on or returns the status of a forked child as defined by the waitpid() system call */
PHP_FUNCTIONnull753 PHP_FUNCTION(pcntl_wait)
754 {
755 	zend_long options = 0;
756 	zval *z_status = NULL, *z_rusage = NULL;
757 	int status;
758 	pid_t child_id;
759 #ifdef HAVE_WAIT3
760 	struct rusage rusage;
761 #endif
762 
763 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|lz", &z_status, &options, &z_rusage) == FAILURE) {
764 		return;
765 	}
766 
767 	status = zval_get_long(z_status);
768 #ifdef HAVE_WAIT3
769 	if (z_rusage) {
770 		z_rusage = zend_try_array_init(z_rusage);
771 		if (!z_rusage) {
772 			return;
773 		}
774 
775 		memset(&rusage, 0, sizeof(struct rusage));
776 		child_id = wait3(&status, options, &rusage);
777 	} else if (options) {
778 		child_id = wait3(&status, options, NULL);
779 	} else {
780 		child_id = wait(&status);
781 	}
782 #else
783 	child_id = wait(&status);
784 #endif
785 	if (child_id < 0) {
786 		PCNTL_G(last_error) = errno;
787 	}
788 
789 #ifdef HAVE_WAIT3
790 	if (child_id > 0) {
791 		PHP_RUSAGE_TO_ARRAY(rusage, z_rusage);
792 	}
793 #endif
794 
795 	ZEND_TRY_ASSIGN_REF_LONG(z_status, status);
796 
797 	RETURN_LONG((zend_long) child_id);
798 }
799 /* }}} */
800 
801 #undef PHP_RUSAGE_PARA
802 #undef PHP_RUSAGE_SPECIAL
803 #undef PHP_RUSAGE_COMMON
804 #undef PHP_RUSAGE_TO_ARRAY
805 
806 /* {{{ proto bool pcntl_wifexited(int status)
807    Returns true if the child status code represents a successful exit */
PHP_FUNCTIONnull808 PHP_FUNCTION(pcntl_wifexited)
809 {
810 #ifdef WIFEXITED
811 	zend_long status_word;
812 	int int_status_word;
813 
814 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
815 	       return;
816 	}
817 
818 	int_status_word = (int) status_word;
819 	if (WIFEXITED(int_status_word))
820 		RETURN_TRUE;
821 #endif
822 
823 	RETURN_FALSE;
824 }
825 /* }}} */
826 
827 /* {{{ proto bool pcntl_wifstopped(int status)
828    Returns true if the child status code represents a stopped process (WUNTRACED must have been used with waitpid) */
PHP_FUNCTIONnull829 PHP_FUNCTION(pcntl_wifstopped)
830 {
831 #ifdef WIFSTOPPED
832 	zend_long status_word;
833 	int int_status_word;
834 
835 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
836 	       return;
837 	}
838 
839 	int_status_word = (int) status_word;
840 	if (WIFSTOPPED(int_status_word))
841 		RETURN_TRUE;
842 #endif
843 	RETURN_FALSE;
844 }
845 /* }}} */
846 
847 /* {{{ proto bool pcntl_wifsignaled(int status)
848    Returns true if the child status code represents a process that was terminated due to a signal */
PHP_FUNCTIONnull849 PHP_FUNCTION(pcntl_wifsignaled)
850 {
851 #ifdef WIFSIGNALED
852 	zend_long status_word;
853 	int int_status_word;
854 
855 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
856 	       return;
857 	}
858 
859 	int_status_word = (int) status_word;
860 	if (WIFSIGNALED(int_status_word))
861 		RETURN_TRUE;
862 #endif
863 	RETURN_FALSE;
864 }
865 /* }}} */
866 /* {{{ proto bool pcntl_wifcontinued(int status)
867    Returns true if the child status code represents a process that was resumed due to a SIGCONT signal */
PHP_FUNCTIONnull868 PHP_FUNCTION(pcntl_wifcontinued)
869 {
870 #ifdef HAVE_WCONTINUED
871 	zend_long status_word;
872 	int int_status_word;
873 
874 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
875 	       return;
876 	}
877 
878 	int_status_word = (int) status_word;
879 	if (WIFCONTINUED(int_status_word))
880 		RETURN_TRUE;
881 #endif
882 	RETURN_FALSE;
883 }
884 /* }}} */
885 
886 
887 /* {{{ proto int pcntl_wexitstatus(int status)
888    Returns the status code of a child's exit */
PHP_FUNCTIONnull889 PHP_FUNCTION(pcntl_wexitstatus)
890 {
891 #ifdef WEXITSTATUS
892 	zend_long status_word;
893 	int int_status_word;
894 
895 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
896 	       return;
897 	}
898 
899 	int_status_word = (int) status_word;
900 	RETURN_LONG(WEXITSTATUS(int_status_word));
901 #else
902 	RETURN_FALSE;
903 #endif
904 }
905 /* }}} */
906 
907 /* {{{ proto int pcntl_wtermsig(int status)
908    Returns the number of the signal that terminated the process who's status code is passed  */
PHP_FUNCTIONnull909 PHP_FUNCTION(pcntl_wtermsig)
910 {
911 #ifdef WTERMSIG
912 	zend_long status_word;
913 	int int_status_word;
914 
915 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
916 	       return;
917 	}
918 
919 	int_status_word = (int) status_word;
920 	RETURN_LONG(WTERMSIG(int_status_word));
921 #else
922 	RETURN_FALSE;
923 #endif
924 }
925 /* }}} */
926 
927 /* {{{ proto int pcntl_wstopsig(int status)
928    Returns the number of the signal that caused the process to stop who's status code is passed */
PHP_FUNCTIONnull929 PHP_FUNCTION(pcntl_wstopsig)
930 {
931 #ifdef WSTOPSIG
932 	zend_long status_word;
933 	int int_status_word;
934 
935 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &status_word) == FAILURE) {
936 	       return;
937 	}
938 
939 	int_status_word = (int) status_word;
940 	RETURN_LONG(WSTOPSIG(int_status_word));
941 #else
942 	RETURN_FALSE;
943 #endif
944 }
945 /* }}} */
946 
947 /* {{{ proto bool pcntl_exec(string path [, array args [, array envs]])
948    Executes specified program in current process space as defined by exec(2) */
PHP_FUNCTIONnull949 PHP_FUNCTION(pcntl_exec)
950 {
951 	zval *args = NULL, *envs = NULL;
952 	zval *element;
953 	HashTable *args_hash, *envs_hash;
954 	int argc = 0, argi = 0;
955 	int envc = 0, envi = 0;
956 	char **argv = NULL, **envp = NULL;
957 	char **current_arg, **pair;
958 	int pair_length;
959 	zend_string *key;
960 	char *path;
961 	size_t path_len;
962 	zend_ulong key_num;
963 
964 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|aa", &path, &path_len, &args, &envs) == FAILURE) {
965 		return;
966 	}
967 
968 	if (ZEND_NUM_ARGS() > 1) {
969 		/* Build argument list */
970 		SEPARATE_ARRAY(args);
971 		args_hash = Z_ARRVAL_P(args);
972 		argc = zend_hash_num_elements(args_hash);
973 
974 		argv = safe_emalloc((argc + 2), sizeof(char *), 0);
975 		*argv = path;
976 		current_arg = argv+1;
977 		ZEND_HASH_FOREACH_VAL(args_hash, element) {
978 			if (argi >= argc) break;
979 			if (!try_convert_to_string(element)) {
980 				efree(argv);
981 				return;
982 			}
983 
984 			*current_arg = Z_STRVAL_P(element);
985 			argi++;
986 			current_arg++;
987 		} ZEND_HASH_FOREACH_END();
988 		*current_arg = NULL;
989 	} else {
990 		argv = emalloc(2 * sizeof(char *));
991 		argv[0] = path;
992 		argv[1] = NULL;
993 	}
994 
995 	if ( ZEND_NUM_ARGS() == 3 ) {
996 		/* Build environment pair list */
997 		SEPARATE_ARRAY(envs);
998 		envs_hash = Z_ARRVAL_P(envs);
999 		envc = zend_hash_num_elements(envs_hash);
1000 
1001 		pair = envp = safe_emalloc((envc + 1), sizeof(char *), 0);
1002 		ZEND_HASH_FOREACH_KEY_VAL(envs_hash, key_num, key, element) {
1003 			if (envi >= envc) break;
1004 			if (!key) {
1005 				key = zend_long_to_str(key_num);
1006 			} else {
1007 				zend_string_addref(key);
1008 			}
1009 
1010 			if (!try_convert_to_string(element)) {
1011 				zend_string_release(key);
1012 				efree(argv);
1013 				efree(envp);
1014 				return;
1015 			}
1016 
1017 			/* Length of element + equal sign + length of key + null */
1018 			pair_length = Z_STRLEN_P(element) + ZSTR_LEN(key) + 2;
1019 			*pair = emalloc(pair_length);
1020 			strlcpy(*pair, ZSTR_VAL(key), ZSTR_LEN(key) + 1);
1021 			strlcat(*pair, "=", pair_length);
1022 			strlcat(*pair, Z_STRVAL_P(element), pair_length);
1023 
1024 			/* Cleanup */
1025 			zend_string_release_ex(key, 0);
1026 			envi++;
1027 			pair++;
1028 		} ZEND_HASH_FOREACH_END();
1029 		*(pair) = NULL;
1030 
1031 		if (execve(path, argv, envp) == -1) {
1032 			PCNTL_G(last_error) = errno;
1033 			php_error_docref(NULL, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
1034 		}
1035 
1036 		/* Cleanup */
1037 		for (pair = envp; *pair != NULL; pair++) efree(*pair);
1038 		efree(envp);
1039 	} else {
1040 
1041 		if (execv(path, argv) == -1) {
1042 			PCNTL_G(last_error) = errno;
1043 			php_error_docref(NULL, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
1044 		}
1045 	}
1046 
1047 	efree(argv);
1048 
1049 	RETURN_FALSE;
1050 }
1051 /* }}} */
1052 
1053 /* {{{ proto bool pcntl_signal(int signo, callback handle [, bool restart_syscalls])
1054    Assigns a system signal handler to a PHP function */
PHP_FUNCTIONnull1055 PHP_FUNCTION(pcntl_signal)
1056 {
1057 	zval *handle;
1058 	zend_long signo;
1059 	zend_bool restart_syscalls = 1;
1060 	zend_bool restart_syscalls_is_null = 1;
1061 	char *error = NULL;
1062 
1063 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz|b!", &signo, &handle, &restart_syscalls, &restart_syscalls_is_null) == FAILURE) {
1064 		return;
1065 	}
1066 
1067 	if (signo < 1 || signo >= NSIG) {
1068 		php_error_docref(NULL, E_WARNING, "Invalid signal");
1069 		RETURN_FALSE;
1070 	}
1071 
1072 	if (!PCNTL_G(spares)) {
1073 		/* since calling malloc() from within a signal handler is not portable,
1074 		 * pre-allocate a few records for recording signals */
1075 		int i;
1076 		for (i = 0; i < NSIG; i++) {
1077 			struct php_pcntl_pending_signal *psig;
1078 
1079 			psig = emalloc(sizeof(*psig));
1080 			psig->next = PCNTL_G(spares);
1081 			PCNTL_G(spares) = psig;
1082 		}
1083 	}
1084 
1085 	/* If restart_syscalls was not explicitly specified and the signal is SIGALRM, then default
1086 	 * restart_syscalls to false. PHP used to enforce that restart_syscalls is false for SIGALRM,
1087 	 * so we keep this differing default to reduce the degree of BC breakage. */
1088 	if (restart_syscalls_is_null && signo == SIGALRM) {
1089 		restart_syscalls = 0;
1090 	}
1091 
1092 	/* Special long value case for SIG_DFL and SIG_IGN */
1093 	if (Z_TYPE_P(handle) == IS_LONG) {
1094 		if (Z_LVAL_P(handle) != (zend_long) SIG_DFL && Z_LVAL_P(handle) != (zend_long) SIG_IGN) {
1095 			php_error_docref(NULL, E_WARNING, "Invalid value for handle argument specified");
1096 			RETURN_FALSE;
1097 		}
1098 		if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == (Sigfunc *)SIG_ERR) {
1099 			PCNTL_G(last_error) = errno;
1100 			php_error_docref(NULL, E_WARNING, "Error assigning signal");
1101 			RETURN_FALSE;
1102 		}
1103 		zend_hash_index_update(&PCNTL_G(php_signal_table), signo, handle);
1104 		RETURN_TRUE;
1105 	}
1106 
1107 	if (!zend_is_callable_ex(handle, NULL, 0, NULL, NULL, &error)) {
1108 		zend_string *func_name = zend_get_callable_name(handle);
1109 		PCNTL_G(last_error) = EINVAL;
1110 		php_error_docref(NULL, E_WARNING, "Specified handler \"%s\" is not callable (%s)", ZSTR_VAL(func_name), error);
1111 		zend_string_release_ex(func_name, 0);
1112 		efree(error);
1113 		RETURN_FALSE;
1114 	}
1115 	ZEND_ASSERT(!error);
1116 
1117 	/* Add the function name to our signal table */
1118 	handle = zend_hash_index_update(&PCNTL_G(php_signal_table), signo, handle);
1119 	Z_TRY_ADDREF_P(handle);
1120 
1121 	if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == (Sigfunc *)SIG_ERR) {
1122 		PCNTL_G(last_error) = errno;
1123 		php_error_docref(NULL, E_WARNING, "Error assigning signal");
1124 		RETURN_FALSE;
1125 	}
1126 	RETURN_TRUE;
1127 }
1128 /* }}} */
1129 
1130 /* {{{ proto bool pcntl_signal_get_handler(int signo)
1131    Gets signal handler */
PHP_FUNCTIONnull1132 PHP_FUNCTION(pcntl_signal_get_handler)
1133 {
1134 	zval *prev_handle;
1135 	zend_long signo;
1136 
1137 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &signo) == FAILURE) {
1138 		return;
1139 	}
1140 
1141 	if (signo < 1 || signo > 32) {
1142 		php_error_docref(NULL, E_WARNING, "Invalid signal");
1143 		RETURN_FALSE;
1144 	}
1145 
1146 	if ((prev_handle = zend_hash_index_find(&PCNTL_G(php_signal_table), signo)) != NULL) {
1147 		RETURN_ZVAL(prev_handle, 1, 0);
1148 	} else {
1149 		RETURN_LONG((zend_long)SIG_DFL);
1150 	}
1151 }
1152 
1153 /* {{{ proto bool pcntl_signal_dispatch()
1154    Dispatch signals to signal handlers */
PHP_FUNCTIONnull1155 PHP_FUNCTION(pcntl_signal_dispatch)
1156 {
1157 	pcntl_signal_dispatch();
1158 	RETURN_TRUE;
1159 }
1160 /* }}} */
1161 
1162 #ifdef HAVE_SIGPROCMASK
1163 /* {{{ proto bool pcntl_sigprocmask(int how, array set[, array &oldset])
1164    Examine and change blocked signals */
PHP_FUNCTIONnull1165 PHP_FUNCTION(pcntl_sigprocmask)
1166 {
1167 	zend_long          how, signo;
1168 	zval         *user_set, *user_oldset = NULL, *user_signo;
1169 	sigset_t      set, oldset;
1170 
1171 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "la|z", &how, &user_set, &user_oldset) == FAILURE) {
1172 		return;
1173 	}
1174 
1175 	if (sigemptyset(&set) != 0 || sigemptyset(&oldset) != 0) {
1176 		PCNTL_G(last_error) = errno;
1177 		php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1178 		RETURN_FALSE;
1179 	}
1180 
1181 	ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(user_set), user_signo) {
1182 		signo = zval_get_long(user_signo);
1183 		if (sigaddset(&set, signo) != 0) {
1184 			PCNTL_G(last_error) = errno;
1185 			php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1186 			RETURN_FALSE;
1187 		}
1188 	} ZEND_HASH_FOREACH_END();
1189 
1190 	if (sigprocmask(how, &set, &oldset) != 0) {
1191 		PCNTL_G(last_error) = errno;
1192 		php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1193 		RETURN_FALSE;
1194 	}
1195 
1196 	if (user_oldset != NULL) {
1197 		user_oldset = zend_try_array_init(user_oldset);
1198 		if (!user_oldset) {
1199 			return;
1200 		}
1201 
1202 		for (signo = 1; signo < NSIG; ++signo) {
1203 			if (sigismember(&oldset, signo) != 1) {
1204 				continue;
1205 			}
1206 			add_next_index_long(user_oldset, signo);
1207 		}
1208 	}
1209 
1210 	RETURN_TRUE;
1211 }
1212 /* }}} */
1213 #endif
1214 
1215 #ifdef HAVE_STRUCT_SIGINFO_T
1216 # if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait)1217 static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */
1218 {
1219 	zval            *user_set, *user_signo, *user_siginfo = NULL;
1220 	zend_long             tv_sec = 0, tv_nsec = 0;
1221 	sigset_t         set;
1222 	int              signo;
1223 	siginfo_t        siginfo;
1224 	struct timespec  timeout;
1225 
1226 	if (timedwait) {
1227 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|zll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
1228 			return;
1229 		}
1230 	} else {
1231 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|z", &user_set, &user_siginfo) == FAILURE) {
1232 			return;
1233 		}
1234 	}
1235 
1236 	if (sigemptyset(&set) != 0) {
1237 		PCNTL_G(last_error) = errno;
1238 		php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1239 		RETURN_FALSE;
1240 	}
1241 
1242 	ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(user_set), user_signo) {
1243 		signo = zval_get_long(user_signo);
1244 		if (sigaddset(&set, signo) != 0) {
1245 			PCNTL_G(last_error) = errno;
1246 			php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1247 			RETURN_FALSE;
1248 		}
1249 	} ZEND_HASH_FOREACH_END();
1250 
1251 	if (timedwait) {
1252 		timeout.tv_sec  = (time_t) tv_sec;
1253 		timeout.tv_nsec = tv_nsec;
1254 		signo = sigtimedwait(&set, &siginfo, &timeout);
1255 	} else {
1256 		signo = sigwaitinfo(&set, &siginfo);
1257 	}
1258 	if (signo == -1 && errno != EAGAIN) {
1259 		PCNTL_G(last_error) = errno;
1260 		php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1261 	}
1262 
1263 	/*
1264 	 * sigtimedwait and sigwaitinfo can return 0 on success on some
1265 	 * platforms, e.g. NetBSD
1266 	 */
1267 	if (!signo && siginfo.si_signo) {
1268 		signo = siginfo.si_signo;
1269 	}
1270 	pcntl_siginfo_to_zval(signo, &siginfo, user_siginfo);
1271 	RETURN_LONG(signo);
1272 }
1273 /* }}} */
1274 
1275 /* {{{ proto int pcnlt_sigwaitinfo(array set[, array &siginfo])
1276    Synchronously wait for queued signals */
PHP_FUNCTIONnull1277 PHP_FUNCTION(pcntl_sigwaitinfo)
1278 {
1279 	pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1280 }
1281 /* }}} */
1282 
1283 /* {{{ proto int pcntl_sigtimedwait(array set[, array &siginfo[, int seconds[, int nanoseconds]]])
1284    Wait for queued signals */
PHP_FUNCTIONnull1285 PHP_FUNCTION(pcntl_sigtimedwait)
1286 {
1287 	pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1288 }
1289 /* }}} */
1290 # endif
1291 
pcntl_siginfo_to_zval(int signo, siginfo_t *siginfo, zval *user_siginfo)1292 static void pcntl_siginfo_to_zval(int signo, siginfo_t *siginfo, zval *user_siginfo) /* {{{ */
1293 {
1294 	if (signo > 0 && user_siginfo) {
1295 		user_siginfo = zend_try_array_init(user_siginfo);
1296 		if (!user_siginfo) {
1297 			return;
1298 		}
1299 
1300 		add_assoc_long_ex(user_siginfo, "signo", sizeof("signo")-1, siginfo->si_signo);
1301 		add_assoc_long_ex(user_siginfo, "errno", sizeof("errno")-1, siginfo->si_errno);
1302 		add_assoc_long_ex(user_siginfo, "code",  sizeof("code")-1,  siginfo->si_code);
1303 		switch(signo) {
1304 #ifdef SIGCHLD
1305 			case SIGCHLD:
1306 				add_assoc_long_ex(user_siginfo,   "status", sizeof("status")-1, siginfo->si_status);
1307 # ifdef si_utime
1308 				add_assoc_double_ex(user_siginfo, "utime",  sizeof("utime")-1,  siginfo->si_utime);
1309 # endif
1310 # ifdef si_stime
1311 				add_assoc_double_ex(user_siginfo, "stime",  sizeof("stime")-1,  siginfo->si_stime);
1312 # endif
1313 				add_assoc_long_ex(user_siginfo,   "pid",    sizeof("pid")-1,    siginfo->si_pid);
1314 				add_assoc_long_ex(user_siginfo,   "uid",    sizeof("uid")-1,    siginfo->si_uid);
1315 				break;
1316 			case SIGUSR1:
1317 			case SIGUSR2:
1318 				add_assoc_long_ex(user_siginfo,   "pid",    sizeof("pid")-1,    siginfo->si_pid);
1319 				add_assoc_long_ex(user_siginfo,   "uid",    sizeof("uid")-1,    siginfo->si_uid);
1320 				break;
1321 #endif
1322 			case SIGILL:
1323 			case SIGFPE:
1324 			case SIGSEGV:
1325 			case SIGBUS:
1326 				add_assoc_double_ex(user_siginfo, "addr", sizeof("addr")-1, (zend_long)siginfo->si_addr);
1327 				break;
1328 #ifdef SIGPOLL
1329 			case SIGPOLL:
1330 				add_assoc_long_ex(user_siginfo, "band", sizeof("band")-1, siginfo->si_band);
1331 # ifdef si_fd
1332 				add_assoc_long_ex(user_siginfo, "fd",   sizeof("fd")-1,   siginfo->si_fd);
1333 # endif
1334 				break;
1335 #endif
1336 		}
1337 #if defined(SIGRTMIN) && defined(SIGRTMAX)
1338 		if (SIGRTMIN <= signo && signo <= SIGRTMAX) {
1339 			add_assoc_long_ex(user_siginfo, "pid", sizeof("pid")-1, siginfo->si_pid);
1340 			add_assoc_long_ex(user_siginfo, "uid", sizeof("uid")-1, siginfo->si_uid);
1341 		}
1342 #endif
1343 	}
1344 }
1345 /* }}} */
1346 #endif
1347 
1348 #ifdef HAVE_GETPRIORITY
1349 /* {{{ proto int pcntl_getpriority([int pid [, int process_identifier]])
1350    Get the priority of any process */
PHP_FUNCTIONnull1351 PHP_FUNCTION(pcntl_getpriority)
1352 {
1353 	zend_long who = PRIO_PROCESS;
1354 	zend_long pid = getpid();
1355 	int pri;
1356 
1357 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &pid, &who) == FAILURE) {
1358 		RETURN_FALSE;
1359 	}
1360 
1361 	/* needs to be cleared, since any returned value is valid */
1362 	errno = 0;
1363 
1364 	pri = getpriority(who, pid);
1365 
1366 	if (errno) {
1367 		PCNTL_G(last_error) = errno;
1368 		switch (errno) {
1369 			case ESRCH:
1370 				php_error_docref(NULL, E_WARNING, "Error %d: No process was located using the given parameters", errno);
1371 				break;
1372 			case EINVAL:
1373 				php_error_docref(NULL, E_WARNING, "Error %d: Invalid identifier flag", errno);
1374 				break;
1375 			default:
1376 				php_error_docref(NULL, E_WARNING, "Unknown error %d has occurred", errno);
1377 				break;
1378 		}
1379 		RETURN_FALSE;
1380 	}
1381 
1382 	RETURN_LONG(pri);
1383 }
1384 /* }}} */
1385 #endif
1386 
1387 #ifdef HAVE_SETPRIORITY
1388 /* {{{ proto bool pcntl_setpriority(int priority [, int pid [, int process_identifier]])
1389    Change the priority of any process */
PHP_FUNCTIONnull1390 PHP_FUNCTION(pcntl_setpriority)
1391 {
1392 	zend_long who = PRIO_PROCESS;
1393 	zend_long pid = getpid();
1394 	zend_long pri;
1395 
1396 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|ll", &pri, &pid, &who) == FAILURE) {
1397 		RETURN_FALSE;
1398 	}
1399 
1400 	if (setpriority(who, pid, pri)) {
1401 		PCNTL_G(last_error) = errno;
1402 		switch (errno) {
1403 			case ESRCH:
1404 				php_error_docref(NULL, E_WARNING, "Error %d: No process was located using the given parameters", errno);
1405 				break;
1406 			case EINVAL:
1407 				php_error_docref(NULL, E_WARNING, "Error %d: Invalid identifier flag", errno);
1408 				break;
1409 			case EPERM:
1410 				php_error_docref(NULL, 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);
1411 				break;
1412 			case EACCES:
1413 				php_error_docref(NULL, E_WARNING, "Error %d: Only a super user may attempt to increase the process priority", errno);
1414 				break;
1415 			default:
1416 				php_error_docref(NULL, E_WARNING, "Unknown error %d has occurred", errno);
1417 				break;
1418 		}
1419 		RETURN_FALSE;
1420 	}
1421 
1422 	RETURN_TRUE;
1423 }
1424 /* }}} */
1425 #endif
1426 
1427 /* {{{ proto int pcntl_get_last_error(void)
1428    Retrieve the error number set by the last pcntl function which failed. */
PHP_FUNCTIONnull1429 PHP_FUNCTION(pcntl_get_last_error)
1430 {
1431         RETURN_LONG(PCNTL_G(last_error));
1432 }
1433 /* }}} */
1434 
1435 /* {{{ proto string pcntl_strerror(int errno)
1436    Retrieve the system error message associated with the given errno. */
PHP_FUNCTIONnull1437 PHP_FUNCTION(pcntl_strerror)
1438 {
1439         zend_long error;
1440 
1441         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &error) == FAILURE) {
1442                 RETURN_FALSE;
1443         }
1444 
1445         RETURN_STRING(strerror(error));
1446 }
1447 /* }}} */
1448 
1449 /* Our custom signal handler that calls the appropriate php_function */
1450 #ifdef HAVE_STRUCT_SIGINFO_T
pcntl_signal_handler(int signo, siginfo_t *siginfo, void *context)1451 static void pcntl_signal_handler(int signo, siginfo_t *siginfo, void *context)
1452 #else
1453 static void pcntl_signal_handler(int signo)
1454 #endif
1455 {
1456 	struct php_pcntl_pending_signal *psig;
1457 
1458 	psig = PCNTL_G(spares);
1459 	if (!psig) {
1460 		/* oops, too many signals for us to track, so we'll forget about this one */
1461 		return;
1462 	}
1463 	PCNTL_G(spares) = psig->next;
1464 
1465 	psig->signo = signo;
1466 	psig->next = NULL;
1467 
1468 #ifdef HAVE_STRUCT_SIGINFO_T
1469 	psig->siginfo = *siginfo;
1470 #endif
1471 
1472 	/* the head check is important, as the tick handler cannot atomically clear both
1473 	 * the head and tail */
1474 	if (PCNTL_G(head) && PCNTL_G(tail)) {
1475 		PCNTL_G(tail)->next = psig;
1476 	} else {
1477 		PCNTL_G(head) = psig;
1478 	}
1479 	PCNTL_G(tail) = psig;
1480 	PCNTL_G(pending_signals) = 1;
1481 	if (PCNTL_G(async_signals)) {
1482 		EG(vm_interrupt) = 1;
1483 	}
1484 }
1485 
pcntl_signal_dispatchnull1486 void pcntl_signal_dispatch()
1487 {
1488 	zval params[2], *handle, retval;
1489 	struct php_pcntl_pending_signal *queue, *next;
1490 	sigset_t mask;
1491 	sigset_t old_mask;
1492 
1493 	if(!PCNTL_G(pending_signals)) {
1494 		return;
1495 	}
1496 
1497 	/* Mask all signals */
1498 	sigfillset(&mask);
1499 	sigprocmask(SIG_BLOCK, &mask, &old_mask);
1500 
1501 	/* Bail if the queue is empty or if we are already playing the queue */
1502 	if (!PCNTL_G(head) || PCNTL_G(processing_signal_queue)) {
1503 		sigprocmask(SIG_SETMASK, &old_mask, NULL);
1504 		return;
1505 	}
1506 
1507 	/* Prevent reentrant handler calls */
1508 	PCNTL_G(processing_signal_queue) = 1;
1509 
1510 	queue = PCNTL_G(head);
1511 	PCNTL_G(head) = NULL; /* simple stores are atomic */
1512 
1513 	/* Allocate */
1514 	while (queue) {
1515 		if ((handle = zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo)) != NULL) {
1516 			if (Z_TYPE_P(handle) != IS_LONG) {
1517 				ZVAL_NULL(&retval);
1518 				ZVAL_LONG(&params[0], queue->signo);
1519 #ifdef HAVE_STRUCT_SIGINFO_T
1520 				array_init(&params[1]);
1521 				pcntl_siginfo_to_zval(queue->signo, &queue->siginfo, &params[1]);
1522 #else
1523 				ZVAL_NULL(&params[1]);
1524 #endif
1525 
1526 				/* Call php signal handler - Note that we do not report errors, and we ignore the return value */
1527 				/* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
1528 				call_user_function(NULL, NULL, handle, &retval, 2, params);
1529 				zval_ptr_dtor(&retval);
1530 #ifdef HAVE_STRUCT_SIGINFO_T
1531 				zval_ptr_dtor(&params[1]);
1532 #endif
1533 			}
1534 		}
1535 
1536 		next = queue->next;
1537 		queue->next = PCNTL_G(spares);
1538 		PCNTL_G(spares) = queue;
1539 		queue = next;
1540 	}
1541 
1542 	PCNTL_G(pending_signals) = 0;
1543 
1544 	/* Re-enable queue */
1545 	PCNTL_G(processing_signal_queue) = 0;
1546 
1547 	/* return signal mask to previous state */
1548 	sigprocmask(SIG_SETMASK, &old_mask, NULL);
1549 }
1550 
1551 /* {{{ proto bool pcntl_async_signals([bool on[)
1552    Enable/disable asynchronous signal handling and return the old setting. */
PHP_FUNCTIONnull1553 PHP_FUNCTION(pcntl_async_signals)
1554 {
1555 	zend_bool on;
1556 
1557 	if (ZEND_NUM_ARGS() == 0) {
1558 		RETURN_BOOL(PCNTL_G(async_signals));
1559 	}
1560 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &on) == FAILURE) {
1561 		return;
1562 	}
1563 	RETVAL_BOOL(PCNTL_G(async_signals));
1564 	PCNTL_G(async_signals) = on;
1565 }
1566 /* }}} */
1567 
1568 #ifdef HAVE_UNSHARE
1569 /* {{{ proto bool pcntl_unshare(int flags)
1570    disassociate parts of the process execution context */
PHP_FUNCTIONnull1571 PHP_FUNCTION(pcntl_unshare)
1572 {
1573 	zend_long flags;
1574 	int ret;
1575 
1576 	ZEND_PARSE_PARAMETERS_START(1, 1)
1577 		Z_PARAM_LONG(flags)
1578 	ZEND_PARSE_PARAMETERS_END();
1579 
1580 	ret = unshare(flags);
1581 	if (ret == -1) {
1582 		PCNTL_G(last_error) = errno;
1583 		switch (errno) {
1584 #ifdef EINVAL
1585 			case EINVAL:
1586 				php_error_docref(NULL, E_WARNING, "Error %d: Invalid flag specified", errno);
1587 				break;
1588 #endif
1589 #ifdef ENOMEM
1590 			case ENOMEM:
1591 				php_error_docref(NULL, E_WARNING, "Error %d: Insufficient memory for unshare", errno);
1592 				break;
1593 #endif
1594 #ifdef EPERM
1595 			case EPERM:
1596 				php_error_docref(NULL, E_WARNING, "Error %d: No privilege to use these flags", errno);
1597 				break;
1598 #endif
1599 #ifdef ENOSPC
1600 			case ENOSPC:
1601 				php_error_docref(NULL, E_WARNING, "Error %d: Reached the maximum nesting limit for one of the specified namespaces", errno);
1602 				break;
1603 #endif
1604 #ifdef EUSERS
1605 			case EUSERS:
1606 				php_error_docref(NULL, E_WARNING, "Error %d: Reached the maximum nesting limit for the user namespace", errno);
1607 				break;
1608 #endif
1609 			default:
1610 				php_error_docref(NULL, E_WARNING, "Unknown error %d has occurred", errno);
1611 				break;
1612 		}
1613 		RETURN_FALSE;
1614 	}
1615 
1616 	RETURN_TRUE;
1617 }
1618 /* }}} */
1619 #endif
1620 
pcntl_interrupt_function(zend_execute_data *execute_data)1621 static void pcntl_interrupt_function(zend_execute_data *execute_data)
1622 {
1623 	pcntl_signal_dispatch();
1624 	if (orig_interrupt_function) {
1625 		orig_interrupt_function(execute_data);
1626 	}
1627 }
1628