Back to home page

Nginx displayed by LXR

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