nginx 0.8.35
[nginx-catap.git] / src / core / nginx.c
bloba5fbccd407f7c031e2ec9d558eebbf7e80402b92
2 /*
3 * Copyright (C) Igor Sysoev
4 */
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <nginx.h>
12 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
13 static ngx_int_t ngx_get_options(int argc, char *const *argv);
14 static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
15 static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
16 static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
17 static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
18 static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
19 static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
20 static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
21 static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd,
22 void *conf);
25 static ngx_conf_enum_t ngx_debug_points[] = {
26 { ngx_string("stop"), NGX_DEBUG_POINTS_STOP },
27 { ngx_string("abort"), NGX_DEBUG_POINTS_ABORT },
28 { ngx_null_string, 0 }
32 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,
38 offsetof(ngx_core_conf_t, daemon),
39 NULL },
41 { ngx_string("master_process"),
42 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
43 ngx_conf_set_flag_slot,
45 offsetof(ngx_core_conf_t, master),
46 NULL },
48 { ngx_string("timer_resolution"),
49 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
50 ngx_conf_set_msec_slot,
52 offsetof(ngx_core_conf_t, timer_resolution),
53 NULL },
55 { ngx_string("pid"),
56 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
57 ngx_conf_set_str_slot,
59 offsetof(ngx_core_conf_t, pid),
60 NULL },
62 { ngx_string("lock_file"),
63 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
64 ngx_conf_set_str_slot,
66 offsetof(ngx_core_conf_t, lock_file),
67 NULL },
69 { ngx_string("worker_processes"),
70 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
71 ngx_conf_set_num_slot,
73 offsetof(ngx_core_conf_t, worker_processes),
74 NULL },
76 { ngx_string("debug_points"),
77 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
78 ngx_conf_set_enum_slot,
80 offsetof(ngx_core_conf_t, debug_points),
81 &ngx_debug_points },
83 { ngx_string("user"),
84 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
85 ngx_set_user,
88 NULL },
90 { ngx_string("worker_priority"),
91 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
92 ngx_set_priority,
95 NULL },
97 { ngx_string("worker_cpu_affinity"),
98 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
99 ngx_set_cpu_affinity,
102 NULL },
104 { ngx_string("worker_rlimit_nofile"),
105 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
106 ngx_conf_set_num_slot,
108 offsetof(ngx_core_conf_t, rlimit_nofile),
109 NULL },
111 { ngx_string("worker_rlimit_core"),
112 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
113 ngx_conf_set_size_slot,
115 offsetof(ngx_core_conf_t, rlimit_core),
116 NULL },
118 { ngx_string("worker_rlimit_sigpending"),
119 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
120 ngx_conf_set_num_slot,
122 offsetof(ngx_core_conf_t, rlimit_sigpending),
123 NULL },
125 { ngx_string("working_directory"),
126 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
127 ngx_conf_set_str_slot,
129 offsetof(ngx_core_conf_t, working_directory),
130 NULL },
132 { ngx_string("env"),
133 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
134 ngx_set_env,
137 NULL },
139 #if (NGX_THREADS)
141 { ngx_string("worker_threads"),
142 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
143 ngx_conf_set_num_slot,
145 offsetof(ngx_core_conf_t, worker_threads),
146 NULL },
148 { ngx_string("thread_stack_size"),
149 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
150 ngx_conf_set_size_slot,
152 offsetof(ngx_core_conf_t, thread_stack_size),
153 NULL },
155 #endif
157 ngx_null_command
161 static ngx_core_module_t ngx_core_module_ctx = {
162 ngx_string("core"),
163 ngx_core_module_create_conf,
164 ngx_core_module_init_conf
168 ngx_module_t ngx_core_module = {
169 NGX_MODULE_V1,
170 &ngx_core_module_ctx, /* module context */
171 ngx_core_commands, /* module directives */
172 NGX_CORE_MODULE, /* module type */
173 NULL, /* init master */
174 NULL, /* init module */
175 NULL, /* init process */
176 NULL, /* init thread */
177 NULL, /* exit thread */
178 NULL, /* exit process */
179 NULL, /* exit master */
180 NGX_MODULE_V1_PADDING
184 ngx_uint_t ngx_max_module;
186 static ngx_uint_t ngx_show_help;
187 static ngx_uint_t ngx_show_version;
188 static ngx_uint_t ngx_show_configure;
189 static u_char *ngx_prefix;
190 static u_char *ngx_conf_file;
191 static u_char *ngx_conf_params;
192 static char *ngx_signal;
195 static char **ngx_os_environ;
198 int ngx_cdecl
199 main(int argc, char *const *argv)
201 ngx_int_t i;
202 ngx_log_t *log;
203 ngx_cycle_t *cycle, init_cycle;
204 ngx_core_conf_t *ccf;
206 if (ngx_get_options(argc, argv) != NGX_OK) {
207 return 1;
210 if (ngx_show_version) {
211 ngx_log_stderr(0, "nginx version: " NGINX_VER);
213 if (ngx_show_help) {
214 ngx_log_stderr(0,
215 "Usage: nginx [-?hvVt] [-s signal] [-c filename] "
216 "[-p prefix] [-g directives]" CRLF CRLF
217 "Options:" CRLF
218 " -?,-h : this help" CRLF
219 " -v : show version and exit" CRLF
220 " -V : show version and configure options then exit"
221 CRLF
222 " -t : test configuration and exit" CRLF
223 " -s signal : send signal to a master process: "
224 "stop, quit, reopen, reload" CRLF
225 #ifdef NGX_PREFIX
226 " -p prefix : set prefix path (default: "
227 NGX_PREFIX ")" CRLF
228 #else
229 " -p prefix : set prefix path (default: NONE)" CRLF
230 #endif
231 " -c filename : set configuration file (default: "
232 NGX_CONF_PATH ")" CRLF
233 " -g directives : set global directives out of configuration "
234 "file" CRLF
238 if (ngx_show_configure) {
239 #ifdef NGX_COMPILER
240 ngx_log_stderr(0, "built by " NGX_COMPILER);
241 #endif
242 #if (NGX_SSL)
243 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
244 ngx_log_stderr(0, "TLS SNI support enabled");
245 #else
246 ngx_log_stderr(0, "TLS SNI support disabled");
247 #endif
248 #endif
249 ngx_log_stderr(0, "configure arguments:" NGX_CONFIGURE);
252 if (!ngx_test_config) {
253 return 0;
257 #if (NGX_FREEBSD)
258 ngx_debug_init();
259 #endif
261 /* TODO */ ngx_max_sockets = -1;
263 ngx_time_init();
265 #if (NGX_PCRE)
266 ngx_regex_init();
267 #endif
269 ngx_pid = ngx_getpid();
271 log = ngx_log_init(ngx_prefix);
272 if (log == NULL) {
273 return 1;
276 /* STUB */
277 #if (NGX_OPENSSL)
278 ngx_ssl_init(log);
279 #endif
282 * init_cycle->log is required for signal handlers and
283 * ngx_process_options()
286 ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
287 init_cycle.log = log;
288 ngx_cycle = &init_cycle;
290 init_cycle.pool = ngx_create_pool(1024, log);
291 if (init_cycle.pool == NULL) {
292 return 1;
295 if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
296 return 1;
299 if (ngx_process_options(&init_cycle) != NGX_OK) {
300 return 1;
303 if (ngx_os_init(log) != NGX_OK) {
304 return 1;
308 * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
311 if (ngx_crc32_table_init() != NGX_OK) {
312 return 1;
315 if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
316 return 1;
319 ngx_max_module = 0;
320 for (i = 0; ngx_modules[i]; i++) {
321 ngx_modules[i]->index = ngx_max_module++;
324 cycle = ngx_init_cycle(&init_cycle);
325 if (cycle == NULL) {
326 if (ngx_test_config) {
327 ngx_log_stderr(0, "configuration file %s test failed",
328 init_cycle.conf_file.data);
331 return 1;
334 if (ngx_test_config) {
335 ngx_log_stderr(0, "configuration file %s test is successful",
336 cycle->conf_file.data);
337 return 0;
340 if (ngx_signal) {
341 return ngx_signal_process(cycle, ngx_signal);
344 ngx_os_status(cycle->log);
346 ngx_cycle = cycle;
348 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
350 if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
351 ngx_process = NGX_PROCESS_MASTER;
354 #if !(NGX_WIN32)
356 if (ngx_init_signals(cycle->log) != NGX_OK) {
357 return 1;
360 if (!ngx_inherited && ccf->daemon) {
361 if (ngx_daemon(cycle->log) != NGX_OK) {
362 return 1;
365 ngx_daemonized = 1;
368 #endif
370 if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
371 return 1;
374 if (cycle->log->file->fd != ngx_stderr) {
376 if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
377 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
378 ngx_set_stderr_n " failed");
379 return 1;
383 if (log->file->fd != ngx_stderr) {
384 if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
385 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
386 ngx_close_file_n " built-in log failed");
390 ngx_use_stderr = 0;
392 if (ngx_process == NGX_PROCESS_SINGLE) {
393 ngx_single_process_cycle(cycle);
395 } else {
396 ngx_master_process_cycle(cycle);
399 return 0;
403 static ngx_int_t
404 ngx_add_inherited_sockets(ngx_cycle_t *cycle)
406 u_char *p, *v, *inherited;
407 ngx_int_t s;
408 ngx_listening_t *ls;
410 inherited = (u_char *) getenv(NGINX_VAR);
412 if (inherited == NULL) {
413 return NGX_OK;
416 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
417 "using inherited sockets from \"%s\"", inherited);
419 if (ngx_array_init(&cycle->listening, cycle->pool, 10,
420 sizeof(ngx_listening_t))
421 != NGX_OK)
423 return NGX_ERROR;
426 for (p = inherited, v = p; *p; p++) {
427 if (*p == ':' || *p == ';') {
428 s = ngx_atoi(v, p - v);
429 if (s == NGX_ERROR) {
430 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
431 "invalid socket number \"%s\" in " NGINX_VAR
432 " environment variable, ignoring the rest"
433 " of the variable", v);
434 break;
437 v = p + 1;
439 ls = ngx_array_push(&cycle->listening);
440 if (ls == NULL) {
441 return NGX_ERROR;
444 ngx_memzero(ls, sizeof(ngx_listening_t));
446 ls->fd = (ngx_socket_t) s;
450 ngx_inherited = 1;
452 return ngx_set_inherited_sockets(cycle);
456 char **
457 ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
459 char **p, **env;
460 ngx_str_t *var;
461 ngx_uint_t i, n;
462 ngx_core_conf_t *ccf;
464 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
466 if (last == NULL && ccf->environment) {
467 return ccf->environment;
470 var = ccf->env.elts;
472 for (i = 0; i < ccf->env.nelts; i++) {
473 if (ngx_strcmp(var[i].data, "TZ") == 0
474 || ngx_strncmp(var[i].data, "TZ=", 3) == 0)
476 goto tz_found;
480 var = ngx_array_push(&ccf->env);
481 if (var == NULL) {
482 return NULL;
485 var->len = 2;
486 var->data = (u_char *) "TZ";
488 var = ccf->env.elts;
490 tz_found:
492 n = 0;
494 for (i = 0; i < ccf->env.nelts; i++) {
496 if (var[i].data[var[i].len] == '=') {
497 n++;
498 continue;
501 for (p = ngx_os_environ; *p; p++) {
503 if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
504 && (*p)[var[i].len] == '=')
506 n++;
507 break;
512 if (last) {
513 env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log);
514 *last = n;
516 } else {
517 env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *));
520 if (env == NULL) {
521 return NULL;
524 n = 0;
526 for (i = 0; i < ccf->env.nelts; i++) {
528 if (var[i].data[var[i].len] == '=') {
529 env[n++] = (char *) var[i].data;
530 continue;
533 for (p = ngx_os_environ; *p; p++) {
535 if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
536 && (*p)[var[i].len] == '=')
538 env[n++] = *p;
539 break;
544 env[n] = NULL;
546 if (last == NULL) {
547 ccf->environment = env;
548 environ = env;
551 return env;
555 ngx_pid_t
556 ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
558 char **env, *var;
559 u_char *p;
560 ngx_uint_t i, n;
561 ngx_pid_t pid;
562 ngx_exec_ctx_t ctx;
563 ngx_core_conf_t *ccf;
564 ngx_listening_t *ls;
566 ngx_memzero(&ctx, sizeof(ngx_exec_ctx_t));
568 ctx.path = argv[0];
569 ctx.name = "new binary process";
570 ctx.argv = argv;
572 n = 2;
573 env = ngx_set_environment(cycle, &n);
574 if (env == NULL) {
575 return NGX_INVALID_PID;
578 var = ngx_alloc(sizeof(NGINX_VAR)
579 + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
580 cycle->log);
582 p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR));
584 ls = cycle->listening.elts;
585 for (i = 0; i < cycle->listening.nelts; i++) {
586 p = ngx_sprintf(p, "%ud;", ls[i].fd);
589 *p = '\0';
591 env[n++] = var;
593 #if (NGX_SETPROCTITLE_USES_ENV)
595 /* allocate the spare 300 bytes for the new binary process title */
597 env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
598 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
599 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
600 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
601 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
603 #endif
605 env[n] = NULL;
607 #if (NGX_DEBUG)
609 char **e;
610 for (e = env; *e; e++) {
611 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e);
614 #endif
616 ctx.envp = (char *const *) env;
618 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
620 if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) != NGX_OK) {
621 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
622 ngx_rename_file_n " %s to %s failed "
623 "before executing new binary process \"%s\"",
624 ccf->pid.data, ccf->oldpid.data, argv[0]);
626 ngx_free(env);
627 ngx_free(var);
629 return NGX_INVALID_PID;
632 pid = ngx_execute(cycle, &ctx);
634 if (pid == NGX_INVALID_PID) {
635 if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data) != NGX_OK) {
636 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
637 ngx_rename_file_n " %s back to %s failed after "
638 "the try to execute the new binary process \"%s\"",
639 ccf->oldpid.data, ccf->pid.data, argv[0]);
643 ngx_free(env);
644 ngx_free(var);
646 return pid;
650 static ngx_int_t
651 ngx_get_options(int argc, char *const *argv)
653 u_char *p;
654 ngx_int_t i;
656 for (i = 1; i < argc; i++) {
658 p = (u_char *) argv[i];
660 if (*p++ != '-') {
661 ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
662 return NGX_ERROR;
665 while (*p) {
667 switch (*p++) {
669 case '?':
670 case 'h':
671 ngx_show_version = 1;
672 ngx_show_help = 1;
673 break;
675 case 'v':
676 ngx_show_version = 1;
677 break;
679 case 'V':
680 ngx_show_version = 1;
681 ngx_show_configure = 1;
682 break;
684 case 't':
685 ngx_test_config = 1;
686 break;
688 case 'p':
689 if (*p) {
690 ngx_prefix = p;
691 goto next;
694 if (argv[++i]) {
695 ngx_prefix = (u_char *) argv[i];
696 goto next;
699 ngx_log_stderr(0, "option \"-p\" requires directory name");
700 return NGX_ERROR;
702 case 'c':
703 if (*p) {
704 ngx_conf_file = p;
705 goto next;
708 if (argv[++i]) {
709 ngx_conf_file = (u_char *) argv[i];
710 goto next;
713 ngx_log_stderr(0, "option \"-c\" requires file name");
714 return NGX_ERROR;
716 case 'g':
717 if (*p) {
718 ngx_conf_params = p;
719 goto next;
722 if (argv[++i]) {
723 ngx_conf_params = (u_char *) argv[i];
724 goto next;
727 ngx_log_stderr(0, "option \"-g\" requires parameter");
728 return NGX_ERROR;
730 case 's':
731 if (*p) {
732 ngx_signal = (char *) p;
734 } else if (argv[++i]) {
735 ngx_signal = argv[i];
737 } else {
738 ngx_log_stderr(0, "option \"-s\" requires parameter");
739 return NGX_ERROR;
742 if (ngx_strcmp(ngx_signal, "stop") == 0
743 || ngx_strcmp(ngx_signal, "quit") == 0
744 || ngx_strcmp(ngx_signal, "reopen") == 0
745 || ngx_strcmp(ngx_signal, "reload") == 0)
747 ngx_process = NGX_PROCESS_SIGNALLER;
748 goto next;
751 ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
752 return NGX_ERROR;
754 default:
755 ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
756 return NGX_ERROR;
760 next:
762 continue;
765 return NGX_OK;
769 static ngx_int_t
770 ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
772 #if (NGX_FREEBSD)
774 ngx_os_argv = (char **) argv;
775 ngx_argc = argc;
776 ngx_argv = (char **) argv;
778 #else
779 size_t len;
780 ngx_int_t i;
782 ngx_os_argv = (char **) argv;
783 ngx_argc = argc;
785 ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
786 if (ngx_argv == NULL) {
787 return NGX_ERROR;
790 for (i = 0; i < argc; i++) {
791 len = ngx_strlen(argv[i]) + 1;
793 ngx_argv[i] = ngx_alloc(len, cycle->log);
794 if (ngx_argv[i] == NULL) {
795 return NGX_ERROR;
798 (void) ngx_cpystrn((u_char *) ngx_argv[i], (u_char *) argv[i], len);
801 ngx_argv[i] = NULL;
803 #endif
805 ngx_os_environ = environ;
807 return NGX_OK;
811 static ngx_int_t
812 ngx_process_options(ngx_cycle_t *cycle)
814 u_char *p;
815 size_t len;
817 if (ngx_prefix) {
818 len = ngx_strlen(ngx_prefix);
819 p = ngx_prefix;
821 if (!ngx_path_separator(*p)) {
822 p = ngx_pnalloc(cycle->pool, len + 1);
823 if (p == NULL) {
824 return NGX_ERROR;
827 ngx_memcpy(p, ngx_prefix, len);
828 p[len++] = '/';
831 cycle->conf_prefix.len = len;
832 cycle->conf_prefix.data = p;
833 cycle->prefix.len = len;
834 cycle->prefix.data = p;
836 } else {
838 #ifndef NGX_PREFIX
840 p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
841 if (p == NULL) {
842 return NGX_ERROR;
845 if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {
846 ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
847 return NGX_ERROR;
850 len = ngx_strlen(p);
852 p[len++] = '/';
854 cycle->conf_prefix.len = len;
855 cycle->conf_prefix.data = p;
856 cycle->prefix.len = len;
857 cycle->prefix.data = p;
859 #else
861 #ifdef NGX_CONF_PREFIX
862 cycle->conf_prefix.len = sizeof(NGX_CONF_PREFIX) - 1;
863 cycle->conf_prefix.data = (u_char *) NGX_CONF_PREFIX;
864 #else
865 cycle->conf_prefix.len = sizeof(NGX_PREFIX) - 1;
866 cycle->conf_prefix.data = (u_char *) NGX_PREFIX;
867 #endif
868 cycle->prefix.len = sizeof(NGX_PREFIX) - 1;
869 cycle->prefix.data = (u_char *) NGX_PREFIX;
871 #endif
874 if (ngx_conf_file) {
875 cycle->conf_file.len = ngx_strlen(ngx_conf_file);
876 cycle->conf_file.data = ngx_conf_file;
878 } else {
879 cycle->conf_file.len = sizeof(NGX_CONF_PATH) - 1;
880 cycle->conf_file.data = (u_char *) NGX_CONF_PATH;
883 if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
884 return NGX_ERROR;
887 for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
888 p > cycle->conf_file.data;
889 p--)
891 if (ngx_path_separator(*p)) {
892 cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1;
893 cycle->conf_prefix.data = ngx_cycle->conf_file.data;
894 break;
898 if (ngx_conf_params) {
899 cycle->conf_param.len = ngx_strlen(ngx_conf_params);
900 cycle->conf_param.data = ngx_conf_params;
903 if (ngx_test_config) {
904 cycle->log->log_level = NGX_LOG_INFO;
907 return NGX_OK;
911 static void *
912 ngx_core_module_create_conf(ngx_cycle_t *cycle)
914 ngx_core_conf_t *ccf;
916 ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t));
917 if (ccf == NULL) {
918 return NULL;
922 * set by ngx_pcalloc()
924 * ccf->pid = NULL;
925 * ccf->oldpid = NULL;
926 * ccf->priority = 0;
927 * ccf->cpu_affinity_n = 0;
928 * ccf->cpu_affinity = NULL;
931 ccf->daemon = NGX_CONF_UNSET;
932 ccf->master = NGX_CONF_UNSET;
933 ccf->timer_resolution = NGX_CONF_UNSET_MSEC;
935 ccf->worker_processes = NGX_CONF_UNSET;
936 ccf->debug_points = NGX_CONF_UNSET;
938 ccf->rlimit_nofile = NGX_CONF_UNSET;
939 ccf->rlimit_core = NGX_CONF_UNSET_SIZE;
940 ccf->rlimit_sigpending = NGX_CONF_UNSET;
942 ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;
943 ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT;
945 #if (NGX_THREADS)
946 ccf->worker_threads = NGX_CONF_UNSET;
947 ccf->thread_stack_size = NGX_CONF_UNSET_SIZE;
948 #endif
950 if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))
951 != NGX_OK)
953 return NULL;
956 return ccf;
960 static char *
961 ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
963 ngx_core_conf_t *ccf = conf;
965 ngx_conf_init_value(ccf->daemon, 1);
966 ngx_conf_init_value(ccf->master, 1);
967 ngx_conf_init_msec_value(ccf->timer_resolution, 0);
969 ngx_conf_init_value(ccf->worker_processes, 1);
970 ngx_conf_init_value(ccf->debug_points, 0);
972 #if (NGX_HAVE_SCHED_SETAFFINITY)
974 if (ccf->cpu_affinity_n
975 && ccf->cpu_affinity_n != 1
976 && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)
978 ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
979 "number of the \"worker_processes\" is not equal to "
980 "the number of the \"worker_cpu_affinity\" mask, "
981 "using last mask for remaining worker processes");
984 #endif
986 #if (NGX_THREADS)
988 ngx_conf_init_value(ccf->worker_threads, 0);
989 ngx_threads_n = ccf->worker_threads;
990 ngx_conf_init_size_value(ccf->thread_stack_size, 2 * 1024 * 1024);
992 #endif
995 if (ccf->pid.len == 0) {
996 ccf->pid.len = sizeof(NGX_PID_PATH) - 1;
997 ccf->pid.data = (u_char *) NGX_PID_PATH;
1000 if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
1001 return NGX_CONF_ERROR;
1004 ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);
1006 ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
1007 if (ccf->oldpid.data == NULL) {
1008 return NGX_CONF_ERROR;
1011 ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len),
1012 NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT));
1015 #if !(NGX_WIN32)
1017 if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) {
1018 struct group *grp;
1019 struct passwd *pwd;
1021 ngx_set_errno(0);
1022 pwd = getpwnam(NGX_USER);
1023 if (pwd == NULL) {
1024 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1025 "getpwnam(\"" NGX_USER "\") failed");
1026 return NGX_CONF_ERROR;
1029 ccf->username = NGX_USER;
1030 ccf->user = pwd->pw_uid;
1032 ngx_set_errno(0);
1033 grp = getgrnam(NGX_GROUP);
1034 if (grp == NULL) {
1035 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1036 "getgrnam(\"" NGX_GROUP "\") failed");
1037 return NGX_CONF_ERROR;
1040 ccf->group = grp->gr_gid;
1044 if (ccf->lock_file.len == 0) {
1045 ccf->lock_file.len = sizeof(NGX_LOCK_PATH) - 1;
1046 ccf->lock_file.data = (u_char *) NGX_LOCK_PATH;
1049 if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) {
1050 return NGX_CONF_ERROR;
1054 ngx_str_t lock_file;
1056 lock_file = cycle->old_cycle->lock_file;
1058 if (lock_file.len) {
1059 lock_file.len--;
1061 if (ccf->lock_file.len != lock_file.len
1062 || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len)
1063 != 0)
1065 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
1066 "\"lock_file\" could not be changed, ignored");
1069 cycle->lock_file.len = lock_file.len + 1;
1070 lock_file.len += sizeof(".accept");
1072 cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file);
1073 if (cycle->lock_file.data == NULL) {
1074 return NGX_CONF_ERROR;
1077 } else {
1078 cycle->lock_file.len = ccf->lock_file.len + 1;
1079 cycle->lock_file.data = ngx_pnalloc(cycle->pool,
1080 ccf->lock_file.len + sizeof(".accept"));
1081 if (cycle->lock_file.data == NULL) {
1082 return NGX_CONF_ERROR;
1085 ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data,
1086 ccf->lock_file.len),
1087 ".accept", sizeof(".accept"));
1091 #endif
1093 return NGX_CONF_OK;
1097 static char *
1098 ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1100 #if (NGX_WIN32)
1102 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1103 "\"user\" is not supported, ignored");
1105 return NGX_CONF_OK;
1107 #else
1109 ngx_core_conf_t *ccf = conf;
1111 char *group;
1112 struct passwd *pwd;
1113 struct group *grp;
1114 ngx_str_t *value;
1116 if (ccf->user != (uid_t) NGX_CONF_UNSET_UINT) {
1117 return "is duplicate";
1120 if (geteuid() != 0) {
1121 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1122 "the \"user\" directive makes sense only "
1123 "if the master process runs "
1124 "with super-user privileges, ignored");
1125 return NGX_CONF_OK;
1128 value = (ngx_str_t *) cf->args->elts;
1130 ccf->username = (char *) value[1].data;
1132 ngx_set_errno(0);
1133 pwd = getpwnam((const char *) value[1].data);
1134 if (pwd == NULL) {
1135 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1136 "getpwnam(\"%s\") failed", value[1].data);
1137 return NGX_CONF_ERROR;
1140 ccf->user = pwd->pw_uid;
1142 group = (char *) ((cf->args->nelts == 2) ? value[1].data : value[2].data);
1144 ngx_set_errno(0);
1145 grp = getgrnam(group);
1146 if (grp == NULL) {
1147 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1148 "getgrnam(\"%s\") failed", group);
1149 return NGX_CONF_ERROR;
1152 ccf->group = grp->gr_gid;
1154 return NGX_CONF_OK;
1156 #endif
1160 static char *
1161 ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1163 ngx_core_conf_t *ccf = conf;
1165 ngx_str_t *value, *var;
1166 ngx_uint_t i;
1168 var = ngx_array_push(&ccf->env);
1169 if (var == NULL) {
1170 return NGX_CONF_ERROR;
1173 value = cf->args->elts;
1174 *var = value[1];
1176 for (i = 0; i < value[1].len; i++) {
1178 if (value[1].data[i] == '=') {
1180 var->len = i;
1182 return NGX_CONF_OK;
1186 return NGX_CONF_OK;
1190 static char *
1191 ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1193 ngx_core_conf_t *ccf = conf;
1195 ngx_str_t *value;
1196 ngx_uint_t n, minus;
1198 if (ccf->priority != 0) {
1199 return "is duplicate";
1202 value = cf->args->elts;
1204 if (value[1].data[0] == '-') {
1205 n = 1;
1206 minus = 1;
1208 } else if (value[1].data[0] == '+') {
1209 n = 1;
1210 minus = 0;
1212 } else {
1213 n = 0;
1214 minus = 0;
1217 ccf->priority = ngx_atoi(&value[1].data[n], value[1].len - n);
1218 if (ccf->priority == NGX_ERROR) {
1219 return "invalid number";
1222 if (minus) {
1223 ccf->priority = -ccf->priority;
1226 return NGX_CONF_OK;
1230 static char *
1231 ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1233 #if (NGX_HAVE_SCHED_SETAFFINITY)
1234 ngx_core_conf_t *ccf = conf;
1236 u_char ch;
1237 u_long *mask;
1238 ngx_str_t *value;
1239 ngx_uint_t i, n;
1241 if (ccf->cpu_affinity) {
1242 return "is duplicate";
1245 mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(long));
1246 if (mask == NULL) {
1247 return NGX_CONF_ERROR;
1250 ccf->cpu_affinity_n = cf->args->nelts - 1;
1251 ccf->cpu_affinity = mask;
1253 value = cf->args->elts;
1255 for (n = 1; n < cf->args->nelts; n++) {
1257 if (value[n].len > 32) {
1258 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1259 "\"worker_cpu_affinity\" supports up to 32 CPU only");
1260 return NGX_CONF_ERROR;
1263 mask[n - 1] = 0;
1265 for (i = 0; i < value[n].len; i++) {
1267 ch = value[n].data[i];
1269 if (ch == ' ') {
1270 continue;
1273 mask[n - 1] <<= 1;
1275 if (ch == '0') {
1276 continue;
1279 if (ch == '1') {
1280 mask[n - 1] |= 1;
1281 continue;
1284 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1285 "invalid character \"%c\" in \"worker_cpu_affinity\"",
1286 ch);
1287 return NGX_CONF_ERROR;
1291 #else
1293 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1294 "\"worker_cpu_affinity\" is not supported "
1295 "on this platform, ignored");
1296 #endif
1298 return NGX_CONF_OK;
1302 u_long
1303 ngx_get_cpu_affinity(ngx_uint_t n)
1305 ngx_core_conf_t *ccf;
1307 ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
1308 ngx_core_module);
1310 if (ccf->cpu_affinity == NULL) {
1311 return 0;
1314 if (ccf->cpu_affinity_n > n) {
1315 return ccf->cpu_affinity[n];
1318 return ccf->cpu_affinity[ccf->cpu_affinity_n - 1];