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