src/core/nginx.c - nginx source code

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <nginx.h>


  8. static void ngx_show_version_info(void);
  9. static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
  10. static void ngx_cleanup_environment(void *data);
  11. static void ngx_cleanup_environment_variable(void *data);
  12. static ngx_int_t ngx_get_options(int argc, char *const *argv);
  13. static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
  14. static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
  15. static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
  16. static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
  17. static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  18. static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  19. static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  20. static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd,
  21.     void *conf);
  22. static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd,
  23.     void *conf);
  24. static char *ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  25. #if (NGX_HAVE_DLOPEN)
  26. static void ngx_unload_module(void *data);
  27. #endif


  28. static ngx_conf_enum_t  ngx_debug_points[] = {
  29.     { ngx_string("stop"), NGX_DEBUG_POINTS_STOP },
  30.     { ngx_string("abort"), NGX_DEBUG_POINTS_ABORT },
  31.     { ngx_null_string, 0 }
  32. };


  33. static ngx_command_t  ngx_core_commands[] = {

  34.     { ngx_string("daemon"),
  35.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
  36.       ngx_conf_set_flag_slot,
  37.       0,
  38.       offsetof(ngx_core_conf_t, daemon),
  39.       NULL },

  40.     { ngx_string("master_process"),
  41.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
  42.       ngx_conf_set_flag_slot,
  43.       0,
  44.       offsetof(ngx_core_conf_t, master),
  45.       NULL },

  46.     { ngx_string("timer_resolution"),
  47.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  48.       ngx_conf_set_msec_slot,
  49.       0,
  50.       offsetof(ngx_core_conf_t, timer_resolution),
  51.       NULL },

  52.     { ngx_string("pid"),
  53.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  54.       ngx_conf_set_str_slot,
  55.       0,
  56.       offsetof(ngx_core_conf_t, pid),
  57.       NULL },

  58.     { ngx_string("lock_file"),
  59.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  60.       ngx_conf_set_str_slot,
  61.       0,
  62.       offsetof(ngx_core_conf_t, lock_file),
  63.       NULL },

  64.     { ngx_string("worker_processes"),
  65.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  66.       ngx_set_worker_processes,
  67.       0,
  68.       0,
  69.       NULL },

  70.     { ngx_string("debug_points"),
  71.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  72.       ngx_conf_set_enum_slot,
  73.       0,
  74.       offsetof(ngx_core_conf_t, debug_points),
  75.       &ngx_debug_points },

  76.     { ngx_string("user"),
  77.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
  78.       ngx_set_user,
  79.       0,
  80.       0,
  81.       NULL },

  82.     { ngx_string("worker_priority"),
  83.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  84.       ngx_set_priority,
  85.       0,
  86.       0,
  87.       NULL },

  88.     { ngx_string("worker_cpu_affinity"),
  89.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
  90.       ngx_set_cpu_affinity,
  91.       0,
  92.       0,
  93.       NULL },

  94.     { ngx_string("worker_rlimit_nofile"),
  95.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  96.       ngx_conf_set_num_slot,
  97.       0,
  98.       offsetof(ngx_core_conf_t, rlimit_nofile),
  99.       NULL },

  100.     { ngx_string("worker_rlimit_core"),
  101.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  102.       ngx_conf_set_off_slot,
  103.       0,
  104.       offsetof(ngx_core_conf_t, rlimit_core),
  105.       NULL },

  106.     { ngx_string("worker_shutdown_timeout"),
  107.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  108.       ngx_conf_set_msec_slot,
  109.       0,
  110.       offsetof(ngx_core_conf_t, shutdown_timeout),
  111.       NULL },

  112.     { ngx_string("working_directory"),
  113.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  114.       ngx_conf_set_str_slot,
  115.       0,
  116.       offsetof(ngx_core_conf_t, working_directory),
  117.       NULL },

  118.     { ngx_string("env"),
  119.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  120.       ngx_set_env,
  121.       0,
  122.       0,
  123.       NULL },

  124.     { ngx_string("load_module"),
  125.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  126.       ngx_load_module,
  127.       0,
  128.       0,
  129.       NULL },

  130.       ngx_null_command
  131. };


  132. static ngx_core_module_t  ngx_core_module_ctx = {
  133.     ngx_string("core"),
  134.     ngx_core_module_create_conf,
  135.     ngx_core_module_init_conf
  136. };


  137. ngx_module_t  ngx_core_module = {
  138.     NGX_MODULE_V1,
  139.     &ngx_core_module_ctx,                  /* module context */
  140.     ngx_core_commands,                     /* module directives */
  141.     NGX_CORE_MODULE,                       /* module type */
  142.     NULL,                                  /* init master */
  143.     NULL,                                  /* init module */
  144.     NULL,                                  /* init process */
  145.     NULL,                                  /* init thread */
  146.     NULL,                                  /* exit thread */
  147.     NULL,                                  /* exit process */
  148.     NULL,                                  /* exit master */
  149.     NGX_MODULE_V1_PADDING
  150. };


  151. static ngx_uint_t   ngx_show_help;
  152. static ngx_uint_t   ngx_show_version;
  153. static ngx_uint_t   ngx_show_configure;
  154. static u_char      *ngx_prefix;
  155. static u_char      *ngx_error_log;
  156. static u_char      *ngx_conf_file;
  157. static u_char      *ngx_conf_params;
  158. static char        *ngx_signal;


  159. static char **ngx_os_environ;


  160. int ngx_cdecl
  161. main(int argc, char *const *argv)
  162. {
  163.     ngx_buf_t        *b;
  164.     ngx_log_t        *log;
  165.     ngx_uint_t        i;
  166.     ngx_cycle_t      *cycle, init_cycle;
  167.     ngx_conf_dump_t  *cd;
  168.     ngx_core_conf_t  *ccf;

  169.     ngx_debug_init();

  170.     if (ngx_strerror_init() != NGX_OK) {
  171.         return 1;
  172.     }

  173.     if (ngx_get_options(argc, argv) != NGX_OK) {
  174.         return 1;
  175.     }

  176.     if (ngx_show_version) {
  177.         ngx_show_version_info();

  178.         if (!ngx_test_config) {
  179.             return 0;
  180.         }
  181.     }

  182.     /* TODO */ ngx_max_sockets = -1;

  183.     ngx_time_init();

  184. #if (NGX_PCRE)
  185.     ngx_regex_init();
  186. #endif

  187.     ngx_pid = ngx_getpid();
  188.     ngx_parent = ngx_getppid();

  189.     log = ngx_log_init(ngx_prefix, ngx_error_log);
  190.     if (log == NULL) {
  191.         return 1;
  192.     }

  193.     /* STUB */
  194. #if (NGX_OPENSSL)
  195.     ngx_ssl_init(log);
  196. #endif

  197.     /*
  198.      * init_cycle->log is required for signal handlers and
  199.      * ngx_process_options()
  200.      */

  201.     ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
  202.     init_cycle.log = log;
  203.     ngx_cycle = &init_cycle;

  204.     init_cycle.pool = ngx_create_pool(1024, log);
  205.     if (init_cycle.pool == NULL) {
  206.         return 1;
  207.     }

  208.     if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
  209.         return 1;
  210.     }

  211.     if (ngx_process_options(&init_cycle) != NGX_OK) {
  212.         return 1;
  213.     }

  214.     if (ngx_os_init(log) != NGX_OK) {
  215.         return 1;
  216.     }

  217.     /*
  218.      * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
  219.      */

  220.     if (ngx_crc32_table_init() != NGX_OK) {
  221.         return 1;
  222.     }

  223.     /*
  224.      * ngx_slab_sizes_init() requires ngx_pagesize set in ngx_os_init()
  225.      */

  226.     ngx_slab_sizes_init();

  227.     if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
  228.         return 1;
  229.     }

  230.     if (ngx_preinit_modules() != NGX_OK) {
  231.         return 1;
  232.     }

  233.     cycle = ngx_init_cycle(&init_cycle);
  234.     if (cycle == NULL) {
  235.         if (ngx_test_config) {
  236.             ngx_log_stderr(0, "configuration file %s test failed",
  237.                            init_cycle.conf_file.data);
  238.         }

  239.         return 1;
  240.     }

  241.     if (ngx_test_config) {
  242.         if (!ngx_quiet_mode) {
  243.             ngx_log_stderr(0, "configuration file %s test is successful",
  244.                            cycle->conf_file.data);
  245.         }

  246.         if (ngx_dump_config) {
  247.             cd = cycle->config_dump.elts;

  248.             for (i = 0; i < cycle->config_dump.nelts; i++) {

  249.                 ngx_write_stdout("# configuration file ");
  250.                 (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
  251.                                     cd[i].name.len);
  252.                 ngx_write_stdout(":" NGX_LINEFEED);

  253.                 b = cd[i].buffer;

  254.                 (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
  255.                 ngx_write_stdout(NGX_LINEFEED);
  256.             }
  257.         }

  258.         return 0;
  259.     }

  260.     if (ngx_signal) {
  261.         return ngx_signal_process(cycle, ngx_signal);
  262.     }

  263.     ngx_os_status(cycle->log);

  264.     ngx_cycle = cycle;

  265.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  266.     if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
  267.         ngx_process = NGX_PROCESS_MASTER;
  268.     }

  269. #if !(NGX_WIN32)

  270.     if (ngx_init_signals(cycle->log) != NGX_OK) {
  271.         return 1;
  272.     }

  273.     if (!ngx_inherited && ccf->daemon) {
  274.         if (ngx_daemon(cycle->log) != NGX_OK) {
  275.             return 1;
  276.         }

  277.         ngx_daemonized = 1;
  278.     }

  279.     if (ngx_inherited) {
  280.         ngx_daemonized = 1;
  281.     }

  282. #endif

  283.     if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
  284.         return 1;
  285.     }

  286.     if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
  287.         return 1;
  288.     }

  289.     if (log->file->fd != ngx_stderr) {
  290.         if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
  291.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  292.                           ngx_close_file_n " built-in log failed");
  293.         }
  294.     }

  295.     ngx_use_stderr = 0;

  296.     if (ngx_process == NGX_PROCESS_SINGLE) {
  297.         ngx_single_process_cycle(cycle);

  298.     } else {
  299.         ngx_master_process_cycle(cycle);
  300.     }

  301.     return 0;
  302. }


  303. static void
  304. ngx_show_version_info(void)
  305. {
  306.     ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);

  307.     if (ngx_show_help) {
  308.         ngx_write_stderr(
  309.             "Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]" NGX_LINEFEED
  310.             "             [-e filename] [-c filename] [-g directives]"
  311.                           NGX_LINEFEED NGX_LINEFEED
  312.             "Options:" NGX_LINEFEED
  313.             "  -?,-h         : this help" NGX_LINEFEED
  314.             "  -v            : show version and exit" NGX_LINEFEED
  315.             "  -V            : show version and configure options then exit"
  316.                                NGX_LINEFEED
  317.             "  -t            : test configuration and exit" NGX_LINEFEED
  318.             "  -T            : test configuration, dump it and exit"
  319.                                NGX_LINEFEED
  320.             "  -q            : suppress non-error messages "
  321.                                "during configuration testing" NGX_LINEFEED
  322.             "  -s signal     : send signal to a master process: "
  323.                                "stop, quit, reopen, reload" NGX_LINEFEED
  324. #ifdef NGX_PREFIX
  325.             "  -p prefix     : set prefix path (default: " NGX_PREFIX ")"
  326.                                NGX_LINEFEED
  327. #else
  328.             "  -p prefix     : set prefix path (default: NONE)" NGX_LINEFEED
  329. #endif
  330.             "  -e filename   : set error log file (default: "
  331. #ifdef NGX_ERROR_LOG_STDERR
  332.                                "stderr)" NGX_LINEFEED
  333. #else
  334.                                NGX_ERROR_LOG_PATH ")" NGX_LINEFEED
  335. #endif
  336.             "  -c filename   : set configuration file (default: " NGX_CONF_PATH
  337.                                ")" NGX_LINEFEED
  338.             "  -g directives : set global directives out of configuration "
  339.                                "file" NGX_LINEFEED NGX_LINEFEED
  340.         );
  341.     }

  342.     if (ngx_show_configure) {

  343. #ifdef NGX_COMPILER
  344.         ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED);
  345. #endif

  346. #if (NGX_SSL)
  347.         if (ngx_strcmp(ngx_ssl_version(), OPENSSL_VERSION_TEXT) == 0) {
  348.             ngx_write_stderr("built with " OPENSSL_VERSION_TEXT NGX_LINEFEED);
  349.         } else {
  350.             ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
  351.                              " (running with ");
  352.             ngx_write_stderr((char *) (uintptr_t) ngx_ssl_version());
  353.             ngx_write_stderr(")" NGX_LINEFEED);
  354.         }
  355. #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
  356.         ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED);
  357. #else
  358.         ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED);
  359. #endif
  360. #endif

  361.         ngx_write_stderr("configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
  362.     }
  363. }


  364. static ngx_int_t
  365. ngx_add_inherited_sockets(ngx_cycle_t *cycle)
  366. {
  367.     u_char           *p, *v, *inherited;
  368.     ngx_int_t         s;
  369.     ngx_listening_t  *ls;

  370.     inherited = (u_char *) getenv(NGINX_VAR);

  371.     if (inherited == NULL) {
  372.         return NGX_OK;
  373.     }

  374.     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
  375.                   "using inherited sockets from \"%s\"", inherited);

  376.     if (ngx_array_init(&cycle->listening, cycle->pool, 10,
  377.                        sizeof(ngx_listening_t))
  378.         != NGX_OK)
  379.     {
  380.         return NGX_ERROR;
  381.     }

  382.     for (p = inherited, v = p; *p; p++) {
  383.         if (*p == ':' || *p == ';') {
  384.             s = ngx_atoi(v, p - v);
  385.             if (s == NGX_ERROR) {
  386.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  387.                               "invalid socket number \"%s\" in " NGINX_VAR
  388.                               " environment variable, ignoring the rest"
  389.                               " of the variable", v);
  390.                 break;
  391.             }

  392.             v = p + 1;

  393.             ls = ngx_array_push(&cycle->listening);
  394.             if (ls == NULL) {
  395.                 return NGX_ERROR;
  396.             }

  397.             ngx_memzero(ls, sizeof(ngx_listening_t));

  398.             ls->fd = (ngx_socket_t) s;
  399.             ls->inherited = 1;
  400.         }
  401.     }

  402.     if (v != p) {
  403.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  404.                       "invalid socket number \"%s\" in " NGINX_VAR
  405.                       " environment variable, ignoring", v);
  406.     }

  407.     ngx_inherited = 1;

  408.     return ngx_set_inherited_sockets(cycle);
  409. }


  410. char **
  411. ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
  412. {
  413.     char                **p, **env, *str;
  414.     size_t                len;
  415.     ngx_str_t            *var;
  416.     ngx_uint_t            i, n;
  417.     ngx_core_conf_t      *ccf;
  418.     ngx_pool_cleanup_t   *cln;

  419.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  420.     if (last == NULL && ccf->environment) {
  421.         return ccf->environment;
  422.     }

  423.     var = ccf->env.elts;

  424.     for (i = 0; i < ccf->env.nelts; i++) {
  425.         if (ngx_strcmp(var[i].data, "TZ") == 0
  426.             || ngx_strncmp(var[i].data, "TZ=", 3) == 0)
  427.         {
  428.             goto tz_found;
  429.         }
  430.     }

  431.     var = ngx_array_push(&ccf->env);
  432.     if (var == NULL) {
  433.         return NULL;
  434.     }

  435.     var->len = 2;
  436.     var->data = (u_char *) "TZ";

  437.     var = ccf->env.elts;

  438. tz_found:

  439.     n = 0;

  440.     for (i = 0; i < ccf->env.nelts; i++) {

  441.         if (var[i].data[var[i].len] == '=') {
  442.             n++;
  443.             continue;
  444.         }

  445.         for (p = ngx_os_environ; *p; p++) {

  446.             if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
  447.                 && (*p)[var[i].len] == '=')
  448.             {
  449.                 n++;
  450.                 break;
  451.             }
  452.         }
  453.     }

  454.     if (last) {
  455.         env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log);
  456.         if (env == NULL) {
  457.             return NULL;
  458.         }

  459.         *last = n;

  460.     } else {
  461.         cln = ngx_pool_cleanup_add(cycle->pool, 0);
  462.         if (cln == NULL) {
  463.             return NULL;
  464.         }

  465.         env = ngx_alloc((n + 1) * sizeof(char *), cycle->log);
  466.         if (env == NULL) {
  467.             return NULL;
  468.         }

  469.         cln->handler = ngx_cleanup_environment;
  470.         cln->data = env;
  471.     }

  472.     n = 0;

  473.     for (i = 0; i < ccf->env.nelts; i++) {

  474.         if (var[i].data[var[i].len] == '=') {

  475.             if (last) {
  476.                 env[n++] = (char *) var[i].data;
  477.                 continue;
  478.             }

  479.             cln = ngx_pool_cleanup_add(cycle->pool, 0);
  480.             if (cln == NULL) {
  481.                 return NULL;
  482.             }

  483.             len = ngx_strlen(var[i].data) + 1;

  484.             str = ngx_alloc(len, cycle->log);
  485.             if (str == NULL) {
  486.                 return NULL;
  487.             }

  488.             ngx_memcpy(str, var[i].data, len);

  489.             cln->handler = ngx_cleanup_environment_variable;
  490.             cln->data = str;

  491.             env[n++] = str;

  492.             continue;
  493.         }

  494.         for (p = ngx_os_environ; *p; p++) {

  495.             if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
  496.                 && (*p)[var[i].len] == '=')
  497.             {
  498.                 env[n++] = *p;
  499.                 break;
  500.             }
  501.         }
  502.     }

  503.     env[n] = NULL;

  504.     if (last == NULL) {
  505.         ccf->environment = env;
  506.         environ = env;
  507.     }

  508.     return env;
  509. }


  510. static void
  511. ngx_cleanup_environment(void *data)
  512. {
  513.     char  **env = data;

  514.     if (environ == env) {

  515.         /*
  516.          * if the environment is still used, as it happens on exit,
  517.          * the only option is to leak it
  518.          */

  519.         return;
  520.     }

  521.     ngx_free(env);
  522. }


  523. static void
  524. ngx_cleanup_environment_variable(void *data)
  525. {
  526.     char  *var = data;

  527.     char  **p;

  528.     for (p = environ; *p; p++) {

  529.         /*
  530.          * if an environment variable is still used, as it happens on exit,
  531.          * the only option is to leak it
  532.          */

  533.         if (*p == var) {
  534.             return;
  535.         }
  536.     }

  537.     ngx_free(var);
  538. }


  539. ngx_pid_t
  540. ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
  541. {
  542.     char             **env, *var;
  543.     u_char            *p;
  544.     ngx_uint_t         i, n;
  545.     ngx_pid_t          pid;
  546.     ngx_exec_ctx_t     ctx;
  547.     ngx_core_conf_t   *ccf;
  548.     ngx_listening_t   *ls;

  549.     ngx_memzero(&ctx, sizeof(ngx_exec_ctx_t));

  550.     ctx.path = argv[0];
  551.     ctx.name = "new binary process";
  552.     ctx.argv = argv;

  553.     n = 2;
  554.     env = ngx_set_environment(cycle, &n);
  555.     if (env == NULL) {
  556.         return NGX_INVALID_PID;
  557.     }

  558.     var = ngx_alloc(sizeof(NGINX_VAR)
  559.                     + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
  560.                     cycle->log);
  561.     if (var == NULL) {
  562.         ngx_free(env);
  563.         return NGX_INVALID_PID;
  564.     }

  565.     p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR));

  566.     ls = cycle->listening.elts;
  567.     for (i = 0; i < cycle->listening.nelts; i++) {
  568.         if (ls[i].ignore) {
  569.             continue;
  570.         }
  571.         p = ngx_sprintf(p, "%ud;", ls[i].fd);
  572.     }

  573.     *p = '\0';

  574.     env[n++] = var;

  575. #if (NGX_SETPROCTITLE_USES_ENV)

  576.     /* allocate the spare 300 bytes for the new binary process title */

  577.     env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  578.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  579.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  580.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  581.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

  582. #endif

  583.     env[n] = NULL;

  584. #if (NGX_DEBUG)
  585.     {
  586.     char  **e;
  587.     for (e = env; *e; e++) {
  588.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e);
  589.     }
  590.     }
  591. #endif

  592.     ctx.envp = (char *const *) env;

  593.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  594.     if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == NGX_FILE_ERROR) {
  595.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  596.                       ngx_rename_file_n " %s to %s failed "
  597.                       "before executing new binary process \"%s\"",
  598.                       ccf->pid.data, ccf->oldpid.data, argv[0]);

  599.         ngx_free(env);
  600.         ngx_free(var);

  601.         return NGX_INVALID_PID;
  602.     }

  603.     pid = ngx_execute(cycle, &ctx);

  604.     if (pid == NGX_INVALID_PID) {
  605.         if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data)
  606.             == NGX_FILE_ERROR)
  607.         {
  608.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  609.                           ngx_rename_file_n " %s back to %s failed after "
  610.                           "an attempt to execute new binary process \"%s\"",
  611.                           ccf->oldpid.data, ccf->pid.data, argv[0]);
  612.         }
  613.     }

  614.     ngx_free(env);
  615.     ngx_free(var);

  616.     return pid;
  617. }


  618. static ngx_int_t
  619. ngx_get_options(int argc, char *const *argv)
  620. {
  621.     u_char     *p;
  622.     ngx_int_t   i;

  623.     for (i = 1; i < argc; i++) {

  624.         p = (u_char *) argv[i];

  625.         if (*p++ != '-') {
  626.             ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
  627.             return NGX_ERROR;
  628.         }

  629.         while (*p) {

  630.             switch (*p++) {

  631.             case '?':
  632.             case 'h':
  633.                 ngx_show_version = 1;
  634.                 ngx_show_help = 1;
  635.                 break;

  636.             case 'v':
  637.                 ngx_show_version = 1;
  638.                 break;

  639.             case 'V':
  640.                 ngx_show_version = 1;
  641.                 ngx_show_configure = 1;
  642.                 break;

  643.             case 't':
  644.                 ngx_test_config = 1;
  645.                 break;

  646.             case 'T':
  647.                 ngx_test_config = 1;
  648.                 ngx_dump_config = 1;
  649.                 break;

  650.             case 'q':
  651.                 ngx_quiet_mode = 1;
  652.                 break;

  653.             case 'p':
  654.                 if (*p) {
  655.                     ngx_prefix = p;
  656.                     goto next;
  657.                 }

  658.                 if (argv[++i]) {
  659.                     ngx_prefix = (u_char *) argv[i];
  660.                     goto next;
  661.                 }

  662.                 ngx_log_stderr(0, "option \"-p\" requires directory name");
  663.                 return NGX_ERROR;

  664.             case 'e':
  665.                 if (*p) {
  666.                     ngx_error_log = p;

  667.                 } else if (argv[++i]) {
  668.                     ngx_error_log = (u_char *) argv[i];

  669.                 } else {
  670.                     ngx_log_stderr(0, "option \"-e\" requires file name");
  671.                     return NGX_ERROR;
  672.                 }

  673.                 if (ngx_strcmp(ngx_error_log, "stderr") == 0) {
  674.                     ngx_error_log = (u_char *) "";
  675.                 }

  676.                 goto next;

  677.             case 'c':
  678.                 if (*p) {
  679.                     ngx_conf_file = p;
  680.                     goto next;
  681.                 }

  682.                 if (argv[++i]) {
  683.                     ngx_conf_file = (u_char *) argv[i];
  684.                     goto next;
  685.                 }

  686.                 ngx_log_stderr(0, "option \"-c\" requires file name");
  687.                 return NGX_ERROR;

  688.             case 'g':
  689.                 if (*p) {
  690.                     ngx_conf_params = p;
  691.                     goto next;
  692.                 }

  693.                 if (argv[++i]) {
  694.                     ngx_conf_params = (u_char *) argv[i];
  695.                     goto next;
  696.                 }

  697.                 ngx_log_stderr(0, "option \"-g\" requires parameter");
  698.                 return NGX_ERROR;

  699.             case 's':
  700.                 if (*p) {
  701.                     ngx_signal = (char *) p;

  702.                 } else if (argv[++i]) {
  703.                     ngx_signal = argv[i];

  704.                 } else {
  705.                     ngx_log_stderr(0, "option \"-s\" requires parameter");
  706.                     return NGX_ERROR;
  707.                 }

  708.                 if (ngx_strcmp(ngx_signal, "stop") == 0
  709.                     || ngx_strcmp(ngx_signal, "quit") == 0
  710.                     || ngx_strcmp(ngx_signal, "reopen") == 0
  711.                     || ngx_strcmp(ngx_signal, "reload") == 0)
  712.                 {
  713.                     ngx_process = NGX_PROCESS_SIGNALLER;
  714.                     goto next;
  715.                 }

  716.                 ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
  717.                 return NGX_ERROR;

  718.             default:
  719.                 ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
  720.                 return NGX_ERROR;
  721.             }
  722.         }

  723.     next:

  724.         continue;
  725.     }

  726.     return NGX_OK;
  727. }


  728. static ngx_int_t
  729. ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
  730. {
  731. #if (NGX_FREEBSD)

  732.     ngx_os_argv = (char **) argv;
  733.     ngx_argc = argc;
  734.     ngx_argv = (char **) argv;

  735. #else
  736.     size_t     len;
  737.     ngx_int_t  i;

  738.     ngx_os_argv = (char **) argv;
  739.     ngx_argc = argc;

  740.     ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
  741.     if (ngx_argv == NULL) {
  742.         return NGX_ERROR;
  743.     }

  744.     for (i = 0; i < argc; i++) {
  745.         len = ngx_strlen(argv[i]) + 1;

  746.         ngx_argv[i] = ngx_alloc(len, cycle->log);
  747.         if (ngx_argv[i] == NULL) {
  748.             return NGX_ERROR;
  749.         }

  750.         (void) ngx_cpystrn((u_char *) ngx_argv[i], (u_char *) argv[i], len);
  751.     }

  752.     ngx_argv[i] = NULL;

  753. #endif

  754.     ngx_os_environ = environ;

  755.     return NGX_OK;
  756. }


  757. static ngx_int_t
  758. ngx_process_options(ngx_cycle_t *cycle)
  759. {
  760.     u_char  *p;
  761.     size_t   len;

  762.     if (ngx_prefix) {
  763.         len = ngx_strlen(ngx_prefix);
  764.         p = ngx_prefix;

  765.         if (len && !ngx_path_separator(p[len - 1])) {
  766.             p = ngx_pnalloc(cycle->pool, len + 1);
  767.             if (p == NULL) {
  768.                 return NGX_ERROR;
  769.             }

  770.             ngx_memcpy(p, ngx_prefix, len);
  771.             p[len++] = '/';
  772.         }

  773.         cycle->conf_prefix.len = len;
  774.         cycle->conf_prefix.data = p;
  775.         cycle->prefix.len = len;
  776.         cycle->prefix.data = p;

  777.     } else {

  778. #ifndef NGX_PREFIX

  779.         p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
  780.         if (p == NULL) {
  781.             return NGX_ERROR;
  782.         }

  783.         if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {
  784.             ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
  785.             return NGX_ERROR;
  786.         }

  787.         len = ngx_strlen(p);

  788.         p[len++] = '/';

  789.         cycle->conf_prefix.len = len;
  790.         cycle->conf_prefix.data = p;
  791.         cycle->prefix.len = len;
  792.         cycle->prefix.data = p;

  793. #else

  794. #ifdef NGX_CONF_PREFIX
  795.         ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
  796. #else
  797.         ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
  798. #endif
  799.         ngx_str_set(&cycle->prefix, NGX_PREFIX);

  800. #endif
  801.     }

  802.     if (ngx_conf_file) {
  803.         cycle->conf_file.len = ngx_strlen(ngx_conf_file);
  804.         cycle->conf_file.data = ngx_conf_file;

  805.     } else {
  806.         ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
  807.     }

  808.     if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
  809.         return NGX_ERROR;
  810.     }

  811.     for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
  812.          p > cycle->conf_file.data;
  813.          p--)
  814.     {
  815.         if (ngx_path_separator(*p)) {
  816.             cycle->conf_prefix.len = p - cycle->conf_file.data + 1;
  817.             cycle->conf_prefix.data = cycle->conf_file.data;
  818.             break;
  819.         }
  820.     }

  821.     if (ngx_error_log) {
  822.         cycle->error_log.len = ngx_strlen(ngx_error_log);
  823.         cycle->error_log.data = ngx_error_log;

  824.     } else {
  825.         ngx_str_set(&cycle->error_log, NGX_ERROR_LOG_PATH);
  826.     }

  827.     if (ngx_conf_params) {
  828.         cycle->conf_param.len = ngx_strlen(ngx_conf_params);
  829.         cycle->conf_param.data = ngx_conf_params;
  830.     }

  831.     if (ngx_test_config) {
  832.         cycle->log->log_level = NGX_LOG_INFO;
  833.     }

  834.     return NGX_OK;
  835. }


  836. static void *
  837. ngx_core_module_create_conf(ngx_cycle_t *cycle)
  838. {
  839.     ngx_core_conf_t  *ccf;

  840.     ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t));
  841.     if (ccf == NULL) {
  842.         return NULL;
  843.     }

  844.     /*
  845.      * set by ngx_pcalloc()
  846.      *
  847.      *     ccf->pid = NULL;
  848.      *     ccf->oldpid = NULL;
  849.      *     ccf->priority = 0;
  850.      *     ccf->cpu_affinity_auto = 0;
  851.      *     ccf->cpu_affinity_n = 0;
  852.      *     ccf->cpu_affinity = NULL;
  853.      */

  854.     ccf->daemon = NGX_CONF_UNSET;
  855.     ccf->master = NGX_CONF_UNSET;
  856.     ccf->timer_resolution = NGX_CONF_UNSET_MSEC;
  857.     ccf->shutdown_timeout = NGX_CONF_UNSET_MSEC;

  858.     ccf->worker_processes = NGX_CONF_UNSET;
  859.     ccf->debug_points = NGX_CONF_UNSET;

  860.     ccf->rlimit_nofile = NGX_CONF_UNSET;
  861.     ccf->rlimit_core = NGX_CONF_UNSET;

  862.     ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;
  863.     ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT;

  864.     if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))
  865.         != NGX_OK)
  866.     {
  867.         return NULL;
  868.     }

  869.     return ccf;
  870. }


  871. static char *
  872. ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
  873. {
  874.     ngx_core_conf_t  *ccf = conf;

  875.     ngx_conf_init_value(ccf->daemon, 1);
  876.     ngx_conf_init_value(ccf->master, 1);
  877.     ngx_conf_init_msec_value(ccf->timer_resolution, 0);
  878.     ngx_conf_init_msec_value(ccf->shutdown_timeout, 0);

  879.     ngx_conf_init_value(ccf->worker_processes, 1);
  880.     ngx_conf_init_value(ccf->debug_points, 0);

  881. #if (NGX_HAVE_CPU_AFFINITY)

  882.     if (!ccf->cpu_affinity_auto
  883.         && ccf->cpu_affinity_n
  884.         && ccf->cpu_affinity_n != 1
  885.         && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)
  886.     {
  887.         ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
  888.                       "the number of \"worker_processes\" is not equal to "
  889.                       "the number of \"worker_cpu_affinity\" masks, "
  890.                       "using last mask for remaining worker processes");
  891.     }

  892. #endif


  893.     if (ccf->pid.len == 0) {
  894.         ngx_str_set(&ccf->pid, NGX_PID_PATH);
  895.     }

  896.     if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
  897.         return NGX_CONF_ERROR;
  898.     }

  899.     ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);

  900.     ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
  901.     if (ccf->oldpid.data == NULL) {
  902.         return NGX_CONF_ERROR;
  903.     }

  904.     ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len),
  905.                NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT));


  906. #if !(NGX_WIN32)

  907.     if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) {
  908.         struct group   *grp;
  909.         struct passwd  *pwd;

  910.         ngx_set_errno(0);
  911.         pwd = getpwnam(NGX_USER);
  912.         if (pwd == NULL) {
  913.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  914.                           "getpwnam(\"" NGX_USER "\") failed");
  915.             return NGX_CONF_ERROR;
  916.         }

  917.         ccf->username = NGX_USER;
  918.         ccf->user = pwd->pw_uid;

  919.         ngx_set_errno(0);
  920.         grp = getgrnam(NGX_GROUP);
  921.         if (grp == NULL) {
  922.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  923.                           "getgrnam(\"" NGX_GROUP "\") failed");
  924.             return NGX_CONF_ERROR;
  925.         }

  926.         ccf->group = grp->gr_gid;
  927.     }


  928.     if (ccf->lock_file.len == 0) {
  929.         ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH);
  930.     }

  931.     if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) {
  932.         return NGX_CONF_ERROR;
  933.     }

  934.     {
  935.     ngx_str_t  lock_file;

  936.     lock_file = cycle->old_cycle->lock_file;

  937.     if (lock_file.len) {
  938.         lock_file.len--;

  939.         if (ccf->lock_file.len != lock_file.len
  940.             || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len)
  941.                != 0)
  942.         {
  943.             ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  944.                           "\"lock_file\" could not be changed, ignored");
  945.         }

  946.         cycle->lock_file.len = lock_file.len + 1;
  947.         lock_file.len += sizeof(".accept");

  948.         cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file);
  949.         if (cycle->lock_file.data == NULL) {
  950.             return NGX_CONF_ERROR;
  951.         }

  952.     } else {
  953.         cycle->lock_file.len = ccf->lock_file.len + 1;
  954.         cycle->lock_file.data = ngx_pnalloc(cycle->pool,
  955.                                       ccf->lock_file.len + sizeof(".accept"));
  956.         if (cycle->lock_file.data == NULL) {
  957.             return NGX_CONF_ERROR;
  958.         }

  959.         ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data,
  960.                               ccf->lock_file.len),
  961.                    ".accept", sizeof(".accept"));
  962.     }
  963.     }

  964. #endif

  965.     return NGX_CONF_OK;
  966. }


  967. static char *
  968. ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  969. {
  970. #if (NGX_WIN32)

  971.     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  972.                        "\"user\" is not supported, ignored");

  973.     return NGX_CONF_OK;

  974. #else

  975.     ngx_core_conf_t  *ccf = conf;

  976.     char             *group;
  977.     struct passwd    *pwd;
  978.     struct group     *grp;
  979.     ngx_str_t        *value;

  980.     if (ccf->user != (uid_t) NGX_CONF_UNSET_UINT) {
  981.         return "is duplicate";
  982.     }

  983.     if (geteuid() != 0) {
  984.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  985.                            "the \"user\" directive makes sense only "
  986.                            "if the master process runs "
  987.                            "with super-user privileges, ignored");
  988.         return NGX_CONF_OK;
  989.     }

  990.     value = cf->args->elts;

  991.     ccf->username = (char *) value[1].data;

  992.     ngx_set_errno(0);
  993.     pwd = getpwnam((const char *) value[1].data);
  994.     if (pwd == NULL) {
  995.         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
  996.                            "getpwnam(\"%s\") failed", value[1].data);
  997.         return NGX_CONF_ERROR;
  998.     }

  999.     ccf->user = pwd->pw_uid;

  1000.     group = (char *) ((cf->args->nelts == 2) ? value[1].data : value[2].data);

  1001.     ngx_set_errno(0);
  1002.     grp = getgrnam(group);
  1003.     if (grp == NULL) {
  1004.         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
  1005.                            "getgrnam(\"%s\") failed", group);
  1006.         return NGX_CONF_ERROR;
  1007.     }

  1008.     ccf->group = grp->gr_gid;

  1009.     return NGX_CONF_OK;

  1010. #endif
  1011. }


  1012. static char *
  1013. ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1014. {
  1015.     ngx_core_conf_t  *ccf = conf;

  1016.     ngx_str_t   *value, *var;
  1017.     ngx_uint_t   i;

  1018.     var = ngx_array_push(&ccf->env);
  1019.     if (var == NULL) {
  1020.         return NGX_CONF_ERROR;
  1021.     }

  1022.     value = cf->args->elts;
  1023.     *var = value[1];

  1024.     for (i = 0; i < value[1].len; i++) {

  1025.         if (value[1].data[i] == '=') {

  1026.             var->len = i;

  1027.             return NGX_CONF_OK;
  1028.         }
  1029.     }

  1030.     return NGX_CONF_OK;
  1031. }


  1032. static char *
  1033. ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1034. {
  1035.     ngx_core_conf_t  *ccf = conf;

  1036.     ngx_str_t        *value;
  1037.     ngx_uint_t        n, minus;

  1038.     if (ccf->priority != 0) {
  1039.         return "is duplicate";
  1040.     }

  1041.     value = cf->args->elts;

  1042.     if (value[1].data[0] == '-') {
  1043.         n = 1;
  1044.         minus = 1;

  1045.     } else if (value[1].data[0] == '+') {
  1046.         n = 1;
  1047.         minus = 0;

  1048.     } else {
  1049.         n = 0;
  1050.         minus = 0;
  1051.     }

  1052.     ccf->priority = ngx_atoi(&value[1].data[n], value[1].len - n);
  1053.     if (ccf->priority == NGX_ERROR) {
  1054.         return "invalid number";
  1055.     }

  1056.     if (minus) {
  1057.         ccf->priority = -ccf->priority;
  1058.     }

  1059.     return NGX_CONF_OK;
  1060. }


  1061. static char *
  1062. ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1063. {
  1064. #if (NGX_HAVE_CPU_AFFINITY)
  1065.     ngx_core_conf_t  *ccf = conf;

  1066.     u_char            ch, *p;
  1067.     ngx_str_t        *value;
  1068.     ngx_uint_t        i, n;
  1069.     ngx_cpuset_t     *mask;

  1070.     if (ccf->cpu_affinity) {
  1071.         return "is duplicate";
  1072.     }

  1073.     mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(ngx_cpuset_t));
  1074.     if (mask == NULL) {
  1075.         return NGX_CONF_ERROR;
  1076.     }

  1077.     ccf->cpu_affinity_n = cf->args->nelts - 1;
  1078.     ccf->cpu_affinity = mask;

  1079.     value = cf->args->elts;

  1080.     if (ngx_strcmp(value[1].data, "auto") == 0) {

  1081.         if (cf->args->nelts > 3) {
  1082.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1083.                                "invalid number of arguments in "
  1084.                                "\"worker_cpu_affinity\" directive");
  1085.             return NGX_CONF_ERROR;
  1086.         }

  1087.         ccf->cpu_affinity_auto = 1;

  1088.         CPU_ZERO(&mask[0]);
  1089.         for (i = 0; i < (ngx_uint_t) ngx_min(ngx_ncpu, CPU_SETSIZE); i++) {
  1090.             CPU_SET(i, &mask[0]);
  1091.         }

  1092.         n = 2;

  1093.     } else {
  1094.         n = 1;
  1095.     }

  1096.     for ( /* void */ ; n < cf->args->nelts; n++) {

  1097.         if (value[n].len > CPU_SETSIZE) {
  1098.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1099.                          "\"worker_cpu_affinity\" supports up to %d CPUs only",
  1100.                          CPU_SETSIZE);
  1101.             return NGX_CONF_ERROR;
  1102.         }

  1103.         i = 0;
  1104.         CPU_ZERO(&mask[n - 1]);

  1105.         for (p = value[n].data + value[n].len - 1;
  1106.              p >= value[n].data;
  1107.              p--)
  1108.         {
  1109.             ch = *p;

  1110.             if (ch == ' ') {
  1111.                 continue;
  1112.             }

  1113.             i++;

  1114.             if (ch == '0') {
  1115.                 continue;
  1116.             }

  1117.             if (ch == '1') {
  1118.                 CPU_SET(i - 1, &mask[n - 1]);
  1119.                 continue;
  1120.             }

  1121.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1122.                           "invalid character \"%c\" in \"worker_cpu_affinity\"",
  1123.                           ch);
  1124.             return NGX_CONF_ERROR;
  1125.         }
  1126.     }

  1127. #else

  1128.     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1129.                        "\"worker_cpu_affinity\" is not supported "
  1130.                        "on this platform, ignored");
  1131. #endif

  1132.     return NGX_CONF_OK;
  1133. }


  1134. ngx_cpuset_t *
  1135. ngx_get_cpu_affinity(ngx_uint_t n)
  1136. {
  1137. #if (NGX_HAVE_CPU_AFFINITY)
  1138.     ngx_uint_t        i, j;
  1139.     ngx_cpuset_t     *mask;
  1140.     ngx_core_conf_t  *ccf;

  1141.     static ngx_cpuset_t  result;

  1142.     ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
  1143.                                            ngx_core_module);

  1144.     if (ccf->cpu_affinity == NULL) {
  1145.         return NULL;
  1146.     }

  1147.     if (ccf->cpu_affinity_auto) {
  1148.         mask = &ccf->cpu_affinity[ccf->cpu_affinity_n - 1];

  1149.         for (i = 0, j = n; /* void */ ; i++) {

  1150.             if (CPU_ISSET(i % CPU_SETSIZE, mask) && j-- == 0) {
  1151.                 break;
  1152.             }

  1153.             if (i == CPU_SETSIZE && j == n) {
  1154.                 /* empty mask */
  1155.                 return NULL;
  1156.             }

  1157.             /* void */
  1158.         }

  1159.         CPU_ZERO(&result);
  1160.         CPU_SET(i % CPU_SETSIZE, &result);

  1161.         return &result;
  1162.     }

  1163.     if (ccf->cpu_affinity_n > n) {
  1164.         return &ccf->cpu_affinity[n];
  1165.     }

  1166.     return &ccf->cpu_affinity[ccf->cpu_affinity_n - 1];

  1167. #else

  1168.     return NULL;

  1169. #endif
  1170. }


  1171. static char *
  1172. ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1173. {
  1174.     ngx_str_t        *value;
  1175.     ngx_core_conf_t  *ccf;

  1176.     ccf = (ngx_core_conf_t *) conf;

  1177.     if (ccf->worker_processes != NGX_CONF_UNSET) {
  1178.         return "is duplicate";
  1179.     }

  1180.     value = cf->args->elts;

  1181.     if (ngx_strcmp(value[1].data, "auto") == 0) {
  1182.         ccf->worker_processes = ngx_ncpu;
  1183.         return NGX_CONF_OK;
  1184.     }

  1185.     ccf->worker_processes = ngx_atoi(value[1].data, value[1].len);

  1186.     if (ccf->worker_processes == NGX_ERROR) {
  1187.         return "invalid value";
  1188.     }

  1189.     return NGX_CONF_OK;
  1190. }


  1191. static char *
  1192. ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1193. {
  1194. #if (NGX_HAVE_DLOPEN)
  1195.     void                *handle;
  1196.     char               **names, **order;
  1197.     ngx_str_t           *value, file;
  1198.     ngx_uint_t           i;
  1199.     ngx_module_t        *module, **modules;
  1200.     ngx_pool_cleanup_t  *cln;

  1201.     if (cf->cycle->modules_used) {
  1202.         return "is specified too late";
  1203.     }

  1204.     value = cf->args->elts;

  1205.     file = value[1];

  1206.     if (ngx_conf_full_name(cf->cycle, &file, 0) != NGX_OK) {
  1207.         return NGX_CONF_ERROR;
  1208.     }

  1209.     cln = ngx_pool_cleanup_add(cf->cycle->pool, 0);
  1210.     if (cln == NULL) {
  1211.         return NGX_CONF_ERROR;
  1212.     }

  1213.     handle = ngx_dlopen(file.data);
  1214.     if (handle == NULL) {
  1215.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1216.                            ngx_dlopen_n " \"%s\" failed (%s)",
  1217.                            file.data, ngx_dlerror());
  1218.         return NGX_CONF_ERROR;
  1219.     }

  1220.     cln->handler = ngx_unload_module;
  1221.     cln->data = handle;

  1222.     modules = ngx_dlsym(handle, "ngx_modules");
  1223.     if (modules == NULL) {
  1224.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1225.                            ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
  1226.                            &value[1], "ngx_modules", ngx_dlerror());
  1227.         return NGX_CONF_ERROR;
  1228.     }

  1229.     names = ngx_dlsym(handle, "ngx_module_names");
  1230.     if (names == NULL) {
  1231.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1232.                            ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
  1233.                            &value[1], "ngx_module_names", ngx_dlerror());
  1234.         return NGX_CONF_ERROR;
  1235.     }

  1236.     order = ngx_dlsym(handle, "ngx_module_order");

  1237.     for (i = 0; modules[i]; i++) {
  1238.         module = modules[i];
  1239.         module->name = names[i];

  1240.         if (ngx_add_module(cf, &file, module, order) != NGX_OK) {
  1241.             return NGX_CONF_ERROR;
  1242.         }

  1243.         ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, "module: %s i:%ui",
  1244.                        module->name, module->index);
  1245.     }

  1246.     return NGX_CONF_OK;

  1247. #else

  1248.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1249.                        "\"load_module\" is not supported "
  1250.                        "on this platform");
  1251.     return NGX_CONF_ERROR;

  1252. #endif
  1253. }


  1254. #if (NGX_HAVE_DLOPEN)

  1255. static void
  1256. ngx_unload_module(void *data)
  1257. {
  1258.     void  *handle = data;

  1259.     if (ngx_dlclose(handle) != 0) {
  1260.         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
  1261.                       ngx_dlclose_n " failed (%s)", ngx_dlerror());
  1262.     }
  1263. }

  1264. #endif