/* +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Kristian Koehntopp | +----------------------------------------------------------------------+ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include #include "ext/standard/info.h" #include "ext/standard/php_string.h" #include "php_posix.h" #ifdef HAVE_POSIX #ifdef HAVE_SYS_TIME_H #include #endif #include #include #include #include #include #include #include #include #include #ifdef MAJOR_IN_MKDEV # include #elif defined(MAJOR_IN_SYSMACROS) # include #endif #include "posix_arginfo.h" ZEND_DECLARE_MODULE_GLOBALS(posix) static PHP_MINFO_FUNCTION(posix); /* {{{ PHP_MINFO_FUNCTION */ static PHP_MINFO_FUNCTION(posix) { php_info_print_table_start(); php_info_print_table_row(2, "POSIX support", "enabled"); php_info_print_table_end(); } /* }}} */ static PHP_GINIT_FUNCTION(posix) /* {{{ */ { #if defined(COMPILE_DL_POSIX) && defined(ZTS) ZEND_TSRMLS_CACHE_UPDATE(); #endif posix_globals->last_error = 0; } /* }}} */ /* {{{ PHP_MINIT_FUNCTION(posix) */ static PHP_MINIT_FUNCTION(posix) { register_posix_symbols(module_number); return SUCCESS; } /* }}} */ /* {{{ posix_module_entry */ zend_module_entry posix_module_entry = { STANDARD_MODULE_HEADER, "posix", ext_functions, PHP_MINIT(posix), NULL, NULL, NULL, PHP_MINFO(posix), PHP_POSIX_VERSION, PHP_MODULE_GLOBALS(posix), PHP_GINIT(posix), NULL, NULL, STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ #ifdef COMPILE_DL_POSIX #ifdef ZTS ZEND_TSRMLS_CACHE_DEFINE() #endif ZEND_GET_MODULE(posix) #endif #define PHP_POSIX_RETURN_LONG_FUNC(func_name) \ ZEND_PARSE_PARAMETERS_NONE(); \ RETURN_LONG(func_name()); #define PHP_POSIX_SINGLE_ARG_FUNC(func_name) \ zend_long val; \ ZEND_PARSE_PARAMETERS_START(1, 1) \ Z_PARAM_LONG(val) \ ZEND_PARSE_PARAMETERS_END(); \ if (func_name(val) < 0) { \ POSIX_G(last_error) = errno; \ RETURN_FALSE; \ } \ RETURN_TRUE; /* {{{ Send a signal to a process (POSIX.1, 3.3.2) */ PHP_FUNCTION(posix_kill) { zend_long pid, sig; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_LONG(pid) Z_PARAM_LONG(sig) ZEND_PARSE_PARAMETERS_END(); if (kill(pid, sig) < 0) { POSIX_G(last_error) = errno; RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ Get the current process id (POSIX.1, 4.1.1) */ PHP_FUNCTION(posix_getpid) { PHP_POSIX_RETURN_LONG_FUNC(getpid); } /* }}} */ /* {{{ Get the parent process id (POSIX.1, 4.1.1) */ PHP_FUNCTION(posix_getppid) { PHP_POSIX_RETURN_LONG_FUNC(getppid); } /* }}} */ /* {{{ Get the current user id (POSIX.1, 4.2.1) */ PHP_FUNCTION(posix_getuid) { PHP_POSIX_RETURN_LONG_FUNC(getuid); } /* }}} */ /* {{{ Get the current group id (POSIX.1, 4.2.1) */ PHP_FUNCTION(posix_getgid) { PHP_POSIX_RETURN_LONG_FUNC(getgid); } /* }}} */ /* {{{ Get the current effective user id (POSIX.1, 4.2.1) */ PHP_FUNCTION(posix_geteuid) { PHP_POSIX_RETURN_LONG_FUNC(geteuid); } /* }}} */ /* {{{ Get the current effective group id (POSIX.1, 4.2.1) */ PHP_FUNCTION(posix_getegid) { PHP_POSIX_RETURN_LONG_FUNC(getegid); } /* }}} */ /* {{{ Set user id (POSIX.1, 4.2.2) */ PHP_FUNCTION(posix_setuid) { PHP_POSIX_SINGLE_ARG_FUNC(setuid); } /* }}} */ /* {{{ Set group id (POSIX.1, 4.2.2) */ PHP_FUNCTION(posix_setgid) { PHP_POSIX_SINGLE_ARG_FUNC(setgid); } /* }}} */ /* {{{ Set effective user id */ #ifdef HAVE_SETEUID PHP_FUNCTION(posix_seteuid) { PHP_POSIX_SINGLE_ARG_FUNC(seteuid); } #endif /* }}} */ /* {{{ Set effective group id */ #ifdef HAVE_SETEGID PHP_FUNCTION(posix_setegid) { PHP_POSIX_SINGLE_ARG_FUNC(setegid); } #endif /* }}} */ /* {{{ Get supplementary group id's (POSIX.1, 4.2.3) */ #ifdef HAVE_GETGROUPS PHP_FUNCTION(posix_getgroups) { gid_t *gidlist; int result; int i; ZEND_PARSE_PARAMETERS_NONE(); /* MacOS may return more than NGROUPS_MAX groups. * Fetch the actual number of groups and create an appropriate allocation. */ if ((result = getgroups(0, NULL)) < 0) { POSIX_G(last_error) = errno; RETURN_FALSE; } gidlist = emalloc(sizeof(gid_t) * result); if ((result = getgroups(result, gidlist)) < 0) { POSIX_G(last_error) = errno; efree(gidlist); RETURN_FALSE; } array_init(return_value); for (i=0; iops->label); return FAILURE; } return SUCCESS; } /* }}} */ /* {{{ Determine terminal device name (POSIX.1, 4.7.2) */ PHP_FUNCTION(posix_ttyname) { zval *z_fd; char *p; zend_long fd = 0; #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX) zend_long buflen; int err; #endif ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL(z_fd) ZEND_PARSE_PARAMETERS_END(); if (Z_TYPE_P(z_fd) == IS_RESOURCE) { if (php_posix_stream_get_fd(z_fd, &fd) == FAILURE) { RETURN_FALSE; } } else { if (!zend_parse_arg_long(z_fd, &fd, /* is_null */ NULL, /* check_null */ false, /* arg_num */ 1)) { php_error_docref(NULL, E_WARNING, "Argument #1 ($file_descriptor) must be of type int|resource, %s given", zend_zval_value_name(z_fd)); fd = zval_get_long(z_fd); } /* fd must fit in an int and be positive */ if (fd < 0 || fd > INT_MAX) { php_error_docref(NULL, E_WARNING, "Argument #1 ($file_descriptor) must be between 0 and %d", INT_MAX); RETURN_FALSE; } } #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX) buflen = sysconf(_SC_TTY_NAME_MAX); if (buflen < 1) { buflen = 32; } #if ZEND_DEBUG /* Test retry logic */ buflen = 1; #endif p = emalloc(buflen); try_again: err = ttyname_r(fd, p, buflen); if (err) { if (err == ERANGE) { buflen *= 2; p = erealloc(p, buflen); goto try_again; } POSIX_G(last_error) = err; efree(p); RETURN_FALSE; } RETVAL_STRING(p); efree(p); #else if (NULL == (p = ttyname(fd))) { POSIX_G(last_error) = errno; RETURN_FALSE; } RETURN_STRING(p); #endif } /* }}} */ /* {{{ Determine if filedesc is a tty (POSIX.1, 4.7.1) */ PHP_FUNCTION(posix_isatty) { zval *z_fd; zend_long fd = 0; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL(z_fd) ZEND_PARSE_PARAMETERS_END(); if (Z_TYPE_P(z_fd) == IS_RESOURCE) { if (php_posix_stream_get_fd(z_fd, &fd) == FAILURE) { RETURN_FALSE; } } else { if (!zend_parse_arg_long(z_fd, &fd, /* is_null */ NULL, /* check_null */ false, /* arg_num */ 1)) { php_error_docref(NULL, E_WARNING, "Argument #1 ($file_descriptor) must be of type int|resource, %s given", zend_zval_value_name(z_fd)); RETURN_FALSE; } } /* A valid file descriptor must fit in an int and be positive */ if (fd < 0 || fd > INT_MAX) { POSIX_G(last_error) = EBADF; RETURN_FALSE; } if (isatty(fd)) { RETURN_TRUE; } else { POSIX_G(last_error) = errno; RETURN_FALSE; } } /* }}} */ /* POSIX.1, 4.8.1 sysconf() POSIX.1, 5.7.1 pathconf(), fpathconf() POSIX.1, 5.1.2 opendir(), readdir(), rewinddir(), closedir() POSIX.1, 5.2.1 chdir() already supported by PHP */ /* {{{ Get working directory pathname (POSIX.1, 5.2.2) */ PHP_FUNCTION(posix_getcwd) { char buffer[MAXPATHLEN]; char *p; ZEND_PARSE_PARAMETERS_NONE(); p = VCWD_GETCWD(buffer, MAXPATHLEN); if (!p) { POSIX_G(last_error) = errno; RETURN_FALSE; } RETURN_STRING(buffer); } /* }}} */ /* POSIX.1, 5.3.x open(), creat(), umask() POSIX.1, 5.4.1 link() already supported by PHP. */ /* {{{ Make a FIFO special file (POSIX.1, 5.4.2) */ #ifdef HAVE_MKFIFO PHP_FUNCTION(posix_mkfifo) { zend_string *path; zend_long mode; int result; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_PATH_STR(path) Z_PARAM_LONG(mode) ZEND_PARSE_PARAMETERS_END(); if (php_check_open_basedir_ex(ZSTR_VAL(path), 0)) { RETURN_FALSE; } result = mkfifo(ZSTR_VAL(path), mode); if (result < 0) { POSIX_G(last_error) = errno; RETURN_FALSE; } RETURN_TRUE; } #endif /* }}} */ /* {{{ Make a special or ordinary file (POSIX.1) */ #ifdef HAVE_MKNOD PHP_FUNCTION(posix_mknod) { zend_string *path; zend_long mode; zend_long major = 0, minor = 0; int result; dev_t php_dev = 0; ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_PATH_STR(path) Z_PARAM_LONG(mode) Z_PARAM_OPTIONAL Z_PARAM_LONG(major) Z_PARAM_LONG(minor) ZEND_PARSE_PARAMETERS_END(); if (php_check_open_basedir_ex(ZSTR_VAL(path), 0)) { RETURN_FALSE; } if ((mode & S_IFCHR) || (mode & S_IFBLK)) { if (major == 0) { zend_argument_value_error(3, "cannot be 0 for the POSIX_S_IFCHR and POSIX_S_IFBLK modes"); RETURN_THROWS(); } else { #ifdef HAVE_MAKEDEV php_dev = makedev(major, minor); #else php_error_docref(NULL, E_WARNING, "Cannot create a block or character device, creating a normal file instead"); #endif } } result = mknod(ZSTR_VAL(path), mode, php_dev); if (result < 0) { POSIX_G(last_error) = errno; RETURN_FALSE; } RETURN_TRUE; } #endif /* }}} */ /* Takes a pointer to posix group and a pointer to an already initialized ZVAL * array container and fills the array with the posix group member data. */ int php_posix_group_to_array(struct group *g, zval *array_group) /* {{{ */ { zval array_members; int count; if (NULL == g) return 0; if (array_group == NULL || Z_TYPE_P(array_group) != IS_ARRAY) return 0; array_init(&array_members); add_assoc_string(array_group, "name", g->gr_name); if (g->gr_passwd) { add_assoc_string(array_group, "passwd", g->gr_passwd); } else { add_assoc_null(array_group, "passwd"); } for (count = 0;; count++) { /* gr_mem entries may be misaligned on macos. */ char *gr_mem; memcpy(&gr_mem, &g->gr_mem[count], sizeof(char *)); if (!gr_mem) { break; } add_next_index_string(&array_members, gr_mem); } zend_hash_str_update(Z_ARRVAL_P(array_group), "members", sizeof("members")-1, &array_members); add_assoc_long(array_group, "gid", g->gr_gid); return 1; } /* }}} */ /* POSIX.1, 5.5.1 unlink() POSIX.1, 5.5.2 rmdir() POSIX.1, 5.5.3 rename() POSIX.1, 5.6.x stat(), chmod(), utime() already supported by PHP. */ /* {{{ Determine accessibility of a file (POSIX.1 5.6.3) */ PHP_FUNCTION(posix_access) { zend_long mode = 0; size_t filename_len, ret; char *filename, *path; ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_PATH(filename, filename_len) Z_PARAM_OPTIONAL Z_PARAM_LONG(mode) ZEND_PARSE_PARAMETERS_END(); path = expand_filepath(filename, NULL); if (!path) { POSIX_G(last_error) = EIO; RETURN_FALSE; } if (php_check_open_basedir_ex(path, 0)) { efree(path); POSIX_G(last_error) = EPERM; RETURN_FALSE; } ret = access(path, mode); efree(path); if (ret) { POSIX_G(last_error) = errno; RETURN_FALSE; } RETURN_TRUE; } #ifdef HAVE_EACCESS PHP_FUNCTION(posix_eaccess) { zend_long mode = 0; size_t filename_len, ret; char *filename, *path; ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_PATH(filename, filename_len) Z_PARAM_OPTIONAL Z_PARAM_LONG(mode) ZEND_PARSE_PARAMETERS_END(); path = expand_filepath(filename, NULL); if (!path) { zend_argument_value_error(1, "cannot be empty"); RETURN_THROWS(); } if (php_check_open_basedir_ex(path, 0)) { efree(path); POSIX_G(last_error) = EPERM; RETURN_FALSE; } ret = eaccess(path, mode); efree(path); if (ret) { POSIX_G(last_error) = errno; RETURN_FALSE; } RETURN_TRUE; } #endif /* }}} */ /* POSIX.1, 6.x most I/O functions already supported by PHP. POSIX.1, 7.x tty functions, TODO POSIX.1, 8.x interactions with other C language functions POSIX.1, 9.x system database access */ /* {{{ Group database access (POSIX.1, 9.2.1) */ PHP_FUNCTION(posix_getgrnam) { char *name; struct group *g; size_t name_len; #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX) struct group gbuf; long buflen; char *buf; int err; #endif ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_STRING(name, name_len) ZEND_PARSE_PARAMETERS_END(); #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX) buflen = sysconf(_SC_GETGR_R_SIZE_MAX); if (buflen < 1) { buflen = 1024; } #if ZEND_DEBUG /* Test retry logic */ buflen = 1; #endif buf = emalloc(buflen); try_again: g = &gbuf; err = getgrnam_r(name, g, buf, buflen, &g); if (err || g == NULL) { if (err == ERANGE) { buflen *= 2; buf = erealloc(buf, buflen); goto try_again; } POSIX_G(last_error) = err; efree(buf); RETURN_FALSE; } #else if (NULL == (g = getgrnam(name))) { POSIX_G(last_error) = errno; RETURN_FALSE; } #endif array_init(return_value); if (!php_posix_group_to_array(g, return_value)) { zend_array_destroy(Z_ARR_P(return_value)); php_error_docref(NULL, E_WARNING, "Unable to convert posix group to array"); RETVAL_FALSE; } #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX) efree(buf); #endif } /* }}} */ /* {{{ Group database access (POSIX.1, 9.2.1) */ PHP_FUNCTION(posix_getgrgid) { zend_long gid; #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX) int err; struct group _g; struct group *retgrptr = NULL; long grbuflen; char *grbuf; #endif struct group *g; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_LONG(gid) ZEND_PARSE_PARAMETERS_END(); #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX) grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); if (grbuflen < 1) { grbuflen = 1024; } #if ZEND_DEBUG /* Test retry logic */ grbuflen = 1; #endif grbuf = emalloc(grbuflen); try_again: err = getgrgid_r(gid, &_g, grbuf, grbuflen, &retgrptr); if (err || retgrptr == NULL) { if (err == ERANGE) { grbuflen *= 2; grbuf = erealloc(grbuf, grbuflen); goto try_again; } POSIX_G(last_error) = err; efree(grbuf); RETURN_FALSE; } g = &_g; #else if (NULL == (g = getgrgid(gid))) { POSIX_G(last_error) = errno; RETURN_FALSE; } #endif array_init(return_value); if (!php_posix_group_to_array(g, return_value)) { zend_array_destroy(Z_ARR_P(return_value)); php_error_docref(NULL, E_WARNING, "Unable to convert posix group struct to array"); RETVAL_FALSE; } #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX) efree(grbuf); #endif } /* }}} */ int php_posix_passwd_to_array(struct passwd *pw, zval *return_value) /* {{{ */ { if (NULL == pw) return 0; if (NULL == return_value || Z_TYPE_P(return_value) != IS_ARRAY) return 0; add_assoc_string(return_value, "name", pw->pw_name); add_assoc_string(return_value, "passwd", pw->pw_passwd); add_assoc_long (return_value, "uid", pw->pw_uid); add_assoc_long (return_value, "gid", pw->pw_gid); add_assoc_string(return_value, "gecos", pw->pw_gecos); add_assoc_string(return_value, "dir", pw->pw_dir); add_assoc_string(return_value, "shell", pw->pw_shell); return 1; } /* }}} */ /* {{{ User database access (POSIX.1, 9.2.2) */ PHP_FUNCTION(posix_getpwnam) { struct passwd *pw; char *name; size_t name_len; #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R) struct passwd pwbuf; long buflen; char *buf; int err; #endif ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_STRING(name, name_len) ZEND_PARSE_PARAMETERS_END(); #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R) buflen = sysconf(_SC_GETPW_R_SIZE_MAX); if (buflen < 1) { buflen = 1024; } #if ZEND_DEBUG /* Test retry logic */ buflen = 1; #endif buf = emalloc(buflen); try_again: pw = &pwbuf; err = getpwnam_r(name, pw, buf, buflen, &pw); if (err || pw == NULL) { if (err == ERANGE) { buflen *= 2; buf = erealloc(buf, buflen); goto try_again; } efree(buf); POSIX_G(last_error) = err; RETURN_FALSE; } #else if (NULL == (pw = getpwnam(name))) { POSIX_G(last_error) = errno; RETURN_FALSE; } #endif array_init(return_value); if (!php_posix_passwd_to_array(pw, return_value)) { zend_array_destroy(Z_ARR_P(return_value)); php_error_docref(NULL, E_WARNING, "Unable to convert posix passwd struct to array"); RETVAL_FALSE; } #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R) efree(buf); #endif } /* }}} */ /* {{{ User database access (POSIX.1, 9.2.2) */ PHP_FUNCTION(posix_getpwuid) { zend_long uid; #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R) struct passwd _pw; struct passwd *retpwptr = NULL; long pwbuflen; char *pwbuf; int err; #endif struct passwd *pw; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_LONG(uid) ZEND_PARSE_PARAMETERS_END(); #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R) pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); if (pwbuflen < 1) { pwbuflen = 1024; } #if ZEND_DEBUG /* Test retry logic */ pwbuflen = 1; #endif pwbuf = emalloc(pwbuflen); try_again: err = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr); if (err || retpwptr == NULL) { if (err == ERANGE) { pwbuflen *= 2; pwbuf = erealloc(pwbuf, pwbuflen); goto try_again; } POSIX_G(last_error) = err; efree(pwbuf); RETURN_FALSE; } pw = &_pw; #else if (NULL == (pw = getpwuid(uid))) { POSIX_G(last_error) = errno; RETURN_FALSE; } #endif array_init(return_value); if (!php_posix_passwd_to_array(pw, return_value)) { zend_array_destroy(Z_ARR_P(return_value)); php_error_docref(NULL, E_WARNING, "Unable to convert posix passwd struct to array"); RETVAL_FALSE; } #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R) efree(pwbuf); #endif } /* }}} */ #ifdef HAVE_GETRLIMIT #define UNLIMITED_STRING "unlimited" /* {{{ posix_addlimit */ static zend_result posix_addlimit(int limit, const char *name, zval *return_value) { int result; struct rlimit rl; char hard[80]; char soft[80]; snprintf(hard, 80, "hard %s", name); snprintf(soft, 80, "soft %s", name); result = getrlimit(limit, &rl); if (result < 0) { POSIX_G(last_error) = errno; return FAILURE; } if (rl.rlim_cur == RLIM_INFINITY) { add_assoc_stringl(return_value, soft, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1); } else { add_assoc_long(return_value, soft, rl.rlim_cur); } if (rl.rlim_max == RLIM_INFINITY) { add_assoc_stringl(return_value, hard, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1); } else { add_assoc_long(return_value, hard, rl.rlim_max); } return SUCCESS; } /* }}} */ /* {{{ limits[] */ static const struct limitlist { int limit; const char *name; } limits[] = { #ifdef RLIMIT_CORE { RLIMIT_CORE, "core" }, #endif #ifdef RLIMIT_DATA { RLIMIT_DATA, "data" }, #endif #ifdef RLIMIT_STACK { RLIMIT_STACK, "stack" }, #endif #ifdef RLIMIT_VMEM { RLIMIT_VMEM, "virtualmem" }, #endif #ifdef RLIMIT_AS { RLIMIT_AS, "totalmem" }, #endif #ifdef RLIMIT_RSS { RLIMIT_RSS, "rss" }, #endif #ifdef RLIMIT_NPROC { RLIMIT_NPROC, "maxproc" }, #endif #ifdef RLIMIT_MEMLOCK { RLIMIT_MEMLOCK, "memlock" }, #endif #ifdef RLIMIT_CPU { RLIMIT_CPU, "cpu" }, #endif #ifdef RLIMIT_FSIZE { RLIMIT_FSIZE, "filesize" }, #endif #ifdef RLIMIT_NOFILE { RLIMIT_NOFILE, "openfiles" }, #endif #ifdef RLIMIT_OFILE { RLIMIT_OFILE, "openfiles" }, #endif #ifdef RLIMIT_KQUEUES { RLIMIT_KQUEUES, "kqueues" }, #endif #ifdef RLIMIT_NPTS { RLIMIT_NPTS, "npts" }, #endif { 0, NULL } }; /* }}} */ /* {{{ Get system resource consumption limits (This is not a POSIX function, but a BSDism and a SVR4ism. We compile conditionally) */ PHP_FUNCTION(posix_getrlimit) { const struct limitlist *l = NULL; zend_long res; bool res_is_null = true; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(res, res_is_null) ZEND_PARSE_PARAMETERS_END(); if (res_is_null) { array_init(return_value); for (l=limits; l->name; l++) { if (posix_addlimit(l->limit, l->name, return_value) == FAILURE) { zend_array_destroy(Z_ARR_P(return_value)); RETURN_FALSE; } } } else { struct rlimit rl; int result = getrlimit(res, &rl); if (result < 0) { POSIX_G(last_error) = errno; RETURN_FALSE; } array_init(return_value); if (rl.rlim_cur == RLIM_INFINITY) { add_next_index_stringl(return_value, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1); } else { add_next_index_long(return_value, rl.rlim_cur); } if (rl.rlim_max == RLIM_INFINITY) { add_next_index_stringl(return_value, UNLIMITED_STRING, sizeof(UNLIMITED_STRING)-1); } else { add_next_index_long(return_value, rl.rlim_max); } } } /* }}} */ #endif /* HAVE_GETRLIMIT */ #ifdef HAVE_SETRLIMIT /* {{{ Set system resource consumption limits (POSIX.1-2001) */ PHP_FUNCTION(posix_setrlimit) { struct rlimit rl; zend_long res, cur, max; ZEND_PARSE_PARAMETERS_START(3, 3) Z_PARAM_LONG(res) Z_PARAM_LONG(cur) Z_PARAM_LONG(max) ZEND_PARSE_PARAMETERS_END(); rl.rlim_cur = cur; rl.rlim_max = max; if (setrlimit(res, &rl) == -1) { POSIX_G(last_error) = errno; RETURN_FALSE; } RETURN_TRUE; } /* }}} */ #endif /* HAVE_SETRLIMIT */ /* {{{ Retrieve the error number set by the last posix function which failed. */ PHP_FUNCTION(posix_get_last_error) { ZEND_PARSE_PARAMETERS_NONE(); RETURN_LONG(POSIX_G(last_error)); } /* }}} */ /* {{{ Retrieve the system error message associated with the given errno. */ PHP_FUNCTION(posix_strerror) { zend_long error; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_LONG(error) ZEND_PARSE_PARAMETERS_END(); RETURN_STRING(strerror(error)); } /* }}} */ #endif #ifdef HAVE_INITGROUPS /* {{{ Calculate the group access list for the user specified in name. */ PHP_FUNCTION(posix_initgroups) { zend_long basegid; char *name; size_t name_len; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_STRING(name, name_len) Z_PARAM_LONG(basegid) ZEND_PARSE_PARAMETERS_END(); if (name_len == 0) { RETURN_FALSE; } RETURN_BOOL(!initgroups((const char *)name, basegid)); } /* }}} */ #endif PHP_FUNCTION(posix_sysconf) { zend_long conf_id; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_LONG(conf_id) ZEND_PARSE_PARAMETERS_END(); RETURN_LONG(sysconf(conf_id)); } #ifdef HAVE_PATHCONF PHP_FUNCTION(posix_pathconf) { zend_long name, ret; char *path; size_t path_len; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_PATH(path, path_len) Z_PARAM_LONG(name); ZEND_PARSE_PARAMETERS_END(); if (path_len == 0) { zend_argument_value_error(1, "cannot be empty"); RETURN_THROWS(); } else if (php_check_open_basedir(path)) { php_error_docref(NULL, E_WARNING, "Invalid path supplied: %s", path); RETURN_FALSE; } ret = pathconf(path, name); if (ret < 0 && errno != 0) { POSIX_G(last_error) = errno; RETURN_FALSE; } RETURN_LONG(ret); } #endif #ifdef HAVE_FPATHCONF PHP_FUNCTION(posix_fpathconf) { zend_long name, ret, fd = 0; zval *z_fd; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_ZVAL(z_fd) Z_PARAM_LONG(name); ZEND_PARSE_PARAMETERS_END(); if (Z_TYPE_P(z_fd) == IS_RESOURCE) { if (php_posix_stream_get_fd(z_fd, &fd) == FAILURE) { RETURN_FALSE; } } else { if (!zend_parse_arg_long(z_fd, &fd, /* is_null */ NULL, /* check_null */ false, /* arg_num */ 1)) { zend_argument_type_error(1, "must be of type int|resource, %s given", zend_zval_value_name(z_fd)); RETURN_THROWS(); } } ret = fpathconf(fd, name); if (ret < 0 && errno != 0) { POSIX_G(last_error) = errno; RETURN_FALSE; } RETURN_LONG(ret); } #endif