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