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: Kristian Koehntopp <kris@koehntopp.de>                       |
16    +----------------------------------------------------------------------+
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 
23 #include "php.h"
24 #include <unistd.h>
25 #include "ext/standard/info.h"
26 #include "ext/standard/php_string.h"
27 #include "php_posix.h"
28 
29 
30 #if HAVE_POSIX
31 
32 #ifdef HAVE_SYS_TIME_H
33 #include <sys/time.h>
34 #endif
35 
36 #include <sys/resource.h>
37 #include <sys/utsname.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <signal.h>
41 #include <sys/times.h>
42 #include <errno.h>
43 #include <grp.h>
44 #include <pwd.h>
45 #if HAVE_SYS_MKDEV_H
46 # include <sys/mkdev.h>
47 #endif
48 #if HAVE_SYS_SYSMACROS_H
49 # include <sys/sysmacros.h>
50 #endif
51 
52 ZEND_DECLARE_MODULE_GLOBALS(posix)
53 static PHP_MINFO_FUNCTION(posix);
54 
55 /* {{{ arginfo */
56 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_kill, 0, 0, 2)
57 	ZEND_ARG_INFO(0, pid)
58 	ZEND_ARG_INFO(0, sig)
59 ZEND_END_ARG_INFO()
60 
61 ZEND_BEGIN_ARG_INFO(arginfo_posix_getpid, 0)
62 ZEND_END_ARG_INFO()
63 
64 ZEND_BEGIN_ARG_INFO(arginfo_posix_getppid, 0)
65 ZEND_END_ARG_INFO()
66 
67 ZEND_BEGIN_ARG_INFO(arginfo_posix_getuid, 0)
68 ZEND_END_ARG_INFO()
69 
70 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_setuid, 0, 0, 1)
71 	ZEND_ARG_INFO(0, uid)
72 ZEND_END_ARG_INFO()
73 
74 ZEND_BEGIN_ARG_INFO(arginfo_posix_geteuid, 0)
75 ZEND_END_ARG_INFO()
76 
77 #ifdef HAVE_SETEUID
78 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_seteuid, 0, 0, 1)
79 	ZEND_ARG_INFO(0, uid)
80 ZEND_END_ARG_INFO()
81 #endif
82 
83 ZEND_BEGIN_ARG_INFO(arginfo_posix_getgid, 0)
84 ZEND_END_ARG_INFO()
85 
86 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_setgid, 0, 0, 1)
87 	ZEND_ARG_INFO(0, gid)
88 ZEND_END_ARG_INFO()
89 
90 ZEND_BEGIN_ARG_INFO(arginfo_posix_getegid, 0)
91 ZEND_END_ARG_INFO()
92 
93 #ifdef HAVE_SETEGID
94 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_setegid, 0, 0, 1)
95 	ZEND_ARG_INFO(0, gid)
96 ZEND_END_ARG_INFO()
97 #endif
98 
99 #ifdef HAVE_GETGROUPS
100 ZEND_BEGIN_ARG_INFO(arginfo_posix_getgroups, 0)
101 ZEND_END_ARG_INFO()
102 #endif
103 
104 #ifdef HAVE_GETLOGIN
105 ZEND_BEGIN_ARG_INFO(arginfo_posix_getlogin, 0)
106 ZEND_END_ARG_INFO()
107 #endif
108 
109 ZEND_BEGIN_ARG_INFO(arginfo_posix_getpgrp, 0)
110 ZEND_END_ARG_INFO()
111 
112 #ifdef HAVE_SETSID
113 ZEND_BEGIN_ARG_INFO(arginfo_posix_setsid, 0)
114 ZEND_END_ARG_INFO()
115 #endif
116 
117 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_setpgid, 0, 0, 2)
118 	ZEND_ARG_INFO(0, pid)
119 	ZEND_ARG_INFO(0, pgid)
120 ZEND_END_ARG_INFO()
121 
122 #ifdef HAVE_GETPGID
123 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_getpgid, 0, 0, 1)
124 	ZEND_ARG_INFO(0, pid)
125 ZEND_END_ARG_INFO()
126 #endif
127 
128 #ifdef HAVE_GETSID
129 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_getsid, 0, 0, 1)
130 	ZEND_ARG_INFO(0, pid)
131 ZEND_END_ARG_INFO()
132 #endif
133 
134 ZEND_BEGIN_ARG_INFO(arginfo_posix_uname, 0)
135 ZEND_END_ARG_INFO()
136 
137 ZEND_BEGIN_ARG_INFO(arginfo_posix_times, 0)
138 ZEND_END_ARG_INFO()
139 
140 #ifdef HAVE_CTERMID
141 ZEND_BEGIN_ARG_INFO(arginfo_posix_ctermid, 0)
142 ZEND_END_ARG_INFO()
143 #endif
144 
145 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_ttyname, 0, 0, 1)
146 	ZEND_ARG_INFO(0, fd)
147 ZEND_END_ARG_INFO()
148 
149 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_isatty, 0, 0, 1)
150 	ZEND_ARG_INFO(0, fd)
151 ZEND_END_ARG_INFO()
152 
153 ZEND_BEGIN_ARG_INFO(arginfo_posix_getcwd, 0)
154 ZEND_END_ARG_INFO()
155 
156 #ifdef HAVE_MKFIFO
157 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_mkfifo, 0, 0, 2)
158 	ZEND_ARG_INFO(0, pathname)
159 	ZEND_ARG_INFO(0, mode)
160 ZEND_END_ARG_INFO()
161 #endif
162 
163 #ifdef HAVE_MKNOD
164 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_mknod, 0, 0, 2)
165 	ZEND_ARG_INFO(0, pathname)
166 	ZEND_ARG_INFO(0, mode)
167 	ZEND_ARG_INFO(0, major)
168 	ZEND_ARG_INFO(0, minor)
169 ZEND_END_ARG_INFO()
170 #endif
171 
172 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_access, 0, 0, 1)
173 	ZEND_ARG_INFO(0, file)
174 	ZEND_ARG_INFO(0, mode)
175 ZEND_END_ARG_INFO()
176 
177 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_getgrnam, 0, 0, 1)
178 	ZEND_ARG_INFO(0, name)
179 ZEND_END_ARG_INFO()
180 
181 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_getgrgid, 0, 0, 1)
182 	ZEND_ARG_INFO(0, gid)
183 ZEND_END_ARG_INFO()
184 
185 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_getpwnam, 0, 0, 1)
186 	ZEND_ARG_INFO(0, username)
187 ZEND_END_ARG_INFO()
188 
189 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_getpwuid, 0, 0, 1)
190 	ZEND_ARG_INFO(0, uid)
191 ZEND_END_ARG_INFO()
192 
193 #ifdef HAVE_GETRLIMIT
194 ZEND_BEGIN_ARG_INFO(arginfo_posix_getrlimit, 0)
195 ZEND_END_ARG_INFO()
196 #endif
197 
198 #ifdef HAVE_SETRLIMIT
199 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_setrlimit, 0, 0, 3)
200 	ZEND_ARG_INFO(0, resource)
201 	ZEND_ARG_INFO(0, softlimit)
202 	ZEND_ARG_INFO(0, hardlimit)
203 ZEND_END_ARG_INFO()
204 #endif
205 
206 ZEND_BEGIN_ARG_INFO(arginfo_posix_get_last_error, 0)
207 ZEND_END_ARG_INFO()
208 
209 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_strerror, 0, 0, 1)
210 	ZEND_ARG_INFO(0, errno)
211 ZEND_END_ARG_INFO()
212 
213 #ifdef HAVE_INITGROUPS
214 ZEND_BEGIN_ARG_INFO_EX(arginfo_posix_initgroups, 0, 0, 2)
215 	ZEND_ARG_INFO(0, name)
216 	ZEND_ARG_INFO(0, base_group_id)
217 ZEND_END_ARG_INFO()
218 #endif
219 /* }}} */
220 
221 /* {{{ posix_functions[]
222  */
223 static const zend_function_entry posix_functions[] = {
224     /* POSIX.1, 3.3 */
225 	PHP_FE(posix_kill,		arginfo_posix_kill)
226 
227 	/* POSIX.1, 4.1 */
228 	PHP_FE(posix_getpid,	arginfo_posix_getpid)
229 	PHP_FE(posix_getppid,	arginfo_posix_getppid)
230 
231 	/* POSIX.1,  4.2 */
232 	PHP_FE(posix_getuid,	arginfo_posix_getuid)
233 	PHP_FE(posix_setuid,	arginfo_posix_setuid)
234 	PHP_FE(posix_geteuid,	arginfo_posix_geteuid)
235 #ifdef HAVE_SETEUID
236 	PHP_FE(posix_seteuid,	arginfo_posix_seteuid)
237 #endif
238 	PHP_FE(posix_getgid,	arginfo_posix_getgid)
239 	PHP_FE(posix_setgid,	arginfo_posix_setgid)
240 	PHP_FE(posix_getegid,	arginfo_posix_getegid)
241 #ifdef HAVE_SETEGID
242 	PHP_FE(posix_setegid,	arginfo_posix_setegid)
243 #endif
244 #ifdef HAVE_GETGROUPS
245 	PHP_FE(posix_getgroups,	arginfo_posix_getgroups)
246 #endif
247 #ifdef HAVE_GETLOGIN
248 	PHP_FE(posix_getlogin,	arginfo_posix_getlogin)
249 #endif
250 
251 	/* POSIX.1, 4.3 */
252 	PHP_FE(posix_getpgrp,	arginfo_posix_getpgrp)
253 #ifdef HAVE_SETSID
254 	PHP_FE(posix_setsid,	arginfo_posix_setsid)
255 #endif
256 	PHP_FE(posix_setpgid,	arginfo_posix_setpgid)
257 	/* Non-Posix functions which are common */
258 #ifdef HAVE_GETPGID
259 	PHP_FE(posix_getpgid,	arginfo_posix_getpgid)
260 #endif /* HAVE_GETPGID */
261 #ifdef HAVE_GETSID
262 	PHP_FE(posix_getsid,	arginfo_posix_getsid)
263 #endif /* HAVE_GETSID */
264 
265 	/* POSIX.1, 4.4 */
266 	PHP_FE(posix_uname,		arginfo_posix_uname)
267 
268 	/* POSIX.1, 4.5 */
269 	PHP_FE(posix_times,		arginfo_posix_times)
270 
271 	/* POSIX.1, 4.7 */
272 #ifdef HAVE_CTERMID
273 	PHP_FE(posix_ctermid,	arginfo_posix_ctermid)
274 #endif
275 	PHP_FE(posix_ttyname,	arginfo_posix_ttyname)
276 	PHP_FE(posix_isatty,	arginfo_posix_isatty)
277 
278     /* POSIX.1, 5.2 */
279 	PHP_FE(posix_getcwd,	arginfo_posix_getcwd)
280 
281 	/* POSIX.1, 5.4 */
282 #ifdef HAVE_MKFIFO
283 	PHP_FE(posix_mkfifo,	arginfo_posix_mkfifo)
284 #endif
285 #ifdef HAVE_MKNOD
286 	PHP_FE(posix_mknod,		arginfo_posix_mknod)
287 #endif
288 
289 	/* POSIX.1, 5.6 */
290 	PHP_FE(posix_access,	arginfo_posix_access)
291 	/* POSIX.1, 9.2 */
292 	PHP_FE(posix_getgrnam,	arginfo_posix_getgrnam)
293 	PHP_FE(posix_getgrgid,	arginfo_posix_getgrgid)
294 	PHP_FE(posix_getpwnam,	arginfo_posix_getpwnam)
295 	PHP_FE(posix_getpwuid,	arginfo_posix_getpwuid)
296 
297 #ifdef HAVE_GETRLIMIT
298 	PHP_FE(posix_getrlimit,	arginfo_posix_getrlimit)
299 #endif
300 #ifdef HAVE_SETRLIMIT
301 	PHP_FE(posix_setrlimit, arginfo_posix_setrlimit)
302 #endif
303 
304 	PHP_FE(posix_get_last_error,					arginfo_posix_get_last_error)
305 	PHP_FALIAS(posix_errno, posix_get_last_error,	arginfo_posix_get_last_error)
306 	PHP_FE(posix_strerror,							arginfo_posix_strerror)
307 #ifdef HAVE_INITGROUPS
308 	PHP_FE(posix_initgroups,	arginfo_posix_initgroups)
309 #endif
310 
311 	PHP_FE_END
312 };
313 /* }}} */
314 
315 /* {{{ PHP_MINFO_FUNCTION
316  */
PHP_MINFO_FUNCTIONnull317 static PHP_MINFO_FUNCTION(posix)
318 {
319 	php_info_print_table_start();
320 	php_info_print_table_row(2, "POSIX support", "enabled");
321 	php_info_print_table_end();
322 }
323 /* }}} */
324 
PHP_GINIT_FUNCTIONnull325 static PHP_GINIT_FUNCTION(posix) /* {{{ */
326 {
327 #if defined(COMPILE_DL_POSIX) && defined(ZTS)
328 	ZEND_TSRMLS_CACHE_UPDATE();
329 #endif
330 	posix_globals->last_error = 0;
331 }
332 /* }}} */
333 
334 /* {{{ PHP_MINIT_FUNCTION(posix)
335  */
PHP_MINIT_FUNCTIONnull336 static PHP_MINIT_FUNCTION(posix)
337 {
338 	REGISTER_LONG_CONSTANT("POSIX_F_OK", F_OK, CONST_CS | CONST_PERSISTENT);
339 	REGISTER_LONG_CONSTANT("POSIX_X_OK", X_OK, CONST_CS | CONST_PERSISTENT);
340 	REGISTER_LONG_CONSTANT("POSIX_W_OK", W_OK, CONST_CS | CONST_PERSISTENT);
341 	REGISTER_LONG_CONSTANT("POSIX_R_OK", R_OK, CONST_CS | CONST_PERSISTENT);
342 #ifdef S_IFREG
343 	REGISTER_LONG_CONSTANT("POSIX_S_IFREG", S_IFREG, CONST_CS | CONST_PERSISTENT);
344 #endif
345 #ifdef S_IFCHR
346 	REGISTER_LONG_CONSTANT("POSIX_S_IFCHR", S_IFCHR, CONST_CS | CONST_PERSISTENT);
347 #endif
348 #ifdef S_IFBLK
349 	REGISTER_LONG_CONSTANT("POSIX_S_IFBLK", S_IFBLK, CONST_CS | CONST_PERSISTENT);
350 #endif
351 #ifdef S_IFIFO
352 	REGISTER_LONG_CONSTANT("POSIX_S_IFIFO", S_IFIFO, CONST_CS | CONST_PERSISTENT);
353 #endif
354 #ifdef S_IFSOCK
355 	REGISTER_LONG_CONSTANT("POSIX_S_IFSOCK", S_IFSOCK, CONST_CS | CONST_PERSISTENT);
356 #endif
357 #ifdef RLIMIT_AS
358 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_AS", RLIMIT_AS, CONST_CS | CONST_PERSISTENT);
359 #endif
360 #ifdef RLIMIT_CORE
361 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_CORE", RLIMIT_CORE, CONST_CS | CONST_PERSISTENT);
362 #endif
363 #ifdef RLIMIT_CPU
364 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_CPU", RLIMIT_CPU, CONST_CS | CONST_PERSISTENT);
365 #endif
366 #ifdef RLIMIT_DATA
367 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_DATA", RLIMIT_DATA, CONST_CS | CONST_PERSISTENT);
368 #endif
369 #ifdef RLIMIT_FSIZE
370 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_FSIZE", RLIMIT_FSIZE, CONST_CS | CONST_PERSISTENT);
371 #endif
372 #ifdef RLIMIT_LOCKS
373 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_LOCKS", RLIMIT_LOCKS, CONST_CS | CONST_PERSISTENT);
374 #endif
375 #ifdef RLIMIT_MEMLOCK
376 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_MEMLOCK", RLIMIT_MEMLOCK, CONST_CS | CONST_PERSISTENT);
377 #endif
378 #ifdef RLIMIT_MSGQUEUE
379 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE, CONST_CS | CONST_PERSISTENT);
380 #endif
381 #ifdef RLIMIT_NICE
382 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_NICE", RLIMIT_NICE, CONST_CS | CONST_PERSISTENT);
383 #endif
384 #ifdef RLIMIT_NOFILE
385 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_NOFILE", RLIMIT_NOFILE, CONST_CS | CONST_PERSISTENT);
386 #endif
387 #ifdef RLIMIT_NPROC
388 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_NPROC", RLIMIT_NPROC, CONST_CS | CONST_PERSISTENT);
389 #endif
390 #ifdef RLIMIT_RSS
391 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_RSS", RLIMIT_RSS, CONST_CS | CONST_PERSISTENT);
392 #endif
393 #ifdef RLIMIT_RTPRIO
394 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_RTPRIO", RLIMIT_RTPRIO, CONST_CS | CONST_PERSISTENT);
395 #endif
396 #ifdef RLIMIT_RTTIME
397 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_RTTIME", RLIMIT_RTTIME, CONST_CS | CONST_PERSISTENT);
398 #endif
399 #ifdef RLIMIT_SIGPENDING
400 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_SIGPENDING", RLIMIT_SIGPENDING, CONST_CS | CONST_PERSISTENT);
401 #endif
402 #ifdef RLIMIT_STACK
403 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_STACK", RLIMIT_STACK, CONST_CS | CONST_PERSISTENT);
404 #endif
405 #ifdef HAVE_SETRLIMIT
406 	REGISTER_LONG_CONSTANT("POSIX_RLIMIT_INFINITY", RLIM_INFINITY, CONST_CS | CONST_PERSISTENT);
407 #endif
408 	return SUCCESS;
409 }
410 /* }}} */
411 
412 /* {{{ posix_module_entry
413  */
414 zend_module_entry posix_module_entry = {
415 	STANDARD_MODULE_HEADER,
416 	"posix",
417 	posix_functions,
418 	PHP_MINIT(posix),
419 	NULL,
420 	NULL,
421 	NULL,
422 	PHP_MINFO(posix),
423 	PHP_POSIX_VERSION,
424 	PHP_MODULE_GLOBALS(posix),
425 	PHP_GINIT(posix),
426 	NULL,
427 	NULL,
428 	STANDARD_MODULE_PROPERTIES_EX
429 };
430 /* }}} */
431 
432 #ifdef COMPILE_DL_POSIX
433 #ifdef ZTS
434 ZEND_TSRMLS_CACHE_DEFINE()
435 #endif
ZEND_GET_MODULEnull436 ZEND_GET_MODULE(posix)
437 #endif
438 
439 #define PHP_POSIX_NO_ARGS	if (zend_parse_parameters_none() == FAILURE) return;
440 
441 #define PHP_POSIX_RETURN_LONG_FUNC(func_name)	\
442 	PHP_POSIX_NO_ARGS	\
443 	RETURN_LONG(func_name());
444 
445 #define PHP_POSIX_SINGLE_ARG_FUNC(func_name)	\
446 	zend_long val;	\
447 	ZEND_PARSE_PARAMETERS_START(1, 1) \
448 		Z_PARAM_LONG(val) \
449 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); \
450 	if (func_name(val) < 0) {	\
451 		POSIX_G(last_error) = errno;	\
452 		RETURN_FALSE;	\
453 	}	\
454 	RETURN_TRUE;
455 
456 /* {{{ proto bool posix_kill(int pid, int sig)
457    Send a signal to a process (POSIX.1, 3.3.2) */
458 
459 PHP_FUNCTION(posix_kill)
460 {
461 	zend_long pid, sig;
462 
463 	ZEND_PARSE_PARAMETERS_START(2, 2)
464 		Z_PARAM_LONG(pid)
465 		Z_PARAM_LONG(sig)
466 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
467 
468 	if (kill(pid, sig) < 0) {
469 		POSIX_G(last_error) = errno;
470 		RETURN_FALSE;
471   	}
472 
473 	RETURN_TRUE;
474 }
475 /* }}} */
476 
477 /* {{{ proto int posix_getpid(void)
478    Get the current process id (POSIX.1, 4.1.1) */
PHP_FUNCTIONnull479 PHP_FUNCTION(posix_getpid)
480 {
481 	PHP_POSIX_RETURN_LONG_FUNC(getpid);
482 }
483 /* }}} */
484 
485 /* {{{ proto int posix_getppid(void)
486    Get the parent process id (POSIX.1, 4.1.1) */
PHP_FUNCTIONnull487 PHP_FUNCTION(posix_getppid)
488 {
489 	PHP_POSIX_RETURN_LONG_FUNC(getppid);
490 }
491 /* }}} */
492 
493 /* {{{ proto int posix_getuid(void)
494    Get the current user id (POSIX.1, 4.2.1) */
PHP_FUNCTIONnull495 PHP_FUNCTION(posix_getuid)
496 {
497 	PHP_POSIX_RETURN_LONG_FUNC(getuid);
498 }
499 /* }}} */
500 
501 /* {{{ proto int posix_getgid(void)
502    Get the current group id (POSIX.1, 4.2.1) */
PHP_FUNCTIONnull503 PHP_FUNCTION(posix_getgid)
504 {
505 	PHP_POSIX_RETURN_LONG_FUNC(getgid);
506 }
507 /* }}} */
508 
509 /* {{{ proto int posix_geteuid(void)
510    Get the current effective user id (POSIX.1, 4.2.1) */
PHP_FUNCTIONnull511 PHP_FUNCTION(posix_geteuid)
512 {
513 	PHP_POSIX_RETURN_LONG_FUNC(geteuid);
514 }
515 /* }}} */
516 
517 /* {{{ proto int posix_getegid(void)
518    Get the current effective group id (POSIX.1, 4.2.1) */
PHP_FUNCTIONnull519 PHP_FUNCTION(posix_getegid)
520 {
521 	PHP_POSIX_RETURN_LONG_FUNC(getegid);
522 }
523 /* }}} */
524 
525 /* {{{ proto bool posix_setuid(int uid)
526    Set user id (POSIX.1, 4.2.2) */
PHP_FUNCTIONnull527 PHP_FUNCTION(posix_setuid)
528 {
529 	PHP_POSIX_SINGLE_ARG_FUNC(setuid);
530 }
531 /* }}} */
532 
533 /* {{{ proto bool posix_setgid(int uid)
534    Set group id (POSIX.1, 4.2.2) */
PHP_FUNCTIONnull535 PHP_FUNCTION(posix_setgid)
536 {
537 	PHP_POSIX_SINGLE_ARG_FUNC(setgid);
538 }
539 /* }}} */
540 
541 /* {{{ proto bool posix_seteuid(int uid)
542    Set effective user id */
543 #ifdef HAVE_SETEUID
PHP_FUNCTIONnull544 PHP_FUNCTION(posix_seteuid)
545 {
546 	PHP_POSIX_SINGLE_ARG_FUNC(seteuid);
547 }
548 #endif
549 /* }}} */
550 
551 /* {{{ proto bool posix_setegid(int uid)
552    Set effective group id */
553 #ifdef HAVE_SETEGID
PHP_FUNCTIONnull554 PHP_FUNCTION(posix_setegid)
555 {
556 	PHP_POSIX_SINGLE_ARG_FUNC(setegid);
557 }
558 #endif
559 /* }}} */
560 
561 /* {{{ proto array posix_getgroups(void)
562    Get supplementary group id's (POSIX.1, 4.2.3) */
563 #ifdef HAVE_GETGROUPS
PHP_FUNCTIONnull564 PHP_FUNCTION(posix_getgroups)
565 {
566 	gid_t  gidlist[NGROUPS_MAX];
567 	int    result;
568 	int    i;
569 
570 	PHP_POSIX_NO_ARGS;
571 
572 	if ((result = getgroups(NGROUPS_MAX, gidlist)) < 0) {
573 		POSIX_G(last_error) = errno;
574 		RETURN_FALSE;
575 	}
576 
577 	array_init(return_value);
578 
579 	for (i=0; i<result; i++) {
580 		add_next_index_long(return_value, gidlist[i]);
581 	}
582 }
583 #endif
584 /* }}} */
585 
586 /* {{{ proto string posix_getlogin(void)
587    Get user name (POSIX.1, 4.2.4) */
588 #ifdef HAVE_GETLOGIN
PHP_FUNCTIONnull589 PHP_FUNCTION(posix_getlogin)
590 {
591 	char *p;
592 
593 	PHP_POSIX_NO_ARGS;
594 
595 	if (NULL == (p = getlogin())) {
596 		POSIX_G(last_error) = errno;
597 		RETURN_FALSE;
598 	}
599 
600 	RETURN_STRING(p);
601 }
602 #endif
603 /* }}} */
604 
605 /* {{{ proto int posix_getpgrp(void)
606    Get current process group id (POSIX.1, 4.3.1) */
PHP_FUNCTIONnull607 PHP_FUNCTION(posix_getpgrp)
608 {
609 	PHP_POSIX_RETURN_LONG_FUNC(getpgrp);
610 }
611 /* }}} */
612 
613 /* {{{ proto int posix_setsid(void)
614    Create session and set process group id (POSIX.1, 4.3.2) */
615 #ifdef HAVE_SETSID
PHP_FUNCTIONnull616 PHP_FUNCTION(posix_setsid)
617 {
618 	PHP_POSIX_RETURN_LONG_FUNC(setsid);
619 }
620 #endif
621 /* }}} */
622 
623 /* {{{ proto bool posix_setpgid(int pid, int pgid)
624    Set process group id for job control (POSIX.1, 4.3.3) */
PHP_FUNCTIONnull625 PHP_FUNCTION(posix_setpgid)
626 {
627 	zend_long pid, pgid;
628 
629 	ZEND_PARSE_PARAMETERS_START(2, 2)
630 		Z_PARAM_LONG(pid)
631 		Z_PARAM_LONG(pgid)
632 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
633 
634 	if (setpgid(pid, pgid) < 0) {
635 		POSIX_G(last_error) = errno;
636 		RETURN_FALSE;
637 	}
638 
639 	RETURN_TRUE;
640 }
641 /* }}} */
642 
643 /* {{{ proto int posix_getpgid(void)
644    Get the process group id of the specified process (This is not a POSIX function, but a SVR4ism, so we compile conditionally) */
645 #ifdef HAVE_GETPGID
PHP_FUNCTIONnull646 PHP_FUNCTION(posix_getpgid)
647 {
648 	zend_long val;
649 
650 	ZEND_PARSE_PARAMETERS_START(1, 1)
651 		Z_PARAM_LONG(val)
652 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
653 
654 	if ((val = getpgid(val)) < 0) {
655 		POSIX_G(last_error) = errno;
656 		RETURN_FALSE;
657 	}
658 	RETURN_LONG(val);
659 }
660 #endif
661 /* }}} */
662 
663 /* {{{ proto int posix_getsid(void)
664    Get process group id of session leader (This is not a POSIX function, but a SVR4ism, so be compile conditionally) */
665 #ifdef HAVE_GETSID
PHP_FUNCTIONnull666 PHP_FUNCTION(posix_getsid)
667 {
668 	zend_long val;
669 
670 	ZEND_PARSE_PARAMETERS_START(1, 1)
671 		Z_PARAM_LONG(val)
672 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
673 
674 	if ((val = getsid(val)) < 0) {
675 		POSIX_G(last_error) = errno;
676 		RETURN_FALSE;
677 	}
678 	RETURN_LONG(val);
679 }
680 #endif
681 /* }}} */
682 
683 /* {{{ proto array posix_uname(void)
684    Get system name (POSIX.1, 4.4.1) */
PHP_FUNCTIONnull685 PHP_FUNCTION(posix_uname)
686 {
687 	struct utsname u;
688 
689 	PHP_POSIX_NO_ARGS;
690 
691 	if (uname(&u) < 0) {
692 		POSIX_G(last_error) = errno;
693 		RETURN_FALSE;
694 	}
695 
696 	array_init(return_value);
697 
698 	add_assoc_string(return_value, "sysname",  u.sysname);
699 	add_assoc_string(return_value, "nodename", u.nodename);
700 	add_assoc_string(return_value, "release",  u.release);
701 	add_assoc_string(return_value, "version",  u.version);
702 	add_assoc_string(return_value, "machine",  u.machine);
703 
704 #if defined(_GNU_SOURCE) && !defined(DARWIN) && defined(HAVE_UTSNAME_DOMAINNAME)
705 	add_assoc_string(return_value, "domainname", u.domainname);
706 #endif
707 }
708 /* }}} */
709 
710 /* POSIX.1, 4.5.1 time() - Get System Time
711 							already covered by PHP
712  */
713 
714 /* {{{ proto array posix_times(void)
715    Get process times (POSIX.1, 4.5.2) */
PHP_FUNCTIONnull716 PHP_FUNCTION(posix_times)
717 {
718 	struct tms t;
719 	clock_t    ticks;
720 
721 	PHP_POSIX_NO_ARGS;
722 
723 	if ((ticks = times(&t)) == -1) {
724 		POSIX_G(last_error) = errno;
725 		RETURN_FALSE;
726 	}
727 
728 	array_init(return_value);
729 
730 	add_assoc_long(return_value, "ticks",	ticks);			/* clock ticks */
731 	add_assoc_long(return_value, "utime",	t.tms_utime);	/* user time */
732 	add_assoc_long(return_value, "stime",	t.tms_stime);	/* system time */
733 	add_assoc_long(return_value, "cutime",	t.tms_cutime);	/* user time of children */
734 	add_assoc_long(return_value, "cstime",	t.tms_cstime);	/* system time of children */
735 }
736 /* }}} */
737 
738 /* POSIX.1, 4.6.1 getenv() - Environment Access
739 							already covered by PHP
740 */
741 
742 /* {{{ proto string posix_ctermid(void)
743    Generate terminal path name (POSIX.1, 4.7.1) */
744 #ifdef HAVE_CTERMID
PHP_FUNCTIONnull745 PHP_FUNCTION(posix_ctermid)
746 {
747 	char  buffer[L_ctermid];
748 
749 	PHP_POSIX_NO_ARGS;
750 
751 	if (NULL == ctermid(buffer)) {
752 		/* Found no documentation how the defined behaviour is when this
753 		 * function fails
754 		 */
755 		POSIX_G(last_error) = errno;
756 		RETURN_FALSE;
757 	}
758 
759 	RETURN_STRING(buffer);
760 }
761 #endif
762 /* }}} */
763 
764 /* Checks if the provides resource is a stream and if it provides a file descriptor */
php_posix_stream_get_fd(zval *zfp, int *fd)765 static int php_posix_stream_get_fd(zval *zfp, int *fd) /* {{{ */
766 {
767 	php_stream *stream;
768 
769 	php_stream_from_zval_no_verify(stream, zfp);
770 
771 	if (stream == NULL) {
772 		php_error_docref(NULL, E_WARNING, "expects argument 1 to be a valid stream resource");
773 		return 0;
774 	}
775 	if (php_stream_can_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT) == SUCCESS) {
776 		php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT, (void*)fd, 0);
777 	} else if (php_stream_can_cast(stream, PHP_STREAM_AS_FD) == SUCCESS) {
778 		php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)fd, 0);
779 	} else {
780 		php_error_docref(NULL, E_WARNING, "could not use stream of type '%s'",
781 				stream->ops->label);
782 		return 0;
783 	}
784 	return 1;
785 }
786 /* }}} */
787 
788 /* {{{ proto string posix_ttyname(int fd)
789    Determine terminal device name (POSIX.1, 4.7.2) */
PHP_FUNCTIONnull790 PHP_FUNCTION(posix_ttyname)
791 {
792 	zval *z_fd;
793 	char *p;
794 	int fd;
795 #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX)
796 	zend_long buflen;
797 #endif
798 
799 	ZEND_PARSE_PARAMETERS_START(1, 1)
800 		Z_PARAM_ZVAL(z_fd)
801 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
802 
803 	switch (Z_TYPE_P(z_fd)) {
804 		case IS_RESOURCE:
805 			if (!php_posix_stream_get_fd(z_fd, &fd)) {
806 				RETURN_FALSE;
807 			}
808 			break;
809 		default:
810 			fd = zval_get_long(z_fd);
811 	}
812 #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX)
813 	buflen = sysconf(_SC_TTY_NAME_MAX);
814 	if (buflen < 1) {
815 		RETURN_FALSE;
816 	}
817 	p = emalloc(buflen);
818 
819 	if (ttyname_r(fd, p, buflen)) {
820 		POSIX_G(last_error) = errno;
821 		efree(p);
822 		RETURN_FALSE;
823 	}
824 	RETURN_STRING(p);
825 	efree(p);
826 #else
827 	if (NULL == (p = ttyname(fd))) {
828 		POSIX_G(last_error) = errno;
829 		RETURN_FALSE;
830 	}
831 #endif
832 	RETURN_STRING(p);
833 }
834 /* }}} */
835 
836 /* {{{ proto bool posix_isatty(int fd)
837    Determine if filedesc is a tty (POSIX.1, 4.7.1) */
PHP_FUNCTIONnull838 PHP_FUNCTION(posix_isatty)
839 {
840 	zval *z_fd;
841 	int fd;
842 
843 	ZEND_PARSE_PARAMETERS_START(1, 1)
844 		Z_PARAM_ZVAL(z_fd)
845 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
846 
847 	switch (Z_TYPE_P(z_fd)) {
848 		case IS_RESOURCE:
849 			if (!php_posix_stream_get_fd(z_fd, &fd)) {
850 				RETURN_FALSE;
851 			}
852 			break;
853 		default:
854 			fd = zval_get_long(z_fd);
855 	}
856 
857 	if (isatty(fd)) {
858 		RETURN_TRUE;
859 	} else {
860 		RETURN_FALSE;
861 	}
862 }
863 /* }}} */
864 
865 /*
866 	POSIX.1, 4.8.1 sysconf() - TODO
867 	POSIX.1, 5.7.1 pathconf(), fpathconf() - TODO
868 
869 	POSIX.1, 5.1.2 opendir(), readdir(), rewinddir(), closedir()
870 	POSIX.1, 5.2.1 chdir()
871 				already supported by PHP
872  */
873 
874 /* {{{ proto string posix_getcwd(void)
875    Get working directory pathname (POSIX.1, 5.2.2) */
PHP_FUNCTIONnull876 PHP_FUNCTION(posix_getcwd)
877 {
878 	char  buffer[MAXPATHLEN];
879 	char *p;
880 
881 	PHP_POSIX_NO_ARGS;
882 
883 	p = VCWD_GETCWD(buffer, MAXPATHLEN);
884 	if (!p) {
885 		POSIX_G(last_error) = errno;
886 		RETURN_FALSE;
887 	}
888 
889 	RETURN_STRING(buffer);
890 }
891 /* }}} */
892 
893 /*
894 	POSIX.1, 5.3.x open(), creat(), umask()
895 	POSIX.1, 5.4.1 link()
896 		already supported by PHP.
897  */
898 
899 /* {{{ proto bool posix_mkfifo(string pathname, int mode)
900    Make a FIFO special file (POSIX.1, 5.4.2) */
901 #ifdef HAVE_MKFIFO
PHP_FUNCTIONnull902 PHP_FUNCTION(posix_mkfifo)
903 {
904 	zend_string *path;
905 	zend_long mode;
906 	int     result;
907 
908 	ZEND_PARSE_PARAMETERS_START(2, 2)
909 		Z_PARAM_PATH_STR(path)
910 		Z_PARAM_LONG(mode)
911 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
912 
913 	if (php_check_open_basedir_ex(ZSTR_VAL(path), 0)) {
914 		RETURN_FALSE;
915 	}
916 
917 	result = mkfifo(ZSTR_VAL(path), mode);
918 	if (result < 0) {
919 		POSIX_G(last_error) = errno;
920 		RETURN_FALSE;
921 	}
922 
923 	RETURN_TRUE;
924 }
925 #endif
926 /* }}} */
927 
928 /* {{{ proto bool posix_mknod(string pathname, int mode [, int major [, int minor]])
929    Make a special or ordinary file (POSIX.1) */
930 #ifdef HAVE_MKNOD
PHP_FUNCTIONnull931 PHP_FUNCTION(posix_mknod)
932 {
933 	zend_string *path;
934 	zend_long mode;
935 	zend_long major = 0, minor = 0;
936 	int result;
937 	dev_t php_dev = 0;
938 
939 	ZEND_PARSE_PARAMETERS_START(2, 4)
940 		Z_PARAM_PATH_STR(path)
941 		Z_PARAM_LONG(mode)
942 		Z_PARAM_OPTIONAL
943 		Z_PARAM_LONG(major)
944 		Z_PARAM_LONG(minor)
945 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
946 
947 	if (php_check_open_basedir_ex(ZSTR_VAL(path), 0)) {
948 		RETURN_FALSE;
949 	}
950 
951 	if ((mode & S_IFCHR) || (mode & S_IFBLK)) {
952 		if (ZEND_NUM_ARGS() == 2) {
953 			php_error_docref(NULL, E_WARNING, "For S_IFCHR and S_IFBLK you need to pass a major device kernel identifier");
954 			RETURN_FALSE;
955 		}
956 		if (major == 0) {
957 			php_error_docref(NULL, E_WARNING,
958 				"Expects argument 3 to be non-zero for POSIX_S_IFCHR and POSIX_S_IFBLK");
959 			RETURN_FALSE;
960 		} else {
961 #if defined(HAVE_MAKEDEV) || defined(makedev)
962 			php_dev = makedev(major, minor);
963 #else
964 			php_error_docref(NULL, E_WARNING, "Cannot create a block or character device, creating a normal file instead");
965 #endif
966 		}
967 	}
968 
969 	result = mknod(ZSTR_VAL(path), mode, php_dev);
970 	if (result < 0) {
971 		POSIX_G(last_error) = errno;
972 		RETURN_FALSE;
973 	}
974 
975 	RETURN_TRUE;
976 }
977 #endif
978 /* }}} */
979 
980 /* Takes a pointer to posix group and a pointer to an already initialized ZVAL
981  * array container and fills the array with the posix group member data. */
php_posix_group_to_array(struct group *g, zval *array_group)982 int php_posix_group_to_array(struct group *g, zval *array_group) /* {{{ */
983 {
984 	zval array_members;
985 	int count;
986 
987 	if (NULL == g)
988 		return 0;
989 
990 	if (array_group == NULL || Z_TYPE_P(array_group) != IS_ARRAY)
991 		return 0;
992 
993 	array_init(&array_members);
994 
995 	add_assoc_string(array_group, "name", g->gr_name);
996 	if (g->gr_passwd) {
997 		add_assoc_string(array_group, "passwd", g->gr_passwd);
998 	} else {
999 		add_assoc_null(array_group, "passwd");
1000 	}
1001 	for (count = 0;; count++) {
1002 		/* gr_mem entries may be misaligned on macos. */
1003 		char *gr_mem;
1004 		memcpy(&gr_mem, &g->gr_mem[count], sizeof(char *));
1005 		if (!gr_mem) {
1006 			break;
1007 		}
1008 
1009 		add_next_index_string(&array_members, gr_mem);
1010 	}
1011 	zend_hash_str_update(Z_ARRVAL_P(array_group), "members", sizeof("members")-1, &array_members);
1012 	add_assoc_long(array_group, "gid", g->gr_gid);
1013 	return 1;
1014 }
1015 /* }}} */
1016 
1017 /*
1018 	POSIX.1, 5.5.1 unlink()
1019 	POSIX.1, 5.5.2 rmdir()
1020 	POSIX.1, 5.5.3 rename()
1021 	POSIX.1, 5.6.x stat(), chmod(), utime() already supported by PHP.
1022 */
1023 
1024 /* {{{ proto bool posix_access(string file [, int mode])
1025    Determine accessibility of a file (POSIX.1 5.6.3) */
PHP_FUNCTIONnull1026 PHP_FUNCTION(posix_access)
1027 {
1028 	zend_long mode = 0;
1029 	size_t filename_len, ret;
1030 	char *filename, *path;
1031 
1032 	ZEND_PARSE_PARAMETERS_START(1, 2)
1033 		Z_PARAM_PATH(filename, filename_len)
1034 		Z_PARAM_OPTIONAL
1035 		Z_PARAM_LONG(mode)
1036 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1037 
1038 	path = expand_filepath(filename, NULL);
1039 	if (!path) {
1040 		POSIX_G(last_error) = EIO;
1041 		RETURN_FALSE;
1042 	}
1043 
1044 	if (php_check_open_basedir_ex(path, 0)) {
1045 		efree(path);
1046 		POSIX_G(last_error) = EPERM;
1047 		RETURN_FALSE;
1048 	}
1049 
1050 	ret = access(path, mode);
1051 	efree(path);
1052 
1053 	if (ret) {
1054 		POSIX_G(last_error) = errno;
1055 		RETURN_FALSE;
1056 	}
1057 
1058 	RETURN_TRUE;
1059 }
1060 /* }}} */
1061 
1062 /*
1063 	POSIX.1, 6.x most I/O functions already supported by PHP.
1064 	POSIX.1, 7.x tty functions, TODO
1065 	POSIX.1, 8.x interactions with other C language functions
1066 	POSIX.1, 9.x system database access
1067 */
1068 
1069 /* {{{ proto array posix_getgrnam(string groupname)
1070    Group database access (POSIX.1, 9.2.1) */
PHP_FUNCTIONnull1071 PHP_FUNCTION(posix_getgrnam)
1072 {
1073 	char *name;
1074 	struct group *g;
1075 	size_t name_len;
1076 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
1077 	struct group gbuf;
1078 	long buflen;
1079 	char *buf;
1080 #endif
1081 
1082 	ZEND_PARSE_PARAMETERS_START(1, 1)
1083 		Z_PARAM_STRING(name, name_len)
1084 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1085 
1086 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
1087 	buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
1088 	if (buflen < 1) {
1089 		RETURN_FALSE;
1090 	}
1091 	buf = emalloc(buflen);
1092 try_again:
1093 	g = &gbuf;
1094 
1095 	if (getgrnam_r(name, g, buf, buflen, &g) || g == NULL) {
1096 		if (errno == ERANGE) {
1097 			buflen *= 2;
1098 			buf = erealloc(buf, buflen);
1099 			goto try_again;
1100 		}
1101 		POSIX_G(last_error) = errno;
1102 		efree(buf);
1103 		RETURN_FALSE;
1104 	}
1105 #else
1106 	if (NULL == (g = getgrnam(name))) {
1107 		POSIX_G(last_error) = errno;
1108 		RETURN_FALSE;
1109 	}
1110 #endif
1111 	array_init(return_value);
1112 
1113 	if (!php_posix_group_to_array(g, return_value)) {
1114 		zend_array_destroy(Z_ARR_P(return_value));
1115 		php_error_docref(NULL, E_WARNING, "unable to convert posix group to array");
1116 		RETVAL_FALSE;
1117 	}
1118 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
1119 	efree(buf);
1120 #endif
1121 }
1122 /* }}} */
1123 
1124 /* {{{ proto array posix_getgrgid(int gid)
1125    Group database access (POSIX.1, 9.2.1) */
PHP_FUNCTIONnull1126 PHP_FUNCTION(posix_getgrgid)
1127 {
1128 	zend_long gid;
1129 #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
1130 	int ret;
1131 	struct group _g;
1132 	struct group *retgrptr = NULL;
1133 	long grbuflen;
1134 	char *grbuf;
1135 #endif
1136 	struct group *g;
1137 
1138 	ZEND_PARSE_PARAMETERS_START(1, 1)
1139 		Z_PARAM_LONG(gid)
1140 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1141 
1142 #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
1143 
1144 	grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
1145 	if (grbuflen < 1) {
1146 		RETURN_FALSE;
1147 	}
1148 
1149 	grbuf = emalloc(grbuflen);
1150 
1151 	ret = getgrgid_r(gid, &_g, grbuf, grbuflen, &retgrptr);
1152 	if (ret || retgrptr == NULL) {
1153 		POSIX_G(last_error) = ret;
1154 		efree(grbuf);
1155 		RETURN_FALSE;
1156 	}
1157 	g = &_g;
1158 #else
1159 	if (NULL == (g = getgrgid(gid))) {
1160 		POSIX_G(last_error) = errno;
1161 		RETURN_FALSE;
1162 	}
1163 #endif
1164 	array_init(return_value);
1165 
1166 	if (!php_posix_group_to_array(g, return_value)) {
1167 		zend_array_destroy(Z_ARR_P(return_value));
1168 		php_error_docref(NULL, E_WARNING, "unable to convert posix group struct to array");
1169 		RETVAL_FALSE;
1170 	}
1171 #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
1172 	efree(grbuf);
1173 #endif
1174 }
1175 /* }}} */
1176 
php_posix_passwd_to_array(struct passwd *pw, zval *return_value)1177 int php_posix_passwd_to_array(struct passwd *pw, zval *return_value) /* {{{ */
1178 {
1179 	if (NULL == pw)
1180 		return 0;
1181 	if (NULL == return_value || Z_TYPE_P(return_value) != IS_ARRAY)
1182 		return 0;
1183 
1184 	add_assoc_string(return_value, "name",      pw->pw_name);
1185 	add_assoc_string(return_value, "passwd",    pw->pw_passwd);
1186 	add_assoc_long  (return_value, "uid",       pw->pw_uid);
1187 	add_assoc_long  (return_value, "gid",		pw->pw_gid);
1188 	add_assoc_string(return_value, "gecos",     pw->pw_gecos);
1189 	add_assoc_string(return_value, "dir",       pw->pw_dir);
1190 	add_assoc_string(return_value, "shell",     pw->pw_shell);
1191 	return 1;
1192 }
1193 /* }}} */
1194 
1195 /* {{{ proto array posix_getpwnam(string groupname)
1196    User database access (POSIX.1, 9.2.2) */
PHP_FUNCTIONnull1197 PHP_FUNCTION(posix_getpwnam)
1198 {
1199 	struct passwd *pw;
1200 	char *name;
1201 	size_t name_len;
1202 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
1203 	struct passwd pwbuf;
1204 	long buflen;
1205 	char *buf;
1206 #endif
1207 
1208 	ZEND_PARSE_PARAMETERS_START(1, 1)
1209 		Z_PARAM_STRING(name, name_len)
1210 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1211 
1212 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
1213 	buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1214 	if (buflen < 1) {
1215 		RETURN_FALSE;
1216 	}
1217 	buf = emalloc(buflen);
1218 	pw = &pwbuf;
1219 
1220 	if (getpwnam_r(name, pw, buf, buflen, &pw) || pw == NULL) {
1221 		efree(buf);
1222 		POSIX_G(last_error) = errno;
1223 		RETURN_FALSE;
1224 	}
1225 #else
1226 	if (NULL == (pw = getpwnam(name))) {
1227 		POSIX_G(last_error) = errno;
1228 		RETURN_FALSE;
1229 	}
1230 #endif
1231 	array_init(return_value);
1232 
1233 	if (!php_posix_passwd_to_array(pw, return_value)) {
1234 		zend_array_destroy(Z_ARR_P(return_value));
1235 		php_error_docref(NULL, E_WARNING, "unable to convert posix passwd struct to array");
1236 		RETVAL_FALSE;
1237 	}
1238 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
1239 	efree(buf);
1240 #endif
1241 }
1242 /* }}} */
1243 
1244 /* {{{ proto array posix_getpwuid(int uid)
1245    User database access (POSIX.1, 9.2.2) */
PHP_FUNCTIONnull1246 PHP_FUNCTION(posix_getpwuid)
1247 {
1248 	zend_long uid;
1249 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1250 	struct passwd _pw;
1251 	struct passwd *retpwptr = NULL;
1252 	long pwbuflen;
1253 	char *pwbuf;
1254 	int ret;
1255 #endif
1256 	struct passwd *pw;
1257 
1258 	ZEND_PARSE_PARAMETERS_START(1, 1)
1259 		Z_PARAM_LONG(uid)
1260 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1261 
1262 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1263 	pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1264 	if (pwbuflen < 1) {
1265 		RETURN_FALSE;
1266 	}
1267 	pwbuf = emalloc(pwbuflen);
1268 
1269 	ret = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr);
1270 	if (ret || retpwptr == NULL) {
1271 		POSIX_G(last_error) = ret;
1272 		efree(pwbuf);
1273 		RETURN_FALSE;
1274 	}
1275 	pw = &_pw;
1276 #else
1277 	if (NULL == (pw = getpwuid(uid))) {
1278 		POSIX_G(last_error) = errno;
1279 		RETURN_FALSE;
1280 	}
1281 #endif
1282 	array_init(return_value);
1283 
1284 	if (!php_posix_passwd_to_array(pw, return_value)) {
1285 		zend_array_destroy(Z_ARR_P(return_value));
1286 		php_error_docref(NULL, E_WARNING, "unable to convert posix passwd struct to array");
1287 		RETVAL_FALSE;
1288 	}
1289 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1290 	efree(pwbuf);
1291 #endif
1292 }
1293 /* }}} */
1294 
1295 
1296 #ifdef HAVE_GETRLIMIT
1297 
1298 #define UNLIMITED_STRING "unlimited"
1299 
1300 /* {{{ posix_addlimit
1301  */
posix_addlimit(int limit, const char *name, zval *return_value)1302 static int posix_addlimit(int limit, const char *name, zval *return_value) {
1303 	int result;
1304 	struct rlimit rl;
1305 	char hard[80];
1306 	char soft[80];
1307 
1308 	snprintf(hard, 80, "hard %s", name);
1309 	snprintf(soft, 80, "soft %s", name);
1310 
1311 	result = getrlimit(limit, &rl);
1312 	if (result < 0) {
1313 		POSIX_G(last_error) = errno;
1314 		return FAILURE;
1315 	}
1316 
1317 	if (rl.rlim_cur == RLIM_INFINITY) {
1318 		add_assoc_stringl(return_value, soft, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1);
1319 	} else {
1320 		add_assoc_long(return_value, soft, rl.rlim_cur);
1321 	}
1322 
1323 	if (rl.rlim_max == RLIM_INFINITY) {
1324 		add_assoc_stringl(return_value, hard, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1);
1325 	} else {
1326 		add_assoc_long(return_value, hard, rl.rlim_max);
1327 	}
1328 
1329 	return SUCCESS;
1330 }
1331 /* }}} */
1332 
1333 /* {{{ limits[]
1334  */
1335 static const struct limitlist {
1336 	int limit;
1337 	const char *name;
1338 } limits[] = {
1339 #ifdef RLIMIT_CORE
1340 	{ RLIMIT_CORE,	"core" },
1341 #endif
1342 
1343 #ifdef RLIMIT_DATA
1344 	{ RLIMIT_DATA,	"data" },
1345 #endif
1346 
1347 #ifdef RLIMIT_STACK
1348 	{ RLIMIT_STACK,	"stack" },
1349 #endif
1350 
1351 #ifdef RLIMIT_VMEM
1352 	{ RLIMIT_VMEM, "virtualmem" },
1353 #endif
1354 
1355 #ifdef RLIMIT_AS
1356 	{ RLIMIT_AS, "totalmem" },
1357 #endif
1358 
1359 #ifdef RLIMIT_RSS
1360 	{ RLIMIT_RSS, "rss" },
1361 #endif
1362 
1363 #ifdef RLIMIT_NPROC
1364 	{ RLIMIT_NPROC, "maxproc" },
1365 #endif
1366 
1367 #ifdef RLIMIT_MEMLOCK
1368 	{ RLIMIT_MEMLOCK, "memlock" },
1369 #endif
1370 
1371 #ifdef RLIMIT_CPU
1372 	{ RLIMIT_CPU,	"cpu" },
1373 #endif
1374 
1375 #ifdef RLIMIT_FSIZE
1376 	{ RLIMIT_FSIZE, "filesize" },
1377 #endif
1378 
1379 #ifdef RLIMIT_NOFILE
1380 	{ RLIMIT_NOFILE, "openfiles" },
1381 #endif
1382 
1383 #ifdef RLIMIT_OFILE
1384 	{ RLIMIT_OFILE, "openfiles" },
1385 #endif
1386 
1387 	{ 0, NULL }
1388 };
1389 /* }}} */
1390 
1391 
1392 /* {{{ proto array posix_getrlimit(void)
1393    Get system resource consumption limits (This is not a POSIX function, but a BSDism and a SVR4ism. We compile conditionally) */
PHP_FUNCTIONnull1394 PHP_FUNCTION(posix_getrlimit)
1395 {
1396 	const struct limitlist *l = NULL;
1397 
1398 	PHP_POSIX_NO_ARGS;
1399 
1400 	array_init(return_value);
1401 
1402 	for (l=limits; l->name; l++) {
1403 		if (posix_addlimit(l->limit, l->name, return_value) == FAILURE) {
1404 			zend_array_destroy(Z_ARR_P(return_value));
1405 			RETURN_FALSE;
1406 		}
1407 	}
1408 }
1409 /* }}} */
1410 
1411 #endif /* HAVE_GETRLIMIT */
1412 
1413 #ifdef HAVE_SETRLIMIT
1414 /* {{{ proto bool posix_setrlimit(int resource, int softlimit, int hardlimit)
1415    Set system resource consumption limits (POSIX.1-2001) */
PHP_FUNCTIONnull1416 PHP_FUNCTION(posix_setrlimit)
1417 {
1418 	struct rlimit rl;
1419 	zend_long res, cur, max;
1420 
1421 	ZEND_PARSE_PARAMETERS_START(3, 3)
1422 		Z_PARAM_LONG(res)
1423 		Z_PARAM_LONG(cur)
1424 		Z_PARAM_LONG(max)
1425 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1426 
1427 	rl.rlim_cur = cur;
1428 	rl.rlim_max = max;
1429 
1430 	if (setrlimit(res, &rl) == -1) {
1431 		POSIX_G(last_error) = errno;
1432 		RETURN_FALSE;
1433 	}
1434 
1435 	RETURN_TRUE;
1436 }
1437 /* }}} */
1438 
1439 #endif /* HAVE_SETRLIMIT */
1440 
1441 
1442 /* {{{ proto int posix_get_last_error(void)
1443    Retrieve the error number set by the last posix function which failed. */
PHP_FUNCTIONnull1444 PHP_FUNCTION(posix_get_last_error)
1445 {
1446 	PHP_POSIX_NO_ARGS;
1447 
1448 	RETURN_LONG(POSIX_G(last_error));
1449 }
1450 /* }}} */
1451 
1452 /* {{{ proto string posix_strerror(int errno)
1453    Retrieve the system error message associated with the given errno. */
PHP_FUNCTIONnull1454 PHP_FUNCTION(posix_strerror)
1455 {
1456 	zend_long error;
1457 
1458 	ZEND_PARSE_PARAMETERS_START(1, 1)
1459 		Z_PARAM_LONG(error)
1460 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1461 
1462 	RETURN_STRING(strerror(error));
1463 }
1464 /* }}} */
1465 
1466 #endif
1467 
1468 #ifdef HAVE_INITGROUPS
1469 /* {{{ proto bool posix_initgroups(string name, int base_group_id)
1470    Calculate the group access list for the user specified in name. */
PHP_FUNCTIONnull1471 PHP_FUNCTION(posix_initgroups)
1472 {
1473 	zend_long basegid;
1474 	char *name;
1475 	size_t name_len;
1476 
1477 	ZEND_PARSE_PARAMETERS_START(2, 2)
1478 		Z_PARAM_STRING(name, name_len)
1479 		Z_PARAM_LONG(basegid)
1480 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1481 
1482 	if (name_len == 0) {
1483 		RETURN_FALSE;
1484 	}
1485 
1486 	RETURN_BOOL(!initgroups((const char *)name, basegid));
1487 }
1488 /* }}} */
1489 #endif
1490