1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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: posix.c 288943 2009-09-29 14:02:50Z rasmus $ */
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 : /* {{{ posix_functions[]
60 : */
61 : zend_function_entry posix_functions[] = {
62 : /* POSIX.1, 3.3 */
63 : PHP_FE(posix_kill, NULL)
64 :
65 : /* POSIX.1, 4.1 */
66 : PHP_FE(posix_getpid, NULL)
67 : PHP_FE(posix_getppid, NULL)
68 :
69 : /* POSIX.1, 4.2 */
70 : PHP_FE(posix_getuid, NULL)
71 : PHP_FE(posix_setuid, NULL)
72 : PHP_FE(posix_geteuid, NULL)
73 : #ifdef HAVE_SETEUID
74 : PHP_FE(posix_seteuid, NULL)
75 : #endif
76 : PHP_FE(posix_getgid, NULL)
77 : PHP_FE(posix_setgid, NULL)
78 : PHP_FE(posix_getegid, NULL)
79 : #ifdef HAVE_SETEGID
80 : PHP_FE(posix_setegid, NULL)
81 : #endif
82 : #ifdef HAVE_GETGROUPS
83 : PHP_FE(posix_getgroups, NULL)
84 : #endif
85 : #ifdef HAVE_GETLOGIN
86 : PHP_FE(posix_getlogin, NULL)
87 : #endif
88 :
89 : /* POSIX.1, 4.3 */
90 : PHP_FE(posix_getpgrp, NULL)
91 : #ifdef HAVE_SETSID
92 : PHP_FE(posix_setsid, NULL)
93 : #endif
94 : PHP_FE(posix_setpgid, NULL)
95 : /* Non-Posix functions which are common */
96 : #ifdef HAVE_GETPGID
97 : PHP_FE(posix_getpgid, NULL)
98 : #endif /* HAVE_GETPGID */
99 : #ifdef HAVE_GETSID
100 : PHP_FE(posix_getsid, NULL)
101 : #endif /* HAVE_GETSID */
102 :
103 : /* POSIX.1, 4.4 */
104 : PHP_FE(posix_uname, NULL)
105 :
106 : /* POSIX.1, 4.5 */
107 : PHP_FE(posix_times, NULL)
108 :
109 : /* POSIX.1, 4.7 */
110 : #ifdef HAVE_CTERMID
111 : PHP_FE(posix_ctermid, NULL)
112 : #endif
113 : PHP_FE(posix_ttyname, NULL)
114 : PHP_FE(posix_isatty, NULL)
115 :
116 : /* POSIX.1, 5.2 */
117 : PHP_FE(posix_getcwd, NULL)
118 :
119 : /* POSIX.1, 5.4 */
120 : #ifdef HAVE_MKFIFO
121 : PHP_FE(posix_mkfifo, NULL)
122 : #endif
123 : #ifdef HAVE_MKNOD
124 : PHP_FE(posix_mknod, NULL)
125 : #endif
126 :
127 : /* POSIX.1, 5.6 */
128 : PHP_FE(posix_access, NULL)
129 : /* POSIX.1, 9.2 */
130 : PHP_FE(posix_getgrnam, NULL)
131 : PHP_FE(posix_getgrgid, NULL)
132 : PHP_FE(posix_getpwnam, NULL)
133 : PHP_FE(posix_getpwuid, NULL)
134 :
135 : #ifdef HAVE_GETRLIMIT
136 : PHP_FE(posix_getrlimit, NULL)
137 : #endif
138 :
139 : PHP_FE(posix_get_last_error, NULL)
140 : PHP_FALIAS(posix_errno, posix_get_last_error, NULL)
141 : PHP_FE(posix_strerror, NULL)
142 : #ifdef HAVE_INITGROUPS
143 : PHP_FE(posix_initgroups, NULL)
144 : #endif
145 :
146 : {NULL, NULL, NULL}
147 : };
148 : /* }}} */
149 :
150 : /* {{{ PHP_MINFO_FUNCTION
151 : */
152 : static PHP_MINFO_FUNCTION(posix)
153 6 : {
154 6 : php_info_print_table_start();
155 6 : php_info_print_table_row(2, "Revision", "$Revision: 288943 $");
156 6 : php_info_print_table_end();
157 6 : }
158 : /* }}} */
159 :
160 : static PHP_GINIT_FUNCTION(posix)
161 13565 : {
162 13565 : posix_globals->last_error = 0;
163 13565 : }
164 :
165 : /* {{{ PHP_MINIT_FUNCTION(posix)
166 : */
167 : static PHP_MINIT_FUNCTION(posix)
168 13565 : {
169 13565 : REGISTER_LONG_CONSTANT("POSIX_F_OK", F_OK, CONST_CS | CONST_PERSISTENT);
170 13565 : REGISTER_LONG_CONSTANT("POSIX_X_OK", X_OK, CONST_CS | CONST_PERSISTENT);
171 13565 : REGISTER_LONG_CONSTANT("POSIX_W_OK", W_OK, CONST_CS | CONST_PERSISTENT);
172 13565 : REGISTER_LONG_CONSTANT("POSIX_R_OK", R_OK, CONST_CS | CONST_PERSISTENT);
173 : #ifdef S_IFREG
174 13565 : REGISTER_LONG_CONSTANT("POSIX_S_IFREG", S_IFREG, CONST_CS | CONST_PERSISTENT);
175 : #endif
176 : #ifdef S_IFCHR
177 13565 : REGISTER_LONG_CONSTANT("POSIX_S_IFCHR", S_IFCHR, CONST_CS | CONST_PERSISTENT);
178 : #endif
179 : #ifdef S_IFBLK
180 13565 : REGISTER_LONG_CONSTANT("POSIX_S_IFBLK", S_IFBLK, CONST_CS | CONST_PERSISTENT);
181 : #endif
182 : #ifdef S_IFIFO
183 13565 : REGISTER_LONG_CONSTANT("POSIX_S_IFIFO", S_IFIFO, CONST_CS | CONST_PERSISTENT);
184 : #endif
185 : #ifdef S_IFSOCK
186 13565 : REGISTER_LONG_CONSTANT("POSIX_S_IFSOCK", S_IFSOCK, CONST_CS | CONST_PERSISTENT);
187 : #endif
188 :
189 13565 : return SUCCESS;
190 : }
191 : /* }}} */
192 :
193 : /* {{{ posix_module_entry
194 : */
195 : zend_module_entry posix_module_entry = {
196 : STANDARD_MODULE_HEADER,
197 : "posix",
198 : posix_functions,
199 : PHP_MINIT(posix),
200 : NULL,
201 : NULL,
202 : NULL,
203 : PHP_MINFO(posix),
204 : NO_VERSION_YET,
205 : PHP_MODULE_GLOBALS(posix),
206 : PHP_GINIT(posix),
207 : NULL,
208 : NULL,
209 : STANDARD_MODULE_PROPERTIES_EX
210 : };
211 : /* }}} */
212 :
213 : #ifdef COMPILE_DL_POSIX
214 : ZEND_GET_MODULE(posix)
215 : #endif
216 :
217 : #define PHP_POSIX_NO_ARGS if (ZEND_NUM_ARGS()) WRONG_PARAM_COUNT;
218 :
219 : #define PHP_POSIX_RETURN_LONG_FUNC(func_name) \
220 : PHP_POSIX_NO_ARGS \
221 : RETURN_LONG(func_name());
222 :
223 : #define PHP_POSIX_SINGLE_ARG_FUNC(func_name) \
224 : long val; \
225 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &val) == FAILURE) RETURN_FALSE; \
226 : if (func_name(val) < 0) { \
227 : POSIX_G(last_error) = errno; \
228 : RETURN_FALSE; \
229 : } \
230 : RETURN_TRUE;
231 :
232 : /* {{{ proto bool posix_kill(int pid, int sig)
233 : Send a signal to a process (POSIX.1, 3.3.2) */
234 :
235 : PHP_FUNCTION(posix_kill)
236 66 : {
237 : long pid, sig;
238 :
239 66 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &pid, &sig) == FAILURE) {
240 20 : RETURN_FALSE;
241 : }
242 :
243 46 : if (kill(pid, sig) < 0) {
244 30 : POSIX_G(last_error) = errno;
245 30 : RETURN_FALSE;
246 : }
247 :
248 16 : RETURN_TRUE;
249 : }
250 : /* }}} */
251 :
252 : /* {{{ proto int posix_getpid(void)
253 : Get the current process id (POSIX.1, 4.1.1) */
254 : PHP_FUNCTION(posix_getpid)
255 8 : {
256 8 : PHP_POSIX_RETURN_LONG_FUNC(getpid);
257 : }
258 : /* }}} */
259 :
260 : /* {{{ proto int posix_getppid(void)
261 : Get the parent process id (POSIX.1, 4.1.1) */
262 : PHP_FUNCTION(posix_getppid)
263 2 : {
264 2 : PHP_POSIX_RETURN_LONG_FUNC(getppid);
265 : }
266 : /* }}} */
267 :
268 : /* {{{ proto int posix_getuid(void)
269 : Get the current user id (POSIX.1, 4.2.1) */
270 : PHP_FUNCTION(posix_getuid)
271 6 : {
272 6 : PHP_POSIX_RETURN_LONG_FUNC(getuid);
273 : }
274 : /* }}} */
275 :
276 : /* {{{ proto int posix_getgid(void)
277 : Get the current group id (POSIX.1, 4.2.1) */
278 : PHP_FUNCTION(posix_getgid)
279 5 : {
280 5 : PHP_POSIX_RETURN_LONG_FUNC(getgid);
281 : }
282 : /* }}} */
283 :
284 : /* {{{ proto int posix_geteuid(void)
285 : Get the current effective user id (POSIX.1, 4.2.1) */
286 : PHP_FUNCTION(posix_geteuid)
287 11 : {
288 11 : PHP_POSIX_RETURN_LONG_FUNC(geteuid);
289 : }
290 : /* }}} */
291 :
292 : /* {{{ proto int posix_getegid(void)
293 : Get the current effective group id (POSIX.1, 4.2.1) */
294 : PHP_FUNCTION(posix_getegid)
295 0 : {
296 0 : PHP_POSIX_RETURN_LONG_FUNC(getegid);
297 : }
298 : /* }}} */
299 :
300 : /* {{{ proto bool posix_setuid(long uid)
301 : Set user id (POSIX.1, 4.2.2) */
302 : PHP_FUNCTION(posix_setuid)
303 32 : {
304 32 : PHP_POSIX_SINGLE_ARG_FUNC(setuid);
305 : }
306 : /* }}} */
307 :
308 : /* {{{ proto bool posix_setgid(int uid)
309 : Set group id (POSIX.1, 4.2.2) */
310 : PHP_FUNCTION(posix_setgid)
311 31 : {
312 31 : PHP_POSIX_SINGLE_ARG_FUNC(setgid);
313 : }
314 : /* }}} */
315 :
316 : /* {{{ proto bool posix_seteuid(long uid)
317 : Set effective user id */
318 : #ifdef HAVE_SETEUID
319 : PHP_FUNCTION(posix_seteuid)
320 31 : {
321 31 : PHP_POSIX_SINGLE_ARG_FUNC(seteuid);
322 : }
323 : #endif
324 : /* }}} */
325 :
326 : /* {{{ proto bool posix_setegid(long uid)
327 : Set effective group id */
328 : #ifdef HAVE_SETEGID
329 : PHP_FUNCTION(posix_setegid)
330 0 : {
331 0 : PHP_POSIX_SINGLE_ARG_FUNC(setegid);
332 : }
333 : #endif
334 : /* }}} */
335 :
336 : /* {{{ proto array posix_getgroups(void)
337 : Get supplementary group id's (POSIX.1, 4.2.3) */
338 : #ifdef HAVE_GETGROUPS
339 : PHP_FUNCTION(posix_getgroups)
340 1 : {
341 : gid_t gidlist[NGROUPS_MAX];
342 : int result;
343 : int i;
344 :
345 1 : PHP_POSIX_NO_ARGS;
346 :
347 1 : if ((result = getgroups(NGROUPS_MAX, gidlist)) < 0) {
348 0 : POSIX_G(last_error) = errno;
349 0 : RETURN_FALSE;
350 : }
351 :
352 1 : array_init(return_value);
353 :
354 3 : for (i=0; i<result; i++) {
355 2 : add_next_index_long(return_value, gidlist[i]);
356 : }
357 : }
358 : #endif
359 : /* }}} */
360 :
361 : /* {{{ proto string posix_getlogin(void)
362 : Get user name (POSIX.1, 4.2.4) */
363 : #ifdef HAVE_GETLOGIN
364 : PHP_FUNCTION(posix_getlogin)
365 0 : {
366 : char *p;
367 :
368 0 : PHP_POSIX_NO_ARGS;
369 :
370 0 : if (NULL == (p = getlogin())) {
371 0 : POSIX_G(last_error) = errno;
372 0 : RETURN_FALSE;
373 : }
374 :
375 0 : RETURN_STRING(p, 1);
376 : }
377 : #endif
378 : /* }}} */
379 :
380 : /* {{{ proto int posix_getpgrp(void)
381 : Get current process group id (POSIX.1, 4.3.1) */
382 : PHP_FUNCTION(posix_getpgrp)
383 2 : {
384 2 : PHP_POSIX_RETURN_LONG_FUNC(getpgrp);
385 : }
386 : /* }}} */
387 :
388 : /* {{{ proto int posix_setsid(void)
389 : Create session and set process group id (POSIX.1, 4.3.2) */
390 : #ifdef HAVE_SETSID
391 : PHP_FUNCTION(posix_setsid)
392 0 : {
393 0 : PHP_POSIX_RETURN_LONG_FUNC(setsid);
394 : }
395 : #endif
396 : /* }}} */
397 :
398 : /* {{{ proto bool posix_setpgid(int pid, int pgid)
399 : Set process group id for job control (POSIX.1, 4.3.3) */
400 : PHP_FUNCTION(posix_setpgid)
401 0 : {
402 : long pid, pgid;
403 :
404 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &pid, &pgid) == FAILURE) {
405 0 : RETURN_FALSE;
406 : }
407 :
408 0 : if (setpgid(pid, pgid) < 0) {
409 0 : POSIX_G(last_error) = errno;
410 0 : RETURN_FALSE;
411 : }
412 :
413 0 : RETURN_TRUE;
414 : }
415 : /* }}} */
416 :
417 : /* {{{ proto int posix_getpgid(void)
418 : Get the process group id of the specified process (This is not a POSIX function, but a SVR4ism, so we compile conditionally) */
419 : #ifdef HAVE_GETPGID
420 : PHP_FUNCTION(posix_getpgid)
421 26 : {
422 : long val;
423 26 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &val) == FAILURE) {
424 11 : RETURN_FALSE;
425 : }
426 :
427 15 : if ((val = getpgid(val)) < 0) {
428 3 : POSIX_G(last_error) = errno;
429 3 : RETURN_FALSE;
430 : }
431 12 : RETURN_LONG(val);
432 : }
433 : #endif
434 : /* }}} */
435 :
436 : /* {{{ proto int posix_getsid(void)
437 : Get process group id of session leader (This is not a POSIX function, but a SVR4ism, so be compile conditionally) */
438 : #ifdef HAVE_GETSID
439 : PHP_FUNCTION(posix_getsid)
440 5 : {
441 : long val;
442 5 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &val) == FAILURE) {
443 2 : RETURN_FALSE;
444 : }
445 :
446 3 : if ((val = getsid(val)) < 0) {
447 1 : POSIX_G(last_error) = errno;
448 1 : RETURN_FALSE;
449 : }
450 2 : RETURN_LONG(val);
451 : }
452 : #endif
453 : /* }}} */
454 :
455 : /* {{{ proto array posix_uname(void)
456 : Get system name (POSIX.1, 4.4.1) */
457 : PHP_FUNCTION(posix_uname)
458 3 : {
459 : struct utsname u;
460 :
461 3 : PHP_POSIX_NO_ARGS;
462 :
463 2 : if (uname(&u) < 0) {
464 0 : POSIX_G(last_error) = errno;
465 0 : RETURN_FALSE;
466 : }
467 :
468 2 : array_init(return_value);
469 :
470 2 : add_assoc_string(return_value, "sysname", u.sysname, 1);
471 2 : add_assoc_string(return_value, "nodename", u.nodename, 1);
472 2 : add_assoc_string(return_value, "release", u.release, 1);
473 2 : add_assoc_string(return_value, "version", u.version, 1);
474 2 : add_assoc_string(return_value, "machine", u.machine, 1);
475 : #if defined(_GNU_SOURCE) && !defined(DARWIN) && defined(HAVE_UTSNAME_DOMAINNAME)
476 : add_assoc_string(return_value, "domainname", u.domainname, 1);
477 : #endif
478 : }
479 : /* }}} */
480 :
481 : /* POSIX.1, 4.5.1 time() - Get System Time
482 : already covered by PHP
483 : */
484 :
485 : /* {{{ proto array posix_times(void)
486 : Get process times (POSIX.1, 4.5.2) */
487 : PHP_FUNCTION(posix_times)
488 3 : {
489 : struct tms t;
490 : clock_t ticks;
491 :
492 3 : PHP_POSIX_NO_ARGS;
493 :
494 2 : if ((ticks = times(&t)) == -1) {
495 0 : POSIX_G(last_error) = errno;
496 0 : RETURN_FALSE;
497 : }
498 :
499 2 : array_init(return_value);
500 :
501 2 : add_assoc_long(return_value, "ticks", ticks); /* clock ticks */
502 2 : add_assoc_long(return_value, "utime", t.tms_utime); /* user time */
503 2 : add_assoc_long(return_value, "stime", t.tms_stime); /* system time */
504 2 : add_assoc_long(return_value, "cutime", t.tms_cutime); /* user time of children */
505 2 : add_assoc_long(return_value, "cstime", t.tms_cstime); /* system time of children */
506 : }
507 : /* }}} */
508 :
509 : /* POSIX.1, 4.6.1 getenv() - Environment Access
510 : already covered by PHP
511 : */
512 :
513 : /* {{{ proto string posix_ctermid(void)
514 : Generate terminal path name (POSIX.1, 4.7.1) */
515 : #ifdef HAVE_CTERMID
516 : PHP_FUNCTION(posix_ctermid)
517 3 : {
518 : char buffer[L_ctermid];
519 :
520 3 : PHP_POSIX_NO_ARGS;
521 :
522 2 : if (NULL == ctermid(buffer)) {
523 : /* Found no documentation how the defined behaviour is when this
524 : * function fails
525 : */
526 0 : POSIX_G(last_error) = errno;
527 0 : RETURN_FALSE;
528 : }
529 :
530 2 : RETURN_STRING(buffer, 1);
531 : }
532 : #endif
533 : /* }}} */
534 :
535 : /* Checks if the provides resource is a stream and if it provides a file descriptor */
536 : static int php_posix_stream_get_fd(zval *zfp, int *fd TSRMLS_DC)
537 4 : {
538 : php_stream *stream;
539 :
540 4 : php_stream_from_zval_no_verify(stream, &zfp);
541 :
542 4 : if (stream == NULL) {
543 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "expects argument 1 to be a valid stream resource");
544 1 : return 0;
545 : }
546 3 : if (php_stream_can_cast(stream, PHP_STREAM_AS_FD) == SUCCESS) {
547 3 : php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)fd, 0);
548 : } else {
549 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not use stream of type '%s'",
550 : stream->ops->label);
551 0 : return 0;
552 : }
553 3 : return 1;
554 : }
555 :
556 : /* {{{ proto string posix_ttyname(int fd)
557 : Determine terminal device name (POSIX.1, 4.7.2) */
558 : PHP_FUNCTION(posix_ttyname)
559 35 : {
560 : zval **z_fd;
561 : char *p;
562 : int fd;
563 : #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX)
564 : long buflen;
565 : #endif
566 :
567 35 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &z_fd) == FAILURE) {
568 3 : RETURN_FALSE;
569 : }
570 :
571 32 : switch (Z_TYPE_PP(z_fd)) {
572 : case IS_RESOURCE:
573 4 : if (!php_posix_stream_get_fd(*z_fd, &fd TSRMLS_CC)) {
574 1 : RETURN_FALSE;
575 : }
576 3 : break;
577 : default:
578 28 : convert_to_long_ex(z_fd);
579 28 : fd = Z_LVAL_PP(z_fd);
580 : }
581 : #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX)
582 : buflen = sysconf(_SC_TTY_NAME_MAX);
583 : if (buflen < 1) {
584 : RETURN_FALSE;
585 : }
586 : p = emalloc(buflen);
587 :
588 : if (ttyname_r(fd, p, buflen)) {
589 : POSIX_G(last_error) = errno;
590 : efree(p);
591 : RETURN_FALSE;
592 : }
593 : RETURN_STRING(p, 0);
594 : #else
595 31 : if (NULL == (p = ttyname(fd))) {
596 31 : POSIX_G(last_error) = errno;
597 31 : RETURN_FALSE;
598 : }
599 : #endif
600 0 : RETURN_STRING(p, 1);
601 : }
602 : /* }}} */
603 :
604 : /* {{{ proto bool posix_isatty(int fd)
605 : Determine if filedesc is a tty (POSIX.1, 4.7.1) */
606 : PHP_FUNCTION(posix_isatty)
607 1 : {
608 : zval **z_fd;
609 : int fd;
610 :
611 1 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &z_fd) == FAILURE) {
612 0 : RETURN_FALSE;
613 : }
614 :
615 1 : switch (Z_TYPE_PP(z_fd)) {
616 : case IS_RESOURCE:
617 0 : if (!php_posix_stream_get_fd(*z_fd, &fd TSRMLS_CC)) {
618 0 : RETURN_FALSE;
619 : }
620 0 : break;
621 : default:
622 1 : convert_to_long_ex(z_fd);
623 1 : fd = Z_LVAL_PP(z_fd);
624 : }
625 :
626 1 : if (isatty(fd)) {
627 0 : RETURN_TRUE;
628 : } else {
629 1 : RETURN_FALSE;
630 : }
631 : }
632 : /* }}} */
633 :
634 : /*
635 : POSIX.1, 4.8.1 sysconf() - TODO
636 : POSIX.1, 5.7.1 pathconf(), fpathconf() - TODO
637 :
638 : POSIX.1, 5.1.2 opendir(), readdir(), rewinddir(), closedir()
639 : POSIX.1, 5.2.1 chdir()
640 : already supported by PHP
641 : */
642 :
643 : /* {{{ proto string posix_getcwd(void)
644 : Get working directory pathname (POSIX.1, 5.2.2) */
645 : PHP_FUNCTION(posix_getcwd)
646 4 : {
647 : char buffer[MAXPATHLEN];
648 : char *p;
649 :
650 4 : PHP_POSIX_NO_ARGS;
651 :
652 2 : p = VCWD_GETCWD(buffer, MAXPATHLEN);
653 2 : if (!p) {
654 0 : POSIX_G(last_error) = errno;
655 0 : RETURN_FALSE;
656 : }
657 :
658 2 : RETURN_STRING(buffer, 1);
659 : }
660 : /* }}} */
661 :
662 : /*
663 : POSIX.1, 5.3.x open(), creat(), umask()
664 : POSIX.1, 5.4.1 link()
665 : already supported by PHP.
666 : */
667 :
668 : /* {{{ proto bool posix_mkfifo(string pathname, int mode)
669 : Make a FIFO special file (POSIX.1, 5.4.2) */
670 : #ifdef HAVE_MKFIFO
671 : PHP_FUNCTION(posix_mkfifo)
672 5 : {
673 : char *path;
674 : int path_len;
675 : long mode;
676 : int result;
677 :
678 5 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &path, &path_len, &mode) == FAILURE) {
679 1 : RETURN_FALSE;
680 : }
681 :
682 4 : if (php_check_open_basedir_ex(path, 0 TSRMLS_CC) ||
683 : (PG(safe_mode) && (!php_checkuid(path, NULL, CHECKUID_ALLOW_ONLY_DIR)))) {
684 1 : RETURN_FALSE;
685 : }
686 :
687 3 : result = mkfifo(path, mode);
688 3 : if (result < 0) {
689 1 : POSIX_G(last_error) = errno;
690 1 : RETURN_FALSE;
691 : }
692 :
693 2 : RETURN_TRUE;
694 : }
695 : #endif
696 : /* }}} */
697 :
698 : /* {{{ proto bool posix_mknod(string pathname, int mode [, int major [, int minor]])
699 : Make a special or ordinary file (POSIX.1) */
700 : #ifdef HAVE_MKNOD
701 : PHP_FUNCTION(posix_mknod)
702 2 : {
703 : char *path;
704 : int path_len;
705 : long mode;
706 2 : long major = 0, minor = 0;
707 : int result;
708 : dev_t php_dev;
709 :
710 2 : php_dev = 0;
711 :
712 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|ll", &path, &path_len,
713 : &mode, &major, &minor) == FAILURE) {
714 0 : RETURN_FALSE;
715 : }
716 :
717 2 : if (php_check_open_basedir_ex(path, 0 TSRMLS_CC) ||
718 : (PG(safe_mode) && (!php_checkuid(path, NULL, CHECKUID_ALLOW_ONLY_DIR)))) {
719 0 : RETURN_FALSE;
720 : }
721 :
722 2 : if ((mode & S_IFCHR) || (mode & S_IFBLK)) {
723 0 : if (ZEND_NUM_ARGS() == 2) {
724 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "For S_IFCHR and S_IFBLK you need to pass a major device kernel identifier");
725 0 : RETURN_FALSE;
726 : }
727 0 : if (major == 0) {
728 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,
729 : "Expects argument 3 to be non-zero for POSIX_S_IFCHR and POSIX_S_IFBLK");
730 0 : RETURN_FALSE;
731 : } else {
732 : #if defined(HAVE_MAKEDEV) || defined(makedev)
733 0 : php_dev = makedev(major, minor);
734 : #else
735 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not create a block or character device, creating a normal file instead");
736 : #endif
737 : }
738 : }
739 :
740 2 : result = mknod(path, mode, php_dev);
741 2 : if (result < 0) {
742 2 : POSIX_G(last_error) = errno;
743 2 : RETURN_FALSE;
744 : }
745 :
746 0 : RETURN_TRUE;
747 : }
748 : #endif
749 : /* }}} */
750 :
751 : /* Takes a pointer to posix group and a pointer to an already initialized ZVAL
752 : * array container and fills the array with the posix group member data. */
753 13 : int php_posix_group_to_array(struct group *g, zval *array_group) {
754 : zval *array_members;
755 : int count;
756 :
757 13 : if (NULL == g)
758 0 : return 0;
759 :
760 13 : if (array_group == NULL || Z_TYPE_P(array_group) != IS_ARRAY)
761 0 : return 0;
762 :
763 13 : MAKE_STD_ZVAL(array_members);
764 13 : array_init(array_members);
765 :
766 13 : add_assoc_string(array_group, "name", g->gr_name, 1);
767 13 : add_assoc_string(array_group, "passwd", g->gr_passwd, 1);
768 30 : for (count=0; g->gr_mem[count] != NULL; count++) {
769 17 : add_next_index_string(array_members, g->gr_mem[count], 1);
770 : }
771 13 : zend_hash_update(Z_ARRVAL_P(array_group), "members", sizeof("members"), (void*)&array_members, sizeof(zval*), NULL);
772 13 : add_assoc_long(array_group, "gid", g->gr_gid);
773 13 : return 1;
774 : }
775 :
776 : /*
777 : POSIX.1, 5.5.1 unlink()
778 : POSIX.1, 5.5.2 rmdir()
779 : POSIX.1, 5.5.3 rename()
780 : POSIX.1, 5.6.x stat(), chmod(), utime() already supported by PHP.
781 : */
782 :
783 : /* {{{ proto bool posix_access(string file [, int mode])
784 : Determine accessibility of a file (POSIX.1 5.6.3) */
785 : PHP_FUNCTION(posix_access)
786 15 : {
787 15 : long mode = 0;
788 : int filename_len, ret;
789 : char *filename, *path;
790 :
791 15 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &filename, &filename_len, &mode) == FAILURE) {
792 3 : RETURN_FALSE;
793 : }
794 :
795 12 : path = expand_filepath(filename, NULL TSRMLS_CC);
796 12 : if (!path) {
797 2 : POSIX_G(last_error) = EIO;
798 2 : RETURN_FALSE;
799 : }
800 :
801 10 : if (php_check_open_basedir_ex(path, 0 TSRMLS_CC) ||
802 : (PG(safe_mode) && (!php_checkuid_ex(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR, CHECKUID_NO_ERRORS)))) {
803 1 : efree(path);
804 1 : POSIX_G(last_error) = EPERM;
805 1 : RETURN_FALSE;
806 : }
807 :
808 9 : ret = access(path, mode);
809 9 : efree(path);
810 :
811 9 : if (ret) {
812 5 : POSIX_G(last_error) = errno;
813 5 : RETURN_FALSE;
814 : }
815 :
816 4 : RETURN_TRUE;
817 : }
818 : /* }}} */
819 :
820 : /*
821 : POSIX.1, 6.x most I/O functions already supported by PHP.
822 : POSIX.1, 7.x tty functions, TODO
823 : POSIX.1, 8.x interactions with other C language functions
824 : POSIX.1, 9.x system database access
825 : */
826 :
827 : /* {{{ proto array posix_getgrnam(string groupname)
828 : Group database access (POSIX.1, 9.2.1) */
829 : PHP_FUNCTION(posix_getgrnam)
830 6 : {
831 : char *name;
832 : struct group *g;
833 : int name_len;
834 : #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
835 : struct group gbuf;
836 : long buflen;
837 : char *buf;
838 : #endif
839 :
840 6 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
841 0 : RETURN_FALSE;
842 : }
843 :
844 : #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
845 : buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
846 : if (buflen < 1) {
847 : RETURN_FALSE;
848 : }
849 : buf = emalloc(buflen);
850 : g = &gbuf;
851 :
852 : if (getgrnam_r(name, g, buf, buflen, &g) || g == NULL) {
853 : POSIX_G(last_error) = errno;
854 : efree(buf);
855 : RETURN_FALSE;
856 : }
857 : #else
858 6 : if (NULL == (g = getgrnam(name))) {
859 6 : POSIX_G(last_error) = errno;
860 6 : RETURN_FALSE;
861 : }
862 : #endif
863 0 : array_init(return_value);
864 :
865 0 : if (!php_posix_group_to_array(g, return_value)) {
866 0 : zval_dtor(return_value);
867 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix group to array");
868 0 : RETVAL_FALSE;
869 : }
870 : #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX)
871 : efree(buf);
872 : #endif
873 : }
874 : /* }}} */
875 :
876 : /* {{{ proto array posix_getgrgid(long gid)
877 : Group database access (POSIX.1, 9.2.1) */
878 : PHP_FUNCTION(posix_getgrgid)
879 30 : {
880 : long gid;
881 : #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
882 : int ret;
883 : struct group _g;
884 : struct group *retgrptr = NULL;
885 : long grbuflen;
886 : char *grbuf;
887 : #endif
888 : struct group *g;
889 :
890 30 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &gid) == FAILURE) {
891 12 : RETURN_FALSE;
892 : }
893 : #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
894 :
895 : grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
896 : if (grbuflen < 1) {
897 : RETURN_FALSE;
898 : }
899 :
900 : grbuf = emalloc(grbuflen);
901 :
902 : ret = getgrgid_r(gid, &_g, grbuf, grbuflen, &retgrptr);
903 : if (ret || retgrptr == NULL) {
904 : POSIX_G(last_error) = ret;
905 : efree(grbuf);
906 : RETURN_FALSE;
907 : }
908 : g = &_g;
909 : #else
910 18 : if (NULL == (g = getgrgid(gid))) {
911 5 : POSIX_G(last_error) = errno;
912 5 : RETURN_FALSE;
913 : }
914 : #endif
915 13 : array_init(return_value);
916 :
917 13 : if (!php_posix_group_to_array(g, return_value)) {
918 0 : zval_dtor(return_value);
919 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix group struct to array");
920 0 : RETVAL_FALSE;
921 : }
922 : #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX)
923 : efree(grbuf);
924 : #endif
925 : }
926 : /* }}} */
927 :
928 12 : int php_posix_passwd_to_array(struct passwd *pw, zval *return_value) {
929 12 : if (NULL == pw)
930 0 : return 0;
931 12 : if (NULL == return_value || Z_TYPE_P(return_value) != IS_ARRAY)
932 0 : return 0;
933 :
934 12 : add_assoc_string(return_value, "name", pw->pw_name, 1);
935 12 : add_assoc_string(return_value, "passwd", pw->pw_passwd, 1);
936 12 : add_assoc_long (return_value, "uid", pw->pw_uid);
937 12 : add_assoc_long (return_value, "gid", pw->pw_gid);
938 12 : add_assoc_string(return_value, "gecos", pw->pw_gecos, 1);
939 12 : add_assoc_string(return_value, "dir", pw->pw_dir, 1);
940 12 : add_assoc_string(return_value, "shell", pw->pw_shell, 1);
941 12 : return 1;
942 : }
943 :
944 : /* {{{ proto array posix_getpwnam(string groupname)
945 : User database access (POSIX.1, 9.2.2) */
946 : PHP_FUNCTION(posix_getpwnam)
947 6 : {
948 : struct passwd *pw;
949 : char *name;
950 : int name_len;
951 : #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
952 : struct passwd pwbuf;
953 : long buflen;
954 : char *buf;
955 : #endif
956 :
957 6 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
958 0 : RETURN_FALSE;
959 : }
960 :
961 : #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
962 : buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
963 : if (buflen < 1) {
964 : RETURN_FALSE;
965 : }
966 : buf = emalloc(buflen);
967 : pw = &pwbuf;
968 :
969 : if (getpwnam_r(name, pw, buf, buflen, &pw) || pw == NULL) {
970 : efree(buf);
971 : POSIX_G(last_error) = errno;
972 : RETURN_FALSE;
973 : }
974 : #else
975 6 : if (NULL == (pw = getpwnam(name))) {
976 6 : POSIX_G(last_error) = errno;
977 6 : RETURN_FALSE;
978 : }
979 : #endif
980 0 : array_init(return_value);
981 :
982 0 : if (!php_posix_passwd_to_array(pw, return_value)) {
983 0 : zval_dtor(return_value);
984 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix passwd struct to array");
985 0 : RETVAL_FALSE;
986 : }
987 : #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R)
988 : efree(buf);
989 : #endif
990 : }
991 : /* }}} */
992 :
993 : /* {{{ proto array posix_getpwuid(long uid)
994 : User database access (POSIX.1, 9.2.2) */
995 : PHP_FUNCTION(posix_getpwuid)
996 26 : {
997 : long uid;
998 : #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
999 : struct passwd _pw;
1000 : struct passwd *retpwptr = NULL;
1001 : long pwbuflen;
1002 : char *pwbuf;
1003 : int ret;
1004 : #endif
1005 : struct passwd *pw;
1006 :
1007 26 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &uid) == FAILURE) {
1008 11 : RETURN_FALSE;
1009 : }
1010 : #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1011 : pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
1012 : if (pwbuflen < 1) {
1013 : RETURN_FALSE;
1014 : }
1015 : pwbuf = emalloc(pwbuflen);
1016 :
1017 : ret = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr);
1018 : if (ret || retpwptr == NULL) {
1019 : POSIX_G(last_error) = ret;
1020 : efree(pwbuf);
1021 : RETURN_FALSE;
1022 : }
1023 : pw = &_pw;
1024 : #else
1025 15 : if (NULL == (pw = getpwuid(uid))) {
1026 3 : POSIX_G(last_error) = errno;
1027 3 : RETURN_FALSE;
1028 : }
1029 : #endif
1030 12 : array_init(return_value);
1031 :
1032 12 : if (!php_posix_passwd_to_array(pw, return_value)) {
1033 0 : zval_dtor(return_value);
1034 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to convert posix passwd struct to array");
1035 0 : RETVAL_FALSE;
1036 : }
1037 : #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R)
1038 : efree(pwbuf);
1039 : #endif
1040 : }
1041 : /* }}} */
1042 :
1043 :
1044 : #ifdef HAVE_GETRLIMIT
1045 :
1046 : #define UNLIMITED_STRING "unlimited"
1047 :
1048 : /* {{{ posix_addlimit
1049 : */
1050 22 : static int posix_addlimit(int limit, char *name, zval *return_value TSRMLS_DC) {
1051 : int result;
1052 : struct rlimit rl;
1053 : char hard[80];
1054 : char soft[80];
1055 :
1056 22 : snprintf(hard, 80, "hard %s", name);
1057 22 : snprintf(soft, 80, "soft %s", name);
1058 :
1059 22 : result = getrlimit(limit, &rl);
1060 22 : if (result < 0) {
1061 0 : POSIX_G(last_error) = errno;
1062 0 : return FAILURE;
1063 : }
1064 :
1065 22 : if (rl.rlim_cur == RLIM_INFINITY) {
1066 10 : add_assoc_stringl(return_value, soft, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1, 1);
1067 : } else {
1068 12 : add_assoc_long(return_value, soft, rl.rlim_cur);
1069 : }
1070 :
1071 22 : if (rl.rlim_max == RLIM_INFINITY) {
1072 14 : add_assoc_stringl(return_value, hard, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1, 1);
1073 : } else {
1074 8 : add_assoc_long(return_value, hard, rl.rlim_max);
1075 : }
1076 :
1077 22 : return SUCCESS;
1078 : }
1079 : /* }}} */
1080 :
1081 : /* {{{ limits[]
1082 : */
1083 : struct limitlist {
1084 : int limit;
1085 : char *name;
1086 : } limits[] = {
1087 : #ifdef RLIMIT_CORE
1088 : { RLIMIT_CORE, "core" },
1089 : #endif
1090 :
1091 : #ifdef RLIMIT_DATA
1092 : { RLIMIT_DATA, "data" },
1093 : #endif
1094 :
1095 : #ifdef RLIMIT_STACK
1096 : { RLIMIT_STACK, "stack" },
1097 : #endif
1098 :
1099 : #ifdef RLIMIT_VMEM
1100 : { RLIMIT_VMEM, "virtualmem" },
1101 : #endif
1102 :
1103 : #ifdef RLIMIT_AS
1104 : { RLIMIT_AS, "totalmem" },
1105 : #endif
1106 :
1107 : #ifdef RLIMIT_RSS
1108 : { RLIMIT_RSS, "rss" },
1109 : #endif
1110 :
1111 : #ifdef RLIMIT_NPROC
1112 : { RLIMIT_NPROC, "maxproc" },
1113 : #endif
1114 :
1115 : #ifdef RLIMIT_MEMLOCK
1116 : { RLIMIT_MEMLOCK, "memlock" },
1117 : #endif
1118 :
1119 : #ifdef RLIMIT_CPU
1120 : { RLIMIT_CPU, "cpu" },
1121 : #endif
1122 :
1123 : #ifdef RLIMIT_FSIZE
1124 : { RLIMIT_FSIZE, "filesize" },
1125 : #endif
1126 :
1127 : #ifdef RLIMIT_NOFILE
1128 : { RLIMIT_NOFILE, "openfiles" },
1129 : #endif
1130 :
1131 : #ifdef RLIMIT_OFILE
1132 : { RLIMIT_OFILE, "openfiles" },
1133 : #endif
1134 :
1135 : { 0, NULL }
1136 : };
1137 : /* }}} */
1138 :
1139 :
1140 : /* {{{ proto array posix_getrlimit(void)
1141 : Get system resource consumption limits (This is not a POSIX function, but a BSDism and a SVR4ism. We compile conditionally) */
1142 : PHP_FUNCTION(posix_getrlimit)
1143 2 : {
1144 2 : struct limitlist *l = NULL;
1145 :
1146 2 : PHP_POSIX_NO_ARGS;
1147 :
1148 2 : array_init(return_value);
1149 :
1150 24 : for (l=limits; l->name; l++) {
1151 22 : if (posix_addlimit(l->limit, l->name, return_value TSRMLS_CC) == FAILURE) {
1152 0 : zval_dtor(return_value);
1153 0 : RETURN_FALSE;
1154 : }
1155 : }
1156 : }
1157 : /* }}} */
1158 :
1159 : #endif /* HAVE_GETRLIMIT */
1160 :
1161 : /* {{{ proto int posix_get_last_error(void)
1162 : Retrieve the error number set by the last posix function which failed. */
1163 : PHP_FUNCTION(posix_get_last_error)
1164 7 : {
1165 7 : PHP_POSIX_NO_ARGS;
1166 :
1167 5 : RETURN_LONG(POSIX_G(last_error));
1168 : }
1169 : /* }}} */
1170 :
1171 : /* {{{ proto string posix_strerror(int errno)
1172 : Retrieve the system error message associated with the given errno. */
1173 : PHP_FUNCTION(posix_strerror)
1174 26 : {
1175 : long error;
1176 :
1177 26 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &error) == FAILURE) {
1178 11 : RETURN_FALSE;
1179 : }
1180 :
1181 15 : RETURN_STRING(strerror(error), 1);
1182 : }
1183 : /* }}} */
1184 :
1185 : #endif
1186 :
1187 : #ifdef HAVE_INITGROUPS
1188 : /* {{{ proto bool posix_initgroups(string name, int base_group_id)
1189 : Calculate the group access list for the user specified in name. */
1190 : PHP_FUNCTION(posix_initgroups)
1191 4 : {
1192 : long basegid;
1193 : char *name;
1194 : int name_len;
1195 :
1196 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name, &name_len, &basegid) == FAILURE) {
1197 2 : RETURN_FALSE;
1198 : }
1199 :
1200 2 : if (name_len == 0) {
1201 2 : RETURN_FALSE;
1202 : }
1203 :
1204 0 : RETURN_BOOL(!initgroups((const char *)name, basegid));
1205 : }
1206 : /* }}} */
1207 : #endif
1208 :
1209 : /*
1210 : * Local variables:
1211 : * tab-width: 4
1212 : * c-basic-offset: 4
1213 : * End:
1214 : * vim600: sw=4 ts=4 fdm=marker
1215 : * vim<600: sw=4 ts=4
1216 : */
|