xref: /PHP-7.4/ext/posix/posix.c (revision 454d2975)
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_FUNCTION(posix)317 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_FUNCTION(posix)325 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_FUNCTION(posix)336 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_MODULE(posix)436 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_FUNCTION(posix_getpid)479 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_FUNCTION(posix_getppid)487 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_FUNCTION(posix_getuid)495 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_FUNCTION(posix_getgid)503 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_FUNCTION(posix_geteuid)511 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_FUNCTION(posix_getegid)519 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_FUNCTION(posix_setuid)527 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_FUNCTION(posix_setgid)535 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_FUNCTION(posix_seteuid)544 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_FUNCTION(posix_setegid)554 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_FUNCTION(posix_getgroups)564 PHP_FUNCTION(posix_getgroups)
565 {
566 	gid_t *gidlist;
567 	int    result;
568 	int    i;
569 
570 	PHP_POSIX_NO_ARGS;
571 
572 	/* MacOS may return more than NGROUPS_MAX groups.
573 	 * Fetch the actual number of groups and create an appropriate allocation. */
574 	if ((result = getgroups(0, NULL)) < 0) {
575 		POSIX_G(last_error) = errno;
576 		RETURN_FALSE;
577 	}
578 
579 	gidlist = emalloc(sizeof(gid_t) * result);
580 	if ((result = getgroups(result, gidlist)) < 0) {
581 		POSIX_G(last_error) = errno;
582 		efree(gidlist);
583 		RETURN_FALSE;
584 	}
585 
586 	array_init(return_value);
587 
588 	for (i=0; i<result; i++) {
589 		add_next_index_long(return_value, gidlist[i]);
590 	}
591 	efree(gidlist);
592 }
593 #endif
594 /* }}} */
595 
596 /* {{{ proto string posix_getlogin(void)
597    Get user name (POSIX.1, 4.2.4) */
598 #ifdef HAVE_GETLOGIN
PHP_FUNCTION(posix_getlogin)599 PHP_FUNCTION(posix_getlogin)
600 {
601 	char *p;
602 
603 	PHP_POSIX_NO_ARGS;
604 
605 	if (NULL == (p = getlogin())) {
606 		POSIX_G(last_error) = errno;
607 		RETURN_FALSE;
608 	}
609 
610 	RETURN_STRING(p);
611 }
612 #endif
613 /* }}} */
614 
615 /* {{{ proto int posix_getpgrp(void)
616    Get current process group id (POSIX.1, 4.3.1) */
PHP_FUNCTION(posix_getpgrp)617 PHP_FUNCTION(posix_getpgrp)
618 {
619 	PHP_POSIX_RETURN_LONG_FUNC(getpgrp);
620 }
621 /* }}} */
622 
623 /* {{{ proto int posix_setsid(void)
624    Create session and set process group id (POSIX.1, 4.3.2) */
625 #ifdef HAVE_SETSID
PHP_FUNCTION(posix_setsid)626 PHP_FUNCTION(posix_setsid)
627 {
628 	PHP_POSIX_RETURN_LONG_FUNC(setsid);
629 }
630 #endif
631 /* }}} */
632 
633 /* {{{ proto bool posix_setpgid(int pid, int pgid)
634    Set process group id for job control (POSIX.1, 4.3.3) */
PHP_FUNCTION(posix_setpgid)635 PHP_FUNCTION(posix_setpgid)
636 {
637 	zend_long pid, pgid;
638 
639 	ZEND_PARSE_PARAMETERS_START(2, 2)
640 		Z_PARAM_LONG(pid)
641 		Z_PARAM_LONG(pgid)
642 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
643 
644 	if (setpgid(pid, pgid) < 0) {
645 		POSIX_G(last_error) = errno;
646 		RETURN_FALSE;
647 	}
648 
649 	RETURN_TRUE;
650 }
651 /* }}} */
652 
653 /* {{{ proto int posix_getpgid(void)
654    Get the process group id of the specified process (This is not a POSIX function, but a SVR4ism, so we compile conditionally) */
655 #ifdef HAVE_GETPGID
PHP_FUNCTION(posix_getpgid)656 PHP_FUNCTION(posix_getpgid)
657 {
658 	zend_long val;
659 
660 	ZEND_PARSE_PARAMETERS_START(1, 1)
661 		Z_PARAM_LONG(val)
662 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
663 
664 	if ((val = getpgid(val)) < 0) {
665 		POSIX_G(last_error) = errno;
666 		RETURN_FALSE;
667 	}
668 	RETURN_LONG(val);
669 }
670 #endif
671 /* }}} */
672 
673 /* {{{ proto int posix_getsid(void)
674    Get process group id of session leader (This is not a POSIX function, but a SVR4ism, so be compile conditionally) */
675 #ifdef HAVE_GETSID
PHP_FUNCTION(posix_getsid)676 PHP_FUNCTION(posix_getsid)
677 {
678 	zend_long val;
679 
680 	ZEND_PARSE_PARAMETERS_START(1, 1)
681 		Z_PARAM_LONG(val)
682 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
683 
684 	if ((val = getsid(val)) < 0) {
685 		POSIX_G(last_error) = errno;
686 		RETURN_FALSE;
687 	}
688 	RETURN_LONG(val);
689 }
690 #endif
691 /* }}} */
692 
693 /* {{{ proto array posix_uname(void)
694    Get system name (POSIX.1, 4.4.1) */
PHP_FUNCTION(posix_uname)695 PHP_FUNCTION(posix_uname)
696 {
697 	struct utsname u;
698 
699 	PHP_POSIX_NO_ARGS;
700 
701 	if (uname(&u) < 0) {
702 		POSIX_G(last_error) = errno;
703 		RETURN_FALSE;
704 	}
705 
706 	array_init(return_value);
707 
708 	add_assoc_string(return_value, "sysname",  u.sysname);
709 	add_assoc_string(return_value, "nodename", u.nodename);
710 	add_assoc_string(return_value, "release",  u.release);
711 	add_assoc_string(return_value, "version",  u.version);
712 	add_assoc_string(return_value, "machine",  u.machine);
713 
714 #if defined(_GNU_SOURCE) && !defined(DARWIN) && defined(HAVE_UTSNAME_DOMAINNAME)
715 	add_assoc_string(return_value, "domainname", u.domainname);
716 #endif
717 }
718 /* }}} */
719 
720 /* POSIX.1, 4.5.1 time() - Get System Time
721 							already covered by PHP
722  */
723 
724 /* {{{ proto array posix_times(void)
725    Get process times (POSIX.1, 4.5.2) */
PHP_FUNCTION(posix_times)726 PHP_FUNCTION(posix_times)
727 {
728 	struct tms t;
729 	clock_t    ticks;
730 
731 	PHP_POSIX_NO_ARGS;
732 
733 	if ((ticks = times(&t)) == -1) {
734 		POSIX_G(last_error) = errno;
735 		RETURN_FALSE;
736 	}
737 
738 	array_init(return_value);
739 
740 	add_assoc_long(return_value, "ticks",	ticks);			/* clock ticks */
741 	add_assoc_long(return_value, "utime",	t.tms_utime);	/* user time */
742 	add_assoc_long(return_value, "stime",	t.tms_stime);	/* system time */
743 	add_assoc_long(return_value, "cutime",	t.tms_cutime);	/* user time of children */
744 	add_assoc_long(return_value, "cstime",	t.tms_cstime);	/* system time of children */
745 }
746 /* }}} */
747 
748 /* POSIX.1, 4.6.1 getenv() - Environment Access
749 							already covered by PHP
750 */
751 
752 /* {{{ proto string posix_ctermid(void)
753    Generate terminal path name (POSIX.1, 4.7.1) */
754 #ifdef HAVE_CTERMID
PHP_FUNCTION(posix_ctermid)755 PHP_FUNCTION(posix_ctermid)
756 {
757 	char  buffer[L_ctermid];
758 
759 	PHP_POSIX_NO_ARGS;
760 
761 	if (NULL == ctermid(buffer)) {
762 		/* Found no documentation how the defined behaviour is when this
763 		 * function fails
764 		 */
765 		POSIX_G(last_error) = errno;
766 		RETURN_FALSE;
767 	}
768 
769 	RETURN_STRING(buffer);
770 }
771 #endif
772 /* }}} */
773 
774 /* Checks if the provides resource is a stream and if it provides a file descriptor */
php_posix_stream_get_fd(zval * zfp,int * fd)775 static int php_posix_stream_get_fd(zval *zfp, int *fd) /* {{{ */
776 {
777 	php_stream *stream;
778 
779 	php_stream_from_zval_no_verify(stream, zfp);
780 
781 	if (stream == NULL) {
782 		php_error_docref(NULL, E_WARNING, "expects argument 1 to be a valid stream resource");
783 		return 0;
784 	}
785 	if (php_stream_can_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT) == SUCCESS) {
786 		php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT, (void*)fd, 0);
787 	} else if (php_stream_can_cast(stream, PHP_STREAM_AS_FD) == SUCCESS) {
788 		php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)fd, 0);
789 	} else {
790 		php_error_docref(NULL, E_WARNING, "could not use stream of type '%s'",
791 				stream->ops->label);
792 		return 0;
793 	}
794 	return 1;
795 }
796 /* }}} */
797 
798 /* {{{ proto string posix_ttyname(int fd)
799    Determine terminal device name (POSIX.1, 4.7.2) */
PHP_FUNCTION(posix_ttyname)800 PHP_FUNCTION(posix_ttyname)
801 {
802 	zval *z_fd;
803 	char *p;
804 	int fd;
805 #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX)
806 	zend_long buflen;
807 #endif
808 
809 	ZEND_PARSE_PARAMETERS_START(1, 1)
810 		Z_PARAM_ZVAL(z_fd)
811 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
812 
813 	switch (Z_TYPE_P(z_fd)) {
814 		case IS_RESOURCE:
815 			if (!php_posix_stream_get_fd(z_fd, &fd)) {
816 				RETURN_FALSE;
817 			}
818 			break;
819 		default:
820 			fd = zval_get_long(z_fd);
821 	}
822 #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX)
823 	buflen = sysconf(_SC_TTY_NAME_MAX);
824 	if (buflen < 1) {
825 		RETURN_FALSE;
826 	}
827 	p = emalloc(buflen);
828 
829 	if (ttyname_r(fd, p, buflen)) {
830 		POSIX_G(last_error) = errno;
831 		efree(p);
832 		RETURN_FALSE;
833 	}
834 	RETURN_STRING(p);
835 	efree(p);
836 #else
837 	if (NULL == (p = ttyname(fd))) {
838 		POSIX_G(last_error) = errno;
839 		RETURN_FALSE;
840 	}
841 #endif
842 	RETURN_STRING(p);
843 }
844 /* }}} */
845 
846 /* {{{ proto bool posix_isatty(int fd)
847    Determine if filedesc is a tty (POSIX.1, 4.7.1) */
PHP_FUNCTION(posix_isatty)848 PHP_FUNCTION(posix_isatty)
849 {
850 	zval *z_fd;
851 	int fd;
852 
853 	ZEND_PARSE_PARAMETERS_START(1, 1)
854 		Z_PARAM_ZVAL(z_fd)
855 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
856 
857 	switch (Z_TYPE_P(z_fd)) {
858 		case IS_RESOURCE:
859 			if (!php_posix_stream_get_fd(z_fd, &fd)) {
860 				RETURN_FALSE;
861 			}
862 			break;
863 		default:
864 			fd = zval_get_long(z_fd);
865 	}
866 
867 	if (isatty(fd)) {
868 		RETURN_TRUE;
869 	} else {
870 		RETURN_FALSE;
871 	}
872 }
873 /* }}} */
874 
875 /*
876 	POSIX.1, 4.8.1 sysconf() - TODO
877 	POSIX.1, 5.7.1 pathconf(), fpathconf() - TODO
878 
879 	POSIX.1, 5.1.2 opendir(), readdir(), rewinddir(), closedir()
880 	POSIX.1, 5.2.1 chdir()
881 				already supported by PHP
882  */
883 
884 /* {{{ proto string posix_getcwd(void)
885    Get working directory pathname (POSIX.1, 5.2.2) */
PHP_FUNCTION(posix_getcwd)886 PHP_FUNCTION(posix_getcwd)
887 {
888 	char  buffer[MAXPATHLEN];
889 	char *p;
890 
891 	PHP_POSIX_NO_ARGS;
892 
893 	p = VCWD_GETCWD(buffer, MAXPATHLEN);
894 	if (!p) {
895 		POSIX_G(last_error) = errno;
896 		RETURN_FALSE;
897 	}
898 
899 	RETURN_STRING(buffer);
900 }
901 /* }}} */
902 
903 /*
904 	POSIX.1, 5.3.x open(), creat(), umask()
905 	POSIX.1, 5.4.1 link()
906 		already supported by PHP.
907  */
908 
909 /* {{{ proto bool posix_mkfifo(string pathname, int mode)
910    Make a FIFO special file (POSIX.1, 5.4.2) */
911 #ifdef HAVE_MKFIFO
PHP_FUNCTION(posix_mkfifo)912 PHP_FUNCTION(posix_mkfifo)
913 {
914 	zend_string *path;
915 	zend_long mode;
916 	int     result;
917 
918 	ZEND_PARSE_PARAMETERS_START(2, 2)
919 		Z_PARAM_PATH_STR(path)
920 		Z_PARAM_LONG(mode)
921 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
922 
923 	if (php_check_open_basedir_ex(ZSTR_VAL(path), 0)) {
924 		RETURN_FALSE;
925 	}
926 
927 	result = mkfifo(ZSTR_VAL(path), mode);
928 	if (result < 0) {
929 		POSIX_G(last_error) = errno;
930 		RETURN_FALSE;
931 	}
932 
933 	RETURN_TRUE;
934 }
935 #endif
936 /* }}} */
937 
938 /* {{{ proto bool posix_mknod(string pathname, int mode [, int major [, int minor]])
939    Make a special or ordinary file (POSIX.1) */
940 #ifdef HAVE_MKNOD
PHP_FUNCTION(posix_mknod)941 PHP_FUNCTION(posix_mknod)
942 {
943 	zend_string *path;
944 	zend_long mode;
945 	zend_long major = 0, minor = 0;
946 	int result;
947 	dev_t php_dev = 0;
948 
949 	ZEND_PARSE_PARAMETERS_START(2, 4)
950 		Z_PARAM_PATH_STR(path)
951 		Z_PARAM_LONG(mode)
952 		Z_PARAM_OPTIONAL
953 		Z_PARAM_LONG(major)
954 		Z_PARAM_LONG(minor)
955 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
956 
957 	if (php_check_open_basedir_ex(ZSTR_VAL(path), 0)) {
958 		RETURN_FALSE;
959 	}
960 
961 	if ((mode & S_IFCHR) || (mode & S_IFBLK)) {
962 		if (ZEND_NUM_ARGS() == 2) {
963 			php_error_docref(NULL, E_WARNING, "For S_IFCHR and S_IFBLK you need to pass a major device kernel identifier");
964 			RETURN_FALSE;
965 		}
966 		if (major == 0) {
967 			php_error_docref(NULL, E_WARNING,
968 				"Expects argument 3 to be non-zero for POSIX_S_IFCHR and POSIX_S_IFBLK");
969 			RETURN_FALSE;
970 		} else {
971 #if defined(HAVE_MAKEDEV) || defined(makedev)
972 			php_dev = makedev(major, minor);
973 #else
974 			php_error_docref(NULL, E_WARNING, "Cannot create a block or character device, creating a normal file instead");
975 #endif
976 		}
977 	}
978 
979 	result = mknod(ZSTR_VAL(path), mode, php_dev);
980 	if (result < 0) {
981 		POSIX_G(last_error) = errno;
982 		RETURN_FALSE;
983 	}
984 
985 	RETURN_TRUE;
986 }
987 #endif
988 /* }}} */
989 
990 /* Takes a pointer to posix group and a pointer to an already initialized ZVAL
991  * array container and fills the array with the posix group member data. */
php_posix_group_to_array(struct group * g,zval * array_group)992 int php_posix_group_to_array(struct group *g, zval *array_group) /* {{{ */
993 {
994 	zval array_members;
995 	int count;
996 
997 	if (NULL == g)
998 		return 0;
999 
1000 	if (array_group == NULL || Z_TYPE_P(array_group) != IS_ARRAY)
1001 		return 0;
1002 
1003 	array_init(&array_members);
1004 
1005 	add_assoc_string(array_group, "name", g->gr_name);
1006 	if (g->gr_passwd) {
1007 		add_assoc_string(array_group, "passwd", g->gr_passwd);
1008 	} else {
1009 		add_assoc_null(array_group, "passwd");
1010 	}
1011 	for (count = 0;; count++) {
1012 		/* gr_mem entries may be misaligned on macos. */
1013 		char *gr_mem;
1014 		memcpy(&gr_mem, &g->gr_mem[count], sizeof(char *));
1015 		if (!gr_mem) {
1016 			break;
1017 		}
1018 
1019 		add_next_index_string(&array_members, gr_mem);
1020 	}
1021 	zend_hash_str_update(Z_ARRVAL_P(array_group), "members", sizeof("members")-1, &array_members);
1022 	add_assoc_long(array_group, "gid", g->gr_gid);
1023 	return 1;
1024 }
1025 /* }}} */
1026 
1027 /*
1028 	POSIX.1, 5.5.1 unlink()
1029 	POSIX.1, 5.5.2 rmdir()
1030 	POSIX.1, 5.5.3 rename()
1031 	POSIX.1, 5.6.x stat(), chmod(), utime() already supported by PHP.
1032 */
1033 
1034 /* {{{ proto bool posix_access(string file [, int mode])
1035    Determine accessibility of a file (POSIX.1 5.6.3) */
PHP_FUNCTION(posix_access)1036 PHP_FUNCTION(posix_access)
1037 {
1038 	zend_long mode = 0;
1039 	size_t filename_len, ret;
1040 	char *filename, *path;
1041 
1042 	ZEND_PARSE_PARAMETERS_START(1, 2)
1043 		Z_PARAM_PATH(filename, filename_len)
1044 		Z_PARAM_OPTIONAL
1045 		Z_PARAM_LONG(mode)
1046 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1047 
1048 	path = expand_filepath(filename, NULL);
1049 	if (!path) {
1050 		POSIX_G(last_error) = EIO;
1051 		RETURN_FALSE;
1052 	}
1053 
1054 	if (php_check_open_basedir_ex(path, 0)) {
1055 		efree(path);
1056 		POSIX_G(last_error) = EPERM;
1057 		RETURN_FALSE;
1058 	}
1059 
1060 	ret = access(path, mode);
1061 	efree(path);
1062 
1063 	if (ret) {
1064 		POSIX_G(last_error) = errno;
1065 		RETURN_FALSE;
1066 	}
1067 
1068 	RETURN_TRUE;
1069 }
1070 /* }}} */
1071 
1072 /*
1073 	POSIX.1, 6.x most I/O functions already supported by PHP.
1074 	POSIX.1, 7.x tty functions, TODO
1075 	POSIX.1, 8.x interactions with other C language functions
1076 	POSIX.1, 9.x system database access
1077 */
1078 
1079 /* {{{ proto array posix_getgrnam(string groupname)
1080    Group database access (POSIX.1, 9.2.1) */
PHP_FUNCTION(posix_getgrnam)1081 PHP_FUNCTION(posix_getgrnam)
1082 {
1083 	char *name;
1084 	struct group *g;
1085 	size_t name_len;
1086 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
1087 	struct group gbuf;
1088 	long buflen;
1089 	char *buf;
1090 #endif
1091 
1092 	ZEND_PARSE_PARAMETERS_START(1, 1)
1093 		Z_PARAM_STRING(name, name_len)
1094 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1095 
1096 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
1097 	buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
1098 	if (buflen < 1) {
1099 		RETURN_FALSE;
1100 	}
1101 	buf = emalloc(buflen);
1102 try_again:
1103 	g = &gbuf;
1104 
1105 	if (getgrnam_r(name, g, buf, buflen, &g) || g == NULL) {
1106 		if (errno == ERANGE) {
1107 			buflen *= 2;
1108 			buf = erealloc(buf, buflen);
1109 			goto try_again;
1110 		}
1111 		POSIX_G(last_error) = errno;
1112 		efree(buf);
1113 		RETURN_FALSE;
1114 	}
1115 #else
1116 	if (NULL == (g = getgrnam(name))) {
1117 		POSIX_G(last_error) = errno;
1118 		RETURN_FALSE;
1119 	}
1120 #endif
1121 	array_init(return_value);
1122 
1123 	if (!php_posix_group_to_array(g, return_value)) {
1124 		zend_array_destroy(Z_ARR_P(return_value));
1125 		php_error_docref(NULL, E_WARNING, "unable to convert posix group to array");
1126 		RETVAL_FALSE;
1127 	}
1128 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
1129 	efree(buf);
1130 #endif
1131 }
1132 /* }}} */
1133 
1134 /* {{{ proto array posix_getgrgid(int gid)
1135    Group database access (POSIX.1, 9.2.1) */
PHP_FUNCTION(posix_getgrgid)1136 PHP_FUNCTION(posix_getgrgid)
1137 {
1138 	zend_long gid;
1139 #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
1140 	int ret;
1141 	struct group _g;
1142 	struct group *retgrptr = NULL;
1143 	long grbuflen;
1144 	char *grbuf;
1145 #endif
1146 	struct group *g;
1147 
1148 	ZEND_PARSE_PARAMETERS_START(1, 1)
1149 		Z_PARAM_LONG(gid)
1150 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1151 
1152 #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
1153 
1154 	grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
1155 	if (grbuflen < 1) {
1156 		RETURN_FALSE;
1157 	}
1158 
1159 	grbuf = emalloc(grbuflen);
1160 
1161 try_again:
1162 	ret = getgrgid_r(gid, &_g, grbuf, grbuflen, &retgrptr);
1163 	if (ret || retgrptr == NULL) {
1164 		if (errno == ERANGE) {
1165 			grbuflen *= 2;
1166 			grbuf = erealloc(grbuf, grbuflen);
1167 			goto try_again;
1168 		}
1169 		POSIX_G(last_error) = ret;
1170 		efree(grbuf);
1171 		RETURN_FALSE;
1172 	}
1173 	g = &_g;
1174 #else
1175 	if (NULL == (g = getgrgid(gid))) {
1176 		POSIX_G(last_error) = errno;
1177 		RETURN_FALSE;
1178 	}
1179 #endif
1180 	array_init(return_value);
1181 
1182 	if (!php_posix_group_to_array(g, return_value)) {
1183 		zend_array_destroy(Z_ARR_P(return_value));
1184 		php_error_docref(NULL, E_WARNING, "unable to convert posix group struct to array");
1185 		RETVAL_FALSE;
1186 	}
1187 #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
1188 	efree(grbuf);
1189 #endif
1190 }
1191 /* }}} */
1192 
php_posix_passwd_to_array(struct passwd * pw,zval * return_value)1193 int php_posix_passwd_to_array(struct passwd *pw, zval *return_value) /* {{{ */
1194 {
1195 	if (NULL == pw)
1196 		return 0;
1197 	if (NULL == return_value || Z_TYPE_P(return_value) != IS_ARRAY)
1198 		return 0;
1199 
1200 	add_assoc_string(return_value, "name",      pw->pw_name);
1201 	add_assoc_string(return_value, "passwd",    pw->pw_passwd);
1202 	add_assoc_long  (return_value, "uid",       pw->pw_uid);
1203 	add_assoc_long  (return_value, "gid",		pw->pw_gid);
1204 	add_assoc_string(return_value, "gecos",     pw->pw_gecos);
1205 	add_assoc_string(return_value, "dir",       pw->pw_dir);
1206 	add_assoc_string(return_value, "shell",     pw->pw_shell);
1207 	return 1;
1208 }
1209 /* }}} */
1210 
1211 /* {{{ proto array posix_getpwnam(string groupname)
1212    User database access (POSIX.1, 9.2.2) */
PHP_FUNCTION(posix_getpwnam)1213 PHP_FUNCTION(posix_getpwnam)
1214 {
1215 	struct passwd *pw;
1216 	char *name;
1217 	size_t name_len;
1218 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
1219 	struct passwd pwbuf;
1220 	long buflen;
1221 	char *buf;
1222 #endif
1223 
1224 	ZEND_PARSE_PARAMETERS_START(1, 1)
1225 		Z_PARAM_STRING(name, name_len)
1226 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1227 
1228 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
1229 	buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1230 	if (buflen < 1) {
1231 		RETURN_FALSE;
1232 	}
1233 	buf = emalloc(buflen);
1234 	pw = &pwbuf;
1235 
1236 try_again:
1237 	if (getpwnam_r(name, pw, buf, buflen, &pw) || pw == NULL) {
1238 		if (errno == ERANGE) {
1239 			buflen *= 2;
1240 			buf = erealloc(buf, buflen);
1241 			goto try_again;
1242 		}
1243 		efree(buf);
1244 		POSIX_G(last_error) = errno;
1245 		RETURN_FALSE;
1246 	}
1247 #else
1248 	if (NULL == (pw = getpwnam(name))) {
1249 		POSIX_G(last_error) = errno;
1250 		RETURN_FALSE;
1251 	}
1252 #endif
1253 	array_init(return_value);
1254 
1255 	if (!php_posix_passwd_to_array(pw, return_value)) {
1256 		zend_array_destroy(Z_ARR_P(return_value));
1257 		php_error_docref(NULL, E_WARNING, "unable to convert posix passwd struct to array");
1258 		RETVAL_FALSE;
1259 	}
1260 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
1261 	efree(buf);
1262 #endif
1263 }
1264 /* }}} */
1265 
1266 /* {{{ proto array posix_getpwuid(int uid)
1267    User database access (POSIX.1, 9.2.2) */
PHP_FUNCTION(posix_getpwuid)1268 PHP_FUNCTION(posix_getpwuid)
1269 {
1270 	zend_long uid;
1271 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1272 	struct passwd _pw;
1273 	struct passwd *retpwptr = NULL;
1274 	long pwbuflen;
1275 	char *pwbuf;
1276 	int ret;
1277 #endif
1278 	struct passwd *pw;
1279 
1280 	ZEND_PARSE_PARAMETERS_START(1, 1)
1281 		Z_PARAM_LONG(uid)
1282 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1283 
1284 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1285 	pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1286 	if (pwbuflen < 1) {
1287 		RETURN_FALSE;
1288 	}
1289 	pwbuf = emalloc(pwbuflen);
1290 
1291 try_again:
1292 	ret = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr);
1293 	if (ret || retpwptr == NULL) {
1294 		if (errno == ERANGE) {
1295 			pwbuflen *= 2;
1296 			pwbuf = erealloc(pwbuf, pwbuflen);
1297 			goto try_again;
1298 		}
1299 		POSIX_G(last_error) = ret;
1300 		efree(pwbuf);
1301 		RETURN_FALSE;
1302 	}
1303 	pw = &_pw;
1304 #else
1305 	if (NULL == (pw = getpwuid(uid))) {
1306 		POSIX_G(last_error) = errno;
1307 		RETURN_FALSE;
1308 	}
1309 #endif
1310 	array_init(return_value);
1311 
1312 	if (!php_posix_passwd_to_array(pw, return_value)) {
1313 		zend_array_destroy(Z_ARR_P(return_value));
1314 		php_error_docref(NULL, E_WARNING, "unable to convert posix passwd struct to array");
1315 		RETVAL_FALSE;
1316 	}
1317 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1318 	efree(pwbuf);
1319 #endif
1320 }
1321 /* }}} */
1322 
1323 
1324 #ifdef HAVE_GETRLIMIT
1325 
1326 #define UNLIMITED_STRING "unlimited"
1327 
1328 /* {{{ posix_addlimit
1329  */
posix_addlimit(int limit,const char * name,zval * return_value)1330 static int posix_addlimit(int limit, const char *name, zval *return_value) {
1331 	int result;
1332 	struct rlimit rl;
1333 	char hard[80];
1334 	char soft[80];
1335 
1336 	snprintf(hard, 80, "hard %s", name);
1337 	snprintf(soft, 80, "soft %s", name);
1338 
1339 	result = getrlimit(limit, &rl);
1340 	if (result < 0) {
1341 		POSIX_G(last_error) = errno;
1342 		return FAILURE;
1343 	}
1344 
1345 	if (rl.rlim_cur == RLIM_INFINITY) {
1346 		add_assoc_stringl(return_value, soft, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1);
1347 	} else {
1348 		add_assoc_long(return_value, soft, rl.rlim_cur);
1349 	}
1350 
1351 	if (rl.rlim_max == RLIM_INFINITY) {
1352 		add_assoc_stringl(return_value, hard, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1);
1353 	} else {
1354 		add_assoc_long(return_value, hard, rl.rlim_max);
1355 	}
1356 
1357 	return SUCCESS;
1358 }
1359 /* }}} */
1360 
1361 /* {{{ limits[]
1362  */
1363 static const struct limitlist {
1364 	int limit;
1365 	const char *name;
1366 } limits[] = {
1367 #ifdef RLIMIT_CORE
1368 	{ RLIMIT_CORE,	"core" },
1369 #endif
1370 
1371 #ifdef RLIMIT_DATA
1372 	{ RLIMIT_DATA,	"data" },
1373 #endif
1374 
1375 #ifdef RLIMIT_STACK
1376 	{ RLIMIT_STACK,	"stack" },
1377 #endif
1378 
1379 #ifdef RLIMIT_VMEM
1380 	{ RLIMIT_VMEM, "virtualmem" },
1381 #endif
1382 
1383 #ifdef RLIMIT_AS
1384 	{ RLIMIT_AS, "totalmem" },
1385 #endif
1386 
1387 #ifdef RLIMIT_RSS
1388 	{ RLIMIT_RSS, "rss" },
1389 #endif
1390 
1391 #ifdef RLIMIT_NPROC
1392 	{ RLIMIT_NPROC, "maxproc" },
1393 #endif
1394 
1395 #ifdef RLIMIT_MEMLOCK
1396 	{ RLIMIT_MEMLOCK, "memlock" },
1397 #endif
1398 
1399 #ifdef RLIMIT_CPU
1400 	{ RLIMIT_CPU,	"cpu" },
1401 #endif
1402 
1403 #ifdef RLIMIT_FSIZE
1404 	{ RLIMIT_FSIZE, "filesize" },
1405 #endif
1406 
1407 #ifdef RLIMIT_NOFILE
1408 	{ RLIMIT_NOFILE, "openfiles" },
1409 #endif
1410 
1411 #ifdef RLIMIT_OFILE
1412 	{ RLIMIT_OFILE, "openfiles" },
1413 #endif
1414 
1415 	{ 0, NULL }
1416 };
1417 /* }}} */
1418 
1419 
1420 /* {{{ proto array posix_getrlimit(void)
1421    Get system resource consumption limits (This is not a POSIX function, but a BSDism and a SVR4ism. We compile conditionally) */
PHP_FUNCTION(posix_getrlimit)1422 PHP_FUNCTION(posix_getrlimit)
1423 {
1424 	const struct limitlist *l = NULL;
1425 
1426 	PHP_POSIX_NO_ARGS;
1427 
1428 	array_init(return_value);
1429 
1430 	for (l=limits; l->name; l++) {
1431 		if (posix_addlimit(l->limit, l->name, return_value) == FAILURE) {
1432 			zend_array_destroy(Z_ARR_P(return_value));
1433 			RETURN_FALSE;
1434 		}
1435 	}
1436 }
1437 /* }}} */
1438 
1439 #endif /* HAVE_GETRLIMIT */
1440 
1441 #ifdef HAVE_SETRLIMIT
1442 /* {{{ proto bool posix_setrlimit(int resource, int softlimit, int hardlimit)
1443    Set system resource consumption limits (POSIX.1-2001) */
PHP_FUNCTION(posix_setrlimit)1444 PHP_FUNCTION(posix_setrlimit)
1445 {
1446 	struct rlimit rl;
1447 	zend_long res, cur, max;
1448 
1449 	ZEND_PARSE_PARAMETERS_START(3, 3)
1450 		Z_PARAM_LONG(res)
1451 		Z_PARAM_LONG(cur)
1452 		Z_PARAM_LONG(max)
1453 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1454 
1455 	rl.rlim_cur = cur;
1456 	rl.rlim_max = max;
1457 
1458 	if (setrlimit(res, &rl) == -1) {
1459 		POSIX_G(last_error) = errno;
1460 		RETURN_FALSE;
1461 	}
1462 
1463 	RETURN_TRUE;
1464 }
1465 /* }}} */
1466 
1467 #endif /* HAVE_SETRLIMIT */
1468 
1469 
1470 /* {{{ proto int posix_get_last_error(void)
1471    Retrieve the error number set by the last posix function which failed. */
PHP_FUNCTION(posix_get_last_error)1472 PHP_FUNCTION(posix_get_last_error)
1473 {
1474 	PHP_POSIX_NO_ARGS;
1475 
1476 	RETURN_LONG(POSIX_G(last_error));
1477 }
1478 /* }}} */
1479 
1480 /* {{{ proto string posix_strerror(int errno)
1481    Retrieve the system error message associated with the given errno. */
PHP_FUNCTION(posix_strerror)1482 PHP_FUNCTION(posix_strerror)
1483 {
1484 	zend_long error;
1485 
1486 	ZEND_PARSE_PARAMETERS_START(1, 1)
1487 		Z_PARAM_LONG(error)
1488 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1489 
1490 	RETURN_STRING(strerror(error));
1491 }
1492 /* }}} */
1493 
1494 #endif
1495 
1496 #ifdef HAVE_INITGROUPS
1497 /* {{{ proto bool posix_initgroups(string name, int base_group_id)
1498    Calculate the group access list for the user specified in name. */
PHP_FUNCTION(posix_initgroups)1499 PHP_FUNCTION(posix_initgroups)
1500 {
1501 	zend_long basegid;
1502 	char *name;
1503 	size_t name_len;
1504 
1505 	ZEND_PARSE_PARAMETERS_START(2, 2)
1506 		Z_PARAM_STRING(name, name_len)
1507 		Z_PARAM_LONG(basegid)
1508 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
1509 
1510 	if (name_len == 0) {
1511 		RETURN_FALSE;
1512 	}
1513 
1514 	RETURN_BOOL(!initgroups((const char *)name, basegid));
1515 }
1516 /* }}} */
1517 #endif
1518