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