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_constants(INIT_FUNC_ARGS)258 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_constants(INIT_FUNC_ARGS)507 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_FUNCTION(pcntl)580 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_FUNCTION(pcntl)588 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_FUNCTION(pcntl)597 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_FUNCTION(pcntl)607 PHP_MSHUTDOWN_FUNCTION(pcntl)
608 {
609 return SUCCESS;
610 }
611
PHP_RSHUTDOWN_FUNCTION(pcntl)612 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_FUNCTION(pcntl)632 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_FUNCTION(pcntl_fork)641 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_FUNCTION(pcntl_alarm)657 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_FUNCTION(pcntl_waitpid)703 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_FUNCTION(pcntl_wait)753 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_FUNCTION(pcntl_wifexited)808 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_FUNCTION(pcntl_wifstopped)829 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_FUNCTION(pcntl_wifsignaled)849 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_FUNCTION(pcntl_wifcontinued)868 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_FUNCTION(pcntl_wexitstatus)889 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_FUNCTION(pcntl_wtermsig)909 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_FUNCTION(pcntl_wstopsig)929 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_FUNCTION(pcntl_exec)949 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 size_t 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 ZEND_ASSERT(Z_STRLEN_P(element) < SIZE_MAX && ZSTR_LEN(key) < SIZE_MAX);
1019 *pair = safe_emalloc(Z_STRLEN_P(element) + 1, sizeof(char), ZSTR_LEN(key) + 1);
1020 pair_length = Z_STRLEN_P(element) + ZSTR_LEN(key) + 2;
1021 strlcpy(*pair, ZSTR_VAL(key), ZSTR_LEN(key) + 1);
1022 strlcat(*pair, "=", pair_length);
1023 strlcat(*pair, Z_STRVAL_P(element), pair_length);
1024
1025 /* Cleanup */
1026 zend_string_release_ex(key, 0);
1027 envi++;
1028 pair++;
1029 } ZEND_HASH_FOREACH_END();
1030 *(pair) = NULL;
1031
1032 if (execve(path, argv, envp) == -1) {
1033 PCNTL_G(last_error) = errno;
1034 php_error_docref(NULL, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
1035 }
1036
1037 /* Cleanup */
1038 for (pair = envp; *pair != NULL; pair++) efree(*pair);
1039 efree(envp);
1040 } else {
1041
1042 if (execv(path, argv) == -1) {
1043 PCNTL_G(last_error) = errno;
1044 php_error_docref(NULL, E_WARNING, "Error has occurred: (errno %d) %s", errno, strerror(errno));
1045 }
1046 }
1047
1048 efree(argv);
1049
1050 RETURN_FALSE;
1051 }
1052 /* }}} */
1053
1054 /* {{{ proto bool pcntl_signal(int signo, callback handle [, bool restart_syscalls])
1055 Assigns a system signal handler to a PHP function */
PHP_FUNCTION(pcntl_signal)1056 PHP_FUNCTION(pcntl_signal)
1057 {
1058 zval *handle;
1059 zend_long signo;
1060 zend_bool restart_syscalls = 1;
1061 zend_bool restart_syscalls_is_null = 1;
1062 char *error = NULL;
1063
1064 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz|b!", &signo, &handle, &restart_syscalls, &restart_syscalls_is_null) == FAILURE) {
1065 return;
1066 }
1067
1068 if (signo < 1 || signo >= NSIG) {
1069 php_error_docref(NULL, E_WARNING, "Invalid signal");
1070 RETURN_FALSE;
1071 }
1072
1073 if (!PCNTL_G(spares)) {
1074 /* since calling malloc() from within a signal handler is not portable,
1075 * pre-allocate a few records for recording signals */
1076 int i;
1077 for (i = 0; i < NSIG; i++) {
1078 struct php_pcntl_pending_signal *psig;
1079
1080 psig = emalloc(sizeof(*psig));
1081 psig->next = PCNTL_G(spares);
1082 PCNTL_G(spares) = psig;
1083 }
1084 }
1085
1086 /* If restart_syscalls was not explicitly specified and the signal is SIGALRM, then default
1087 * restart_syscalls to false. PHP used to enforce that restart_syscalls is false for SIGALRM,
1088 * so we keep this differing default to reduce the degree of BC breakage. */
1089 if (restart_syscalls_is_null && signo == SIGALRM) {
1090 restart_syscalls = 0;
1091 }
1092
1093 /* Special long value case for SIG_DFL and SIG_IGN */
1094 if (Z_TYPE_P(handle) == IS_LONG) {
1095 if (Z_LVAL_P(handle) != (zend_long) SIG_DFL && Z_LVAL_P(handle) != (zend_long) SIG_IGN) {
1096 php_error_docref(NULL, E_WARNING, "Invalid value for handle argument specified");
1097 RETURN_FALSE;
1098 }
1099 if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == (Sigfunc *)SIG_ERR) {
1100 PCNTL_G(last_error) = errno;
1101 php_error_docref(NULL, E_WARNING, "Error assigning signal");
1102 RETURN_FALSE;
1103 }
1104 zend_hash_index_update(&PCNTL_G(php_signal_table), signo, handle);
1105 RETURN_TRUE;
1106 }
1107
1108 if (!zend_is_callable_ex(handle, NULL, 0, NULL, NULL, &error)) {
1109 zend_string *func_name = zend_get_callable_name(handle);
1110 PCNTL_G(last_error) = EINVAL;
1111 php_error_docref(NULL, E_WARNING, "Specified handler \"%s\" is not callable (%s)", ZSTR_VAL(func_name), error);
1112 zend_string_release_ex(func_name, 0);
1113 efree(error);
1114 RETURN_FALSE;
1115 }
1116 ZEND_ASSERT(!error);
1117
1118 /* Add the function name to our signal table */
1119 handle = zend_hash_index_update(&PCNTL_G(php_signal_table), signo, handle);
1120 Z_TRY_ADDREF_P(handle);
1121
1122 if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == (Sigfunc *)SIG_ERR) {
1123 PCNTL_G(last_error) = errno;
1124 php_error_docref(NULL, E_WARNING, "Error assigning signal");
1125 RETURN_FALSE;
1126 }
1127 RETURN_TRUE;
1128 }
1129 /* }}} */
1130
1131 /* {{{ proto bool pcntl_signal_get_handler(int signo)
1132 Gets signal handler */
PHP_FUNCTION(pcntl_signal_get_handler)1133 PHP_FUNCTION(pcntl_signal_get_handler)
1134 {
1135 zval *prev_handle;
1136 zend_long signo;
1137
1138 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &signo) == FAILURE) {
1139 return;
1140 }
1141
1142 if (signo < 1 || signo > 32) {
1143 php_error_docref(NULL, E_WARNING, "Invalid signal");
1144 RETURN_FALSE;
1145 }
1146
1147 if ((prev_handle = zend_hash_index_find(&PCNTL_G(php_signal_table), signo)) != NULL) {
1148 RETURN_ZVAL(prev_handle, 1, 0);
1149 } else {
1150 RETURN_LONG((zend_long)SIG_DFL);
1151 }
1152 }
1153
1154 /* {{{ proto bool pcntl_signal_dispatch()
1155 Dispatch signals to signal handlers */
PHP_FUNCTION(pcntl_signal_dispatch)1156 PHP_FUNCTION(pcntl_signal_dispatch)
1157 {
1158 pcntl_signal_dispatch();
1159 RETURN_TRUE;
1160 }
1161 /* }}} */
1162
1163 #ifdef HAVE_SIGPROCMASK
1164 /* {{{ proto bool pcntl_sigprocmask(int how, array set[, array &oldset])
1165 Examine and change blocked signals */
PHP_FUNCTION(pcntl_sigprocmask)1166 PHP_FUNCTION(pcntl_sigprocmask)
1167 {
1168 zend_long how, signo;
1169 zval *user_set, *user_oldset = NULL, *user_signo;
1170 sigset_t set, oldset;
1171
1172 if (zend_parse_parameters(ZEND_NUM_ARGS(), "la|z", &how, &user_set, &user_oldset) == FAILURE) {
1173 return;
1174 }
1175
1176 if (sigemptyset(&set) != 0 || sigemptyset(&oldset) != 0) {
1177 PCNTL_G(last_error) = errno;
1178 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1179 RETURN_FALSE;
1180 }
1181
1182 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(user_set), user_signo) {
1183 signo = zval_get_long(user_signo);
1184 if (sigaddset(&set, signo) != 0) {
1185 PCNTL_G(last_error) = errno;
1186 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1187 RETURN_FALSE;
1188 }
1189 } ZEND_HASH_FOREACH_END();
1190
1191 if (sigprocmask(how, &set, &oldset) != 0) {
1192 PCNTL_G(last_error) = errno;
1193 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1194 RETURN_FALSE;
1195 }
1196
1197 if (user_oldset != NULL) {
1198 user_oldset = zend_try_array_init(user_oldset);
1199 if (!user_oldset) {
1200 return;
1201 }
1202
1203 for (signo = 1; signo < NSIG; ++signo) {
1204 if (sigismember(&oldset, signo) != 1) {
1205 continue;
1206 }
1207 add_next_index_long(user_oldset, signo);
1208 }
1209 }
1210
1211 RETURN_TRUE;
1212 }
1213 /* }}} */
1214 #endif
1215
1216 #ifdef HAVE_STRUCT_SIGINFO_T
1217 # if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS,int timedwait)1218 static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */
1219 {
1220 zval *user_set, *user_signo, *user_siginfo = NULL;
1221 zend_long tv_sec = 0, tv_nsec = 0;
1222 sigset_t set;
1223 int signo;
1224 siginfo_t siginfo;
1225 struct timespec timeout;
1226
1227 if (timedwait) {
1228 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|zll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
1229 return;
1230 }
1231 } else {
1232 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|z", &user_set, &user_siginfo) == FAILURE) {
1233 return;
1234 }
1235 }
1236
1237 if (sigemptyset(&set) != 0) {
1238 PCNTL_G(last_error) = errno;
1239 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1240 RETURN_FALSE;
1241 }
1242
1243 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(user_set), user_signo) {
1244 signo = zval_get_long(user_signo);
1245 if (sigaddset(&set, signo) != 0) {
1246 PCNTL_G(last_error) = errno;
1247 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1248 RETURN_FALSE;
1249 }
1250 } ZEND_HASH_FOREACH_END();
1251
1252 if (timedwait) {
1253 timeout.tv_sec = (time_t) tv_sec;
1254 timeout.tv_nsec = tv_nsec;
1255 signo = sigtimedwait(&set, &siginfo, &timeout);
1256 } else {
1257 signo = sigwaitinfo(&set, &siginfo);
1258 }
1259 if (signo == -1 && errno != EAGAIN) {
1260 PCNTL_G(last_error) = errno;
1261 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
1262 }
1263
1264 /*
1265 * sigtimedwait and sigwaitinfo can return 0 on success on some
1266 * platforms, e.g. NetBSD
1267 */
1268 if (!signo && siginfo.si_signo) {
1269 signo = siginfo.si_signo;
1270 }
1271 pcntl_siginfo_to_zval(signo, &siginfo, user_siginfo);
1272 RETURN_LONG(signo);
1273 }
1274 /* }}} */
1275
1276 /* {{{ proto int pcnlt_sigwaitinfo(array set[, array &siginfo])
1277 Synchronously wait for queued signals */
PHP_FUNCTION(pcntl_sigwaitinfo)1278 PHP_FUNCTION(pcntl_sigwaitinfo)
1279 {
1280 pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1281 }
1282 /* }}} */
1283
1284 /* {{{ proto int pcntl_sigtimedwait(array set[, array &siginfo[, int seconds[, int nanoseconds]]])
1285 Wait for queued signals */
PHP_FUNCTION(pcntl_sigtimedwait)1286 PHP_FUNCTION(pcntl_sigtimedwait)
1287 {
1288 pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1289 }
1290 /* }}} */
1291 # endif
1292
pcntl_siginfo_to_zval(int signo,siginfo_t * siginfo,zval * user_siginfo)1293 static void pcntl_siginfo_to_zval(int signo, siginfo_t *siginfo, zval *user_siginfo) /* {{{ */
1294 {
1295 if (signo > 0 && user_siginfo) {
1296 user_siginfo = zend_try_array_init(user_siginfo);
1297 if (!user_siginfo) {
1298 return;
1299 }
1300
1301 add_assoc_long_ex(user_siginfo, "signo", sizeof("signo")-1, siginfo->si_signo);
1302 add_assoc_long_ex(user_siginfo, "errno", sizeof("errno")-1, siginfo->si_errno);
1303 add_assoc_long_ex(user_siginfo, "code", sizeof("code")-1, siginfo->si_code);
1304 switch(signo) {
1305 #ifdef SIGCHLD
1306 case SIGCHLD:
1307 add_assoc_long_ex(user_siginfo, "status", sizeof("status")-1, siginfo->si_status);
1308 # ifdef si_utime
1309 add_assoc_double_ex(user_siginfo, "utime", sizeof("utime")-1, siginfo->si_utime);
1310 # endif
1311 # ifdef si_stime
1312 add_assoc_double_ex(user_siginfo, "stime", sizeof("stime")-1, siginfo->si_stime);
1313 # endif
1314 add_assoc_long_ex(user_siginfo, "pid", sizeof("pid")-1, siginfo->si_pid);
1315 add_assoc_long_ex(user_siginfo, "uid", sizeof("uid")-1, siginfo->si_uid);
1316 break;
1317 case SIGUSR1:
1318 case SIGUSR2:
1319 add_assoc_long_ex(user_siginfo, "pid", sizeof("pid")-1, siginfo->si_pid);
1320 add_assoc_long_ex(user_siginfo, "uid", sizeof("uid")-1, siginfo->si_uid);
1321 break;
1322 #endif
1323 case SIGILL:
1324 case SIGFPE:
1325 case SIGSEGV:
1326 case SIGBUS:
1327 add_assoc_double_ex(user_siginfo, "addr", sizeof("addr")-1, (zend_long)siginfo->si_addr);
1328 break;
1329 #ifdef SIGPOLL
1330 case SIGPOLL:
1331 add_assoc_long_ex(user_siginfo, "band", sizeof("band")-1, siginfo->si_band);
1332 # ifdef si_fd
1333 add_assoc_long_ex(user_siginfo, "fd", sizeof("fd")-1, siginfo->si_fd);
1334 # endif
1335 break;
1336 #endif
1337 }
1338 #if defined(SIGRTMIN) && defined(SIGRTMAX)
1339 if (SIGRTMIN <= signo && signo <= SIGRTMAX) {
1340 add_assoc_long_ex(user_siginfo, "pid", sizeof("pid")-1, siginfo->si_pid);
1341 add_assoc_long_ex(user_siginfo, "uid", sizeof("uid")-1, siginfo->si_uid);
1342 }
1343 #endif
1344 }
1345 }
1346 /* }}} */
1347 #endif
1348
1349 #ifdef HAVE_GETPRIORITY
1350 /* {{{ proto int pcntl_getpriority([int pid [, int process_identifier]])
1351 Get the priority of any process */
PHP_FUNCTION(pcntl_getpriority)1352 PHP_FUNCTION(pcntl_getpriority)
1353 {
1354 zend_long who = PRIO_PROCESS;
1355 zend_long pid = getpid();
1356 int pri;
1357
1358 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &pid, &who) == FAILURE) {
1359 RETURN_FALSE;
1360 }
1361
1362 /* needs to be cleared, since any returned value is valid */
1363 errno = 0;
1364
1365 pri = getpriority(who, pid);
1366
1367 if (errno) {
1368 PCNTL_G(last_error) = errno;
1369 switch (errno) {
1370 case ESRCH:
1371 php_error_docref(NULL, E_WARNING, "Error %d: No process was located using the given parameters", errno);
1372 break;
1373 case EINVAL:
1374 php_error_docref(NULL, E_WARNING, "Error %d: Invalid identifier flag", errno);
1375 break;
1376 default:
1377 php_error_docref(NULL, E_WARNING, "Unknown error %d has occurred", errno);
1378 break;
1379 }
1380 RETURN_FALSE;
1381 }
1382
1383 RETURN_LONG(pri);
1384 }
1385 /* }}} */
1386 #endif
1387
1388 #ifdef HAVE_SETPRIORITY
1389 /* {{{ proto bool pcntl_setpriority(int priority [, int pid [, int process_identifier]])
1390 Change the priority of any process */
PHP_FUNCTION(pcntl_setpriority)1391 PHP_FUNCTION(pcntl_setpriority)
1392 {
1393 zend_long who = PRIO_PROCESS;
1394 zend_long pid = getpid();
1395 zend_long pri;
1396
1397 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|ll", &pri, &pid, &who) == FAILURE) {
1398 RETURN_FALSE;
1399 }
1400
1401 if (setpriority(who, pid, pri)) {
1402 PCNTL_G(last_error) = errno;
1403 switch (errno) {
1404 case ESRCH:
1405 php_error_docref(NULL, E_WARNING, "Error %d: No process was located using the given parameters", errno);
1406 break;
1407 case EINVAL:
1408 php_error_docref(NULL, E_WARNING, "Error %d: Invalid identifier flag", errno);
1409 break;
1410 case EPERM:
1411 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);
1412 break;
1413 case EACCES:
1414 php_error_docref(NULL, E_WARNING, "Error %d: Only a super user may attempt to increase the process priority", errno);
1415 break;
1416 default:
1417 php_error_docref(NULL, E_WARNING, "Unknown error %d has occurred", errno);
1418 break;
1419 }
1420 RETURN_FALSE;
1421 }
1422
1423 RETURN_TRUE;
1424 }
1425 /* }}} */
1426 #endif
1427
1428 /* {{{ proto int pcntl_get_last_error(void)
1429 Retrieve the error number set by the last pcntl function which failed. */
PHP_FUNCTION(pcntl_get_last_error)1430 PHP_FUNCTION(pcntl_get_last_error)
1431 {
1432 RETURN_LONG(PCNTL_G(last_error));
1433 }
1434 /* }}} */
1435
1436 /* {{{ proto string pcntl_strerror(int errno)
1437 Retrieve the system error message associated with the given errno. */
PHP_FUNCTION(pcntl_strerror)1438 PHP_FUNCTION(pcntl_strerror)
1439 {
1440 zend_long error;
1441
1442 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &error) == FAILURE) {
1443 RETURN_FALSE;
1444 }
1445
1446 RETURN_STRING(strerror(error));
1447 }
1448 /* }}} */
1449
1450 /* Our custom signal handler that calls the appropriate php_function */
1451 #ifdef HAVE_STRUCT_SIGINFO_T
pcntl_signal_handler(int signo,siginfo_t * siginfo,void * context)1452 static void pcntl_signal_handler(int signo, siginfo_t *siginfo, void *context)
1453 #else
1454 static void pcntl_signal_handler(int signo)
1455 #endif
1456 {
1457 struct php_pcntl_pending_signal *psig;
1458
1459 psig = PCNTL_G(spares);
1460 if (!psig) {
1461 /* oops, too many signals for us to track, so we'll forget about this one */
1462 return;
1463 }
1464 PCNTL_G(spares) = psig->next;
1465
1466 psig->signo = signo;
1467 psig->next = NULL;
1468
1469 #ifdef HAVE_STRUCT_SIGINFO_T
1470 psig->siginfo = *siginfo;
1471 #endif
1472
1473 /* the head check is important, as the tick handler cannot atomically clear both
1474 * the head and tail */
1475 if (PCNTL_G(head) && PCNTL_G(tail)) {
1476 PCNTL_G(tail)->next = psig;
1477 } else {
1478 PCNTL_G(head) = psig;
1479 }
1480 PCNTL_G(tail) = psig;
1481 PCNTL_G(pending_signals) = 1;
1482 if (PCNTL_G(async_signals)) {
1483 EG(vm_interrupt) = 1;
1484 }
1485 }
1486
pcntl_signal_dispatch()1487 void pcntl_signal_dispatch()
1488 {
1489 zval params[2], *handle, retval;
1490 struct php_pcntl_pending_signal *queue, *next;
1491 sigset_t mask;
1492 sigset_t old_mask;
1493
1494 if(!PCNTL_G(pending_signals)) {
1495 return;
1496 }
1497
1498 /* Mask all signals */
1499 sigfillset(&mask);
1500 sigprocmask(SIG_BLOCK, &mask, &old_mask);
1501
1502 /* Bail if the queue is empty or if we are already playing the queue */
1503 if (!PCNTL_G(head) || PCNTL_G(processing_signal_queue)) {
1504 sigprocmask(SIG_SETMASK, &old_mask, NULL);
1505 return;
1506 }
1507
1508 /* Prevent reentrant handler calls */
1509 PCNTL_G(processing_signal_queue) = 1;
1510
1511 queue = PCNTL_G(head);
1512 PCNTL_G(head) = NULL; /* simple stores are atomic */
1513
1514 /* Allocate */
1515 while (queue) {
1516 if ((handle = zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo)) != NULL) {
1517 if (Z_TYPE_P(handle) != IS_LONG) {
1518 ZVAL_NULL(&retval);
1519 ZVAL_LONG(¶ms[0], queue->signo);
1520 #ifdef HAVE_STRUCT_SIGINFO_T
1521 array_init(¶ms[1]);
1522 pcntl_siginfo_to_zval(queue->signo, &queue->siginfo, ¶ms[1]);
1523 #else
1524 ZVAL_NULL(¶ms[1]);
1525 #endif
1526
1527 /* Call php signal handler - Note that we do not report errors, and we ignore the return value */
1528 /* FIXME: this is probably broken when multiple signals are handled in this while loop (retval) */
1529 call_user_function(NULL, NULL, handle, &retval, 2, params);
1530 zval_ptr_dtor(&retval);
1531 #ifdef HAVE_STRUCT_SIGINFO_T
1532 zval_ptr_dtor(¶ms[1]);
1533 #endif
1534 }
1535 }
1536
1537 next = queue->next;
1538 queue->next = PCNTL_G(spares);
1539 PCNTL_G(spares) = queue;
1540 queue = next;
1541 }
1542
1543 PCNTL_G(pending_signals) = 0;
1544
1545 /* Re-enable queue */
1546 PCNTL_G(processing_signal_queue) = 0;
1547
1548 /* return signal mask to previous state */
1549 sigprocmask(SIG_SETMASK, &old_mask, NULL);
1550 }
1551
1552 /* {{{ proto bool pcntl_async_signals([bool on[)
1553 Enable/disable asynchronous signal handling and return the old setting. */
PHP_FUNCTION(pcntl_async_signals)1554 PHP_FUNCTION(pcntl_async_signals)
1555 {
1556 zend_bool on;
1557
1558 if (ZEND_NUM_ARGS() == 0) {
1559 RETURN_BOOL(PCNTL_G(async_signals));
1560 }
1561 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &on) == FAILURE) {
1562 return;
1563 }
1564 RETVAL_BOOL(PCNTL_G(async_signals));
1565 PCNTL_G(async_signals) = on;
1566 }
1567 /* }}} */
1568
1569 #ifdef HAVE_UNSHARE
1570 /* {{{ proto bool pcntl_unshare(int flags)
1571 disassociate parts of the process execution context */
PHP_FUNCTION(pcntl_unshare)1572 PHP_FUNCTION(pcntl_unshare)
1573 {
1574 zend_long flags;
1575 int ret;
1576
1577 ZEND_PARSE_PARAMETERS_START(1, 1)
1578 Z_PARAM_LONG(flags)
1579 ZEND_PARSE_PARAMETERS_END();
1580
1581 ret = unshare(flags);
1582 if (ret == -1) {
1583 PCNTL_G(last_error) = errno;
1584 switch (errno) {
1585 #ifdef EINVAL
1586 case EINVAL:
1587 php_error_docref(NULL, E_WARNING, "Error %d: Invalid flag specified", errno);
1588 break;
1589 #endif
1590 #ifdef ENOMEM
1591 case ENOMEM:
1592 php_error_docref(NULL, E_WARNING, "Error %d: Insufficient memory for unshare", errno);
1593 break;
1594 #endif
1595 #ifdef EPERM
1596 case EPERM:
1597 php_error_docref(NULL, E_WARNING, "Error %d: No privilege to use these flags", errno);
1598 break;
1599 #endif
1600 #ifdef ENOSPC
1601 case ENOSPC:
1602 php_error_docref(NULL, E_WARNING, "Error %d: Reached the maximum nesting limit for one of the specified namespaces", errno);
1603 break;
1604 #endif
1605 #ifdef EUSERS
1606 case EUSERS:
1607 php_error_docref(NULL, E_WARNING, "Error %d: Reached the maximum nesting limit for the user namespace", errno);
1608 break;
1609 #endif
1610 default:
1611 php_error_docref(NULL, E_WARNING, "Unknown error %d has occurred", errno);
1612 break;
1613 }
1614 RETURN_FALSE;
1615 }
1616
1617 RETURN_TRUE;
1618 }
1619 /* }}} */
1620 #endif
1621
pcntl_interrupt_function(zend_execute_data * execute_data)1622 static void pcntl_interrupt_function(zend_execute_data *execute_data)
1623 {
1624 pcntl_signal_dispatch();
1625 if (orig_interrupt_function) {
1626 orig_interrupt_function(execute_data);
1627 }
1628 }
1629