Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
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,                  /* module context */
0169     ngx_core_commands,                     /* module directives */
0170     NGX_CORE_MODULE,                       /* module type */
0171     NULL,                                  /* init master */
0172     NULL,                                  /* init module */
0173     NULL,                                  /* init process */
0174     NULL,                                  /* init thread */
0175     NULL,                                  /* exit thread */
0176     NULL,                                  /* exit process */
0177     NULL,                                  /* exit master */
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     /* TODO */ 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     /* STUB */
0238 #if (NGX_OPENSSL)
0239     ngx_ssl_init(log);
0240 #endif
0241 
0242     /*
0243      * init_cycle->log is required for signal handlers and
0244      * ngx_process_options()
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      * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
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          * if the environment is still used, as it happens on exit,
0623          * the only option is to leak it
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     /* allocate the spare 300 bytes for the new binary process title */
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      * set by ngx_pcalloc()
1012      *
1013      *     ccf->pid = NULL;
1014      *     ccf->oldpid = NULL;
1015      *     ccf->priority = 0;
1016      *     ccf->cpu_affinity_auto = 0;
1017      *     ccf->cpu_affinity_n = 0;
1018      *     ccf->cpu_affinity = NULL;
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 ( /* void */ ; 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; /* void */ ; i++) {
1426 
1427             if (CPU_ISSET(i % CPU_SETSIZE, mask) && j-- == 0) {
1428                 break;
1429             }
1430 
1431             if (i == CPU_SETSIZE && j == n) {
1432                 /* empty mask */
1433                 return NULL;
1434             }
1435 
1436             /* void */
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