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