root/sapi/fpm/fpm/fpm_conf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fpm_conf_is_dir
  2. fpm_conf_expand_pool_name
  3. fpm_conf_set_boolean
  4. fpm_conf_set_string
  5. fpm_conf_set_integer
  6. fpm_conf_set_long
  7. fpm_conf_set_time
  8. fpm_conf_set_log_level
  9. fpm_conf_set_syslog_facility
  10. fpm_conf_set_rlimit_core
  11. fpm_conf_set_pm
  12. fpm_conf_set_array
  13. fpm_worker_pool_config_alloc
  14. fpm_worker_pool_config_free
  15. fpm_evaluate_full_path
  16. fpm_conf_process_all_pools
  17. fpm_conf_unlink_pid
  18. fpm_conf_write_pid
  19. fpm_conf_post_process
  20. fpm_conf_cleanup
  21. fpm_conf_ini_parser_include
  22. fpm_conf_ini_parser_section
  23. fpm_conf_ini_parser_entry
  24. fpm_conf_ini_parser_array
  25. fpm_conf_ini_parser
  26. fpm_conf_load_ini_file
  27. fpm_conf_dump
  28. fpm_conf_init_main

   1 
   2         /* $Id: fpm_conf.c,v 1.33.2.3 2008/12/13 03:50:29 anight Exp $ */
   3         /* (c) 2007,2008 Andrei Nigmatulin */
   4 
   5 #include "fpm_config.h"
   6 
   7 #include <sys/types.h>
   8 #include <sys/stat.h>
   9 #include <fcntl.h>
  10 #include <string.h>
  11 #include <stdlib.h>
  12 #include <stddef.h>
  13 #include <string.h>
  14 #if HAVE_INTTYPES_H
  15 # include <inttypes.h>
  16 #else
  17 # include <stdint.h>
  18 #endif
  19 #ifdef HAVE_GLOB
  20 # ifndef PHP_WIN32
  21 #  include <glob.h>
  22 # else
  23 #  include "win32/glob.h"
  24 # endif
  25 #endif
  26 
  27 #include <stdio.h>
  28 #include <unistd.h>
  29 
  30 #include "php.h"
  31 #include "zend_ini_scanner.h"
  32 #include "zend_globals.h"
  33 #include "zend_stream.h"
  34 #include "php_syslog.h"
  35 
  36 #include "fpm.h"
  37 #include "fpm_conf.h"
  38 #include "fpm_stdio.h"
  39 #include "fpm_worker_pool.h"
  40 #include "fpm_cleanup.h"
  41 #include "fpm_php.h"
  42 #include "fpm_sockets.h"
  43 #include "fpm_shm.h"
  44 #include "fpm_status.h"
  45 #include "fpm_log.h"
  46 #include "fpm_events.h"
  47 #include "zlog.h"
  48 #ifdef HAVE_SYSTEMD
  49 #include "fpm_systemd.h"
  50 #endif
  51 
  52 
  53 #define STR2STR(a) (a ? a : "undefined")
  54 #define BOOL2STR(a) (a ? "yes" : "no")
  55 #define GO(field) offsetof(struct fpm_global_config_s, field)
  56 #define WPO(field) offsetof(struct fpm_worker_pool_config_s, field)
  57 
  58 static int fpm_conf_load_ini_file(char *filename);
  59 static char *fpm_conf_set_integer(zval *value, void **config, intptr_t offset);
  60 #if 0 /* not used for now */
  61 static char *fpm_conf_set_long(zval *value, void **config, intptr_t offset);
  62 #endif
  63 static char *fpm_conf_set_time(zval *value, void **config, intptr_t offset);
  64 static char *fpm_conf_set_boolean(zval *value, void **config, intptr_t offset);
  65 static char *fpm_conf_set_string(zval *value, void **config, intptr_t offset);
  66 static char *fpm_conf_set_log_level(zval *value, void **config, intptr_t offset);
  67 static char *fpm_conf_set_rlimit_core(zval *value, void **config, intptr_t offset);
  68 static char *fpm_conf_set_pm(zval *value, void **config, intptr_t offset);
  69 #ifdef HAVE_SYSLOG_H
  70 static char *fpm_conf_set_syslog_facility(zval *value, void **config, intptr_t offset);
  71 #endif
  72 
  73 struct fpm_global_config_s fpm_global_config = {
  74         .daemonize = 1,
  75 #ifdef HAVE_SYSLOG_H
  76         .syslog_facility = -1,
  77 #endif
  78         .process_max = 0,
  79         .process_priority = 64, /* 64 means unset */
  80 #ifdef HAVE_SYSTEMD
  81         .systemd_watchdog = 0,
  82         .systemd_interval = -1, /* -1 means not set */
  83 #endif
  84 };
  85 static struct fpm_worker_pool_s *current_wp = NULL;
  86 static int ini_recursion = 0;
  87 static char *ini_filename = NULL;
  88 static int ini_lineno = 0;
  89 static char *ini_include = NULL;
  90 
  91 /*
  92  * Please keep the same order as in fpm_conf.h and in php-fpm.conf.in
  93  */
  94 static struct ini_value_parser_s ini_fpm_global_options[] = {
  95         { "pid",                         &fpm_conf_set_string,          GO(pid_file) },
  96         { "error_log",                   &fpm_conf_set_string,          GO(error_log) },
  97 #ifdef HAVE_SYSLOG_H
  98         { "syslog.ident",                &fpm_conf_set_string,          GO(syslog_ident) },
  99         { "syslog.facility",             &fpm_conf_set_syslog_facility, GO(syslog_facility) },
 100 #endif
 101         { "log_level",                   &fpm_conf_set_log_level,       GO(log_level) },
 102         { "emergency_restart_threshold", &fpm_conf_set_integer,         GO(emergency_restart_threshold) },
 103         { "emergency_restart_interval",  &fpm_conf_set_time,            GO(emergency_restart_interval) },
 104         { "process_control_timeout",     &fpm_conf_set_time,            GO(process_control_timeout) },
 105         { "process.max",                 &fpm_conf_set_integer,         GO(process_max) },
 106         { "process.priority",            &fpm_conf_set_integer,         GO(process_priority) },
 107         { "daemonize",                   &fpm_conf_set_boolean,         GO(daemonize) },
 108         { "rlimit_files",                &fpm_conf_set_integer,         GO(rlimit_files) },
 109         { "rlimit_core",                 &fpm_conf_set_rlimit_core,     GO(rlimit_core) },
 110         { "events.mechanism",            &fpm_conf_set_string,          GO(events_mechanism) },
 111 #ifdef HAVE_SYSTEMD
 112         { "systemd_interval",            &fpm_conf_set_time,            GO(systemd_interval) },
 113 #endif
 114         { 0, 0, 0 }
 115 };
 116 
 117 /*
 118  * Please keep the same order as in fpm_conf.h and in php-fpm.conf.in
 119  */
 120 static struct ini_value_parser_s ini_fpm_pool_options[] = {
 121         { "prefix",                    &fpm_conf_set_string,      WPO(prefix) },
 122         { "user",                      &fpm_conf_set_string,      WPO(user) },
 123         { "group",                     &fpm_conf_set_string,      WPO(group) },
 124         { "listen",                    &fpm_conf_set_string,      WPO(listen_address) },
 125         { "listen.backlog",            &fpm_conf_set_integer,     WPO(listen_backlog) },
 126 #ifdef HAVE_FPM_ACL
 127         { "listen.acl_users",          &fpm_conf_set_string,      WPO(listen_acl_users) },
 128         { "listen.acl_groups",         &fpm_conf_set_string,      WPO(listen_acl_groups) },
 129 #endif
 130         { "listen.owner",              &fpm_conf_set_string,      WPO(listen_owner) },
 131         { "listen.group",              &fpm_conf_set_string,      WPO(listen_group) },
 132         { "listen.mode",               &fpm_conf_set_string,      WPO(listen_mode) },
 133         { "listen.allowed_clients",    &fpm_conf_set_string,      WPO(listen_allowed_clients) },
 134         { "process.priority",          &fpm_conf_set_integer,     WPO(process_priority) },
 135         { "pm",                        &fpm_conf_set_pm,          WPO(pm) },
 136         { "pm.max_children",           &fpm_conf_set_integer,     WPO(pm_max_children) },
 137         { "pm.start_servers",          &fpm_conf_set_integer,     WPO(pm_start_servers) },
 138         { "pm.min_spare_servers",      &fpm_conf_set_integer,     WPO(pm_min_spare_servers) },
 139         { "pm.max_spare_servers",      &fpm_conf_set_integer,     WPO(pm_max_spare_servers) },
 140         { "pm.process_idle_timeout",   &fpm_conf_set_time,        WPO(pm_process_idle_timeout) },
 141         { "pm.max_requests",           &fpm_conf_set_integer,     WPO(pm_max_requests) },
 142         { "pm.status_path",            &fpm_conf_set_string,      WPO(pm_status_path) },
 143         { "ping.path",                 &fpm_conf_set_string,      WPO(ping_path) },
 144         { "ping.response",             &fpm_conf_set_string,      WPO(ping_response) },
 145         { "access.log",                &fpm_conf_set_string,      WPO(access_log) },
 146         { "access.format",             &fpm_conf_set_string,      WPO(access_format) },
 147         { "slowlog",                   &fpm_conf_set_string,      WPO(slowlog) },
 148         { "request_slowlog_timeout",   &fpm_conf_set_time,        WPO(request_slowlog_timeout) },
 149         { "request_terminate_timeout", &fpm_conf_set_time,        WPO(request_terminate_timeout) },
 150         { "rlimit_files",              &fpm_conf_set_integer,     WPO(rlimit_files) },
 151         { "rlimit_core",               &fpm_conf_set_rlimit_core, WPO(rlimit_core) },
 152         { "chroot",                    &fpm_conf_set_string,      WPO(chroot) },
 153         { "chdir",                     &fpm_conf_set_string,      WPO(chdir) },
 154         { "catch_workers_output",      &fpm_conf_set_boolean,     WPO(catch_workers_output) },
 155         { "clear_env",                 &fpm_conf_set_boolean,     WPO(clear_env) },
 156         { "security.limit_extensions", &fpm_conf_set_string,      WPO(security_limit_extensions) },
 157 #ifdef HAVE_APPARMOR
 158         { "apparmor_hat",              &fpm_conf_set_string,      WPO(apparmor_hat) },
 159 #endif
 160         { 0, 0, 0 }
 161 };
 162 
 163 static int fpm_conf_is_dir(char *path) /* {{{ */
 164 {
 165         struct stat sb;
 166 
 167         if (stat(path, &sb) != 0) {
 168                 return 0;
 169         }
 170 
 171         return (sb.st_mode & S_IFMT) == S_IFDIR;
 172 }
 173 /* }}} */
 174 
 175 /*
 176  * Expands the '$pool' token in a dynamically allocated string
 177  */
 178 static int fpm_conf_expand_pool_name(char **value) {
 179         char *token;
 180 
 181         if (!value || !*value) {
 182                 return 0;
 183         }
 184 
 185         while (*value && (token = strstr(*value, "$pool"))) {
 186                 char *buf;
 187                 char *p2 = token + strlen("$pool");
 188 
 189                 /* If we are not in a pool, we cannot expand this name now */
 190                 if (!current_wp || !current_wp->config  || !current_wp->config->name) {
 191                         return -1;
 192                 }
 193 
 194                 /* "aaa$poolbbb" becomes "aaa\0oolbbb" */
 195                 token[0] = '\0';
 196 
 197                 /* Build a brand new string with the expanded token */
 198                 spprintf(&buf, 0, "%s%s%s", *value, current_wp->config->name, p2);
 199 
 200                 /* Free the previous value and save the new one */
 201                 free(*value);
 202                 *value = strdup(buf);
 203                 efree(buf);
 204         }
 205 
 206         return 0;
 207 }
 208 
 209 static char *fpm_conf_set_boolean(zval *value, void **config, intptr_t offset) /* {{{ */
 210 {
 211         char *val = Z_STRVAL_P(value);
 212         long value_y = !strcasecmp(val, "1");
 213         long value_n = !strcasecmp(val, "");
 214 
 215         if (!value_y && !value_n) {
 216                 return "invalid boolean value";
 217         }
 218 
 219         * (int *) ((char *) *config + offset) = value_y ? 1 : 0;
 220         return NULL;
 221 }
 222 /* }}} */
 223 
 224 static char *fpm_conf_set_string(zval *value, void **config, intptr_t offset) /* {{{ */
 225 {
 226         char **config_val = (char **) ((char *) *config + offset);
 227 
 228         if (!config_val) {
 229                 return "internal error: NULL value";
 230         }
 231 
 232         /* Check if there is a previous value to deallocate */
 233         if (*config_val) {
 234                 free(*config_val);
 235         }
 236 
 237         *config_val = strdup(Z_STRVAL_P(value));
 238         if (!*config_val) {
 239                 return "fpm_conf_set_string(): strdup() failed";
 240         }
 241         if (fpm_conf_expand_pool_name(config_val) == -1) {
 242                 return "Can't use '$pool' when the pool is not defined";
 243         }
 244 
 245         return NULL;
 246 }
 247 /* }}} */
 248 
 249 static char *fpm_conf_set_integer(zval *value, void **config, intptr_t offset) /* {{{ */
 250 {
 251         char *val = Z_STRVAL_P(value);
 252         char *p;
 253 
 254         /* we don't use strtol because we don't want to allow negative values */
 255         for (p = val; *p; p++) {
 256                 if (p == val && *p == '-') continue;
 257                 if (*p < '0' || *p > '9') {
 258                         return "is not a valid number (greater or equal than zero)";
 259                 }
 260         }
 261         * (int *) ((char *) *config + offset) = atoi(val);
 262         return NULL;
 263 }
 264 /* }}} */
 265 
 266 #if 0 /* not used for now */
 267 static char *fpm_conf_set_long(zval *value, void **config, intptr_t offset) /* {{{ */
 268 {
 269         char *val = Z_STRVAL_P(value);
 270         char *p;
 271 
 272         for (p = val; *p; p++) {
 273                 if ( p == val && *p == '-' ) continue;
 274                 if (*p < '0' || *p > '9') {
 275                         return "is not a valid number (greater or equal than zero)";
 276                 }
 277         }
 278         * (long int *) ((char *) *config + offset) = atol(val);
 279         return NULL;
 280 }
 281 /* }}} */
 282 #endif
 283 
 284 static char *fpm_conf_set_time(zval *value, void **config, intptr_t offset) /* {{{ */
 285 {
 286         char *val = Z_STRVAL_P(value);
 287         int len = strlen(val);
 288         char suffix;
 289         int seconds;
 290         if (!len) {
 291                 return "invalid time value";
 292         }
 293 
 294         suffix = val[len-1];
 295         switch (suffix) {
 296                 case 'm' :
 297                         val[len-1] = '\0';
 298                         seconds = 60 * atoi(val);
 299                         break;
 300                 case 'h' :
 301                         val[len-1] = '\0';
 302                         seconds = 60 * 60 * atoi(val);
 303                         break;
 304                 case 'd' :
 305                         val[len-1] = '\0';
 306                         seconds = 24 * 60 * 60 * atoi(val);
 307                         break;
 308                 case 's' : /* s is the default suffix */
 309                         val[len-1] = '\0';
 310                         suffix = '0';
 311                 default :
 312                         if (suffix < '0' || suffix > '9') {
 313                                 return "unknown suffix used in time value";
 314                         }
 315                         seconds = atoi(val);
 316                         break;
 317         }
 318 
 319         * (int *) ((char *) *config + offset) = seconds;
 320         return NULL;
 321 }
 322 /* }}} */
 323 
 324 static char *fpm_conf_set_log_level(zval *value, void **config, intptr_t offset) /* {{{ */
 325 {
 326         char *val = Z_STRVAL_P(value);
 327         int log_level;
 328 
 329         if (!strcasecmp(val, "debug")) {
 330                 log_level = ZLOG_DEBUG;
 331         } else if (!strcasecmp(val, "notice")) {
 332                 log_level = ZLOG_NOTICE;
 333         } else if (!strcasecmp(val, "warning") || !strcasecmp(val, "warn")) {
 334                 log_level = ZLOG_WARNING;
 335         } else if (!strcasecmp(val, "error")) {
 336                 log_level = ZLOG_ERROR;
 337         } else if (!strcasecmp(val, "alert")) {
 338                 log_level = ZLOG_ALERT;
 339         } else {
 340                 return "invalid value for 'log_level'";
 341         }
 342 
 343         * (int *) ((char *) *config + offset) = log_level;
 344         return NULL;
 345 }
 346 /* }}} */
 347 
 348 #ifdef HAVE_SYSLOG_H
 349 static char *fpm_conf_set_syslog_facility(zval *value, void **config, intptr_t offset) /* {{{ */
 350 {
 351         char *val = Z_STRVAL_P(value);
 352         int *conf = (int *) ((char *) *config + offset);
 353 
 354 #ifdef LOG_AUTH
 355         if (!strcasecmp(val, "AUTH")) {
 356                 *conf = LOG_AUTH;
 357                 return NULL;
 358         }
 359 #endif
 360 
 361 #ifdef LOG_AUTHPRIV
 362         if (!strcasecmp(val, "AUTHPRIV")) {
 363                 *conf = LOG_AUTHPRIV;
 364                 return NULL;
 365         }
 366 #endif
 367 
 368 #ifdef LOG_CRON
 369         if (!strcasecmp(val, "CRON")) {
 370                 *conf = LOG_CRON;
 371                 return NULL;
 372         }
 373 #endif
 374 
 375 #ifdef LOG_DAEMON
 376         if (!strcasecmp(val, "DAEMON")) {
 377                 *conf = LOG_DAEMON;
 378                 return NULL;
 379         }
 380 #endif
 381 
 382 #ifdef LOG_FTP
 383         if (!strcasecmp(val, "FTP")) {
 384                 *conf = LOG_FTP;
 385                 return NULL;
 386         }
 387 #endif
 388 
 389 #ifdef LOG_KERN
 390         if (!strcasecmp(val, "KERN")) {
 391                 *conf = LOG_KERN;
 392                 return NULL;
 393         }
 394 #endif
 395 
 396 #ifdef LOG_LPR
 397         if (!strcasecmp(val, "LPR")) {
 398                 *conf = LOG_LPR;
 399                 return NULL;
 400         }
 401 #endif
 402 
 403 #ifdef LOG_MAIL
 404         if (!strcasecmp(val, "MAIL")) {
 405                 *conf = LOG_MAIL;
 406                 return NULL;
 407         }
 408 #endif
 409 
 410 #ifdef LOG_NEWS
 411         if (!strcasecmp(val, "NEWS")) {
 412                 *conf = LOG_NEWS;
 413                 return NULL;
 414         }
 415 #endif
 416 
 417 #ifdef LOG_SYSLOG
 418         if (!strcasecmp(val, "SYSLOG")) {
 419                 *conf = LOG_SYSLOG;
 420                 return NULL;
 421         }
 422 #endif
 423 
 424 #ifdef LOG_USER
 425         if (!strcasecmp(val, "USER")) {
 426                 *conf = LOG_USER;
 427                 return NULL;
 428         }
 429 #endif
 430 
 431 #ifdef LOG_UUCP
 432         if (!strcasecmp(val, "UUCP")) {
 433                 *conf = LOG_UUCP;
 434                 return NULL;
 435         }
 436 #endif
 437 
 438 #ifdef LOG_LOCAL0
 439         if (!strcasecmp(val, "LOCAL0")) {
 440                 *conf = LOG_LOCAL0;
 441                 return NULL;
 442         }
 443 #endif
 444 
 445 #ifdef LOG_LOCAL1
 446         if (!strcasecmp(val, "LOCAL1")) {
 447                 *conf = LOG_LOCAL1;
 448                 return NULL;
 449         }
 450 #endif
 451 
 452 #ifdef LOG_LOCAL2
 453         if (!strcasecmp(val, "LOCAL2")) {
 454                 *conf = LOG_LOCAL2;
 455                 return NULL;
 456         }
 457 #endif
 458 
 459 #ifdef LOG_LOCAL3
 460         if (!strcasecmp(val, "LOCAL3")) {
 461                 *conf = LOG_LOCAL3;
 462                 return NULL;
 463         }
 464 #endif
 465 
 466 #ifdef LOG_LOCAL4
 467         if (!strcasecmp(val, "LOCAL4")) {
 468                 *conf = LOG_LOCAL4;
 469                 return NULL;
 470         }
 471 #endif
 472 
 473 #ifdef LOG_LOCAL5
 474         if (!strcasecmp(val, "LOCAL5")) {
 475                 *conf = LOG_LOCAL5;
 476                 return NULL;
 477         }
 478 #endif
 479 
 480 #ifdef LOG_LOCAL6
 481         if (!strcasecmp(val, "LOCAL6")) {
 482                 *conf = LOG_LOCAL6;
 483                 return NULL;
 484         }
 485 #endif
 486 
 487 #ifdef LOG_LOCAL7
 488         if (!strcasecmp(val, "LOCAL7")) {
 489                 *conf = LOG_LOCAL7;
 490                 return NULL;
 491         }
 492 #endif
 493 
 494         return "invalid value";
 495 }
 496 /* }}} */
 497 #endif
 498 
 499 static char *fpm_conf_set_rlimit_core(zval *value, void **config, intptr_t offset) /* {{{ */
 500 {
 501         char *val = Z_STRVAL_P(value);
 502         int *ptr = (int *) ((char *) *config + offset);
 503 
 504         if (!strcasecmp(val, "unlimited")) {
 505                 *ptr = -1;
 506         } else {
 507                 int int_value;
 508                 void *subconf = &int_value;
 509                 char *error;
 510 
 511                 error = fpm_conf_set_integer(value, &subconf, 0);
 512 
 513                 if (error) {
 514                         return error;
 515                 }
 516 
 517                 if (int_value < 0) {
 518                         return "must be greater than zero or 'unlimited'";
 519                 }
 520 
 521                 *ptr = int_value;
 522         }
 523 
 524         return NULL;
 525 }
 526 /* }}} */
 527 
 528 static char *fpm_conf_set_pm(zval *value, void **config, intptr_t offset) /* {{{ */
 529 {
 530         char *val = Z_STRVAL_P(value);
 531         struct fpm_worker_pool_config_s  *c = *config;
 532         if (!strcasecmp(val, "static")) {
 533                 c->pm = PM_STYLE_STATIC;
 534         } else if (!strcasecmp(val, "dynamic")) {
 535                 c->pm = PM_STYLE_DYNAMIC;
 536         } else if (!strcasecmp(val, "ondemand")) {
 537                 c->pm = PM_STYLE_ONDEMAND;
 538         } else {
 539                 return "invalid process manager (static, dynamic or ondemand)";
 540         }
 541         return NULL;
 542 }
 543 /* }}} */
 544 
 545 static char *fpm_conf_set_array(zval *key, zval *value, void **config, int convert_to_bool) /* {{{ */
 546 {
 547         struct key_value_s *kv;
 548         struct key_value_s ***parent = (struct key_value_s ***) config;
 549         int b;
 550         void *subconf = &b;
 551 
 552         kv = malloc(sizeof(*kv));
 553 
 554         if (!kv) {
 555                 return "malloc() failed";
 556         }
 557 
 558         memset(kv, 0, sizeof(*kv));
 559         kv->key = strdup(Z_STRVAL_P(key));
 560 
 561         if (!kv->key) {
 562                 free(kv);
 563                 return "fpm_conf_set_array: strdup(key) failed";
 564         }
 565 
 566         if (convert_to_bool) {
 567                 char *err = fpm_conf_set_boolean(value, &subconf, 0);
 568                 if (err) {
 569                         free(kv->key);
 570                         free(kv);
 571                         return err;
 572                 }
 573                 kv->value = strdup(b ? "1" : "0");
 574         } else {
 575                 kv->value = strdup(Z_STRVAL_P(value));
 576                 if (fpm_conf_expand_pool_name(&kv->value) == -1) {
 577                         free(kv->key);
 578                         free(kv);
 579                         return "Can't use '$pool' when the pool is not defined";
 580                 }
 581         }
 582 
 583         if (!kv->value) {
 584                 free(kv->key);
 585                 free(kv);
 586                 return "fpm_conf_set_array: strdup(value) failed";
 587         }
 588 
 589         kv->next = **parent;
 590         **parent = kv;
 591         return NULL;
 592 }
 593 /* }}} */
 594 
 595 static void *fpm_worker_pool_config_alloc() /* {{{ */
 596 {
 597         struct fpm_worker_pool_s *wp;
 598 
 599         wp = fpm_worker_pool_alloc();
 600 
 601         if (!wp) {
 602                 return 0;
 603         }
 604 
 605         wp->config = malloc(sizeof(struct fpm_worker_pool_config_s));
 606 
 607         if (!wp->config) {
 608                 fpm_worker_pool_free(wp);
 609                 return 0;
 610         }
 611 
 612         memset(wp->config, 0, sizeof(struct fpm_worker_pool_config_s));
 613         wp->config->listen_backlog = FPM_BACKLOG_DEFAULT;
 614         wp->config->pm_process_idle_timeout = 10; /* 10s by default */
 615         wp->config->process_priority = 64; /* 64 means unset */
 616         wp->config->clear_env = 1;
 617 
 618         if (!fpm_worker_all_pools) {
 619                 fpm_worker_all_pools = wp;
 620         } else {
 621                 struct fpm_worker_pool_s *tmp = fpm_worker_all_pools;
 622                 while (tmp) {
 623                         if (!tmp->next) {
 624                                 tmp->next = wp;
 625                                 break;
 626                         }
 627                         tmp = tmp->next;
 628                 }
 629         }
 630 
 631         current_wp = wp;
 632         return wp->config;
 633 }
 634 /* }}} */
 635 
 636 int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc) /* {{{ */
 637 {
 638         struct key_value_s *kv, *kv_next;
 639 
 640         free(wpc->name);
 641         free(wpc->prefix);
 642         free(wpc->user);
 643         free(wpc->group);
 644         free(wpc->listen_address);
 645         free(wpc->listen_owner);
 646         free(wpc->listen_group);
 647         free(wpc->listen_mode);
 648         free(wpc->listen_allowed_clients);
 649         free(wpc->pm_status_path);
 650         free(wpc->ping_path);
 651         free(wpc->ping_response);
 652         free(wpc->access_log);
 653         free(wpc->access_format);
 654         free(wpc->slowlog);
 655         free(wpc->chroot);
 656         free(wpc->chdir);
 657         free(wpc->security_limit_extensions);
 658 #ifdef HAVE_APPARMOR
 659         free(wpc->apparmor_hat);
 660 #endif
 661 
 662         for (kv = wpc->php_values; kv; kv = kv_next) {
 663                 kv_next = kv->next;
 664                 free(kv->key);
 665                 free(kv->value);
 666                 free(kv);
 667         }
 668         for (kv = wpc->php_admin_values; kv; kv = kv_next) {
 669                 kv_next = kv->next;
 670                 free(kv->key);
 671                 free(kv->value);
 672                 free(kv);
 673         }
 674         for (kv = wpc->env; kv; kv = kv_next) {
 675                 kv_next = kv->next;
 676                 free(kv->key);
 677                 free(kv->value);
 678                 free(kv);
 679         }
 680 
 681         return 0;
 682 }
 683 /* }}} */
 684 
 685 static int fpm_evaluate_full_path(char **path, struct fpm_worker_pool_s *wp, char *default_prefix, int expand) /* {{{ */
 686 {
 687         char *prefix = NULL;
 688         char *full_path;
 689 
 690         if (!path || !*path || **path == '/') {
 691                 return 0;
 692         }
 693 
 694         if (wp && wp->config) {
 695                 prefix = wp->config->prefix;
 696         }
 697 
 698         /* if the wp prefix is not set */
 699         if (prefix == NULL) {
 700                 prefix = fpm_globals.prefix;
 701         }
 702 
 703         /* if the global prefix is not set */
 704         if (prefix == NULL) {
 705                 prefix = default_prefix ? default_prefix : PHP_PREFIX;
 706         }
 707 
 708         if (expand) {
 709                 char *tmp;
 710                 tmp = strstr(*path, "$prefix");
 711                 if (tmp != NULL) {
 712 
 713                         if (tmp != *path) {
 714                                 zlog(ZLOG_ERROR, "'$prefix' must be use at the beginning of the value");
 715                                 return -1;
 716                         }
 717 
 718                         if (strlen(*path) > strlen("$prefix")) {
 719                                 free(*path);
 720                                 tmp = strdup((*path) + strlen("$prefix"));
 721                                 *path = tmp;
 722                         } else {
 723                                 free(*path);
 724                                 *path = NULL;
 725                         }
 726                 }
 727         }
 728 
 729         if (*path) {
 730                 spprintf(&full_path, 0, "%s/%s", prefix, *path);
 731                 free(*path);
 732                 *path = strdup(full_path);
 733                 efree(full_path);
 734         } else {
 735                 *path = strdup(prefix);
 736         }
 737 
 738         if (**path != '/' && wp != NULL && wp->config) {
 739                 return fpm_evaluate_full_path(path, NULL, default_prefix, expand);
 740         }
 741         return 0;
 742 }
 743 /* }}} */
 744 
 745 static int fpm_conf_process_all_pools() /* {{{ */
 746 {
 747         struct fpm_worker_pool_s *wp, *wp2;
 748 
 749         if (!fpm_worker_all_pools) {
 750                 zlog(ZLOG_ERROR, "No pool defined. at least one pool section must be specified in config file");
 751                 return -1;
 752         }
 753 
 754         for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
 755 
 756                 /* prefix */
 757                 if (wp->config->prefix && *wp->config->prefix) {
 758                         fpm_evaluate_full_path(&wp->config->prefix, NULL, NULL, 0);
 759 
 760                         if (!fpm_conf_is_dir(wp->config->prefix)) {
 761                                 zlog(ZLOG_ERROR, "[pool %s] the prefix '%s' does not exist or is not a directory", wp->config->name, wp->config->prefix);
 762                                 return -1;
 763                         }
 764                 }
 765 
 766                 /* alert if user is not set only if we are not root*/
 767                 if (!wp->config->user && !geteuid()) {
 768                         zlog(ZLOG_ALERT, "[pool %s] user has not been defined", wp->config->name);
 769                         return -1;
 770                 }
 771 
 772                 /* listen */
 773                 if (wp->config->listen_address && *wp->config->listen_address) {
 774                         wp->listen_address_domain = fpm_sockets_domain_from_address(wp->config->listen_address);
 775 
 776                         if (wp->listen_address_domain == FPM_AF_UNIX && *wp->config->listen_address != '/') {
 777                                 fpm_evaluate_full_path(&wp->config->listen_address, wp, NULL, 0);
 778                         }
 779                 } else {
 780                         zlog(ZLOG_ALERT, "[pool %s] no listen address have been defined!", wp->config->name);
 781                         return -1;
 782                 }
 783 
 784                 if (wp->config->process_priority != 64 && (wp->config->process_priority < -19 || wp->config->process_priority > 20)) {
 785                         zlog(ZLOG_ERROR, "[pool %s] process.priority must be included into [-19,20]", wp->config->name);
 786                         return -1;
 787                 }
 788 
 789                 /* pm */
 790                 if (wp->config->pm != PM_STYLE_STATIC && wp->config->pm != PM_STYLE_DYNAMIC && wp->config->pm != PM_STYLE_ONDEMAND) {
 791                         zlog(ZLOG_ALERT, "[pool %s] the process manager is missing (static, dynamic or ondemand)", wp->config->name);
 792                         return -1;
 793                 }
 794 
 795                 /* pm.max_children */
 796                 if (wp->config->pm_max_children < 1) {
 797                         zlog(ZLOG_ALERT, "[pool %s] pm.max_children must be a positive value", wp->config->name);
 798                         return -1;
 799                 }
 800 
 801                 /* pm.start_servers, pm.min_spare_servers, pm.max_spare_servers */
 802                 if (wp->config->pm == PM_STYLE_DYNAMIC) {
 803                         struct fpm_worker_pool_config_s *config = wp->config;
 804 
 805                         if (config->pm_min_spare_servers <= 0) {
 806                                 zlog(ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) must be a positive value", wp->config->name, config->pm_min_spare_servers);
 807                                 return -1;
 808                         }
 809 
 810                         if (config->pm_max_spare_servers <= 0) {
 811                                 zlog(ZLOG_ALERT, "[pool %s] pm.max_spare_servers(%d) must be a positive value", wp->config->name, config->pm_max_spare_servers);
 812                                 return -1;
 813                         }
 814 
 815                         if (config->pm_min_spare_servers > config->pm_max_children ||
 816                                         config->pm_max_spare_servers > config->pm_max_children) {
 817                                 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);
 818                                 return -1;
 819                         }
 820 
 821                         if (config->pm_max_spare_servers < config->pm_min_spare_servers) {
 822                                 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);
 823                                 return -1;
 824                         }
 825 
 826                         if (config->pm_start_servers <= 0) {
 827                                 config->pm_start_servers = config->pm_min_spare_servers + ((config->pm_max_spare_servers - config->pm_min_spare_servers) / 2);
 828                                 zlog(ZLOG_NOTICE, "[pool %s] pm.start_servers is not set. It's been set to %d.", wp->config->name, config->pm_start_servers);
 829 
 830                         } else if (config->pm_start_servers < config->pm_min_spare_servers || config->pm_start_servers > config->pm_max_spare_servers) {
 831                                 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);
 832                                 return -1;
 833                         }
 834                 } else if (wp->config->pm == PM_STYLE_ONDEMAND) {
 835                         struct fpm_worker_pool_config_s *config = wp->config;
 836 
 837                         if (!fpm_event_support_edge_trigger()) {
 838                                 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);
 839                                 return -1;
 840                         }
 841 
 842                         if (config->pm_process_idle_timeout < 1) {
 843                                 zlog(ZLOG_ALERT, "[pool %s] pm.process_idle_timeout(%ds) must be greater than 0s", wp->config->name, config->pm_process_idle_timeout);
 844                                 return -1;
 845                         }
 846 
 847                         if (config->listen_backlog < FPM_BACKLOG_DEFAULT) {
 848                                 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);
 849                                 config->listen_backlog = FPM_BACKLOG_DEFAULT;
 850                         }
 851 
 852                         /* certainely useless but proper */
 853                         config->pm_start_servers = 0;
 854                         config->pm_min_spare_servers = 0;
 855                         config->pm_max_spare_servers = 0;
 856                 }
 857 
 858                 /* status */
 859                 if (wp->config->pm_status_path && *wp->config->pm_status_path) {
 860                         int i;
 861                         char *status = wp->config->pm_status_path;
 862 
 863                         if (*status != '/') {
 864                                 zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must start with a '/'", wp->config->name, status);
 865                                 return -1;
 866                         }
 867 
 868                         if (strlen(status) < 2) {
 869                                 zlog(ZLOG_ERROR, "[pool %s] the status path '%s' is not long enough", wp->config->name, status);
 870                                 return -1;
 871                         }
 872 
 873                         for (i = 0; i < strlen(status); i++) {
 874                                 if (!isalnum(status[i]) && status[i] != '/' && status[i] != '-' && status[i] != '_' && status[i] != '.') {
 875                                         zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must contain only the following characters '[alphanum]/_-.'", wp->config->name, status);
 876                                         return -1;
 877                                 }
 878                         }
 879                 }
 880 
 881                 /* ping */
 882                 if (wp->config->ping_path && *wp->config->ping_path) {
 883                         char *ping = wp->config->ping_path;
 884                         int i;
 885 
 886                         if (*ping != '/') {
 887                                 zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must start with a '/'", wp->config->name, ping);
 888                                 return -1;
 889                         }
 890 
 891                         if (strlen(ping) < 2) {
 892                                 zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' is not long enough", wp->config->name, ping);
 893                                 return -1;
 894                         }
 895 
 896                         for (i = 0; i < strlen(ping); i++) {
 897                                 if (!isalnum(ping[i]) && ping[i] != '/' && ping[i] != '-' && ping[i] != '_' && ping[i] != '.') {
 898                                         zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must containt only the following characters '[alphanum]/_-.'", wp->config->name, ping);
 899                                         return -1;
 900                                 }
 901                         }
 902 
 903                         if (!wp->config->ping_response) {
 904                                 wp->config->ping_response = strdup("pong");
 905                         } else {
 906                                 if (strlen(wp->config->ping_response) < 1) {
 907                                         zlog(ZLOG_ERROR, "[pool %s] the ping response page '%s' is not long enough", wp->config->name, wp->config->ping_response);
 908                                         return -1;
 909                                 }
 910                         }
 911                 } else {
 912                         if (wp->config->ping_response) {
 913                                 free(wp->config->ping_response);
 914                                 wp->config->ping_response = NULL;
 915                         }
 916                 }
 917 
 918                 /* access.log, access.format */
 919                 if (wp->config->access_log && *wp->config->access_log) {
 920                         fpm_evaluate_full_path(&wp->config->access_log, wp, NULL, 0);
 921                         if (!wp->config->access_format) {
 922                                 wp->config->access_format = strdup("%R - %u %t \"%m %r\" %s");
 923                         }
 924                 }
 925 
 926                 if (wp->config->request_terminate_timeout) {
 927                         fpm_globals.heartbeat = fpm_globals.heartbeat ? MIN(fpm_globals.heartbeat, (wp->config->request_terminate_timeout * 1000) / 3) : (wp->config->request_terminate_timeout * 1000) / 3;
 928                 }
 929 
 930                 /* slowlog */
 931                 if (wp->config->slowlog && *wp->config->slowlog) {
 932                         fpm_evaluate_full_path(&wp->config->slowlog, wp, NULL, 0);
 933                 }
 934 
 935                 /* request_slowlog_timeout */
 936                 if (wp->config->request_slowlog_timeout) {
 937 #if HAVE_FPM_TRACE
 938                         if (! (wp->config->slowlog && *wp->config->slowlog)) {
 939                                 zlog(ZLOG_ERROR, "[pool %s] 'slowlog' must be specified for use with 'request_slowlog_timeout'", wp->config->name);
 940                                 return -1;
 941                         }
 942 #else
 943                         static int warned = 0;
 944 
 945                         if (!warned) {
 946                                 zlog(ZLOG_WARNING, "[pool %s] 'request_slowlog_timeout' is not supported on your system",       wp->config->name);
 947                                 warned = 1;
 948                         }
 949 
 950                         wp->config->request_slowlog_timeout = 0;
 951 #endif
 952 
 953                         if (wp->config->slowlog && *wp->config->slowlog) {
 954                                 int fd;
 955 
 956                                 fd = open(wp->config->slowlog, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
 957 
 958                                 if (0 > fd) {
 959                                         zlog(ZLOG_SYSERROR, "Unable to create or open slowlog(%s)", wp->config->slowlog);
 960                                         return -1;
 961                                 }
 962                                 close(fd);
 963                         }
 964 
 965                         fpm_globals.heartbeat = fpm_globals.heartbeat ? MIN(fpm_globals.heartbeat, (wp->config->request_slowlog_timeout * 1000) / 3) : (wp->config->request_slowlog_timeout * 1000) / 3;
 966 
 967                         if (wp->config->request_terminate_timeout && wp->config->request_slowlog_timeout > wp->config->request_terminate_timeout) {
 968                                 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);
 969                                 return -1;
 970                         }
 971                 }
 972 
 973                 /* chroot */
 974                 if (wp->config->chroot && *wp->config->chroot) {
 975 
 976                         fpm_evaluate_full_path(&wp->config->chroot, wp, NULL, 1);
 977 
 978                         if (*wp->config->chroot != '/') {
 979                                 zlog(ZLOG_ERROR, "[pool %s] the chroot path '%s' must start with a '/'", wp->config->name, wp->config->chroot);
 980                                 return -1;
 981                         }
 982 
 983                         if (!fpm_conf_is_dir(wp->config->chroot)) {
 984                                 zlog(ZLOG_ERROR, "[pool %s] the chroot path '%s' does not exist or is not a directory", wp->config->name, wp->config->chroot);
 985                                 return -1;
 986                         }
 987                 }
 988 
 989                 /* chdir */
 990                 if (wp->config->chdir && *wp->config->chdir) {
 991 
 992                         fpm_evaluate_full_path(&wp->config->chdir, wp, NULL, 0);
 993 
 994                         if (*wp->config->chdir != '/') {
 995                                 zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' must start with a '/'", wp->config->name, wp->config->chdir);
 996                                 return -1;
 997                         }
 998 
 999                         if (wp->config->chroot) {
1000                                 char *buf;
1001 
1002                                 spprintf(&buf, 0, "%s/%s", wp->config->chroot, wp->config->chdir);
1003 
1004                                 if (!fpm_conf_is_dir(buf)) {
1005                                         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);
1006                                         efree(buf);
1007                                         return -1;
1008                                 }
1009 
1010                                 efree(buf);
1011                         } else {
1012                                 if (!fpm_conf_is_dir(wp->config->chdir)) {
1013                                         zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' does not exist or is not a directory", wp->config->name, wp->config->chdir);
1014                                         return -1;
1015                                 }
1016                         }
1017                 }
1018 
1019                 /* security.limit_extensions */
1020                 if (!wp->config->security_limit_extensions) {
1021                         wp->config->security_limit_extensions = strdup(".php .phar");
1022                 }
1023 
1024                 if (*wp->config->security_limit_extensions) {
1025                         int nb_ext;
1026                         char *ext;
1027                         char *security_limit_extensions;
1028                         char *limit_extensions;
1029 
1030 
1031                         /* strdup because strtok(3) alters the string it parses */
1032                         security_limit_extensions = strdup(wp->config->security_limit_extensions);
1033                         limit_extensions = security_limit_extensions;
1034                         nb_ext = 0;
1035 
1036                         /* find the number of extensions */
1037                         while (strtok(limit_extensions, " \t")) {
1038                                 limit_extensions = NULL;
1039                                 nb_ext++;
1040                         }
1041                         free(security_limit_extensions);
1042 
1043                         /* if something found */
1044                         if (nb_ext > 0) {
1045 
1046                                 /* malloc the extension array */
1047                                 wp->limit_extensions = malloc(sizeof(char *) * (nb_ext + 1));
1048                                 if (!wp->limit_extensions) {
1049                                         zlog(ZLOG_ERROR, "[pool %s] unable to malloc extensions array", wp->config->name);
1050                                         return -1;
1051                                 }
1052 
1053                                 /* strdup because strtok(3) alters the string it parses */
1054                                 security_limit_extensions = strdup(wp->config->security_limit_extensions);
1055                                 limit_extensions = security_limit_extensions;
1056                                 nb_ext = 0;
1057 
1058                                 /* parse the string and save the extension in the array */
1059                                 while ((ext = strtok(limit_extensions, " \t"))) {
1060                                         limit_extensions = NULL;
1061                                         wp->limit_extensions[nb_ext++] = strdup(ext);
1062                                 }
1063 
1064                                 /* end the array with NULL in order to parse it */
1065                                 wp->limit_extensions[nb_ext] = NULL;
1066                                 free(security_limit_extensions);
1067                         }
1068                 }
1069 
1070                 /* env[], php_value[], php_admin_values[] */
1071                 if (!wp->config->chroot) {
1072                         struct key_value_s *kv;
1073                         char *options[] = FPM_PHP_INI_TO_EXPAND;
1074                         char **p;
1075 
1076                         for (kv = wp->config->php_values; kv; kv = kv->next) {
1077                                 for (p = options; *p; p++) {
1078                                         if (!strcasecmp(kv->key, *p)) {
1079                                                 fpm_evaluate_full_path(&kv->value, wp, NULL, 0);
1080                                         }
1081                                 }
1082                         }
1083                         for (kv = wp->config->php_admin_values; kv; kv = kv->next) {
1084                                 if (!strcasecmp(kv->key, "error_log") && !strcasecmp(kv->value, "syslog")) {
1085                                         continue;
1086                                 }
1087                                 for (p = options; *p; p++) {
1088                                         if (!strcasecmp(kv->key, *p)) {
1089                                                 fpm_evaluate_full_path(&kv->value, wp, NULL, 0);
1090                                         }
1091                                 }
1092                         }
1093                 }
1094         }
1095 
1096         /* ensure 2 pools do not use the same listening address */
1097         for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
1098                 for (wp2 = fpm_worker_all_pools; wp2; wp2 = wp2->next) {
1099                         if (wp == wp2) {
1100                                 continue;
1101                         }
1102 
1103                         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)) {
1104                                 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);
1105                                 return -1;
1106                         }
1107                 }
1108         }
1109         return 0;
1110 }
1111 /* }}} */
1112 
1113 int fpm_conf_unlink_pid() /* {{{ */
1114 {
1115         if (fpm_global_config.pid_file) {
1116                 if (0 > unlink(fpm_global_config.pid_file)) {
1117                         zlog(ZLOG_SYSERROR, "Unable to remove the PID file (%s).", fpm_global_config.pid_file);
1118                         return -1;
1119                 }
1120         }
1121         return 0;
1122 }
1123 /* }}} */
1124 
1125 int fpm_conf_write_pid() /* {{{ */
1126 {
1127         int fd;
1128 
1129         if (fpm_global_config.pid_file) {
1130                 char buf[64];
1131                 int len;
1132 
1133                 unlink(fpm_global_config.pid_file);
1134                 fd = creat(fpm_global_config.pid_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1135 
1136                 if (fd < 0) {
1137                         zlog(ZLOG_SYSERROR, "Unable to create the PID file (%s).", fpm_global_config.pid_file);
1138                         return -1;
1139                 }
1140 
1141                 len = sprintf(buf, "%d", (int) fpm_globals.parent_pid);
1142 
1143                 if (len != write(fd, buf, len)) {
1144                         zlog(ZLOG_SYSERROR, "Unable to write to the PID file.");
1145                         close(fd);
1146                         return -1;
1147                 }
1148                 close(fd);
1149         }
1150         return 0;
1151 }
1152 /* }}} */
1153 
1154 static int fpm_conf_post_process(int force_daemon) /* {{{ */
1155 {
1156         struct fpm_worker_pool_s *wp;
1157 
1158         if (fpm_global_config.pid_file) {
1159                 fpm_evaluate_full_path(&fpm_global_config.pid_file, NULL, PHP_LOCALSTATEDIR, 0);
1160         }
1161 
1162         if (force_daemon >= 0) {
1163                 /* forced from command line options */
1164                 fpm_global_config.daemonize = force_daemon;
1165         }
1166 
1167         fpm_globals.log_level = fpm_global_config.log_level;
1168         zlog_set_level(fpm_globals.log_level);
1169 
1170         if (fpm_global_config.process_max < 0) {
1171                 zlog(ZLOG_ERROR, "process_max can't be negative");
1172                 return -1;
1173         }
1174 
1175         if (fpm_global_config.process_priority != 64 && (fpm_global_config.process_priority < -19 || fpm_global_config.process_priority > 20)) {
1176                 zlog(ZLOG_ERROR, "process.priority must be included into [-19,20]");
1177                 return -1;
1178         }
1179 
1180         if (!fpm_global_config.error_log) {
1181                 fpm_global_config.error_log = strdup("log/php-fpm.log");
1182         }
1183 
1184 #ifdef HAVE_SYSTEMD
1185         if (0 > fpm_systemd_conf()) {
1186                 return -1;
1187         }
1188 #endif
1189 
1190 #ifdef HAVE_SYSLOG_H
1191         if (!fpm_global_config.syslog_ident) {
1192                 fpm_global_config.syslog_ident = strdup("php-fpm");
1193         }
1194 
1195         if (fpm_global_config.syslog_facility < 0) {
1196                 fpm_global_config.syslog_facility = LOG_DAEMON;
1197         }
1198 
1199         if (strcasecmp(fpm_global_config.error_log, "syslog") != 0)
1200 #endif
1201         {
1202                 fpm_evaluate_full_path(&fpm_global_config.error_log, NULL, PHP_LOCALSTATEDIR, 0);
1203         }
1204 
1205         if (0 > fpm_stdio_open_error_log(0)) {
1206                 return -1;
1207         }
1208 
1209         if (0 > fpm_event_pre_init(fpm_global_config.events_mechanism)) {
1210                 return -1;
1211         }
1212 
1213         if (0 > fpm_conf_process_all_pools()) {
1214                 return -1;
1215         }
1216 
1217         if (0 > fpm_log_open(0)) {
1218                 return -1;
1219         }
1220 
1221         for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
1222                 if (!wp->config->access_log || !*wp->config->access_log) {
1223                         continue;
1224                 }
1225                 if (0 > fpm_log_write(wp->config->access_format)) {
1226                         zlog(ZLOG_ERROR, "[pool %s] wrong format for access.format '%s'", wp->config->name, wp->config->access_format);
1227                         return -1;
1228                 }
1229         }
1230 
1231         return 0;
1232 }
1233 /* }}} */
1234 
1235 static void fpm_conf_cleanup(int which, void *arg) /* {{{ */
1236 {
1237         free(fpm_global_config.pid_file);
1238         free(fpm_global_config.error_log);
1239         free(fpm_global_config.events_mechanism);
1240         fpm_global_config.pid_file = 0;
1241         fpm_global_config.error_log = 0;
1242 #ifdef HAVE_SYSLOG_H
1243         free(fpm_global_config.syslog_ident);
1244         fpm_global_config.syslog_ident = 0;
1245 #endif
1246         free(fpm_globals.config);
1247 }
1248 /* }}} */
1249 
1250 static void fpm_conf_ini_parser_include(char *inc, void *arg) /* {{{ */
1251 {
1252         char *filename;
1253         int *error = (int *)arg;;
1254 #ifdef HAVE_GLOB
1255         glob_t g;
1256 #endif
1257         int i;
1258 
1259         if (!inc || !arg) return;
1260         if (*error) return; /* We got already an error. Switch to the end. */
1261         spprintf(&filename, 0, "%s", ini_filename);
1262 
1263 #ifdef HAVE_GLOB
1264         {
1265                 g.gl_offs = 0;
1266                 if ((i = glob(inc, GLOB_ERR | GLOB_MARK, NULL, &g)) != 0) {
1267 #ifdef GLOB_NOMATCH
1268                         if (i == GLOB_NOMATCH) {
1269                                 zlog(ZLOG_WARNING, "Nothing matches the include pattern '%s' from %s at line %d.", inc, filename, ini_lineno);
1270                                 efree(filename);
1271                                 return;
1272                         }
1273 #endif /* GLOB_NOMATCH */
1274                         zlog(ZLOG_ERROR, "Unable to globalize '%s' (ret=%d) from %s at line %d.", inc, i, filename, ini_lineno);
1275                         *error = 1;
1276                         efree(filename);
1277                         return;
1278                 }
1279 
1280                 for (i = 0; i < g.gl_pathc; i++) {
1281                         int len = strlen(g.gl_pathv[i]);
1282                         if (len < 1) continue;
1283                         if (g.gl_pathv[i][len - 1] == '/') continue; /* don't parse directories */
1284                         if (0 > fpm_conf_load_ini_file(g.gl_pathv[i])) {
1285                                 zlog(ZLOG_ERROR, "Unable to include %s from %s at line %d", g.gl_pathv[i], filename, ini_lineno);
1286                                 *error = 1;
1287                                 efree(filename);
1288                                 return;
1289                         }
1290                 }
1291                 globfree(&g);
1292         }
1293 #else /* HAVE_GLOB */
1294         if (0 > fpm_conf_load_ini_file(inc)) {
1295                 zlog(ZLOG_ERROR, "Unable to include %s from %s at line %d", inc, filename, ini_lineno);
1296                 *error = 1;
1297                 efree(filename);
1298                 return;
1299         }
1300 #endif /* HAVE_GLOB */
1301 
1302         efree(filename);
1303 }
1304 /* }}} */
1305 
1306 static void fpm_conf_ini_parser_section(zval *section, void *arg) /* {{{ */
1307 {
1308         struct fpm_worker_pool_s *wp;
1309         struct fpm_worker_pool_config_s *config;
1310         int *error = (int *)arg;
1311 
1312         /* switch to global conf */
1313         if (!strcasecmp(Z_STRVAL_P(section), "global")) {
1314                 current_wp = NULL;
1315                 return;
1316         }
1317 
1318         for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
1319                 if (!wp->config) continue;
1320                 if (!wp->config->name) continue;
1321                 if (!strcasecmp(wp->config->name, Z_STRVAL_P(section))) {
1322                         /* Found a wp with the same name. Bring it back */
1323                         current_wp = wp;
1324                         return;
1325                 }
1326         }
1327 
1328         /* it's a new pool */
1329         config = (struct fpm_worker_pool_config_s *)fpm_worker_pool_config_alloc();
1330         if (!current_wp || !config) {
1331                 zlog(ZLOG_ERROR, "[%s:%d] Unable to alloc a new WorkerPool for worker '%s'", ini_filename, ini_lineno, Z_STRVAL_P(section));
1332                 *error = 1;
1333                 return;
1334         }
1335         config->name = strdup(Z_STRVAL_P(section));
1336         if (!config->name) {
1337                 zlog(ZLOG_ERROR, "[%s:%d] Unable to alloc memory for configuration name for worker '%s'", ini_filename, ini_lineno, Z_STRVAL_P(section));
1338                 *error = 1;
1339                 return;
1340         }
1341 }
1342 /* }}} */
1343 
1344 static void fpm_conf_ini_parser_entry(zval *name, zval *value, void *arg) /* {{{ */
1345 {
1346         struct ini_value_parser_s *parser;
1347         void *config = NULL;
1348 
1349         int *error = (int *)arg;
1350         if (!value) {
1351                 zlog(ZLOG_ERROR, "[%s:%d] value is NULL for a ZEND_INI_PARSER_ENTRY", ini_filename, ini_lineno);
1352                 *error = 1;
1353                 return;
1354         }
1355 
1356         if (!strcmp(Z_STRVAL_P(name), "include")) {
1357                 if (ini_include) {
1358                         zlog(ZLOG_ERROR, "[%s:%d] two includes at the same time !", ini_filename, ini_lineno);
1359                         *error = 1;
1360                         return;
1361                 }
1362                 ini_include = strdup(Z_STRVAL_P(value));
1363                 return;
1364         }
1365 
1366         if (!current_wp) { /* we are in the global section */
1367                 parser = ini_fpm_global_options;
1368                 config = &fpm_global_config;
1369         } else {
1370                 parser = ini_fpm_pool_options;
1371                 config = current_wp->config;
1372         }
1373 
1374         for (; parser->name; parser++) {
1375                 if (!strcasecmp(parser->name, Z_STRVAL_P(name))) {
1376                         char *ret;
1377                         if (!parser->parser) {
1378                                 zlog(ZLOG_ERROR, "[%s:%d] the parser for entry '%s' is not defined", ini_filename, ini_lineno, parser->name);
1379                                 *error = 1;
1380                                 return;
1381                         }
1382 
1383                         ret = parser->parser(value, &config, parser->offset);
1384                         if (ret) {
1385                                 zlog(ZLOG_ERROR, "[%s:%d] unable to parse value for entry '%s': %s", ini_filename, ini_lineno, parser->name, ret);
1386                                 *error = 1;
1387                                 return;
1388                         }
1389 
1390                         /* all is good ! */
1391                         return;
1392                 }
1393         }
1394 
1395         /* nothing has been found if we got here */
1396         zlog(ZLOG_ERROR, "[%s:%d] unknown entry '%s'", ini_filename, ini_lineno, Z_STRVAL_P(name));
1397         *error = 1;
1398 }
1399 /* }}} */
1400 
1401 static void fpm_conf_ini_parser_array(zval *name, zval *key, zval *value, void *arg) /* {{{ */
1402 {
1403         int *error = (int *)arg;
1404         char *err = NULL;
1405         void *config;
1406 
1407         if (!Z_STRVAL_P(key) || !Z_STRVAL_P(value) || !*Z_STRVAL_P(key)) {
1408                 zlog(ZLOG_ERROR, "[%s:%d] Misspelled  array ?", ini_filename, ini_lineno);
1409                 *error = 1;
1410                 return;
1411         }
1412         if (!current_wp || !current_wp->config) {
1413                 zlog(ZLOG_ERROR, "[%s:%d] Array are not allowed in the global section", ini_filename, ini_lineno);
1414                 *error = 1;
1415                 return;
1416         }
1417 
1418         if (!strcmp("env", Z_STRVAL_P(name))) {
1419                 if (!*Z_STRVAL_P(value)) {
1420                         zlog(ZLOG_ERROR, "[%s:%d] empty value", ini_filename, ini_lineno);
1421                         *error = 1;
1422                         return;
1423                 }
1424                 config = (char *)current_wp->config + WPO(env);
1425                 err = fpm_conf_set_array(key, value, &config, 0);
1426 
1427         } else if (!strcmp("php_value", Z_STRVAL_P(name))) {
1428                 config = (char *)current_wp->config + WPO(php_values);
1429                 err = fpm_conf_set_array(key, value, &config, 0);
1430 
1431         } else if (!strcmp("php_admin_value", Z_STRVAL_P(name))) {
1432                 config = (char *)current_wp->config + WPO(php_admin_values);
1433                 err = fpm_conf_set_array(key, value, &config, 0);
1434 
1435         } else if (!strcmp("php_flag", Z_STRVAL_P(name))) {
1436                 config = (char *)current_wp->config + WPO(php_values);
1437                 err = fpm_conf_set_array(key, value, &config, 1);
1438 
1439         } else if (!strcmp("php_admin_flag", Z_STRVAL_P(name))) {
1440                 config = (char *)current_wp->config + WPO(php_admin_values);
1441                 err = fpm_conf_set_array(key, value, &config, 1);
1442 
1443         } else {
1444                 zlog(ZLOG_ERROR, "[%s:%d] unknown directive '%s'", ini_filename, ini_lineno, Z_STRVAL_P(name));
1445                 *error = 1;
1446                 return;
1447         }
1448 
1449         if (err) {
1450                 zlog(ZLOG_ERROR, "[%s:%d] error while parsing '%s[%s]' : %s", ini_filename, ini_lineno, Z_STRVAL_P(name), Z_STRVAL_P(key), err);
1451                 *error = 1;
1452                 return;
1453         }
1454 }
1455 /* }}} */
1456 
1457 static void fpm_conf_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg) /* {{{ */
1458 {
1459         int *error;
1460 
1461         if (!arg1 || !arg) return;
1462         error = (int *)arg;
1463         if (*error) return; /* We got already an error. Switch to the end. */
1464 
1465         switch(callback_type) {
1466                 case ZEND_INI_PARSER_ENTRY:
1467                         fpm_conf_ini_parser_entry(arg1, arg2, error);
1468                         break;;
1469                 case ZEND_INI_PARSER_SECTION:
1470                         fpm_conf_ini_parser_section(arg1, error);
1471                         break;;
1472                 case ZEND_INI_PARSER_POP_ENTRY:
1473                         fpm_conf_ini_parser_array(arg1, arg3, arg2, error);
1474                         break;;
1475                 default:
1476                         zlog(ZLOG_ERROR, "[%s:%d] Unknown INI syntax", ini_filename, ini_lineno);
1477                         *error = 1;
1478                         break;;
1479         }
1480 }
1481 /* }}} */
1482 
1483 int fpm_conf_load_ini_file(char *filename) /* {{{ */
1484 {
1485         int error = 0;
1486         char *buf = NULL, *newbuf = NULL;
1487         int bufsize = 0;
1488         int fd, n;
1489         int nb_read = 1;
1490         char c = '*';
1491 
1492         int ret = 1;
1493 
1494         if (!filename || !filename[0]) {
1495                 zlog(ZLOG_ERROR, "configuration filename is empty");
1496                 return -1;
1497         }
1498 
1499         fd = open(filename, O_RDONLY, 0);
1500         if (fd < 0) {
1501                 zlog(ZLOG_SYSERROR, "failed to open configuration file '%s'", filename);
1502                 return -1;
1503         }
1504 
1505         if (ini_recursion++ > 4) {
1506                 zlog(ZLOG_ERROR, "failed to include more than 5 files recusively");
1507                 close(fd);
1508                 return -1;
1509         }
1510 
1511         ini_lineno = 0;
1512         while (nb_read > 0) {
1513                 int tmp;
1514                 ini_lineno++;
1515                 ini_filename = filename;
1516                 for (n = 0; (nb_read = read(fd, &c, sizeof(char))) == sizeof(char) && c != '\n'; n++) {
1517                         if (n == bufsize) {
1518                                 bufsize += 1024;
1519                                 newbuf = (char*) realloc(buf, sizeof(char) * (bufsize + 2));
1520                                 if (newbuf == NULL) {
1521                                         ini_recursion--;
1522                                         close(fd);
1523                                         free(buf);
1524                                         return -1;
1525                                 }
1526                                 buf = newbuf;
1527                         }
1528 
1529                         buf[n] = c;
1530                 }
1531                 if (n == 0) {
1532                         continue;
1533                 }
1534                 /* always append newline and null terminate */
1535                 buf[n++] = '\n';
1536                 buf[n] = '\0';
1537                 tmp = zend_parse_ini_string(buf, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fpm_conf_ini_parser, &error);
1538                 ini_filename = filename;
1539                 if (error || tmp == FAILURE) {
1540                         if (ini_include) free(ini_include);
1541                         ini_recursion--;
1542                         close(fd);
1543                         free(buf);
1544                         return -1;
1545                 }
1546                 if (ini_include) {
1547                         char *tmp = ini_include;
1548                         ini_include = NULL;
1549                         fpm_evaluate_full_path(&tmp, NULL, NULL, 0);
1550                         fpm_conf_ini_parser_include(tmp, &error);
1551                         if (error) {
1552                                 free(tmp);
1553                                 ini_recursion--;
1554                                 close(fd);
1555                                 free(buf);
1556                                 return -1;
1557                         }
1558                         free(tmp);
1559                 }
1560         }
1561         free(buf);
1562 
1563         ini_recursion--;
1564         close(fd);
1565         return ret;
1566 }
1567 /* }}} */
1568 
1569 static void fpm_conf_dump() /* {{{ */
1570 {
1571         struct fpm_worker_pool_s *wp;
1572 
1573         /*
1574          * Please keep the same order as in fpm_conf.h and in php-fpm.conf.in
1575          */
1576         zlog(ZLOG_NOTICE, "[General]");
1577         zlog(ZLOG_NOTICE, "\tpid = %s",                         STR2STR(fpm_global_config.pid_file));
1578         zlog(ZLOG_NOTICE, "\terror_log = %s",                   STR2STR(fpm_global_config.error_log));
1579 #ifdef HAVE_SYSLOG_H
1580         zlog(ZLOG_NOTICE, "\tsyslog.ident = %s",                STR2STR(fpm_global_config.syslog_ident));
1581         zlog(ZLOG_NOTICE, "\tsyslog.facility = %d",             fpm_global_config.syslog_facility); /* FIXME: convert to string */
1582 #endif
1583         zlog(ZLOG_NOTICE, "\tlog_level = %s",                   zlog_get_level_name(fpm_globals.log_level));
1584         zlog(ZLOG_NOTICE, "\temergency_restart_interval = %ds", fpm_global_config.emergency_restart_interval);
1585         zlog(ZLOG_NOTICE, "\temergency_restart_threshold = %d", fpm_global_config.emergency_restart_threshold);
1586         zlog(ZLOG_NOTICE, "\tprocess_control_timeout = %ds",    fpm_global_config.process_control_timeout);
1587         zlog(ZLOG_NOTICE, "\tprocess.max = %d",                 fpm_global_config.process_max);
1588         if (fpm_global_config.process_priority == 64) {
1589                 zlog(ZLOG_NOTICE, "\tprocess.priority = undefined");
1590         } else {
1591                 zlog(ZLOG_NOTICE, "\tprocess.priority = %d", fpm_global_config.process_priority);
1592         }
1593         zlog(ZLOG_NOTICE, "\tdaemonize = %s",                   BOOL2STR(fpm_global_config.daemonize));
1594         zlog(ZLOG_NOTICE, "\trlimit_files = %d",                fpm_global_config.rlimit_files);
1595         zlog(ZLOG_NOTICE, "\trlimit_core = %d",                 fpm_global_config.rlimit_core);
1596         zlog(ZLOG_NOTICE, "\tevents.mechanism = %s",            fpm_event_machanism_name());
1597 #ifdef HAVE_SYSTEMD
1598         zlog(ZLOG_NOTICE, "\tsystemd_interval = %ds",           fpm_global_config.systemd_interval/1000);
1599 #endif
1600         zlog(ZLOG_NOTICE, " ");
1601 
1602         for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
1603                 struct key_value_s *kv;
1604                 if (!wp->config) continue;
1605                 zlog(ZLOG_NOTICE, "[%s]",                              STR2STR(wp->config->name));
1606                 zlog(ZLOG_NOTICE, "\tprefix = %s",                     STR2STR(wp->config->prefix));
1607                 zlog(ZLOG_NOTICE, "\tuser = %s",                       STR2STR(wp->config->user));
1608                 zlog(ZLOG_NOTICE, "\tgroup = %s",                      STR2STR(wp->config->group));
1609                 zlog(ZLOG_NOTICE, "\tlisten = %s",                     STR2STR(wp->config->listen_address));
1610                 zlog(ZLOG_NOTICE, "\tlisten.backlog = %d",             wp->config->listen_backlog);
1611 #ifdef HAVE_FPM_ACL
1612                 zlog(ZLOG_NOTICE, "\tlisten.acl_users = %s",           STR2STR(wp->config->listen_acl_users));
1613                 zlog(ZLOG_NOTICE, "\tlisten.acl_groups = %s",          STR2STR(wp->config->listen_acl_groups));
1614 #endif
1615                 zlog(ZLOG_NOTICE, "\tlisten.owner = %s",               STR2STR(wp->config->listen_owner));
1616                 zlog(ZLOG_NOTICE, "\tlisten.group = %s",               STR2STR(wp->config->listen_group));
1617                 zlog(ZLOG_NOTICE, "\tlisten.mode = %s",                STR2STR(wp->config->listen_mode));
1618                 zlog(ZLOG_NOTICE, "\tlisten.allowed_clients = %s",     STR2STR(wp->config->listen_allowed_clients));
1619                 if (wp->config->process_priority == 64) {
1620                         zlog(ZLOG_NOTICE, "\tprocess.priority = undefined");
1621                 } else {
1622                         zlog(ZLOG_NOTICE, "\tprocess.priority = %d", wp->config->process_priority);
1623                 }
1624                 zlog(ZLOG_NOTICE, "\tpm = %s",                         PM2STR(wp->config->pm));
1625                 zlog(ZLOG_NOTICE, "\tpm.max_children = %d",            wp->config->pm_max_children);
1626                 zlog(ZLOG_NOTICE, "\tpm.start_servers = %d",           wp->config->pm_start_servers);
1627                 zlog(ZLOG_NOTICE, "\tpm.min_spare_servers = %d",       wp->config->pm_min_spare_servers);
1628                 zlog(ZLOG_NOTICE, "\tpm.max_spare_servers = %d",       wp->config->pm_max_spare_servers);
1629                 zlog(ZLOG_NOTICE, "\tpm.process_idle_timeout = %d",    wp->config->pm_process_idle_timeout);
1630                 zlog(ZLOG_NOTICE, "\tpm.max_requests = %d",            wp->config->pm_max_requests);
1631                 zlog(ZLOG_NOTICE, "\tpm.status_path = %s",             STR2STR(wp->config->pm_status_path));
1632                 zlog(ZLOG_NOTICE, "\tping.path = %s",                  STR2STR(wp->config->ping_path));
1633                 zlog(ZLOG_NOTICE, "\tping.response = %s",              STR2STR(wp->config->ping_response));
1634                 zlog(ZLOG_NOTICE, "\taccess.log = %s",                 STR2STR(wp->config->access_log));
1635                 zlog(ZLOG_NOTICE, "\taccess.format = %s",              STR2STR(wp->config->access_format));
1636                 zlog(ZLOG_NOTICE, "\tslowlog = %s",                    STR2STR(wp->config->slowlog));
1637                 zlog(ZLOG_NOTICE, "\trequest_slowlog_timeout = %ds",   wp->config->request_slowlog_timeout);
1638                 zlog(ZLOG_NOTICE, "\trequest_terminate_timeout = %ds", wp->config->request_terminate_timeout);
1639                 zlog(ZLOG_NOTICE, "\trlimit_files = %d",               wp->config->rlimit_files);
1640                 zlog(ZLOG_NOTICE, "\trlimit_core = %d",                wp->config->rlimit_core);
1641                 zlog(ZLOG_NOTICE, "\tchroot = %s",                     STR2STR(wp->config->chroot));
1642                 zlog(ZLOG_NOTICE, "\tchdir = %s",                      STR2STR(wp->config->chdir));
1643                 zlog(ZLOG_NOTICE, "\tcatch_workers_output = %s",       BOOL2STR(wp->config->catch_workers_output));
1644                 zlog(ZLOG_NOTICE, "\tclear_env = %s",                  BOOL2STR(wp->config->clear_env));
1645                 zlog(ZLOG_NOTICE, "\tsecurity.limit_extensions = %s",  wp->config->security_limit_extensions);
1646 
1647                 for (kv = wp->config->env; kv; kv = kv->next) {
1648                         zlog(ZLOG_NOTICE, "\tenv[%s] = %s", kv->key, kv->value);
1649                 }
1650 
1651                 for (kv = wp->config->php_values; kv; kv = kv->next) {
1652                         zlog(ZLOG_NOTICE, "\tphp_value[%s] = %s", kv->key, kv->value);
1653                 }
1654 
1655                 for (kv = wp->config->php_admin_values; kv; kv = kv->next) {
1656                         zlog(ZLOG_NOTICE, "\tphp_admin_value[%s] = %s", kv->key, kv->value);
1657                 }
1658                 zlog(ZLOG_NOTICE, " ");
1659         }
1660 }
1661 /* }}} */
1662 
1663 int fpm_conf_init_main(int test_conf, int force_daemon) /* {{{ */
1664 {
1665         int ret;
1666 
1667         if (fpm_globals.prefix && *fpm_globals.prefix) {
1668                 if (!fpm_conf_is_dir(fpm_globals.prefix)) {
1669                         zlog(ZLOG_ERROR, "the global prefix '%s' does not exist or is not a directory", fpm_globals.prefix);
1670                         return -1;
1671                 }
1672         }
1673 
1674         if (fpm_globals.pid && *fpm_globals.pid) {
1675                 fpm_global_config.pid_file = strdup(fpm_globals.pid);
1676         }
1677 
1678         if (fpm_globals.config == NULL) {
1679                 char *tmp;
1680 
1681                 if (fpm_globals.prefix == NULL) {
1682                         spprintf(&tmp, 0, "%s/php-fpm.conf", PHP_SYSCONFDIR);
1683                 } else {
1684                         spprintf(&tmp, 0, "%s/etc/php-fpm.conf", fpm_globals.prefix);
1685                 }
1686 
1687                 if (!tmp) {
1688                         zlog(ZLOG_SYSERROR, "spprintf() failed (tmp for fpm_globals.config)");
1689                         return -1;
1690                 }
1691 
1692                 fpm_globals.config = strdup(tmp);
1693                 efree(tmp);
1694 
1695                 if (!fpm_globals.config) {
1696                         zlog(ZLOG_SYSERROR, "spprintf() failed (fpm_globals.config)");
1697                         return -1;
1698                 }
1699         }
1700 
1701         ret = fpm_conf_load_ini_file(fpm_globals.config);
1702 
1703         if (0 > ret) {
1704                 zlog(ZLOG_ERROR, "failed to load configuration file '%s'", fpm_globals.config);
1705                 return -1;
1706         }
1707 
1708         if (0 > fpm_conf_post_process(force_daemon)) {
1709                 zlog(ZLOG_ERROR, "failed to post process the configuration");
1710                 return -1;
1711         }
1712 
1713         if (test_conf) {
1714                 if (test_conf > 1) {
1715                         fpm_conf_dump();
1716                 }
1717                 zlog(ZLOG_NOTICE, "configuration file %s test is successful\n", fpm_globals.config);
1718                 fpm_globals.test_successful = 1;
1719                 return -1;
1720         }
1721 
1722         if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_conf_cleanup, 0)) {
1723                 return -1;
1724         }
1725 
1726         return 0;
1727 }
1728 /* }}} */

/* [<][>][^][v][top][bottom][index][help] */