xref: /PHP-5.5/ext/posix/posix.c (revision 73c1be26)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2015 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: 5d20de77687b7d961b15450873fa23b9e64a136a $ */
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: 5d20de77687b7d961b15450873fa23b9e64a136a $");
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, "pl", &path, &path_len, &mode) == FAILURE) {
842 		RETURN_FALSE;
843 	}
844 
845 	if (php_check_open_basedir_ex(path, 0 TSRMLS_CC)) {
846 		RETURN_FALSE;
847 	}
848 
849 	result = mkfifo(path, mode);
850 	if (result < 0) {
851 		POSIX_G(last_error) = errno;
852 		RETURN_FALSE;
853 	}
854 
855 	RETURN_TRUE;
856 }
857 #endif
858 /* }}} */
859 
860 /* {{{ proto bool posix_mknod(string pathname, int mode [, int major [, int minor]])
861    Make a special or ordinary file (POSIX.1) */
862 #ifdef HAVE_MKNOD
PHP_FUNCTION(posix_mknod)863 PHP_FUNCTION(posix_mknod)
864 {
865 	char *path;
866 	int path_len;
867 	long mode;
868 	long major = 0, minor = 0;
869 	int result;
870 	dev_t php_dev;
871 
872 	php_dev = 0;
873 
874 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pl|ll", &path, &path_len,
875 			&mode, &major, &minor) == FAILURE) {
876 		RETURN_FALSE;
877 	}
878 
879 	if (php_check_open_basedir_ex(path, 0 TSRMLS_CC)) {
880 		RETURN_FALSE;
881 	}
882 
883 	if ((mode & S_IFCHR) || (mode & S_IFBLK)) {
884 		if (ZEND_NUM_ARGS() == 2) {
885 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "For S_IFCHR and S_IFBLK you need to pass a major device kernel identifier");
886 			RETURN_FALSE;
887 		}
888 		if (major == 0) {
889 			php_error_docref(NULL TSRMLS_CC, E_WARNING,
890 				"Expects argument 3 to be non-zero for POSIX_S_IFCHR and POSIX_S_IFBLK");
891 			RETURN_FALSE;
892 		} else {
893 #if defined(HAVE_MAKEDEV) || defined(makedev)
894 			php_dev = makedev(major, minor);
895 #else
896 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create a block or character device, creating a normal file instead");
897 #endif
898 		}
899 	}
900 
901 	result = mknod(path, mode, php_dev);
902 	if (result < 0) {
903 		POSIX_G(last_error) = errno;
904 		RETURN_FALSE;
905 	}
906 
907 	RETURN_TRUE;
908 }
909 #endif
910 /* }}} */
911 
912 /* Takes a pointer to posix group and a pointer to an already initialized ZVAL
913  * array container and fills the array with the posix group member data. */
php_posix_group_to_array(struct group * g,zval * array_group)914 int php_posix_group_to_array(struct group *g, zval *array_group) /* {{{ */
915 {
916 	zval *array_members;
917 	int count;
918 
919 	if (NULL == g)
920 		return 0;
921 
922 	if (array_group == NULL || Z_TYPE_P(array_group) != IS_ARRAY)
923 		return 0;
924 
925 	MAKE_STD_ZVAL(array_members);
926 	array_init(array_members);
927 
928 	add_assoc_string(array_group, "name", g->gr_name, 1);
929 	add_assoc_string(array_group, "passwd", g->gr_passwd, 1);
930 	for (count=0; g->gr_mem[count] != NULL; count++) {
931 		add_next_index_string(array_members, g->gr_mem[count], 1);
932 	}
933 	zend_hash_update(Z_ARRVAL_P(array_group), "members", sizeof("members"), (void*)&array_members, sizeof(zval*), NULL);
934 	add_assoc_long(array_group, "gid", g->gr_gid);
935 	return 1;
936 }
937 /* }}} */
938 
939 /*
940 	POSIX.1, 5.5.1 unlink()
941 	POSIX.1, 5.5.2 rmdir()
942 	POSIX.1, 5.5.3 rename()
943 	POSIX.1, 5.6.x stat(), chmod(), utime() already supported by PHP.
944 */
945 
946 /* {{{ proto bool posix_access(string file [, int mode])
947    Determine accessibility of a file (POSIX.1 5.6.3) */
PHP_FUNCTION(posix_access)948 PHP_FUNCTION(posix_access)
949 {
950 	long mode = 0;
951 	int filename_len, ret;
952 	char *filename, *path;
953 
954 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &mode) == FAILURE) {
955 		RETURN_FALSE;
956 	}
957 
958 	path = expand_filepath(filename, NULL TSRMLS_CC);
959 	if (!path) {
960 		POSIX_G(last_error) = EIO;
961 		RETURN_FALSE;
962 	}
963 
964 	if (php_check_open_basedir_ex(path, 0 TSRMLS_CC)) {
965 		efree(path);
966 		POSIX_G(last_error) = EPERM;
967 		RETURN_FALSE;
968 	}
969 
970 	ret = access(path, mode);
971 	efree(path);
972 
973 	if (ret) {
974 		POSIX_G(last_error) = errno;
975 		RETURN_FALSE;
976 	}
977 
978 	RETURN_TRUE;
979 }
980 /* }}} */
981 
982 /*
983 	POSIX.1, 6.x most I/O functions already supported by PHP.
984 	POSIX.1, 7.x tty functions, TODO
985 	POSIX.1, 8.x interactions with other C language functions
986 	POSIX.1, 9.x system database access
987 */
988 
989 /* {{{ proto array posix_getgrnam(string groupname)
990    Group database access (POSIX.1, 9.2.1) */
PHP_FUNCTION(posix_getgrnam)991 PHP_FUNCTION(posix_getgrnam)
992 {
993 	char *name;
994 	struct group *g;
995 	int name_len;
996 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
997 	struct group gbuf;
998 	long buflen;
999 	char *buf;
1000 #endif
1001 
1002 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
1003 		RETURN_FALSE;
1004 	}
1005 
1006 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
1007 	buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
1008 	if (buflen < 1) {
1009 		RETURN_FALSE;
1010 	}
1011 	buf = emalloc(buflen);
1012 	g = &gbuf;
1013 
1014 	if (getgrnam_r(name, g, buf, buflen, &g) || g == NULL) {
1015 		POSIX_G(last_error) = errno;
1016 		efree(buf);
1017 		RETURN_FALSE;
1018 	}
1019 #else
1020 	if (NULL == (g = getgrnam(name))) {
1021 		POSIX_G(last_error) = errno;
1022 		RETURN_FALSE;
1023 	}
1024 #endif
1025 	array_init(return_value);
1026 
1027 	if (!php_posix_group_to_array(g, return_value)) {
1028 		zval_dtor(return_value);
1029 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix group to array");
1030 		RETVAL_FALSE;
1031 	}
1032 #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
1033 	efree(buf);
1034 #endif
1035 }
1036 /* }}} */
1037 
1038 /* {{{ proto array posix_getgrgid(long gid)
1039    Group database access (POSIX.1, 9.2.1) */
PHP_FUNCTION(posix_getgrgid)1040 PHP_FUNCTION(posix_getgrgid)
1041 {
1042 	long gid;
1043 #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
1044 	int ret;
1045 	struct group _g;
1046 	struct group *retgrptr = NULL;
1047 	long grbuflen;
1048 	char *grbuf;
1049 #endif
1050 	struct group *g;
1051 
1052 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &gid) == FAILURE) {
1053 		RETURN_FALSE;
1054 	}
1055 #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
1056 
1057 	grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
1058 	if (grbuflen < 1) {
1059 		RETURN_FALSE;
1060 	}
1061 
1062 	grbuf = emalloc(grbuflen);
1063 
1064 	ret = getgrgid_r(gid, &_g, grbuf, grbuflen, &retgrptr);
1065 	if (ret || retgrptr == NULL) {
1066 		POSIX_G(last_error) = ret;
1067 		efree(grbuf);
1068 		RETURN_FALSE;
1069 	}
1070 	g = &_g;
1071 #else
1072 	if (NULL == (g = getgrgid(gid))) {
1073 		POSIX_G(last_error) = errno;
1074 		RETURN_FALSE;
1075 	}
1076 #endif
1077 	array_init(return_value);
1078 
1079 	if (!php_posix_group_to_array(g, return_value)) {
1080 		zval_dtor(return_value);
1081 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix group struct to array");
1082 		RETVAL_FALSE;
1083 	}
1084 #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
1085 	efree(grbuf);
1086 #endif
1087 }
1088 /* }}} */
1089 
php_posix_passwd_to_array(struct passwd * pw,zval * return_value)1090 int php_posix_passwd_to_array(struct passwd *pw, zval *return_value) /* {{{ */
1091 {
1092 	if (NULL == pw)
1093 		return 0;
1094 	if (NULL == return_value || Z_TYPE_P(return_value) != IS_ARRAY)
1095 		return 0;
1096 
1097 	add_assoc_string(return_value, "name",      pw->pw_name, 1);
1098 	add_assoc_string(return_value, "passwd",    pw->pw_passwd, 1);
1099 	add_assoc_long  (return_value, "uid",       pw->pw_uid);
1100 	add_assoc_long  (return_value, "gid",		pw->pw_gid);
1101 	add_assoc_string(return_value, "gecos",     pw->pw_gecos, 1);
1102 	add_assoc_string(return_value, "dir",       pw->pw_dir, 1);
1103 	add_assoc_string(return_value, "shell",     pw->pw_shell, 1);
1104 	return 1;
1105 }
1106 /* }}} */
1107 
1108 /* {{{ proto array posix_getpwnam(string groupname)
1109    User database access (POSIX.1, 9.2.2) */
PHP_FUNCTION(posix_getpwnam)1110 PHP_FUNCTION(posix_getpwnam)
1111 {
1112 	struct passwd *pw;
1113 	char *name;
1114 	int name_len;
1115 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
1116 	struct passwd pwbuf;
1117 	long buflen;
1118 	char *buf;
1119 #endif
1120 
1121 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
1122 		RETURN_FALSE;
1123 	}
1124 
1125 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
1126 	buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1127 	if (buflen < 1) {
1128 		RETURN_FALSE;
1129 	}
1130 	buf = emalloc(buflen);
1131 	pw = &pwbuf;
1132 
1133 	if (getpwnam_r(name, pw, buf, buflen, &pw) || pw == NULL) {
1134 		efree(buf);
1135 		POSIX_G(last_error) = errno;
1136 		RETURN_FALSE;
1137 	}
1138 #else
1139 	if (NULL == (pw = getpwnam(name))) {
1140 		POSIX_G(last_error) = errno;
1141 		RETURN_FALSE;
1142 	}
1143 #endif
1144 	array_init(return_value);
1145 
1146 	if (!php_posix_passwd_to_array(pw, return_value)) {
1147 		zval_dtor(return_value);
1148 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix passwd struct to array");
1149 		RETVAL_FALSE;
1150 	}
1151 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
1152 	efree(buf);
1153 #endif
1154 }
1155 /* }}} */
1156 
1157 /* {{{ proto array posix_getpwuid(long uid)
1158    User database access (POSIX.1, 9.2.2) */
PHP_FUNCTION(posix_getpwuid)1159 PHP_FUNCTION(posix_getpwuid)
1160 {
1161 	long uid;
1162 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1163 	struct passwd _pw;
1164 	struct passwd *retpwptr = NULL;
1165 	long pwbuflen;
1166 	char *pwbuf;
1167 	int ret;
1168 #endif
1169 	struct passwd *pw;
1170 
1171 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &uid) == FAILURE) {
1172 		RETURN_FALSE;
1173 	}
1174 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1175 	pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1176 	if (pwbuflen < 1) {
1177 		RETURN_FALSE;
1178 	}
1179 	pwbuf = emalloc(pwbuflen);
1180 
1181 	ret = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr);
1182 	if (ret || retpwptr == NULL) {
1183 		POSIX_G(last_error) = ret;
1184 		efree(pwbuf);
1185 		RETURN_FALSE;
1186 	}
1187 	pw = &_pw;
1188 #else
1189 	if (NULL == (pw = getpwuid(uid))) {
1190 		POSIX_G(last_error) = errno;
1191 		RETURN_FALSE;
1192 	}
1193 #endif
1194 	array_init(return_value);
1195 
1196 	if (!php_posix_passwd_to_array(pw, return_value)) {
1197 		zval_dtor(return_value);
1198 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix passwd struct to array");
1199 		RETVAL_FALSE;
1200 	}
1201 #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1202 	efree(pwbuf);
1203 #endif
1204 }
1205 /* }}} */
1206 
1207 
1208 #ifdef HAVE_GETRLIMIT
1209 
1210 #define UNLIMITED_STRING "unlimited"
1211 
1212 /* {{{ posix_addlimit
1213  */
posix_addlimit(int limit,char * name,zval * return_value TSRMLS_DC)1214 static int posix_addlimit(int limit, char *name, zval *return_value TSRMLS_DC) {
1215 	int result;
1216 	struct rlimit rl;
1217 	char hard[80];
1218 	char soft[80];
1219 
1220 	snprintf(hard, 80, "hard %s", name);
1221 	snprintf(soft, 80, "soft %s", name);
1222 
1223 	result = getrlimit(limit, &rl);
1224 	if (result < 0) {
1225 		POSIX_G(last_error) = errno;
1226 		return FAILURE;
1227 	}
1228 
1229 	if (rl.rlim_cur == RLIM_INFINITY) {
1230 		add_assoc_stringl(return_value, soft, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1, 1);
1231 	} else {
1232 		add_assoc_long(return_value, soft, rl.rlim_cur);
1233 	}
1234 
1235 	if (rl.rlim_max == RLIM_INFINITY) {
1236 		add_assoc_stringl(return_value, hard, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1, 1);
1237 	} else {
1238 		add_assoc_long(return_value, hard, rl.rlim_max);
1239 	}
1240 
1241 	return SUCCESS;
1242 }
1243 /* }}} */
1244 
1245 /* {{{ limits[]
1246  */
1247 struct limitlist {
1248 	int limit;
1249 	char *name;
1250 } limits[] = {
1251 #ifdef RLIMIT_CORE
1252 	{ RLIMIT_CORE,	"core" },
1253 #endif
1254 
1255 #ifdef RLIMIT_DATA
1256 	{ RLIMIT_DATA,	"data" },
1257 #endif
1258 
1259 #ifdef RLIMIT_STACK
1260 	{ RLIMIT_STACK,	"stack" },
1261 #endif
1262 
1263 #ifdef RLIMIT_VMEM
1264 	{ RLIMIT_VMEM, "virtualmem" },
1265 #endif
1266 
1267 #ifdef RLIMIT_AS
1268 	{ RLIMIT_AS, "totalmem" },
1269 #endif
1270 
1271 #ifdef RLIMIT_RSS
1272 	{ RLIMIT_RSS, "rss" },
1273 #endif
1274 
1275 #ifdef RLIMIT_NPROC
1276 	{ RLIMIT_NPROC, "maxproc" },
1277 #endif
1278 
1279 #ifdef RLIMIT_MEMLOCK
1280 	{ RLIMIT_MEMLOCK, "memlock" },
1281 #endif
1282 
1283 #ifdef RLIMIT_CPU
1284 	{ RLIMIT_CPU,	"cpu" },
1285 #endif
1286 
1287 #ifdef RLIMIT_FSIZE
1288 	{ RLIMIT_FSIZE, "filesize" },
1289 #endif
1290 
1291 #ifdef RLIMIT_NOFILE
1292 	{ RLIMIT_NOFILE, "openfiles" },
1293 #endif
1294 
1295 #ifdef RLIMIT_OFILE
1296 	{ RLIMIT_OFILE, "openfiles" },
1297 #endif
1298 
1299 	{ 0, NULL }
1300 };
1301 /* }}} */
1302 
1303 
1304 /* {{{ proto array posix_getrlimit(void)
1305    Get system resource consumption limits (This is not a POSIX function, but a BSDism and a SVR4ism. We compile conditionally) */
PHP_FUNCTION(posix_getrlimit)1306 PHP_FUNCTION(posix_getrlimit)
1307 {
1308 	struct limitlist *l = NULL;
1309 
1310 	PHP_POSIX_NO_ARGS;
1311 
1312 	array_init(return_value);
1313 
1314 	for (l=limits; l->name; l++) {
1315 		if (posix_addlimit(l->limit, l->name, return_value TSRMLS_CC) == FAILURE) {
1316 			zval_dtor(return_value);
1317 			RETURN_FALSE;
1318 		}
1319 	}
1320 }
1321 /* }}} */
1322 
1323 #endif /* HAVE_GETRLIMIT */
1324 
1325 /* {{{ proto int posix_get_last_error(void)
1326    Retrieve the error number set by the last posix function which failed. */
PHP_FUNCTION(posix_get_last_error)1327 PHP_FUNCTION(posix_get_last_error)
1328 {
1329 	PHP_POSIX_NO_ARGS;
1330 
1331 	RETURN_LONG(POSIX_G(last_error));
1332 }
1333 /* }}} */
1334 
1335 /* {{{ proto string posix_strerror(int errno)
1336    Retrieve the system error message associated with the given errno. */
PHP_FUNCTION(posix_strerror)1337 PHP_FUNCTION(posix_strerror)
1338 {
1339 	long error;
1340 
1341 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &error) == FAILURE) {
1342 		RETURN_FALSE;
1343 	}
1344 
1345 	RETURN_STRING(strerror(error), 1);
1346 }
1347 /* }}} */
1348 
1349 #endif
1350 
1351 #ifdef HAVE_INITGROUPS
1352 /* {{{ proto bool posix_initgroups(string name, int base_group_id)
1353    Calculate the group access list for the user specified in name. */
PHP_FUNCTION(posix_initgroups)1354 PHP_FUNCTION(posix_initgroups)
1355 {
1356 	long basegid;
1357 	char *name;
1358 	int name_len;
1359 
1360 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name, &name_len, &basegid) == FAILURE) {
1361 		RETURN_FALSE;
1362 	}
1363 
1364 	if (name_len == 0) {
1365 		RETURN_FALSE;
1366 	}
1367 
1368 	RETURN_BOOL(!initgroups((const char *)name, basegid));
1369 }
1370 /* }}} */
1371 #endif
1372 
1373 /*
1374  * Local variables:
1375  * tab-width: 4
1376  * c-basic-offset: 4
1377  * End:
1378  * vim600: sw=4 ts=4 fdm=marker
1379  * vim<600: sw=4 ts=4
1380  */
1381