#ifndef ZEND_WIN32
# include <sys/types.h>
+# include <sys/wait.h>
# include <sys/ipc.h>
+# include <pwd.h>
+# include <grp.h>
#endif
#include <sys/stat.h>
}
if (ZCG(accel_directives).preload && *ZCG(accel_directives).preload) {
+#ifndef ZEND_WIN32
+ int in_child = 0;
+#endif
int ret = SUCCESS;
int rc;
int orig_error_reporting;
return SUCCESS;
}
+#ifndef ZEND_WIN32
+ if (geteuid() == 0) {
+ pid_t pid;
+ struct passwd *pw;
+
+ if (!ZCG(accel_directives).preload_user
+ || !*ZCG(accel_directives).preload_user) {
+ zend_shared_alloc_unlock();
+ zend_accel_error(ACCEL_LOG_FATAL, "\"opcache.preload_user\" has not been defined");
+ return FAILURE;
+ }
+
+ pw = getpwnam(ZCG(accel_directives).preload_user);
+ if (pw == NULL) {
+ zend_shared_alloc_unlock();
+ zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to getpwnam(\"%s\")", ZCG(accel_directives).preload_user);
+ return FAILURE;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ zend_shared_alloc_unlock();
+ zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to fork()");
+ return FAILURE;
+ } else if (pid == 0) { /* children */
+ if (setgid(pw->pw_gid) < 0) {
+ zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setgid(%d)", pw->pw_gid);
+ exit(1);
+ }
+ if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
+ zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to initgroups(\"%s\", %d)", pw->pw_name, pw->pw_uid);
+ exit(1);
+ }
+ if (setuid(pw->pw_uid) < 0) {
+ zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setuid(%d)", pw->pw_uid);
+ exit(1);
+ }
+ in_child = 1;
+ } else { /* parent */
+ int status;
+
+ if (waitpid(pid, &status, 0) < 0) {
+ zend_shared_alloc_unlock();
+ zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
+ return FAILURE;
+ }
+ zend_shared_alloc_unlock();
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ return SUCCESS;
+ } else {
+ return FAILURE;
+ }
+ }
+ } else {
+ if (ZCG(accel_directives).preload_user
+ && *ZCG(accel_directives).preload_user) {
+ zend_accel_error(ACCEL_LOG_WARNING, "\"opcache.preload_user\" is ignored");
+ }
+ }
+#endif
+
sapi_module.activate = NULL;
sapi_module.deactivate = NULL;
sapi_module.register_server_variables = NULL;
sapi_activate();
+#ifndef ZEND_WIN32
+ if (in_child) {
+ if (ret == SUCCESS) {
+ exit(0);
+ } else {
+ exit(2);
+ }
+ }
+#endif
+
return ret;
}
STD_PHP_INI_BOOLEAN("opcache.huge_code_pages" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.huge_code_pages, zend_accel_globals, accel_globals)
#endif
STD_PHP_INI_ENTRY("opcache.preload" , "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.preload, zend_accel_globals, accel_globals)
+#ifndef ZEND_WIN32
+ STD_PHP_INI_ENTRY("opcache.preload_user" , "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.preload_user, zend_accel_globals, accel_globals)
+#endif
#if ZEND_WIN32
STD_PHP_INI_ENTRY("opcache.cache_id" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.cache_id, zend_accel_globals, accel_globals)
#endif
add_assoc_bool(&directives, "opcache.huge_code_pages", ZCG(accel_directives).huge_code_pages);
#endif
add_assoc_string(&directives, "opcache.preload", STRING_NOT_NULL(ZCG(accel_directives).preload));
+#ifndef ZEND_WIN32
+ add_assoc_string(&directives, "opcache.preload_user", STRING_NOT_NULL(ZCG(accel_directives).preload_user));
+#endif
#if ZEND_WIN32
add_assoc_string(&directives, "opcache.cache_id", STRING_NOT_NULL(ZCG(accel_directives).cache_id));
#endif