src/core/nginx.c - nginx-1.7.10

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 ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
  9. static ngx_int_t ngx_get_options(int argc, char *const *argv);
  10. static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
  11. static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
  12. static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
  13. static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
  14. static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  15. static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  16. static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  17. static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd,
  18.     void *conf);
  19. static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd,
  20.     void *conf);


  21. static ngx_conf_enum_t  ngx_debug_points[] = {
  22.     { ngx_string("stop"), NGX_DEBUG_POINTS_STOP },
  23.     { ngx_string("abort"), NGX_DEBUG_POINTS_ABORT },
  24.     { ngx_null_string, 0 }
  25. };


  26. static ngx_command_t  ngx_core_commands[] = {

  27.     { ngx_string("daemon"),
  28.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
  29.       ngx_conf_set_flag_slot,
  30.       0,
  31.       offsetof(ngx_core_conf_t, daemon),
  32.       NULL },

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

  39.     { ngx_string("timer_resolution"),
  40.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  41.       ngx_conf_set_msec_slot,
  42.       0,
  43.       offsetof(ngx_core_conf_t, timer_resolution),
  44.       NULL },

  45.     { ngx_string("pid"),
  46.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  47.       ngx_conf_set_str_slot,
  48.       0,
  49.       offsetof(ngx_core_conf_t, pid),
  50.       NULL },

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

  57.     { ngx_string("worker_processes"),
  58.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  59.       ngx_set_worker_processes,
  60.       0,
  61.       0,
  62.       NULL },

  63.     { ngx_string("debug_points"),
  64.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  65.       ngx_conf_set_enum_slot,
  66.       0,
  67.       offsetof(ngx_core_conf_t, debug_points),
  68.       &ngx_debug_points },

  69.     { ngx_string("user"),
  70.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
  71.       ngx_set_user,
  72.       0,
  73.       0,
  74.       NULL },

  75.     { ngx_string("worker_priority"),
  76.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  77.       ngx_set_priority,
  78.       0,
  79.       0,
  80.       NULL },

  81.     { ngx_string("worker_cpu_affinity"),
  82.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
  83.       ngx_set_cpu_affinity,
  84.       0,
  85.       0,
  86.       NULL },

  87.     { ngx_string("worker_rlimit_nofile"),
  88.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  89.       ngx_conf_set_num_slot,
  90.       0,
  91.       offsetof(ngx_core_conf_t, rlimit_nofile),
  92.       NULL },

  93.     { ngx_string("worker_rlimit_core"),
  94.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  95.       ngx_conf_set_off_slot,
  96.       0,
  97.       offsetof(ngx_core_conf_t, rlimit_core),
  98.       NULL },

  99.     { ngx_string("worker_rlimit_sigpending"),
  100.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  101.       ngx_conf_set_num_slot,
  102.       0,
  103.       offsetof(ngx_core_conf_t, rlimit_sigpending),
  104.       NULL },

  105.     { ngx_string("working_directory"),
  106.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  107.       ngx_conf_set_str_slot,
  108.       0,
  109.       offsetof(ngx_core_conf_t, working_directory),
  110.       NULL },

  111.     { ngx_string("env"),
  112.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  113.       ngx_set_env,
  114.       0,
  115.       0,
  116.       NULL },

  117. #if (NGX_THREADS)

  118.     { ngx_string("worker_threads"),
  119.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  120.       ngx_conf_set_num_slot,
  121.       0,
  122.       offsetof(ngx_core_conf_t, worker_threads),
  123.       NULL },

  124.     { ngx_string("thread_stack_size"),
  125.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  126.       ngx_conf_set_size_slot,
  127.       0,
  128.       offsetof(ngx_core_conf_t, thread_stack_size),
  129.       NULL },

  130. #endif

  131.       ngx_null_command
  132. };


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


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


  152. ngx_uint_t          ngx_max_module;

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


  160. static char **ngx_os_environ;


  161. int ngx_cdecl
  162. main(int argc, char *const *argv)
  163. {
  164.     ngx_int_t         i;
  165.     ngx_log_t        *log;
  166.     ngx_cycle_t      *cycle, init_cycle;
  167.     ngx_core_conf_t  *ccf;

  168.     ngx_debug_init();

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

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

  175.     if (ngx_show_version) {
  176.         ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);

  177.         if (ngx_show_help) {
  178.             ngx_write_stderr(
  179.                 "Usage: nginx [-?hvVtq] [-s signal] [-c filename] "
  180.                              "[-p prefix] [-g directives]" NGX_LINEFEED
  181.                              NGX_LINEFEED
  182.                 "Options:" NGX_LINEFEED
  183.                 "  -?,-h         : this help" NGX_LINEFEED
  184.                 "  -v            : show version and exit" NGX_LINEFEED
  185.                 "  -V            : show version and configure options then exit"
  186.                                    NGX_LINEFEED
  187.                 "  -t            : test configuration and exit" NGX_LINEFEED
  188.                 "  -q            : suppress non-error messages "
  189.                                    "during configuration testing" NGX_LINEFEED
  190.                 "  -s signal     : send signal to a master process: "
  191.                                    "stop, quit, reopen, reload" NGX_LINEFEED
  192. #ifdef NGX_PREFIX
  193.                 "  -p prefix     : set prefix path (default: "
  194.                                    NGX_PREFIX ")" NGX_LINEFEED
  195. #else
  196.                 "  -p prefix     : set prefix path (default: NONE)" NGX_LINEFEED
  197. #endif
  198.                 "  -c filename   : set configuration file (default: "
  199.                                    NGX_CONF_PATH ")" NGX_LINEFEED
  200.                 "  -g directives : set global directives out of configuration "
  201.                                    "file" NGX_LINEFEED NGX_LINEFEED
  202.                 );
  203.         }

  204.         if (ngx_show_configure) {
  205.             ngx_write_stderr(
  206. #ifdef NGX_COMPILER
  207.                 "built by " NGX_COMPILER NGX_LINEFEED
  208. #endif
  209. #if (NGX_SSL)
  210. #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
  211.                 "TLS SNI support enabled" NGX_LINEFEED
  212. #else
  213.                 "TLS SNI support disabled" NGX_LINEFEED
  214. #endif
  215. #endif
  216.                 "configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
  217.         }

  218.         if (!ngx_test_config) {
  219.             return 0;
  220.         }
  221.     }

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

  223.     ngx_time_init();

  224. #if (NGX_PCRE)
  225.     ngx_regex_init();
  226. #endif

  227.     ngx_pid = ngx_getpid();

  228.     log = ngx_log_init(ngx_prefix);
  229.     if (log == NULL) {
  230.         return 1;
  231.     }

  232.     /* STUB */
  233. #if (NGX_OPENSSL)
  234.     ngx_ssl_init(log);
  235. #endif

  236.     /*
  237.      * init_cycle->log is required for signal handlers and
  238.      * ngx_process_options()
  239.      */

  240.     ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
  241.     init_cycle.log = log;
  242.     ngx_cycle = &init_cycle;

  243.     init_cycle.pool = ngx_create_pool(1024, log);
  244.     if (init_cycle.pool == NULL) {
  245.         return 1;
  246.     }

  247.     if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
  248.         return 1;
  249.     }

  250.     if (ngx_process_options(&init_cycle) != NGX_OK) {
  251.         return 1;
  252.     }

  253.     if (ngx_os_init(log) != NGX_OK) {
  254.         return 1;
  255.     }

  256.     /*
  257.      * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
  258.      */

  259.     if (ngx_crc32_table_init() != NGX_OK) {
  260.         return 1;
  261.     }

  262.     if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
  263.         return 1;
  264.     }

  265.     ngx_max_module = 0;
  266.     for (i = 0; ngx_modules[i]; i++) {
  267.         ngx_modules[i]->index = ngx_max_module++;
  268.     }

  269.     cycle = ngx_init_cycle(&init_cycle);
  270.     if (cycle == NULL) {
  271.         if (ngx_test_config) {
  272.             ngx_log_stderr(0, "configuration file %s test failed",
  273.                            init_cycle.conf_file.data);
  274.         }

  275.         return 1;
  276.     }

  277.     if (ngx_test_config) {
  278.         if (!ngx_quiet_mode) {
  279.             ngx_log_stderr(0, "configuration file %s test is successful",
  280.                            cycle->conf_file.data);
  281.         }

  282.         return 0;
  283.     }

  284.     if (ngx_signal) {
  285.         return ngx_signal_process(cycle, ngx_signal);
  286.     }

  287.     ngx_os_status(cycle->log);

  288.     ngx_cycle = cycle;

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

  290.     if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
  291.         ngx_process = NGX_PROCESS_MASTER;
  292.     }

  293. #if !(NGX_WIN32)

  294.     if (ngx_init_signals(cycle->log) != NGX_OK) {
  295.         return 1;
  296.     }

  297.     if (!ngx_inherited && ccf->daemon) {
  298.         if (ngx_daemon(cycle->log) != NGX_OK) {
  299.             return 1;
  300.         }

  301.         ngx_daemonized = 1;
  302.     }

  303.     if (ngx_inherited) {
  304.         ngx_daemonized = 1;
  305.     }

  306. #endif

  307.     if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
  308.         return 1;
  309.     }

  310.     if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
  311.         return 1;
  312.     }

  313.     if (log->file->fd != ngx_stderr) {
  314.         if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
  315.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  316.                           ngx_close_file_n " built-in log failed");
  317.         }
  318.     }

  319.     ngx_use_stderr = 0;

  320.     if (ngx_process == NGX_PROCESS_SINGLE) {
  321.         ngx_single_process_cycle(cycle);

  322.     } else {
  323.         ngx_master_process_cycle(cycle);
  324.     }

  325.     return 0;
  326. }


  327. static ngx_int_t
  328. ngx_add_inherited_sockets(ngx_cycle_t *cycle)
  329. {
  330.     u_char           *p, *v, *inherited;
  331.     ngx_int_t         s;
  332.     ngx_listening_t  *ls;

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

  334.     if (inherited == NULL) {
  335.         return NGX_OK;
  336.     }

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

  339.     if (ngx_array_init(&cycle->listening, cycle->pool, 10,
  340.                        sizeof(ngx_listening_t))
  341.         != NGX_OK)
  342.     {
  343.         return NGX_ERROR;
  344.     }

  345.     for (p = inherited, v = p; *p; p++) {
  346.         if (*p == ':' || *p == ';') {
  347.             s = ngx_atoi(v, p - v);
  348.             if (s == NGX_ERROR) {
  349.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  350.                               "invalid socket number \"%s\" in " NGINX_VAR
  351.                               " environment variable, ignoring the rest"
  352.                               " of the variable", v);
  353.                 break;
  354.             }

  355.             v = p + 1;

  356.             ls = ngx_array_push(&cycle->listening);
  357.             if (ls == NULL) {
  358.                 return NGX_ERROR;
  359.             }

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

  361.             ls->fd = (ngx_socket_t) s;
  362.         }
  363.     }

  364.     ngx_inherited = 1;

  365.     return ngx_set_inherited_sockets(cycle);
  366. }


  367. char **
  368. ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
  369. {
  370.     char             **p, **env;
  371.     ngx_str_t         *var;
  372.     ngx_uint_t         i, n;
  373.     ngx_core_conf_t   *ccf;

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

  375.     if (last == NULL && ccf->environment) {
  376.         return ccf->environment;
  377.     }

  378.     var = ccf->env.elts;

  379.     for (i = 0; i < ccf->env.nelts; i++) {
  380.         if (ngx_strcmp(var[i].data, "TZ") == 0
  381.             || ngx_strncmp(var[i].data, "TZ=", 3) == 0)
  382.         {
  383.             goto tz_found;
  384.         }
  385.     }

  386.     var = ngx_array_push(&ccf->env);
  387.     if (var == NULL) {
  388.         return NULL;
  389.     }

  390.     var->len = 2;
  391.     var->data = (u_char *) "TZ";

  392.     var = ccf->env.elts;

  393. tz_found:

  394.     n = 0;

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

  396.         if (var[i].data[var[i].len] == '=') {
  397.             n++;
  398.             continue;
  399.         }

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

  401.             if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
  402.                 && (*p)[var[i].len] == '=')
  403.             {
  404.                 n++;
  405.                 break;
  406.             }
  407.         }
  408.     }

  409.     if (last) {
  410.         env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log);
  411.         *last = n;

  412.     } else {
  413.         env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *));
  414.     }

  415.     if (env == NULL) {
  416.         return NULL;
  417.     }

  418.     n = 0;

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

  420.         if (var[i].data[var[i].len] == '=') {
  421.             env[n++] = (char *) var[i].data;
  422.             continue;
  423.         }

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

  425.             if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
  426.                 && (*p)[var[i].len] == '=')
  427.             {
  428.                 env[n++] = *p;
  429.                 break;
  430.             }
  431.         }
  432.     }

  433.     env[n] = NULL;

  434.     if (last == NULL) {
  435.         ccf->environment = env;
  436.         environ = env;
  437.     }

  438.     return env;
  439. }


  440. ngx_pid_t
  441. ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
  442. {
  443.     char             **env, *var;
  444.     u_char            *p;
  445.     ngx_uint_t         i, n;
  446.     ngx_pid_t          pid;
  447.     ngx_exec_ctx_t     ctx;
  448.     ngx_core_conf_t   *ccf;
  449.     ngx_listening_t   *ls;

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

  451.     ctx.path = argv[0];
  452.     ctx.name = "new binary process";
  453.     ctx.argv = argv;

  454.     n = 2;
  455.     env = ngx_set_environment(cycle, &n);
  456.     if (env == NULL) {
  457.         return NGX_INVALID_PID;
  458.     }

  459.     var = ngx_alloc(sizeof(NGINX_VAR)
  460.                     + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
  461.                     cycle->log);
  462.     if (var == NULL) {
  463.         ngx_free(env);
  464.         return NGX_INVALID_PID;
  465.     }

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

  467.     ls = cycle->listening.elts;
  468.     for (i = 0; i < cycle->listening.nelts; i++) {
  469.         p = ngx_sprintf(p, "%ud;", ls[i].fd);
  470.     }

  471.     *p = '\0';

  472.     env[n++] = var;

  473. #if (NGX_SETPROCTITLE_USES_ENV)

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

  475.     env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  476.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  477.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  478.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  479.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

  480. #endif

  481.     env[n] = NULL;

  482. #if (NGX_DEBUG)
  483.     {
  484.     char  **e;
  485.     for (e = env; *e; e++) {
  486.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e);
  487.     }
  488.     }
  489. #endif

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

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

  492.     if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == NGX_FILE_ERROR) {
  493.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  494.                       ngx_rename_file_n " %s to %s failed "
  495.                       "before executing new binary process \"%s\"",
  496.                       ccf->pid.data, ccf->oldpid.data, argv[0]);

  497.         ngx_free(env);
  498.         ngx_free(var);

  499.         return NGX_INVALID_PID;
  500.     }

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

  502.     if (pid == NGX_INVALID_PID) {
  503.         if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data)
  504.             == NGX_FILE_ERROR)
  505.         {
  506.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  507.                           ngx_rename_file_n " %s back to %s failed after "
  508.                           "an attempt to execute new binary process \"%s\"",
  509.                           ccf->oldpid.data, ccf->pid.data, argv[0]);
  510.         }
  511.     }

  512.     ngx_free(env);
  513.     ngx_free(var);

  514.     return pid;
  515. }


  516. static ngx_int_t
  517. ngx_get_options(int argc, char *const *argv)
  518. {
  519.     u_char     *p;
  520.     ngx_int_t   i;

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

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

  523.         if (*p++ != '-') {
  524.             ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
  525.             return NGX_ERROR;
  526.         }

  527.         while (*p) {

  528.             switch (*p++) {

  529.             case '?':
  530.             case 'h':
  531.                 ngx_show_version = 1;
  532.                 ngx_show_help = 1;
  533.                 break;

  534.             case 'v':
  535.                 ngx_show_version = 1;
  536.                 break;

  537.             case 'V':
  538.                 ngx_show_version = 1;
  539.                 ngx_show_configure = 1;
  540.                 break;

  541.             case 't':
  542.                 ngx_test_config = 1;
  543.                 break;

  544.             case 'q':
  545.                 ngx_quiet_mode = 1;
  546.                 break;

  547.             case 'p':
  548.                 if (*p) {
  549.                     ngx_prefix = p;
  550.                     goto next;
  551.                 }

  552.                 if (argv[++i]) {
  553.                     ngx_prefix = (u_char *) argv[i];
  554.                     goto next;
  555.                 }

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

  558.             case 'c':
  559.                 if (*p) {
  560.                     ngx_conf_file = p;
  561.                     goto next;
  562.                 }

  563.                 if (argv[++i]) {
  564.                     ngx_conf_file = (u_char *) argv[i];
  565.                     goto next;
  566.                 }

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

  569.             case 'g':
  570.                 if (*p) {
  571.                     ngx_conf_params = p;
  572.                     goto next;
  573.                 }

  574.                 if (argv[++i]) {
  575.                     ngx_conf_params = (u_char *) argv[i];
  576.                     goto next;
  577.                 }

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

  580.             case 's':
  581.                 if (*p) {
  582.                     ngx_signal = (char *) p;

  583.                 } else if (argv[++i]) {
  584.                     ngx_signal = argv[i];

  585.                 } else {
  586.                     ngx_log_stderr(0, "option \"-s\" requires parameter");
  587.                     return NGX_ERROR;
  588.                 }

  589.                 if (ngx_strcmp(ngx_signal, "stop") == 0
  590.                     || ngx_strcmp(ngx_signal, "quit") == 0
  591.                     || ngx_strcmp(ngx_signal, "reopen") == 0
  592.                     || ngx_strcmp(ngx_signal, "reload") == 0)
  593.                 {
  594.                     ngx_process = NGX_PROCESS_SIGNALLER;
  595.                     goto next;
  596.                 }

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

  599.             default:
  600.                 ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
  601.                 return NGX_ERROR;
  602.             }
  603.         }

  604.     next:

  605.         continue;
  606.     }

  607.     return NGX_OK;
  608. }


  609. static ngx_int_t
  610. ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
  611. {
  612. #if (NGX_FREEBSD)

  613.     ngx_os_argv = (char **) argv;
  614.     ngx_argc = argc;
  615.     ngx_argv = (char **) argv;

  616. #else
  617.     size_t     len;
  618.     ngx_int_t  i;

  619.     ngx_os_argv = (char **) argv;
  620.     ngx_argc = argc;

  621.     ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
  622.     if (ngx_argv == NULL) {
  623.         return NGX_ERROR;
  624.     }

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

  627.         ngx_argv[i] = ngx_alloc(len, cycle->log);
  628.         if (ngx_argv[i] == NULL) {
  629.             return NGX_ERROR;
  630.         }

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

  633.     ngx_argv[i] = NULL;

  634. #endif

  635.     ngx_os_environ = environ;

  636.     return NGX_OK;
  637. }


  638. static ngx_int_t
  639. ngx_process_options(ngx_cycle_t *cycle)
  640. {
  641.     u_char  *p;
  642.     size_t   len;

  643.     if (ngx_prefix) {
  644.         len = ngx_strlen(ngx_prefix);
  645.         p = ngx_prefix;

  646.         if (len && !ngx_path_separator(p[len - 1])) {
  647.             p = ngx_pnalloc(cycle->pool, len + 1);
  648.             if (p == NULL) {
  649.                 return NGX_ERROR;
  650.             }

  651.             ngx_memcpy(p, ngx_prefix, len);
  652.             p[len++] = '/';
  653.         }

  654.         cycle->conf_prefix.len = len;
  655.         cycle->conf_prefix.data = p;
  656.         cycle->prefix.len = len;
  657.         cycle->prefix.data = p;

  658.     } else {

  659. #ifndef NGX_PREFIX

  660.         p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
  661.         if (p == NULL) {
  662.             return NGX_ERROR;
  663.         }

  664.         if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {
  665.             ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
  666.             return NGX_ERROR;
  667.         }

  668.         len = ngx_strlen(p);

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

  670.         cycle->conf_prefix.len = len;
  671.         cycle->conf_prefix.data = p;
  672.         cycle->prefix.len = len;
  673.         cycle->prefix.data = p;

  674. #else

  675. #ifdef NGX_CONF_PREFIX
  676.         ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
  677. #else
  678.         ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
  679. #endif
  680.         ngx_str_set(&cycle->prefix, NGX_PREFIX);

  681. #endif
  682.     }

  683.     if (ngx_conf_file) {
  684.         cycle->conf_file.len = ngx_strlen(ngx_conf_file);
  685.         cycle->conf_file.data = ngx_conf_file;

  686.     } else {
  687.         ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
  688.     }

  689.     if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
  690.         return NGX_ERROR;
  691.     }

  692.     for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
  693.          p > cycle->conf_file.data;
  694.          p--)
  695.     {
  696.         if (ngx_path_separator(*p)) {
  697.             cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1;
  698.             cycle->conf_prefix.data = ngx_cycle->conf_file.data;
  699.             break;
  700.         }
  701.     }

  702.     if (ngx_conf_params) {
  703.         cycle->conf_param.len = ngx_strlen(ngx_conf_params);
  704.         cycle->conf_param.data = ngx_conf_params;
  705.     }

  706.     if (ngx_test_config) {
  707.         cycle->log->log_level = NGX_LOG_INFO;
  708.     }

  709.     return NGX_OK;
  710. }


  711. static void *
  712. ngx_core_module_create_conf(ngx_cycle_t *cycle)
  713. {
  714.     ngx_core_conf_t  *ccf;

  715.     ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t));
  716.     if (ccf == NULL) {
  717.         return NULL;
  718.     }

  719.     /*
  720.      * set by ngx_pcalloc()
  721.      *
  722.      *     ccf->pid = NULL;
  723.      *     ccf->oldpid = NULL;
  724.      *     ccf->priority = 0;
  725.      *     ccf->cpu_affinity_n = 0;
  726.      *     ccf->cpu_affinity = NULL;
  727.      */

  728.     ccf->daemon = NGX_CONF_UNSET;
  729.     ccf->master = NGX_CONF_UNSET;
  730.     ccf->timer_resolution = NGX_CONF_UNSET_MSEC;

  731.     ccf->worker_processes = NGX_CONF_UNSET;
  732.     ccf->debug_points = NGX_CONF_UNSET;

  733.     ccf->rlimit_nofile = NGX_CONF_UNSET;
  734.     ccf->rlimit_core = NGX_CONF_UNSET;
  735.     ccf->rlimit_sigpending = NGX_CONF_UNSET;

  736.     ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;
  737.     ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT;

  738. #if (NGX_THREADS)
  739.     ccf->worker_threads = NGX_CONF_UNSET;
  740.     ccf->thread_stack_size = NGX_CONF_UNSET_SIZE;
  741. #endif

  742.     if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))
  743.         != NGX_OK)
  744.     {
  745.         return NULL;
  746.     }

  747.     return ccf;
  748. }


  749. static char *
  750. ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
  751. {
  752.     ngx_core_conf_t  *ccf = conf;

  753.     ngx_conf_init_value(ccf->daemon, 1);
  754.     ngx_conf_init_value(ccf->master, 1);
  755.     ngx_conf_init_msec_value(ccf->timer_resolution, 0);

  756.     ngx_conf_init_value(ccf->worker_processes, 1);
  757.     ngx_conf_init_value(ccf->debug_points, 0);

  758. #if (NGX_HAVE_CPU_AFFINITY)

  759.     if (ccf->cpu_affinity_n
  760.         && ccf->cpu_affinity_n != 1
  761.         && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)
  762.     {
  763.         ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
  764.                       "the number of \"worker_processes\" is not equal to "
  765.                       "the number of \"worker_cpu_affinity\" masks, "
  766.                       "using last mask for remaining worker processes");
  767.     }

  768. #endif

  769. #if (NGX_THREADS)

  770.     ngx_conf_init_value(ccf->worker_threads, 0);
  771.     ngx_threads_n = ccf->worker_threads;
  772.     ngx_conf_init_size_value(ccf->thread_stack_size, 2 * 1024 * 1024);

  773. #endif


  774.     if (ccf->pid.len == 0) {
  775.         ngx_str_set(&ccf->pid, NGX_PID_PATH);
  776.     }

  777.     if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
  778.         return NGX_CONF_ERROR;
  779.     }

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

  781.     ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
  782.     if (ccf->oldpid.data == NULL) {
  783.         return NGX_CONF_ERROR;
  784.     }

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


  787. #if !(NGX_WIN32)

  788.     if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) {
  789.         struct group   *grp;
  790.         struct passwd  *pwd;

  791.         ngx_set_errno(0);
  792.         pwd = getpwnam(NGX_USER);
  793.         if (pwd == NULL) {
  794.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  795.                           "getpwnam(\"" NGX_USER "\") failed");
  796.             return NGX_CONF_ERROR;
  797.         }

  798.         ccf->username = NGX_USER;
  799.         ccf->user = pwd->pw_uid;

  800.         ngx_set_errno(0);
  801.         grp = getgrnam(NGX_GROUP);
  802.         if (grp == NULL) {
  803.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  804.                           "getgrnam(\"" NGX_GROUP "\") failed");
  805.             return NGX_CONF_ERROR;
  806.         }

  807.         ccf->group = grp->gr_gid;
  808.     }


  809.     if (ccf->lock_file.len == 0) {
  810.         ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH);
  811.     }

  812.     if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) {
  813.         return NGX_CONF_ERROR;
  814.     }

  815.     {
  816.     ngx_str_t  lock_file;

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

  818.     if (lock_file.len) {
  819.         lock_file.len--;

  820.         if (ccf->lock_file.len != lock_file.len
  821.             || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len)
  822.                != 0)
  823.         {
  824.             ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  825.                           "\"lock_file\" could not be changed, ignored");
  826.         }

  827.         cycle->lock_file.len = lock_file.len + 1;
  828.         lock_file.len += sizeof(".accept");

  829.         cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file);
  830.         if (cycle->lock_file.data == NULL) {
  831.             return NGX_CONF_ERROR;
  832.         }

  833.     } else {
  834.         cycle->lock_file.len = ccf->lock_file.len + 1;
  835.         cycle->lock_file.data = ngx_pnalloc(cycle->pool,
  836.                                       ccf->lock_file.len + sizeof(".accept"));
  837.         if (cycle->lock_file.data == NULL) {
  838.             return NGX_CONF_ERROR;
  839.         }

  840.         ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data,
  841.                               ccf->lock_file.len),
  842.                    ".accept", sizeof(".accept"));
  843.     }
  844.     }

  845. #endif

  846.     return NGX_CONF_OK;
  847. }


  848. static char *
  849. ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  850. {
  851. #if (NGX_WIN32)

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

  854.     return NGX_CONF_OK;

  855. #else

  856.     ngx_core_conf_t  *ccf = conf;

  857.     char             *group;
  858.     struct passwd    *pwd;
  859.     struct group     *grp;
  860.     ngx_str_t        *value;

  861.     if (ccf->user != (uid_t) NGX_CONF_UNSET_UINT) {
  862.         return "is duplicate";
  863.     }

  864.     if (geteuid() != 0) {
  865.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  866.                            "the \"user\" directive makes sense only "
  867.                            "if the master process runs "
  868.                            "with super-user privileges, ignored");
  869.         return NGX_CONF_OK;
  870.     }

  871.     value = (ngx_str_t *) cf->args->elts;

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

  873.     ngx_set_errno(0);
  874.     pwd = getpwnam((const char *) value[1].data);
  875.     if (pwd == NULL) {
  876.         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
  877.                            "getpwnam(\"%s\") failed", value[1].data);
  878.         return NGX_CONF_ERROR;
  879.     }

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

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

  882.     ngx_set_errno(0);
  883.     grp = getgrnam(group);
  884.     if (grp == NULL) {
  885.         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
  886.                            "getgrnam(\"%s\") failed", group);
  887.         return NGX_CONF_ERROR;
  888.     }

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

  890.     return NGX_CONF_OK;

  891. #endif
  892. }


  893. static char *
  894. ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  895. {
  896.     ngx_core_conf_t  *ccf = conf;

  897.     ngx_str_t   *value, *var;
  898.     ngx_uint_t   i;

  899.     var = ngx_array_push(&ccf->env);
  900.     if (var == NULL) {
  901.         return NGX_CONF_ERROR;
  902.     }

  903.     value = cf->args->elts;
  904.     *var = value[1];

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

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

  907.             var->len = i;

  908.             return NGX_CONF_OK;
  909.         }
  910.     }

  911.     return NGX_CONF_OK;
  912. }


  913. static char *
  914. ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  915. {
  916.     ngx_core_conf_t  *ccf = conf;

  917.     ngx_str_t        *value;
  918.     ngx_uint_t        n, minus;

  919.     if (ccf->priority != 0) {
  920.         return "is duplicate";
  921.     }

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

  923.     if (value[1].data[0] == '-') {
  924.         n = 1;
  925.         minus = 1;

  926.     } else if (value[1].data[0] == '+') {
  927.         n = 1;
  928.         minus = 0;

  929.     } else {
  930.         n = 0;
  931.         minus = 0;
  932.     }

  933.     ccf->priority = ngx_atoi(&value[1].data[n], value[1].len - n);
  934.     if (ccf->priority == NGX_ERROR) {
  935.         return "invalid number";
  936.     }

  937.     if (minus) {
  938.         ccf->priority = -ccf->priority;
  939.     }

  940.     return NGX_CONF_OK;
  941. }


  942. static char *
  943. ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  944. {
  945. #if (NGX_HAVE_CPU_AFFINITY)
  946.     ngx_core_conf_t  *ccf = conf;

  947.     u_char            ch;
  948.     uint64_t         *mask;
  949.     ngx_str_t        *value;
  950.     ngx_uint_t        i, n;

  951.     if (ccf->cpu_affinity) {
  952.         return "is duplicate";
  953.     }

  954.     mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(uint64_t));
  955.     if (mask == NULL) {
  956.         return NGX_CONF_ERROR;
  957.     }

  958.     ccf->cpu_affinity_n = cf->args->nelts - 1;
  959.     ccf->cpu_affinity = mask;

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

  961.     for (n = 1; n < cf->args->nelts; n++) {

  962.         if (value[n].len > 64) {
  963.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  964.                          "\"worker_cpu_affinity\" supports up to 64 CPUs only");
  965.             return NGX_CONF_ERROR;
  966.         }

  967.         mask[n - 1] = 0;

  968.         for (i = 0; i < value[n].len; i++) {

  969.             ch = value[n].data[i];

  970.             if (ch == ' ') {
  971.                 continue;
  972.             }

  973.             mask[n - 1] <<= 1;

  974.             if (ch == '0') {
  975.                 continue;
  976.             }

  977.             if (ch == '1') {
  978.                 mask[n - 1] |= 1;
  979.                 continue;
  980.             }

  981.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  982.                           "invalid character \"%c\" in \"worker_cpu_affinity\"",
  983.                           ch);
  984.             return NGX_CONF_ERROR;
  985.         }
  986.     }

  987. #else

  988.     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  989.                        "\"worker_cpu_affinity\" is not supported "
  990.                        "on this platform, ignored");
  991. #endif

  992.     return NGX_CONF_OK;
  993. }


  994. uint64_t
  995. ngx_get_cpu_affinity(ngx_uint_t n)
  996. {
  997.     ngx_core_conf_t  *ccf;

  998.     ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
  999.                                            ngx_core_module);

  1000.     if (ccf->cpu_affinity == NULL) {
  1001.         return 0;
  1002.     }

  1003.     if (ccf->cpu_affinity_n > n) {
  1004.         return ccf->cpu_affinity[n];
  1005.     }

  1006.     return ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
  1007. }


  1008. static char *
  1009. ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1010. {
  1011.     ngx_str_t        *value;
  1012.     ngx_core_conf_t  *ccf;

  1013.     ccf = (ngx_core_conf_t *) conf;

  1014.     if (ccf->worker_processes != NGX_CONF_UNSET) {
  1015.         return "is duplicate";
  1016.     }

  1017.     value = (ngx_str_t *) cf->args->elts;

  1018.     if (ngx_strcmp(value[1].data, "auto") == 0) {
  1019.         ccf->worker_processes = ngx_ncpu;
  1020.         return NGX_CONF_OK;
  1021.     }

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

  1023.     if (ccf->worker_processes == NGX_ERROR) {
  1024.         return "invalid value";
  1025.     }

  1026.     return NGX_CONF_OK;
  1027. }