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