0001
0002
0003
0004
0005
0006
0007
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <nginx.h>
0011
0012
0013 static void ngx_show_version_info(void);
0014 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
0015 static void ngx_cleanup_environment(void *data);
0016 static ngx_int_t ngx_get_options(int argc, char *const *argv);
0017 static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
0018 static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
0019 static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
0020 static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
0021 static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
0022 static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
0023 static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
0024 static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd,
0025 void *conf);
0026 static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd,
0027 void *conf);
0028 static char *ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
0029 #if (NGX_HAVE_DLOPEN)
0030 static void ngx_unload_module(void *data);
0031 #endif
0032
0033
0034 static ngx_conf_enum_t ngx_debug_points[] = {
0035 { ngx_string("stop"), NGX_DEBUG_POINTS_STOP },
0036 { ngx_string("abort"), NGX_DEBUG_POINTS_ABORT },
0037 { ngx_null_string, 0 }
0038 };
0039
0040
0041 static ngx_command_t ngx_core_commands[] = {
0042
0043 { ngx_string("daemon"),
0044 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
0045 ngx_conf_set_flag_slot,
0046 0,
0047 offsetof(ngx_core_conf_t, daemon),
0048 NULL },
0049
0050 { ngx_string("master_process"),
0051 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
0052 ngx_conf_set_flag_slot,
0053 0,
0054 offsetof(ngx_core_conf_t, master),
0055 NULL },
0056
0057 { ngx_string("timer_resolution"),
0058 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0059 ngx_conf_set_msec_slot,
0060 0,
0061 offsetof(ngx_core_conf_t, timer_resolution),
0062 NULL },
0063
0064 { ngx_string("pid"),
0065 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0066 ngx_conf_set_str_slot,
0067 0,
0068 offsetof(ngx_core_conf_t, pid),
0069 NULL },
0070
0071 { ngx_string("lock_file"),
0072 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0073 ngx_conf_set_str_slot,
0074 0,
0075 offsetof(ngx_core_conf_t, lock_file),
0076 NULL },
0077
0078 { ngx_string("worker_processes"),
0079 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0080 ngx_set_worker_processes,
0081 0,
0082 0,
0083 NULL },
0084
0085 { ngx_string("debug_points"),
0086 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0087 ngx_conf_set_enum_slot,
0088 0,
0089 offsetof(ngx_core_conf_t, debug_points),
0090 &ngx_debug_points },
0091
0092 { ngx_string("user"),
0093 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
0094 ngx_set_user,
0095 0,
0096 0,
0097 NULL },
0098
0099 { ngx_string("worker_priority"),
0100 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0101 ngx_set_priority,
0102 0,
0103 0,
0104 NULL },
0105
0106 { ngx_string("worker_cpu_affinity"),
0107 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
0108 ngx_set_cpu_affinity,
0109 0,
0110 0,
0111 NULL },
0112
0113 { ngx_string("worker_rlimit_nofile"),
0114 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0115 ngx_conf_set_num_slot,
0116 0,
0117 offsetof(ngx_core_conf_t, rlimit_nofile),
0118 NULL },
0119
0120 { ngx_string("worker_rlimit_core"),
0121 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0122 ngx_conf_set_off_slot,
0123 0,
0124 offsetof(ngx_core_conf_t, rlimit_core),
0125 NULL },
0126
0127 { ngx_string("worker_shutdown_timeout"),
0128 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0129 ngx_conf_set_msec_slot,
0130 0,
0131 offsetof(ngx_core_conf_t, shutdown_timeout),
0132 NULL },
0133
0134 { ngx_string("working_directory"),
0135 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0136 ngx_conf_set_str_slot,
0137 0,
0138 offsetof(ngx_core_conf_t, working_directory),
0139 NULL },
0140
0141 { ngx_string("env"),
0142 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0143 ngx_set_env,
0144 0,
0145 0,
0146 NULL },
0147
0148 { ngx_string("load_module"),
0149 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
0150 ngx_load_module,
0151 0,
0152 0,
0153 NULL },
0154
0155 ngx_null_command
0156 };
0157
0158
0159 static ngx_core_module_t ngx_core_module_ctx = {
0160 ngx_string("core"),
0161 ngx_core_module_create_conf,
0162 ngx_core_module_init_conf
0163 };
0164
0165
0166 ngx_module_t ngx_core_module = {
0167 NGX_MODULE_V1,
0168 &ngx_core_module_ctx,
0169 ngx_core_commands,
0170 NGX_CORE_MODULE,
0171 NULL,
0172 NULL,
0173 NULL,
0174 NULL,
0175 NULL,
0176 NULL,
0177 NULL,
0178 NGX_MODULE_V1_PADDING
0179 };
0180
0181
0182 static ngx_uint_t ngx_show_help;
0183 static ngx_uint_t ngx_show_version;
0184 static ngx_uint_t ngx_show_configure;
0185 static u_char *ngx_prefix;
0186 static u_char *ngx_conf_file;
0187 static u_char *ngx_conf_params;
0188 static char *ngx_signal;
0189
0190
0191 static char **ngx_os_environ;
0192
0193
0194 int ngx_cdecl
0195 main(int argc, char *const *argv)
0196 {
0197 ngx_buf_t *b;
0198 ngx_log_t *log;
0199 ngx_uint_t i;
0200 ngx_cycle_t *cycle, init_cycle;
0201 ngx_conf_dump_t *cd;
0202 ngx_core_conf_t *ccf;
0203
0204 ngx_debug_init();
0205
0206 if (ngx_strerror_init() != NGX_OK) {
0207 return 1;
0208 }
0209
0210 if (ngx_get_options(argc, argv) != NGX_OK) {
0211 return 1;
0212 }
0213
0214 if (ngx_show_version) {
0215 ngx_show_version_info();
0216
0217 if (!ngx_test_config) {
0218 return 0;
0219 }
0220 }
0221
0222 ngx_max_sockets = -1;
0223
0224 ngx_time_init();
0225
0226 #if (NGX_PCRE)
0227 ngx_regex_init();
0228 #endif
0229
0230 ngx_pid = ngx_getpid();
0231
0232 log = ngx_log_init(ngx_prefix);
0233 if (log == NULL) {
0234 return 1;
0235 }
0236
0237
0238 #if (NGX_OPENSSL)
0239 ngx_ssl_init(log);
0240 #endif
0241
0242
0243
0244
0245
0246
0247 ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
0248 init_cycle.log = log;
0249 ngx_cycle = &init_cycle;
0250
0251 init_cycle.pool = ngx_create_pool(1024, log);
0252 if (init_cycle.pool == NULL) {
0253 return 1;
0254 }
0255
0256 if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
0257 return 1;
0258 }
0259
0260 if (ngx_process_options(&init_cycle) != NGX_OK) {
0261 return 1;
0262 }
0263
0264 if (ngx_os_init(log) != NGX_OK) {
0265 return 1;
0266 }
0267
0268
0269
0270
0271
0272 if (ngx_crc32_table_init() != NGX_OK) {
0273 return 1;
0274 }
0275
0276 if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
0277 return 1;
0278 }
0279
0280 if (ngx_preinit_modules() != NGX_OK) {
0281 return 1;
0282 }
0283
0284 cycle = ngx_init_cycle(&init_cycle);
0285 if (cycle == NULL) {
0286 if (ngx_test_config) {
0287 ngx_log_stderr(0, "configuration file %s test failed",
0288 init_cycle.conf_file.data);
0289 }
0290
0291 return 1;
0292 }
0293
0294 if (ngx_test_config) {
0295 if (!ngx_quiet_mode) {
0296 ngx_log_stderr(0, "configuration file %s test is successful",
0297 cycle->conf_file.data);
0298 }
0299
0300 if (ngx_dump_config) {
0301 cd = cycle->config_dump.elts;
0302
0303 for (i = 0; i < cycle->config_dump.nelts; i++) {
0304
0305 ngx_write_stdout("# configuration file ");
0306 (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
0307 cd[i].name.len);
0308 ngx_write_stdout(":" NGX_LINEFEED);
0309
0310 b = cd[i].buffer;
0311
0312 (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
0313 ngx_write_stdout(NGX_LINEFEED);
0314 }
0315 }
0316
0317 return 0;
0318 }
0319
0320 if (ngx_signal) {
0321 return ngx_signal_process(cycle, ngx_signal);
0322 }
0323
0324 ngx_os_status(cycle->log);
0325
0326 ngx_cycle = cycle;
0327
0328 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
0329
0330 if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
0331 ngx_process = NGX_PROCESS_MASTER;
0332 }
0333
0334 #if !(NGX_WIN32)
0335
0336 if (ngx_init_signals(cycle->log) != NGX_OK) {
0337 return 1;
0338 }
0339
0340 if (!ngx_inherited && ccf->daemon) {
0341 if (ngx_daemon(cycle->log) != NGX_OK) {
0342 return 1;
0343 }
0344
0345 ngx_daemonized = 1;
0346 }
0347
0348 if (ngx_inherited) {
0349 ngx_daemonized = 1;
0350 }
0351
0352 #endif
0353
0354 if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
0355 return 1;
0356 }
0357
0358 if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
0359 return 1;
0360 }
0361
0362 if (log->file->fd != ngx_stderr) {
0363 if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
0364 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0365 ngx_close_file_n " built-in log failed");
0366 }
0367 }
0368
0369 ngx_use_stderr = 0;
0370
0371 if (ngx_process == NGX_PROCESS_SINGLE) {
0372 ngx_single_process_cycle(cycle);
0373
0374 } else {
0375 ngx_master_process_cycle(cycle);
0376 }
0377
0378 return 0;
0379 }
0380
0381
0382 static void
0383 ngx_show_version_info(void)
0384 {
0385 ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);
0386
0387 if (ngx_show_help) {
0388 ngx_write_stderr(
0389 "Usage: nginx [-?hvVtTq] [-s signal] [-c filename] "
0390 "[-p prefix] [-g directives]" NGX_LINEFEED
0391 NGX_LINEFEED
0392 "Options:" NGX_LINEFEED
0393 " -?,-h : this help" NGX_LINEFEED
0394 " -v : show version and exit" NGX_LINEFEED
0395 " -V : show version and configure options then exit"
0396 NGX_LINEFEED
0397 " -t : test configuration and exit" NGX_LINEFEED
0398 " -T : test configuration, dump it and exit"
0399 NGX_LINEFEED
0400 " -q : suppress non-error messages "
0401 "during configuration testing" NGX_LINEFEED
0402 " -s signal : send signal to a master process: "
0403 "stop, quit, reopen, reload" NGX_LINEFEED
0404 #ifdef NGX_PREFIX
0405 " -p prefix : set prefix path (default: " NGX_PREFIX ")"
0406 NGX_LINEFEED
0407 #else
0408 " -p prefix : set prefix path (default: NONE)" NGX_LINEFEED
0409 #endif
0410 " -c filename : set configuration file (default: " NGX_CONF_PATH
0411 ")" NGX_LINEFEED
0412 " -g directives : set global directives out of configuration "
0413 "file" NGX_LINEFEED NGX_LINEFEED
0414 );
0415 }
0416
0417 if (ngx_show_configure) {
0418
0419 #ifdef NGX_COMPILER
0420 ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED);
0421 #endif
0422
0423 #if (NGX_SSL)
0424 if (ngx_strcmp(ngx_ssl_version(), OPENSSL_VERSION_TEXT) == 0) {
0425 ngx_write_stderr("built with " OPENSSL_VERSION_TEXT NGX_LINEFEED);
0426 } else {
0427 ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
0428 " (running with ");
0429 ngx_write_stderr((char *) (uintptr_t) ngx_ssl_version());
0430 ngx_write_stderr(")" NGX_LINEFEED);
0431 }
0432 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
0433 ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED);
0434 #else
0435 ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED);
0436 #endif
0437 #endif
0438
0439 ngx_write_stderr("configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
0440 }
0441 }
0442
0443
0444 static ngx_int_t
0445 ngx_add_inherited_sockets(ngx_cycle_t *cycle)
0446 {
0447 u_char *p, *v, *inherited;
0448 ngx_int_t s;
0449 ngx_listening_t *ls;
0450
0451 inherited = (u_char *) getenv(NGINX_VAR);
0452
0453 if (inherited == NULL) {
0454 return NGX_OK;
0455 }
0456
0457 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
0458 "using inherited sockets from \"%s\"", inherited);
0459
0460 if (ngx_array_init(&cycle->listening, cycle->pool, 10,
0461 sizeof(ngx_listening_t))
0462 != NGX_OK)
0463 {
0464 return NGX_ERROR;
0465 }
0466
0467 for (p = inherited, v = p; *p; p++) {
0468 if (*p == ':' || *p == ';') {
0469 s = ngx_atoi(v, p - v);
0470 if (s == NGX_ERROR) {
0471 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
0472 "invalid socket number \"%s\" in " NGINX_VAR
0473 " environment variable, ignoring the rest"
0474 " of the variable", v);
0475 break;
0476 }
0477
0478 v = p + 1;
0479
0480 ls = ngx_array_push(&cycle->listening);
0481 if (ls == NULL) {
0482 return NGX_ERROR;
0483 }
0484
0485 ngx_memzero(ls, sizeof(ngx_listening_t));
0486
0487 ls->fd = (ngx_socket_t) s;
0488 }
0489 }
0490
0491 if (v != p) {
0492 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
0493 "invalid socket number \"%s\" in " NGINX_VAR
0494 " environment variable, ignoring", v);
0495 }
0496
0497 ngx_inherited = 1;
0498
0499 return ngx_set_inherited_sockets(cycle);
0500 }
0501
0502
0503 char **
0504 ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
0505 {
0506 char **p, **env;
0507 ngx_str_t *var;
0508 ngx_uint_t i, n;
0509 ngx_core_conf_t *ccf;
0510 ngx_pool_cleanup_t *cln;
0511
0512 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
0513
0514 if (last == NULL && ccf->environment) {
0515 return ccf->environment;
0516 }
0517
0518 var = ccf->env.elts;
0519
0520 for (i = 0; i < ccf->env.nelts; i++) {
0521 if (ngx_strcmp(var[i].data, "TZ") == 0
0522 || ngx_strncmp(var[i].data, "TZ=", 3) == 0)
0523 {
0524 goto tz_found;
0525 }
0526 }
0527
0528 var = ngx_array_push(&ccf->env);
0529 if (var == NULL) {
0530 return NULL;
0531 }
0532
0533 var->len = 2;
0534 var->data = (u_char *) "TZ";
0535
0536 var = ccf->env.elts;
0537
0538 tz_found:
0539
0540 n = 0;
0541
0542 for (i = 0; i < ccf->env.nelts; i++) {
0543
0544 if (var[i].data[var[i].len] == '=') {
0545 n++;
0546 continue;
0547 }
0548
0549 for (p = ngx_os_environ; *p; p++) {
0550
0551 if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
0552 && (*p)[var[i].len] == '=')
0553 {
0554 n++;
0555 break;
0556 }
0557 }
0558 }
0559
0560 if (last) {
0561 env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log);
0562 if (env == NULL) {
0563 return NULL;
0564 }
0565
0566 *last = n;
0567
0568 } else {
0569 cln = ngx_pool_cleanup_add(cycle->pool, 0);
0570 if (cln == NULL) {
0571 return NULL;
0572 }
0573
0574 env = ngx_alloc((n + 1) * sizeof(char *), cycle->log);
0575 if (env == NULL) {
0576 return NULL;
0577 }
0578
0579 cln->handler = ngx_cleanup_environment;
0580 cln->data = env;
0581 }
0582
0583 n = 0;
0584
0585 for (i = 0; i < ccf->env.nelts; i++) {
0586
0587 if (var[i].data[var[i].len] == '=') {
0588 env[n++] = (char *) var[i].data;
0589 continue;
0590 }
0591
0592 for (p = ngx_os_environ; *p; p++) {
0593
0594 if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
0595 && (*p)[var[i].len] == '=')
0596 {
0597 env[n++] = *p;
0598 break;
0599 }
0600 }
0601 }
0602
0603 env[n] = NULL;
0604
0605 if (last == NULL) {
0606 ccf->environment = env;
0607 environ = env;
0608 }
0609
0610 return env;
0611 }
0612
0613
0614 static void
0615 ngx_cleanup_environment(void *data)
0616 {
0617 char **env = data;
0618
0619 if (environ == env) {
0620
0621
0622
0623
0624
0625
0626 return;
0627 }
0628
0629 ngx_free(env);
0630 }
0631
0632
0633 ngx_pid_t
0634 ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
0635 {
0636 char **env, *var;
0637 u_char *p;
0638 ngx_uint_t i, n;
0639 ngx_pid_t pid;
0640 ngx_exec_ctx_t ctx;
0641 ngx_core_conf_t *ccf;
0642 ngx_listening_t *ls;
0643
0644 ngx_memzero(&ctx, sizeof(ngx_exec_ctx_t));
0645
0646 ctx.path = argv[0];
0647 ctx.name = "new binary process";
0648 ctx.argv = argv;
0649
0650 n = 2;
0651 env = ngx_set_environment(cycle, &n);
0652 if (env == NULL) {
0653 return NGX_INVALID_PID;
0654 }
0655
0656 var = ngx_alloc(sizeof(NGINX_VAR)
0657 + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
0658 cycle->log);
0659 if (var == NULL) {
0660 ngx_free(env);
0661 return NGX_INVALID_PID;
0662 }
0663
0664 p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR));
0665
0666 ls = cycle->listening.elts;
0667 for (i = 0; i < cycle->listening.nelts; i++) {
0668 p = ngx_sprintf(p, "%ud;", ls[i].fd);
0669 }
0670
0671 *p = '\0';
0672
0673 env[n++] = var;
0674
0675 #if (NGX_SETPROCTITLE_USES_ENV)
0676
0677
0678
0679 env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
0680 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
0681 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
0682 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
0683 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
0684
0685 #endif
0686
0687 env[n] = NULL;
0688
0689 #if (NGX_DEBUG)
0690 {
0691 char **e;
0692 for (e = env; *e; e++) {
0693 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e);
0694 }
0695 }
0696 #endif
0697
0698 ctx.envp = (char *const *) env;
0699
0700 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
0701
0702 if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == NGX_FILE_ERROR) {
0703 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0704 ngx_rename_file_n " %s to %s failed "
0705 "before executing new binary process \"%s\"",
0706 ccf->pid.data, ccf->oldpid.data, argv[0]);
0707
0708 ngx_free(env);
0709 ngx_free(var);
0710
0711 return NGX_INVALID_PID;
0712 }
0713
0714 pid = ngx_execute(cycle, &ctx);
0715
0716 if (pid == NGX_INVALID_PID) {
0717 if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data)
0718 == NGX_FILE_ERROR)
0719 {
0720 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0721 ngx_rename_file_n " %s back to %s failed after "
0722 "an attempt to execute new binary process \"%s\"",
0723 ccf->oldpid.data, ccf->pid.data, argv[0]);
0724 }
0725 }
0726
0727 ngx_free(env);
0728 ngx_free(var);
0729
0730 return pid;
0731 }
0732
0733
0734 static ngx_int_t
0735 ngx_get_options(int argc, char *const *argv)
0736 {
0737 u_char *p;
0738 ngx_int_t i;
0739
0740 for (i = 1; i < argc; i++) {
0741
0742 p = (u_char *) argv[i];
0743
0744 if (*p++ != '-') {
0745 ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
0746 return NGX_ERROR;
0747 }
0748
0749 while (*p) {
0750
0751 switch (*p++) {
0752
0753 case '?':
0754 case 'h':
0755 ngx_show_version = 1;
0756 ngx_show_help = 1;
0757 break;
0758
0759 case 'v':
0760 ngx_show_version = 1;
0761 break;
0762
0763 case 'V':
0764 ngx_show_version = 1;
0765 ngx_show_configure = 1;
0766 break;
0767
0768 case 't':
0769 ngx_test_config = 1;
0770 break;
0771
0772 case 'T':
0773 ngx_test_config = 1;
0774 ngx_dump_config = 1;
0775 break;
0776
0777 case 'q':
0778 ngx_quiet_mode = 1;
0779 break;
0780
0781 case 'p':
0782 if (*p) {
0783 ngx_prefix = p;
0784 goto next;
0785 }
0786
0787 if (argv[++i]) {
0788 ngx_prefix = (u_char *) argv[i];
0789 goto next;
0790 }
0791
0792 ngx_log_stderr(0, "option \"-p\" requires directory name");
0793 return NGX_ERROR;
0794
0795 case 'c':
0796 if (*p) {
0797 ngx_conf_file = p;
0798 goto next;
0799 }
0800
0801 if (argv[++i]) {
0802 ngx_conf_file = (u_char *) argv[i];
0803 goto next;
0804 }
0805
0806 ngx_log_stderr(0, "option \"-c\" requires file name");
0807 return NGX_ERROR;
0808
0809 case 'g':
0810 if (*p) {
0811 ngx_conf_params = p;
0812 goto next;
0813 }
0814
0815 if (argv[++i]) {
0816 ngx_conf_params = (u_char *) argv[i];
0817 goto next;
0818 }
0819
0820 ngx_log_stderr(0, "option \"-g\" requires parameter");
0821 return NGX_ERROR;
0822
0823 case 's':
0824 if (*p) {
0825 ngx_signal = (char *) p;
0826
0827 } else if (argv[++i]) {
0828 ngx_signal = argv[i];
0829
0830 } else {
0831 ngx_log_stderr(0, "option \"-s\" requires parameter");
0832 return NGX_ERROR;
0833 }
0834
0835 if (ngx_strcmp(ngx_signal, "stop") == 0
0836 || ngx_strcmp(ngx_signal, "quit") == 0
0837 || ngx_strcmp(ngx_signal, "reopen") == 0
0838 || ngx_strcmp(ngx_signal, "reload") == 0)
0839 {
0840 ngx_process = NGX_PROCESS_SIGNALLER;
0841 goto next;
0842 }
0843
0844 ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
0845 return NGX_ERROR;
0846
0847 default:
0848 ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
0849 return NGX_ERROR;
0850 }
0851 }
0852
0853 next:
0854
0855 continue;
0856 }
0857
0858 return NGX_OK;
0859 }
0860
0861
0862 static ngx_int_t
0863 ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
0864 {
0865 #if (NGX_FREEBSD)
0866
0867 ngx_os_argv = (char **) argv;
0868 ngx_argc = argc;
0869 ngx_argv = (char **) argv;
0870
0871 #else
0872 size_t len;
0873 ngx_int_t i;
0874
0875 ngx_os_argv = (char **) argv;
0876 ngx_argc = argc;
0877
0878 ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
0879 if (ngx_argv == NULL) {
0880 return NGX_ERROR;
0881 }
0882
0883 for (i = 0; i < argc; i++) {
0884 len = ngx_strlen(argv[i]) + 1;
0885
0886 ngx_argv[i] = ngx_alloc(len, cycle->log);
0887 if (ngx_argv[i] == NULL) {
0888 return NGX_ERROR;
0889 }
0890
0891 (void) ngx_cpystrn((u_char *) ngx_argv[i], (u_char *) argv[i], len);
0892 }
0893
0894 ngx_argv[i] = NULL;
0895
0896 #endif
0897
0898 ngx_os_environ = environ;
0899
0900 return NGX_OK;
0901 }
0902
0903
0904 static ngx_int_t
0905 ngx_process_options(ngx_cycle_t *cycle)
0906 {
0907 u_char *p;
0908 size_t len;
0909
0910 if (ngx_prefix) {
0911 len = ngx_strlen(ngx_prefix);
0912 p = ngx_prefix;
0913
0914 if (len && !ngx_path_separator(p[len - 1])) {
0915 p = ngx_pnalloc(cycle->pool, len + 1);
0916 if (p == NULL) {
0917 return NGX_ERROR;
0918 }
0919
0920 ngx_memcpy(p, ngx_prefix, len);
0921 p[len++] = '/';
0922 }
0923
0924 cycle->conf_prefix.len = len;
0925 cycle->conf_prefix.data = p;
0926 cycle->prefix.len = len;
0927 cycle->prefix.data = p;
0928
0929 } else {
0930
0931 #ifndef NGX_PREFIX
0932
0933 p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
0934 if (p == NULL) {
0935 return NGX_ERROR;
0936 }
0937
0938 if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {
0939 ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
0940 return NGX_ERROR;
0941 }
0942
0943 len = ngx_strlen(p);
0944
0945 p[len++] = '/';
0946
0947 cycle->conf_prefix.len = len;
0948 cycle->conf_prefix.data = p;
0949 cycle->prefix.len = len;
0950 cycle->prefix.data = p;
0951
0952 #else
0953
0954 #ifdef NGX_CONF_PREFIX
0955 ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
0956 #else
0957 ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
0958 #endif
0959 ngx_str_set(&cycle->prefix, NGX_PREFIX);
0960
0961 #endif
0962 }
0963
0964 if (ngx_conf_file) {
0965 cycle->conf_file.len = ngx_strlen(ngx_conf_file);
0966 cycle->conf_file.data = ngx_conf_file;
0967
0968 } else {
0969 ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
0970 }
0971
0972 if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
0973 return NGX_ERROR;
0974 }
0975
0976 for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
0977 p > cycle->conf_file.data;
0978 p--)
0979 {
0980 if (ngx_path_separator(*p)) {
0981 cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1;
0982 cycle->conf_prefix.data = ngx_cycle->conf_file.data;
0983 break;
0984 }
0985 }
0986
0987 if (ngx_conf_params) {
0988 cycle->conf_param.len = ngx_strlen(ngx_conf_params);
0989 cycle->conf_param.data = ngx_conf_params;
0990 }
0991
0992 if (ngx_test_config) {
0993 cycle->log->log_level = NGX_LOG_INFO;
0994 }
0995
0996 return NGX_OK;
0997 }
0998
0999
1000 static void *
1001 ngx_core_module_create_conf(ngx_cycle_t *cycle)
1002 {
1003 ngx_core_conf_t *ccf;
1004
1005 ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t));
1006 if (ccf == NULL) {
1007 return NULL;
1008 }
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021 ccf->daemon = NGX_CONF_UNSET;
1022 ccf->master = NGX_CONF_UNSET;
1023 ccf->timer_resolution = NGX_CONF_UNSET_MSEC;
1024 ccf->shutdown_timeout = NGX_CONF_UNSET_MSEC;
1025
1026 ccf->worker_processes = NGX_CONF_UNSET;
1027 ccf->debug_points = NGX_CONF_UNSET;
1028
1029 ccf->rlimit_nofile = NGX_CONF_UNSET;
1030 ccf->rlimit_core = NGX_CONF_UNSET;
1031
1032 ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;
1033 ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT;
1034
1035 if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))
1036 != NGX_OK)
1037 {
1038 return NULL;
1039 }
1040
1041 return ccf;
1042 }
1043
1044
1045 static char *
1046 ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
1047 {
1048 ngx_core_conf_t *ccf = conf;
1049
1050 ngx_conf_init_value(ccf->daemon, 1);
1051 ngx_conf_init_value(ccf->master, 1);
1052 ngx_conf_init_msec_value(ccf->timer_resolution, 0);
1053 ngx_conf_init_msec_value(ccf->shutdown_timeout, 0);
1054
1055 ngx_conf_init_value(ccf->worker_processes, 1);
1056 ngx_conf_init_value(ccf->debug_points, 0);
1057
1058 #if (NGX_HAVE_CPU_AFFINITY)
1059
1060 if (!ccf->cpu_affinity_auto
1061 && ccf->cpu_affinity_n
1062 && ccf->cpu_affinity_n != 1
1063 && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)
1064 {
1065 ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
1066 "the number of \"worker_processes\" is not equal to "
1067 "the number of \"worker_cpu_affinity\" masks, "
1068 "using last mask for remaining worker processes");
1069 }
1070
1071 #endif
1072
1073
1074 if (ccf->pid.len == 0) {
1075 ngx_str_set(&ccf->pid, NGX_PID_PATH);
1076 }
1077
1078 if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
1079 return NGX_CONF_ERROR;
1080 }
1081
1082 ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);
1083
1084 ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
1085 if (ccf->oldpid.data == NULL) {
1086 return NGX_CONF_ERROR;
1087 }
1088
1089 ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len),
1090 NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT));
1091
1092
1093 #if !(NGX_WIN32)
1094
1095 if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) {
1096 struct group *grp;
1097 struct passwd *pwd;
1098
1099 ngx_set_errno(0);
1100 pwd = getpwnam(NGX_USER);
1101 if (pwd == NULL) {
1102 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1103 "getpwnam(\"" NGX_USER "\") failed");
1104 return NGX_CONF_ERROR;
1105 }
1106
1107 ccf->username = NGX_USER;
1108 ccf->user = pwd->pw_uid;
1109
1110 ngx_set_errno(0);
1111 grp = getgrnam(NGX_GROUP);
1112 if (grp == NULL) {
1113 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1114 "getgrnam(\"" NGX_GROUP "\") failed");
1115 return NGX_CONF_ERROR;
1116 }
1117
1118 ccf->group = grp->gr_gid;
1119 }
1120
1121
1122 if (ccf->lock_file.len == 0) {
1123 ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH);
1124 }
1125
1126 if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) {
1127 return NGX_CONF_ERROR;
1128 }
1129
1130 {
1131 ngx_str_t lock_file;
1132
1133 lock_file = cycle->old_cycle->lock_file;
1134
1135 if (lock_file.len) {
1136 lock_file.len--;
1137
1138 if (ccf->lock_file.len != lock_file.len
1139 || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len)
1140 != 0)
1141 {
1142 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
1143 "\"lock_file\" could not be changed, ignored");
1144 }
1145
1146 cycle->lock_file.len = lock_file.len + 1;
1147 lock_file.len += sizeof(".accept");
1148
1149 cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file);
1150 if (cycle->lock_file.data == NULL) {
1151 return NGX_CONF_ERROR;
1152 }
1153
1154 } else {
1155 cycle->lock_file.len = ccf->lock_file.len + 1;
1156 cycle->lock_file.data = ngx_pnalloc(cycle->pool,
1157 ccf->lock_file.len + sizeof(".accept"));
1158 if (cycle->lock_file.data == NULL) {
1159 return NGX_CONF_ERROR;
1160 }
1161
1162 ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data,
1163 ccf->lock_file.len),
1164 ".accept", sizeof(".accept"));
1165 }
1166 }
1167
1168 #endif
1169
1170 return NGX_CONF_OK;
1171 }
1172
1173
1174 static char *
1175 ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1176 {
1177 #if (NGX_WIN32)
1178
1179 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1180 "\"user\" is not supported, ignored");
1181
1182 return NGX_CONF_OK;
1183
1184 #else
1185
1186 ngx_core_conf_t *ccf = conf;
1187
1188 char *group;
1189 struct passwd *pwd;
1190 struct group *grp;
1191 ngx_str_t *value;
1192
1193 if (ccf->user != (uid_t) NGX_CONF_UNSET_UINT) {
1194 return "is duplicate";
1195 }
1196
1197 if (geteuid() != 0) {
1198 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1199 "the \"user\" directive makes sense only "
1200 "if the master process runs "
1201 "with super-user privileges, ignored");
1202 return NGX_CONF_OK;
1203 }
1204
1205 value = cf->args->elts;
1206
1207 ccf->username = (char *) value[1].data;
1208
1209 ngx_set_errno(0);
1210 pwd = getpwnam((const char *) value[1].data);
1211 if (pwd == NULL) {
1212 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1213 "getpwnam(\"%s\") failed", value[1].data);
1214 return NGX_CONF_ERROR;
1215 }
1216
1217 ccf->user = pwd->pw_uid;
1218
1219 group = (char *) ((cf->args->nelts == 2) ? value[1].data : value[2].data);
1220
1221 ngx_set_errno(0);
1222 grp = getgrnam(group);
1223 if (grp == NULL) {
1224 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1225 "getgrnam(\"%s\") failed", group);
1226 return NGX_CONF_ERROR;
1227 }
1228
1229 ccf->group = grp->gr_gid;
1230
1231 return NGX_CONF_OK;
1232
1233 #endif
1234 }
1235
1236
1237 static char *
1238 ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1239 {
1240 ngx_core_conf_t *ccf = conf;
1241
1242 ngx_str_t *value, *var;
1243 ngx_uint_t i;
1244
1245 var = ngx_array_push(&ccf->env);
1246 if (var == NULL) {
1247 return NGX_CONF_ERROR;
1248 }
1249
1250 value = cf->args->elts;
1251 *var = value[1];
1252
1253 for (i = 0; i < value[1].len; i++) {
1254
1255 if (value[1].data[i] == '=') {
1256
1257 var->len = i;
1258
1259 return NGX_CONF_OK;
1260 }
1261 }
1262
1263 return NGX_CONF_OK;
1264 }
1265
1266
1267 static char *
1268 ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1269 {
1270 ngx_core_conf_t *ccf = conf;
1271
1272 ngx_str_t *value;
1273 ngx_uint_t n, minus;
1274
1275 if (ccf->priority != 0) {
1276 return "is duplicate";
1277 }
1278
1279 value = cf->args->elts;
1280
1281 if (value[1].data[0] == '-') {
1282 n = 1;
1283 minus = 1;
1284
1285 } else if (value[1].data[0] == '+') {
1286 n = 1;
1287 minus = 0;
1288
1289 } else {
1290 n = 0;
1291 minus = 0;
1292 }
1293
1294 ccf->priority = ngx_atoi(&value[1].data[n], value[1].len - n);
1295 if (ccf->priority == NGX_ERROR) {
1296 return "invalid number";
1297 }
1298
1299 if (minus) {
1300 ccf->priority = -ccf->priority;
1301 }
1302
1303 return NGX_CONF_OK;
1304 }
1305
1306
1307 static char *
1308 ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1309 {
1310 #if (NGX_HAVE_CPU_AFFINITY)
1311 ngx_core_conf_t *ccf = conf;
1312
1313 u_char ch, *p;
1314 ngx_str_t *value;
1315 ngx_uint_t i, n;
1316 ngx_cpuset_t *mask;
1317
1318 if (ccf->cpu_affinity) {
1319 return "is duplicate";
1320 }
1321
1322 mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(ngx_cpuset_t));
1323 if (mask == NULL) {
1324 return NGX_CONF_ERROR;
1325 }
1326
1327 ccf->cpu_affinity_n = cf->args->nelts - 1;
1328 ccf->cpu_affinity = mask;
1329
1330 value = cf->args->elts;
1331
1332 if (ngx_strcmp(value[1].data, "auto") == 0) {
1333
1334 if (cf->args->nelts > 3) {
1335 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1336 "invalid number of arguments in "
1337 "\"worker_cpu_affinity\" directive");
1338 return NGX_CONF_ERROR;
1339 }
1340
1341 ccf->cpu_affinity_auto = 1;
1342
1343 CPU_ZERO(&mask[0]);
1344 for (i = 0; i < (ngx_uint_t) ngx_min(ngx_ncpu, CPU_SETSIZE); i++) {
1345 CPU_SET(i, &mask[0]);
1346 }
1347
1348 n = 2;
1349
1350 } else {
1351 n = 1;
1352 }
1353
1354 for ( ; n < cf->args->nelts; n++) {
1355
1356 if (value[n].len > CPU_SETSIZE) {
1357 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1358 "\"worker_cpu_affinity\" supports up to %d CPUs only",
1359 CPU_SETSIZE);
1360 return NGX_CONF_ERROR;
1361 }
1362
1363 i = 0;
1364 CPU_ZERO(&mask[n - 1]);
1365
1366 for (p = value[n].data + value[n].len - 1;
1367 p >= value[n].data;
1368 p--)
1369 {
1370 ch = *p;
1371
1372 if (ch == ' ') {
1373 continue;
1374 }
1375
1376 i++;
1377
1378 if (ch == '0') {
1379 continue;
1380 }
1381
1382 if (ch == '1') {
1383 CPU_SET(i - 1, &mask[n - 1]);
1384 continue;
1385 }
1386
1387 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1388 "invalid character \"%c\" in \"worker_cpu_affinity\"",
1389 ch);
1390 return NGX_CONF_ERROR;
1391 }
1392 }
1393
1394 #else
1395
1396 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1397 "\"worker_cpu_affinity\" is not supported "
1398 "on this platform, ignored");
1399 #endif
1400
1401 return NGX_CONF_OK;
1402 }
1403
1404
1405 ngx_cpuset_t *
1406 ngx_get_cpu_affinity(ngx_uint_t n)
1407 {
1408 #if (NGX_HAVE_CPU_AFFINITY)
1409 ngx_uint_t i, j;
1410 ngx_cpuset_t *mask;
1411 ngx_core_conf_t *ccf;
1412
1413 static ngx_cpuset_t result;
1414
1415 ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
1416 ngx_core_module);
1417
1418 if (ccf->cpu_affinity == NULL) {
1419 return NULL;
1420 }
1421
1422 if (ccf->cpu_affinity_auto) {
1423 mask = &ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
1424
1425 for (i = 0, j = n; ; i++) {
1426
1427 if (CPU_ISSET(i % CPU_SETSIZE, mask) && j-- == 0) {
1428 break;
1429 }
1430
1431 if (i == CPU_SETSIZE && j == n) {
1432
1433 return NULL;
1434 }
1435
1436
1437 }
1438
1439 CPU_ZERO(&result);
1440 CPU_SET(i % CPU_SETSIZE, &result);
1441
1442 return &result;
1443 }
1444
1445 if (ccf->cpu_affinity_n > n) {
1446 return &ccf->cpu_affinity[n];
1447 }
1448
1449 return &ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
1450
1451 #else
1452
1453 return NULL;
1454
1455 #endif
1456 }
1457
1458
1459 static char *
1460 ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1461 {
1462 ngx_str_t *value;
1463 ngx_core_conf_t *ccf;
1464
1465 ccf = (ngx_core_conf_t *) conf;
1466
1467 if (ccf->worker_processes != NGX_CONF_UNSET) {
1468 return "is duplicate";
1469 }
1470
1471 value = cf->args->elts;
1472
1473 if (ngx_strcmp(value[1].data, "auto") == 0) {
1474 ccf->worker_processes = ngx_ncpu;
1475 return NGX_CONF_OK;
1476 }
1477
1478 ccf->worker_processes = ngx_atoi(value[1].data, value[1].len);
1479
1480 if (ccf->worker_processes == NGX_ERROR) {
1481 return "invalid value";
1482 }
1483
1484 return NGX_CONF_OK;
1485 }
1486
1487
1488 static char *
1489 ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1490 {
1491 #if (NGX_HAVE_DLOPEN)
1492 void *handle;
1493 char **names, **order;
1494 ngx_str_t *value, file;
1495 ngx_uint_t i;
1496 ngx_module_t *module, **modules;
1497 ngx_pool_cleanup_t *cln;
1498
1499 if (cf->cycle->modules_used) {
1500 return "is specified too late";
1501 }
1502
1503 value = cf->args->elts;
1504
1505 file = value[1];
1506
1507 if (ngx_conf_full_name(cf->cycle, &file, 0) != NGX_OK) {
1508 return NGX_CONF_ERROR;
1509 }
1510
1511 cln = ngx_pool_cleanup_add(cf->cycle->pool, 0);
1512 if (cln == NULL) {
1513 return NGX_CONF_ERROR;
1514 }
1515
1516 handle = ngx_dlopen(file.data);
1517 if (handle == NULL) {
1518 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1519 ngx_dlopen_n " \"%s\" failed (%s)",
1520 file.data, ngx_dlerror());
1521 return NGX_CONF_ERROR;
1522 }
1523
1524 cln->handler = ngx_unload_module;
1525 cln->data = handle;
1526
1527 modules = ngx_dlsym(handle, "ngx_modules");
1528 if (modules == NULL) {
1529 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1530 ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
1531 &value[1], "ngx_modules", ngx_dlerror());
1532 return NGX_CONF_ERROR;
1533 }
1534
1535 names = ngx_dlsym(handle, "ngx_module_names");
1536 if (names == NULL) {
1537 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1538 ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
1539 &value[1], "ngx_module_names", ngx_dlerror());
1540 return NGX_CONF_ERROR;
1541 }
1542
1543 order = ngx_dlsym(handle, "ngx_module_order");
1544
1545 for (i = 0; modules[i]; i++) {
1546 module = modules[i];
1547 module->name = names[i];
1548
1549 if (ngx_add_module(cf, &file, module, order) != NGX_OK) {
1550 return NGX_CONF_ERROR;
1551 }
1552
1553 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, "module: %s i:%ui",
1554 module->name, module->index);
1555 }
1556
1557 return NGX_CONF_OK;
1558
1559 #else
1560
1561 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1562 "\"load_module\" is not supported "
1563 "on this platform");
1564 return NGX_CONF_ERROR;
1565
1566 #endif
1567 }
1568
1569
1570 #if (NGX_HAVE_DLOPEN)
1571
1572 static void
1573 ngx_unload_module(void *data)
1574 {
1575 void *handle = data;
1576
1577 if (ngx_dlclose(handle) != 0) {
1578 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
1579 ngx_dlclose_n " failed (%s)", ngx_dlerror());
1580 }
1581 }
1582
1583 #endif