static int fpm_conf_post_process(TSRMLS_D) /* {{{ */ { struct fpm_worker_pool_s *wp; if (fpm_global_config.pid_file) { fpm_evaluate_full_path(&fpm_global_config.pid_file, NULL, PHP_LOCALSTATEDIR, 0); } fpm_globals.log_level = fpm_global_config.log_level; if (fpm_global_config.process_max < 0) { zlog(ZLOG_ERROR, "process_max can't be negative"); return -1; } if (!fpm_global_config.error_log) { fpm_global_config.error_log = strdup("log/php-fpm.log"); } #ifdef HAVE_SYSLOG_H if (!fpm_global_config.syslog_ident) { fpm_global_config.syslog_ident = strdup("php-fpm"); } if (fpm_global_config.syslog_facility < 0) { fpm_global_config.syslog_facility = LOG_DAEMON; } if (strcasecmp(fpm_global_config.error_log, "syslog") != 0) #endif { fpm_evaluate_full_path(&fpm_global_config.error_log, NULL, PHP_LOCALSTATEDIR, 0); } if (0 > fpm_stdio_open_error_log(0)) { return -1; } if (0 > fpm_log_open(0)) { return -1; } if (0 > fpm_conf_process_all_pools()) { return -1; } for (wp = fpm_worker_all_pools; wp; wp = wp->next) { if (!wp->config->access_log || !*wp->config->access_log) { continue; } if (0 > fpm_log_write(wp->config->access_format TSRMLS_CC)) { zlog(ZLOG_ERROR, "[pool %s] wrong format for access.format '%s'", wp->config->name, wp->config->access_format); return -1; } } return 0; }
static int fpm_evaluate_full_path(char **path, struct fpm_worker_pool_s *wp, char *default_prefix, int expand) /* {{{ */ { char *prefix = NULL; char *full_path; if (!path || !*path || **path == '/') { return 0; } if (wp && wp->config) { prefix = wp->config->prefix; } /* if the wp prefix is not set */ if (prefix == NULL) { prefix = fpm_globals.prefix; } /* if the global prefix is not set */ if (prefix == NULL) { prefix = default_prefix ? default_prefix : PHP_PREFIX; } if (expand) { char *tmp; tmp = strstr(*path, "$prefix"); if (tmp != NULL) { if (tmp != *path) { zlog(ZLOG_ERROR, "'$prefix' must be use at the beginning of the value"); return -1; } if (strlen(*path) > strlen("$prefix")) { free(*path); tmp = strdup((*path) + strlen("$prefix")); *path = tmp; } else { free(*path); *path = NULL; } } } if (*path) { spprintf(&full_path, 0, "%s/%s", prefix, *path); free(*path); *path = strdup(full_path); efree(full_path); } else { *path = strdup(prefix); } if (**path != '/' && wp != NULL && wp->config) { return fpm_evaluate_full_path(path, NULL, default_prefix, expand); } return 0; }
static int fpm_conf_process_all_pools() /* {{{ */ { struct fpm_worker_pool_s *wp, *wp2; if (!fpm_worker_all_pools) { zlog(ZLOG_ERROR, "No pool defined. at least one pool section must be specified in config file"); return -1; } for (wp = fpm_worker_all_pools; wp; wp = wp->next) { /* prefix */ if (wp->config->prefix && *wp->config->prefix) { fpm_evaluate_full_path(&wp->config->prefix, NULL, NULL, 0); if (!fpm_conf_is_dir(wp->config->prefix)) { zlog(ZLOG_ERROR, "[pool %s] the prefix '%s' does not exist or is not a directory", wp->config->name, wp->config->prefix); return -1; } } /* alert if user is not set only if we are not root*/ if (!wp->config->user && !geteuid()) { zlog(ZLOG_ALERT, "[pool %s] user has not been defined", wp->config->name); return -1; } /* listen */ if (wp->config->listen_address && *wp->config->listen_address) { wp->listen_address_domain = fpm_sockets_domain_from_address(wp->config->listen_address); if (wp->listen_address_domain == FPM_AF_UNIX && *wp->config->listen_address != '/') { fpm_evaluate_full_path(&wp->config->listen_address, wp, NULL, 0); } } else { zlog(ZLOG_ALERT, "[pool %s] no listen address have been defined!", wp->config->name); return -1; } if (wp->config->process_priority != 64 && (wp->config->process_priority < -19 || wp->config->process_priority > 20)) { zlog(ZLOG_ERROR, "[pool %s] process.priority must be included into [-19,20]", wp->config->name); return -1; } /* pm */ if (wp->config->pm != PM_STYLE_STATIC && wp->config->pm != PM_STYLE_DYNAMIC && wp->config->pm != PM_STYLE_ONDEMAND) { zlog(ZLOG_ALERT, "[pool %s] the process manager is missing (static, dynamic or ondemand)", wp->config->name); return -1; } /* pm.max_children */ if (wp->config->pm_max_children < 1) { zlog(ZLOG_ALERT, "[pool %s] pm.max_children must be a positive value", wp->config->name); return -1; } /* pm.start_servers, pm.min_spare_servers, pm.max_spare_servers */ if (wp->config->pm == PM_STYLE_DYNAMIC) { struct fpm_worker_pool_config_s *config = wp->config; if (config->pm_min_spare_servers <= 0) { zlog(ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) must be a positive value", wp->config->name, config->pm_min_spare_servers); return -1; } if (config->pm_max_spare_servers <= 0) { zlog(ZLOG_ALERT, "[pool %s] pm.max_spare_servers(%d) must be a positive value", wp->config->name, config->pm_max_spare_servers); return -1; } if (config->pm_min_spare_servers > config->pm_max_children || config->pm_max_spare_servers > config->pm_max_children) { zlog(ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) and pm.max_spare_servers(%d) cannot be greater than pm.max_children(%d)", wp->config->name, config->pm_min_spare_servers, config->pm_max_spare_servers, config->pm_max_children); return -1; } if (config->pm_max_spare_servers < config->pm_min_spare_servers) { zlog(ZLOG_ALERT, "[pool %s] pm.max_spare_servers(%d) must not be less than pm.min_spare_servers(%d)", wp->config->name, config->pm_max_spare_servers, config->pm_min_spare_servers); return -1; } if (config->pm_start_servers <= 0) { config->pm_start_servers = config->pm_min_spare_servers + ((config->pm_max_spare_servers - config->pm_min_spare_servers) / 2); zlog(ZLOG_NOTICE, "[pool %s] pm.start_servers is not set. It's been set to %d.", wp->config->name, config->pm_start_servers); } else if (config->pm_start_servers < config->pm_min_spare_servers || config->pm_start_servers > config->pm_max_spare_servers) { zlog(ZLOG_ALERT, "[pool %s] pm.start_servers(%d) must not be less than pm.min_spare_servers(%d) and not greater than pm.max_spare_servers(%d)", wp->config->name, config->pm_start_servers, config->pm_min_spare_servers, config->pm_max_spare_servers); return -1; } } else if (wp->config->pm == PM_STYLE_ONDEMAND) { struct fpm_worker_pool_config_s *config = wp->config; if (!fpm_event_support_edge_trigger()) { zlog(ZLOG_ALERT, "[pool %s] ondemand process manager can ONLY be used when events.mechanisme is either epoll (Linux) or kqueue (*BSD).", wp->config->name); return -1; } if (config->pm_process_idle_timeout < 1) { zlog(ZLOG_ALERT, "[pool %s] pm.process_idle_timeout(%ds) must be greater than 0s", wp->config->name, config->pm_process_idle_timeout); return -1; } if (config->listen_backlog < FPM_BACKLOG_DEFAULT) { zlog(ZLOG_WARNING, "[pool %s] listen.backlog(%d) was too low for the ondemand process manager. I updated it for you to %d.", wp->config->name, config->listen_backlog, FPM_BACKLOG_DEFAULT); config->listen_backlog = FPM_BACKLOG_DEFAULT; } /* certainely useless but proper */ config->pm_start_servers = 0; config->pm_min_spare_servers = 0; config->pm_max_spare_servers = 0; } /* status */ if (wp->config->pm_status_path && *wp->config->pm_status_path) { size_t i; char *status = wp->config->pm_status_path; if (*status != '/') { zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must start with a '/'", wp->config->name, status); return -1; } if (strlen(status) < 2) { zlog(ZLOG_ERROR, "[pool %s] the status path '%s' is not long enough", wp->config->name, status); return -1; } for (i = 0; i < strlen(status); i++) { if (!isalnum(status[i]) && status[i] != '/' && status[i] != '-' && status[i] != '_' && status[i] != '.') { zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must contain only the following characters '[alphanum]/_-.'", wp->config->name, status); return -1; } } } /* ping */ if (wp->config->ping_path && *wp->config->ping_path) { char *ping = wp->config->ping_path; size_t i; if (*ping != '/') { zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must start with a '/'", wp->config->name, ping); return -1; } if (strlen(ping) < 2) { zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' is not long enough", wp->config->name, ping); return -1; } for (i = 0; i < strlen(ping); i++) { if (!isalnum(ping[i]) && ping[i] != '/' && ping[i] != '-' && ping[i] != '_' && ping[i] != '.') { zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must containt only the following characters '[alphanum]/_-.'", wp->config->name, ping); return -1; } } if (!wp->config->ping_response) { wp->config->ping_response = strdup("pong"); } else { if (strlen(wp->config->ping_response) < 1) { zlog(ZLOG_ERROR, "[pool %s] the ping response page '%s' is not long enough", wp->config->name, wp->config->ping_response); return -1; } } } else { if (wp->config->ping_response) { free(wp->config->ping_response); wp->config->ping_response = NULL; } } /* access.log, access.format */ if (wp->config->access_log && *wp->config->access_log) { fpm_evaluate_full_path(&wp->config->access_log, wp, NULL, 0); if (!wp->config->access_format) { wp->config->access_format = strdup("%R - %u %t \"%m %r\" %s"); } } if (wp->config->request_terminate_timeout) { fpm_globals.heartbeat = fpm_globals.heartbeat ? MIN(fpm_globals.heartbeat, (wp->config->request_terminate_timeout * 1000) / 3) : (wp->config->request_terminate_timeout * 1000) / 3; } /* slowlog */ if (wp->config->slowlog && *wp->config->slowlog) { fpm_evaluate_full_path(&wp->config->slowlog, wp, NULL, 0); } /* request_slowlog_timeout */ if (wp->config->request_slowlog_timeout) { #if HAVE_FPM_TRACE if (! (wp->config->slowlog && *wp->config->slowlog)) { zlog(ZLOG_ERROR, "[pool %s] 'slowlog' must be specified for use with 'request_slowlog_timeout'", wp->config->name); return -1; } #else static int warned = 0; if (!warned) { zlog(ZLOG_WARNING, "[pool %s] 'request_slowlog_timeout' is not supported on your system", wp->config->name); warned = 1; } wp->config->request_slowlog_timeout = 0; #endif if (wp->config->slowlog && *wp->config->slowlog) { int fd; fd = open(wp->config->slowlog, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); if (0 > fd) { zlog(ZLOG_SYSERROR, "Unable to create or open slowlog(%s)", wp->config->slowlog); return -1; } close(fd); } fpm_globals.heartbeat = fpm_globals.heartbeat ? MIN(fpm_globals.heartbeat, (wp->config->request_slowlog_timeout * 1000) / 3) : (wp->config->request_slowlog_timeout * 1000) / 3; if (wp->config->request_terminate_timeout && wp->config->request_slowlog_timeout > wp->config->request_terminate_timeout) { zlog(ZLOG_ERROR, "[pool %s] 'request_slowlog_timeout' (%d) can't be greater than 'request_terminate_timeout' (%d)", wp->config->name, wp->config->request_slowlog_timeout, wp->config->request_terminate_timeout); return -1; } } /* chroot */ if (wp->config->chroot && *wp->config->chroot) { fpm_evaluate_full_path(&wp->config->chroot, wp, NULL, 1); if (*wp->config->chroot != '/') { zlog(ZLOG_ERROR, "[pool %s] the chroot path '%s' must start with a '/'", wp->config->name, wp->config->chroot); return -1; } if (!fpm_conf_is_dir(wp->config->chroot)) { zlog(ZLOG_ERROR, "[pool %s] the chroot path '%s' does not exist or is not a directory", wp->config->name, wp->config->chroot); return -1; } } /* chdir */ if (wp->config->chdir && *wp->config->chdir) { fpm_evaluate_full_path(&wp->config->chdir, wp, NULL, 0); if (*wp->config->chdir != '/') { zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' must start with a '/'", wp->config->name, wp->config->chdir); return -1; } if (wp->config->chroot) { char *buf; spprintf(&buf, 0, "%s/%s", wp->config->chroot, wp->config->chdir); if (!fpm_conf_is_dir(buf)) { zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' within the chroot path '%s' ('%s') does not exist or is not a directory", wp->config->name, wp->config->chdir, wp->config->chroot, buf); efree(buf); return -1; } efree(buf); } else { if (!fpm_conf_is_dir(wp->config->chdir)) { zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' does not exist or is not a directory", wp->config->name, wp->config->chdir); return -1; } } } /* security.limit_extensions */ if (!wp->config->security_limit_extensions) { wp->config->security_limit_extensions = strdup(".php .phar"); } if (*wp->config->security_limit_extensions) { int nb_ext; char *ext; char *security_limit_extensions; char *limit_extensions; /* strdup because strtok(3) alters the string it parses */ security_limit_extensions = strdup(wp->config->security_limit_extensions); limit_extensions = security_limit_extensions; nb_ext = 0; /* find the number of extensions */ while (strtok(limit_extensions, " \t")) { limit_extensions = NULL; nb_ext++; } free(security_limit_extensions); /* if something found */ if (nb_ext > 0) { /* malloc the extension array */ wp->limit_extensions = malloc(sizeof(char *) * (nb_ext + 1)); if (!wp->limit_extensions) { zlog(ZLOG_ERROR, "[pool %s] unable to malloc extensions array", wp->config->name); return -1; } /* strdup because strtok(3) alters the string it parses */ security_limit_extensions = strdup(wp->config->security_limit_extensions); limit_extensions = security_limit_extensions; nb_ext = 0; /* parse the string and save the extension in the array */ while ((ext = strtok(limit_extensions, " \t"))) { limit_extensions = NULL; wp->limit_extensions[nb_ext++] = strdup(ext); } /* end the array with NULL in order to parse it */ wp->limit_extensions[nb_ext] = NULL; free(security_limit_extensions); } } /* env[], php_value[], php_admin_values[] */ if (!wp->config->chroot) { struct key_value_s *kv; char *options[] = FPM_PHP_INI_TO_EXPAND; char **p; for (kv = wp->config->php_values; kv; kv = kv->next) { for (p = options; *p; p++) { if (!strcasecmp(kv->key, *p)) { fpm_evaluate_full_path(&kv->value, wp, NULL, 0); } } } for (kv = wp->config->php_admin_values; kv; kv = kv->next) { if (!strcasecmp(kv->key, "error_log") && !strcasecmp(kv->value, "syslog")) { continue; } for (p = options; *p; p++) { if (!strcasecmp(kv->key, *p)) { fpm_evaluate_full_path(&kv->value, wp, NULL, 0); } } } } } /* ensure 2 pools do not use the same listening address */ for (wp = fpm_worker_all_pools; wp; wp = wp->next) { for (wp2 = fpm_worker_all_pools; wp2; wp2 = wp2->next) { if (wp == wp2) { continue; } if (wp->config->listen_address && *wp->config->listen_address && wp2->config->listen_address && *wp2->config->listen_address && !strcmp(wp->config->listen_address, wp2->config->listen_address)) { zlog(ZLOG_ERROR, "[pool %s] unable to set listen address as it's already used in another pool '%s'", wp2->config->name, wp->config->name); return -1; } } } return 0; }
int fpm_conf_load_ini_file(char *filename) /* {{{ */ { int error = 0; char *buf = NULL, *newbuf = NULL; int bufsize = 0; int fd, n; int nb_read = 1; char c = '*'; int ret = 1; if (!filename || !filename[0]) { zlog(ZLOG_ERROR, "configuration filename is empty"); return -1; } fd = open(filename, O_RDONLY, 0); if (fd < 0) { zlog(ZLOG_SYSERROR, "failed to open configuration file '%s'", filename); return -1; } if (ini_recursion++ > 4) { zlog(ZLOG_ERROR, "failed to include more than 5 files recusively"); close(fd); return -1; } ini_lineno = 0; while (nb_read > 0) { int tmp; ini_lineno++; ini_filename = filename; for (n = 0; (nb_read = read(fd, &c, sizeof(char))) == sizeof(char) && c != '\n'; n++) { if (n == bufsize) { bufsize += 1024; newbuf = (char*) realloc(buf, sizeof(char) * (bufsize + 2)); if (newbuf == NULL) { ini_recursion--; close(fd); free(buf); return -1; } buf = newbuf; } buf[n] = c; } if (n == 0) { continue; } /* always append newline and null terminate */ buf[n++] = '\n'; buf[n] = '\0'; tmp = zend_parse_ini_string(buf, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fpm_conf_ini_parser, &error); ini_filename = filename; if (error || tmp == FAILURE) { if (ini_include) free(ini_include); ini_recursion--; close(fd); free(buf); return -1; } if (ini_include) { char *tmp = ini_include; ini_include = NULL; fpm_evaluate_full_path(&tmp, NULL, NULL, 0); fpm_conf_ini_parser_include(tmp, &error); if (error) { free(tmp); ini_recursion--; close(fd); free(buf); return -1; } free(tmp); } } free(buf); ini_recursion--; close(fd); return ret; }
static int fpm_conf_post_process(int force_daemon) /* {{{ */ { struct fpm_worker_pool_s *wp; if (fpm_global_config.pid_file) { fpm_evaluate_full_path(&fpm_global_config.pid_file, NULL, PHP_LOCALSTATEDIR, 0); } if (force_daemon >= 0) { /* forced from command line options */ fpm_global_config.daemonize = force_daemon; } fpm_globals.log_level = fpm_global_config.log_level; zlog_set_level(fpm_globals.log_level); if (fpm_global_config.process_max < 0) { zlog(ZLOG_ERROR, "process_max can't be negative"); return -1; } if (fpm_global_config.process_priority != 64 && (fpm_global_config.process_priority < -19 || fpm_global_config.process_priority > 20)) { zlog(ZLOG_ERROR, "process.priority must be included into [-19,20]"); return -1; } if (!fpm_global_config.error_log) { fpm_global_config.error_log = strdup("log/php-fpm.log"); } #ifdef HAVE_SYSTEMD if (0 > fpm_systemd_conf()) { return -1; } #endif #ifdef HAVE_SYSLOG_H if (!fpm_global_config.syslog_ident) { fpm_global_config.syslog_ident = strdup("php-fpm"); } if (fpm_global_config.syslog_facility < 0) { fpm_global_config.syslog_facility = LOG_DAEMON; } if (strcasecmp(fpm_global_config.error_log, "syslog") != 0) #endif { fpm_evaluate_full_path(&fpm_global_config.error_log, NULL, PHP_LOCALSTATEDIR, 0); } if (0 > fpm_stdio_open_error_log(0)) { return -1; } if (0 > fpm_event_pre_init(fpm_global_config.events_mechanism)) { return -1; } if (0 > fpm_conf_process_all_pools()) { return -1; } if (0 > fpm_log_open(0)) { return -1; } for (wp = fpm_worker_all_pools; wp; wp = wp->next) { if (!wp->config->access_log || !*wp->config->access_log) { continue; } if (0 > fpm_log_write(wp->config->access_format)) { zlog(ZLOG_ERROR, "[pool %s] wrong format for access.format '%s'", wp->config->name, wp->config->access_format); return -1; } } return 0; }
static int fpm_conf_process_all_pools() /* {{{ */ { struct fpm_worker_pool_s *wp; if (!fpm_worker_all_pools) { zlog(ZLOG_ERROR, "No pool defined. at least one pool section must be specified in config file"); return -1; } for (wp = fpm_worker_all_pools; wp; wp = wp->next) { /* prefix */ if (wp->config->prefix && *wp->config->prefix) { fpm_evaluate_full_path(&wp->config->prefix, NULL, NULL, 0); if (!fpm_conf_is_dir(wp->config->prefix)) { zlog(ZLOG_ERROR, "[pool %s] the prefix '%s' does not exist or is not a directory", wp->config->name, wp->config->prefix); return -1; } } /* user */ if (!wp->config->user) { zlog(ZLOG_ALERT, "[pool %s] user has not been defined", wp->config->name); return -1; } /* listen */ if (wp->config->listen_address && *wp->config->listen_address) { wp->listen_address_domain = fpm_sockets_domain_from_address(wp->config->listen_address); if (wp->listen_address_domain == FPM_AF_UNIX && *wp->config->listen_address != '/') { fpm_evaluate_full_path(&wp->config->listen_address, wp, NULL, 0); } } else { zlog(ZLOG_ALERT, "[pool %s] no listen address have been defined!", wp->config->name); return -1; } /* pm */ if (wp->config->pm != PM_STYLE_STATIC && wp->config->pm != PM_STYLE_DYNAMIC) { zlog(ZLOG_ALERT, "[pool %s] the process manager is missing (static or dynamic)", wp->config->name); return -1; } /* pm.max_children */ if (wp->config->pm_max_children < 1) { zlog(ZLOG_ALERT, "[pool %s] pm.max_children must be a positive value", wp->config->name); return -1; } /* pm.start_servers, pm.min_spare_servers, pm.max_spare_servers */ if (wp->config->pm == PM_STYLE_DYNAMIC) { struct fpm_worker_pool_config_s *config = wp->config; if (config->pm_min_spare_servers <= 0) { zlog(ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) must be a positive value", wp->config->name, config->pm_min_spare_servers); return -1; } if (config->pm_max_spare_servers <= 0) { zlog(ZLOG_ALERT, "[pool %s] pm.max_spare_servers(%d) must be a positive value", wp->config->name, config->pm_max_spare_servers); return -1; } if (config->pm_min_spare_servers > config->pm_max_children || config->pm_max_spare_servers > config->pm_max_children) { zlog(ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) and pm.max_spare_servers(%d) cannot be greater than pm.max_children(%d)", wp->config->name, config->pm_min_spare_servers, config->pm_max_spare_servers, config->pm_max_children); return -1; } if (config->pm_max_spare_servers < config->pm_min_spare_servers) { zlog(ZLOG_ALERT, "[pool %s] pm.max_spare_servers(%d) must not be less than pm.min_spare_servers(%d)", wp->config->name, config->pm_max_spare_servers, config->pm_min_spare_servers); return -1; } if (config->pm_start_servers <= 0) { config->pm_start_servers = config->pm_min_spare_servers + ((config->pm_max_spare_servers - config->pm_min_spare_servers) / 2); zlog(ZLOG_WARNING, "[pool %s] pm.start_servers is not set. It's been set to %d.", wp->config->name, config->pm_start_servers); } else if (config->pm_start_servers < config->pm_min_spare_servers || config->pm_start_servers > config->pm_max_spare_servers) { zlog(ZLOG_ALERT, "[pool %s] pm.start_servers(%d) must not be less than pm.min_spare_servers(%d) and not greater than pm.max_spare_servers(%d)", wp->config->name, config->pm_start_servers, config->pm_min_spare_servers, config->pm_max_spare_servers); return -1; } } /* status */ if (wp->config->pm_status_path && *wp->config->pm_status_path) { int i; char *status = wp->config->pm_status_path; if (*status != '/') { zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must start with a '/'", wp->config->name, status); return -1; } if (strlen(status) < 2) { zlog(ZLOG_ERROR, "[pool %s] the status path '%s' is not long enough", wp->config->name, status); return -1; } for (i = 0; i < strlen(status); i++) { if (!isalnum(status[i]) && status[i] != '/' && status[i] != '-' && status[i] != '_' && status[i] != '.') { zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must contain only the following characters '[alphanum]/_-.'", wp->config->name, status); return -1; } } } /* ping */ if (wp->config->ping_path && *wp->config->ping_path) { char *ping = wp->config->ping_path; int i; if (*ping != '/') { zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must start with a '/'", wp->config->name, ping); return -1; } if (strlen(ping) < 2) { zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' is not long enough", wp->config->name, ping); return -1; } for (i = 0; i < strlen(ping); i++) { if (!isalnum(ping[i]) && ping[i] != '/' && ping[i] != '-' && ping[i] != '_' && ping[i] != '.') { zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must containt only the following characters '[alphanum]/_-.'", wp->config->name, ping); return -1; } } if (!wp->config->ping_response) { wp->config->ping_response = strdup("pong"); } else { if (strlen(wp->config->ping_response) < 1) { zlog(ZLOG_ERROR, "[pool %s] the ping response page '%s' is not long enough", wp->config->name, wp->config->ping_response); return -1; } } } else { if (wp->config->ping_response) { free(wp->config->ping_response); wp->config->ping_response = NULL; } } /* access.log, access.format */ if (wp->config->access_log && *wp->config->access_log) { fpm_evaluate_full_path(&wp->config->access_log, wp, NULL, 0); if (!wp->config->access_format) { wp->config->access_format = strdup("%R - %u %t \"%m %r\" %s"); } } /* slowlog */ if (wp->config->slowlog && *wp->config->slowlog) { fpm_evaluate_full_path(&wp->config->slowlog, wp, NULL, 0); } /* request_slowlog_timeout */ if (wp->config->request_slowlog_timeout) { #if HAVE_FPM_TRACE if (! (wp->config->slowlog && *wp->config->slowlog)) { zlog(ZLOG_ERROR, "[pool %s] 'slowlog' must be specified for use with 'request_slowlog_timeout'", wp->config->name); return -1; } #else static int warned = 0; if (!warned) { zlog(ZLOG_WARNING, "[pool %s] 'request_slowlog_timeout' is not supported on your system", wp->config->name); warned = 1; } wp->config->request_slowlog_timeout = 0; #endif if (wp->config->slowlog && *wp->config->slowlog) { int fd; fd = open(wp->config->slowlog, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); if (0 > fd) { zlog(ZLOG_SYSERROR, "Unable to create or open slowlog(%s)", wp->config->slowlog); return -1; } close(fd); } } /* chroot */ if (wp->config->chroot && *wp->config->chroot) { fpm_evaluate_full_path(&wp->config->chroot, wp, NULL, 1); if (*wp->config->chroot != '/') { zlog(ZLOG_ERROR, "[pool %s] the chroot path '%s' must start with a '/'", wp->config->name, wp->config->chroot); return -1; } if (!fpm_conf_is_dir(wp->config->chroot)) { zlog(ZLOG_ERROR, "[pool %s] the chroot path '%s' does not exist or is not a directory", wp->config->name, wp->config->chroot); return -1; } } /* chdir */ if (wp->config->chdir && *wp->config->chdir) { fpm_evaluate_full_path(&wp->config->chdir, wp, NULL, 0); if (*wp->config->chdir != '/') { zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' must start with a '/'", wp->config->name, wp->config->chdir); return -1; } if (wp->config->chroot) { char *buf; spprintf(&buf, 0, "%s/%s", wp->config->chroot, wp->config->chdir); if (!fpm_conf_is_dir(buf)) { zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' within the chroot path '%s' ('%s') does not exist or is not a directory", wp->config->name, wp->config->chdir, wp->config->chroot, buf); efree(buf); return -1; } efree(buf); } else { if (!fpm_conf_is_dir(wp->config->chdir)) { zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' does not exist or is not a directory", wp->config->name, wp->config->chdir); return -1; } } } /* security.limit_extensions */ if (!wp->config->security_limit_extensions) { wp->config->security_limit_extensions = strdup(".php"); } if (*wp->config->security_limit_extensions) { int nb_ext; char *ext; char *security_limit_extensions; char *limit_extensions; /* strdup because strtok(3) alters the string it parses */ security_limit_extensions = strdup(wp->config->security_limit_extensions); limit_extensions = security_limit_extensions; nb_ext = 0; /* find the number of extensions */ while ((ext = strtok(limit_extensions, " \t"))) { limit_extensions = NULL; nb_ext++; } free(security_limit_extensions); /* if something found */ if (nb_ext > 0) { /* malloc the extension array */ wp->limit_extensions = malloc(sizeof(char *) * (nb_ext + 1)); if (!wp->limit_extensions) { zlog(ZLOG_ERROR, "[pool %s] unable to malloc extensions array", wp->config->name); return -1; } /* strdup because strtok(3) alters the string it parses */ security_limit_extensions = strdup(wp->config->security_limit_extensions); limit_extensions = security_limit_extensions; nb_ext = 0; /* parse the string and save the extension in the array */ while ((ext = strtok(security_limit_extensions, " \t"))) { security_limit_extensions = NULL; wp->limit_extensions[nb_ext++] = strdup(ext); } /* end the array with NULL in order to parse it */ wp->limit_extensions[nb_ext] = NULL; free(security_limit_extensions); } } /* env[], php_value[], php_admin_values[] */ if (!wp->config->chroot) { struct key_value_s *kv; char *options[] = FPM_PHP_INI_TO_EXPAND; char **p; for (kv = wp->config->php_values; kv; kv = kv->next) { for (p = options; *p; p++) { if (!strcasecmp(kv->key, *p)) { fpm_evaluate_full_path(&kv->value, wp, NULL, 0); } } } for (kv = wp->config->php_admin_values; kv; kv = kv->next) { for (p = options; *p; p++) { if (!strcasecmp(kv->key, *p)) { fpm_evaluate_full_path(&kv->value, wp, NULL, 0); } } } } } return 0; }