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