Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / core / nginx.c
blob94df9bf74d01bfd9b45b013983bcf005525e8c57
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <nginx.h>
13 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
14 static ngx_int_t ngx_get_options(int argc, char *const *argv);
15 static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
16 static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
17 static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
18 static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
19 static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
20 static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
21 static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
22 static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd,
23 void *conf);
24 static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd,
25 void *conf);
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 }
35 static ngx_command_t ngx_core_commands[] = {
37 { ngx_string("daemon"),
38 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
39 ngx_conf_set_flag_slot,
41 offsetof(ngx_core_conf_t, daemon),
42 NULL },
44 { ngx_string("master_process"),
45 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
46 ngx_conf_set_flag_slot,
48 offsetof(ngx_core_conf_t, master),
49 NULL },
51 { ngx_string("timer_resolution"),
52 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
53 ngx_conf_set_msec_slot,
55 offsetof(ngx_core_conf_t, timer_resolution),
56 NULL },
58 { ngx_string("pid"),
59 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
60 ngx_conf_set_str_slot,
62 offsetof(ngx_core_conf_t, pid),
63 NULL },
65 { ngx_string("lock_file"),
66 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
67 ngx_conf_set_str_slot,
69 offsetof(ngx_core_conf_t, lock_file),
70 NULL },
72 { ngx_string("worker_processes"),
73 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
74 ngx_set_worker_processes,
77 NULL },
79 { ngx_string("debug_points"),
80 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
81 ngx_conf_set_enum_slot,
83 offsetof(ngx_core_conf_t, debug_points),
84 &ngx_debug_points },
86 { ngx_string("user"),
87 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
88 ngx_set_user,
91 NULL },
93 { ngx_string("worker_priority"),
94 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
95 ngx_set_priority,
98 NULL },
100 { ngx_string("worker_cpu_affinity"),
101 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
102 ngx_set_cpu_affinity,
105 NULL },
107 { ngx_string("worker_rlimit_nofile"),
108 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
109 ngx_conf_set_num_slot,
111 offsetof(ngx_core_conf_t, rlimit_nofile),
112 NULL },
114 { ngx_string("worker_rlimit_core"),
115 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
116 ngx_conf_set_off_slot,
118 offsetof(ngx_core_conf_t, rlimit_core),
119 NULL },
121 { ngx_string("worker_rlimit_sigpending"),
122 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
123 ngx_conf_set_num_slot,
125 offsetof(ngx_core_conf_t, rlimit_sigpending),
126 NULL },
128 { ngx_string("working_directory"),
129 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
130 ngx_conf_set_str_slot,
132 offsetof(ngx_core_conf_t, working_directory),
133 NULL },
135 { ngx_string("env"),
136 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
137 ngx_set_env,
140 NULL },
142 #if (NGX_THREADS)
144 { ngx_string("worker_threads"),
145 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
146 ngx_conf_set_num_slot,
148 offsetof(ngx_core_conf_t, worker_threads),
149 NULL },
151 { ngx_string("thread_stack_size"),
152 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
153 ngx_conf_set_size_slot,
155 offsetof(ngx_core_conf_t, thread_stack_size),
156 NULL },
158 #endif
160 ngx_null_command
164 static ngx_core_module_t ngx_core_module_ctx = {
165 ngx_string("core"),
166 ngx_core_module_create_conf,
167 ngx_core_module_init_conf
171 ngx_module_t ngx_core_module = {
172 NGX_MODULE_V1,
173 &ngx_core_module_ctx, /* module context */
174 ngx_core_commands, /* module directives */
175 NGX_CORE_MODULE, /* module type */
176 NULL, /* init master */
177 NULL, /* init module */
178 NULL, /* init process */
179 NULL, /* init thread */
180 NULL, /* exit thread */
181 NULL, /* exit process */
182 NULL, /* exit master */
183 NGX_MODULE_V1_PADDING
187 ngx_uint_t ngx_max_module;
189 static ngx_uint_t ngx_show_help;
190 static ngx_uint_t ngx_show_version;
191 static ngx_uint_t ngx_show_configure;
192 static u_char *ngx_prefix;
193 static u_char *ngx_conf_file;
194 static u_char *ngx_conf_params;
195 static char *ngx_signal;
198 static char **ngx_os_environ;
201 int ngx_cdecl
202 main(int argc, char *const *argv)
204 ngx_int_t i;
205 ngx_log_t *log;
206 ngx_cycle_t *cycle, init_cycle;
207 ngx_core_conf_t *ccf;
209 ngx_debug_init();
211 if (ngx_strerror_init() != NGX_OK) {
212 return 1;
215 if (ngx_get_options(argc, argv) != NGX_OK) {
216 return 1;
219 if (ngx_show_version) {
220 ngx_write_stderr("nginx version: " NGINX_VER NGX_LINEFEED);
222 if (ngx_show_help) {
223 ngx_write_stderr(
224 "Usage: nginx [-?hvVtq] [-s signal] [-c filename] "
225 "[-p prefix] [-g directives]" NGX_LINEFEED
226 NGX_LINEFEED
227 "Options:" NGX_LINEFEED
228 " -?,-h : this help" NGX_LINEFEED
229 " -v : show version and exit" NGX_LINEFEED
230 " -V : show version and configure options then exit"
231 NGX_LINEFEED
232 " -t : test configuration and exit" NGX_LINEFEED
233 " -q : suppress non-error messages "
234 "during configuration testing" NGX_LINEFEED
235 " -s signal : send signal to a master process: "
236 "stop, quit, reopen, reload" NGX_LINEFEED
237 #ifdef NGX_PREFIX
238 " -p prefix : set prefix path (default: "
239 NGX_PREFIX ")" NGX_LINEFEED
240 #else
241 " -p prefix : set prefix path (default: NONE)" NGX_LINEFEED
242 #endif
243 " -c filename : set configuration file (default: "
244 NGX_CONF_PATH ")" NGX_LINEFEED
245 " -g directives : set global directives out of configuration "
246 "file" NGX_LINEFEED NGX_LINEFEED
250 if (ngx_show_configure) {
251 ngx_write_stderr(
252 #ifdef NGX_COMPILER
253 "built by " NGX_COMPILER NGX_LINEFEED
254 #endif
255 #if (NGX_SSL)
256 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
257 "TLS SNI support enabled" NGX_LINEFEED
258 #else
259 "TLS SNI support disabled" NGX_LINEFEED
260 #endif
261 #endif
262 "configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
265 if (!ngx_test_config) {
266 return 0;
270 /* TODO */ ngx_max_sockets = -1;
272 ngx_time_init();
274 #if (NGX_PCRE)
275 ngx_regex_init();
276 #endif
278 ngx_pid = ngx_getpid();
280 log = ngx_log_init(ngx_prefix);
281 if (log == NULL) {
282 return 1;
285 /* STUB */
286 #if (NGX_OPENSSL)
287 ngx_ssl_init(log);
288 #endif
291 * init_cycle->log is required for signal handlers and
292 * ngx_process_options()
295 ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
296 init_cycle.log = log;
297 ngx_cycle = &init_cycle;
299 init_cycle.pool = ngx_create_pool(1024, log);
300 if (init_cycle.pool == NULL) {
301 return 1;
304 if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
305 return 1;
308 if (ngx_process_options(&init_cycle) != NGX_OK) {
309 return 1;
312 if (ngx_os_init(log) != NGX_OK) {
313 return 1;
317 * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
320 if (ngx_crc32_table_init() != NGX_OK) {
321 return 1;
324 if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
325 return 1;
328 ngx_max_module = 0;
329 for (i = 0; ngx_modules[i]; i++) {
330 ngx_modules[i]->index = ngx_max_module++;
333 cycle = ngx_init_cycle(&init_cycle);
334 if (cycle == NULL) {
335 if (ngx_test_config) {
336 ngx_log_stderr(0, "configuration file %s test failed",
337 init_cycle.conf_file.data);
340 return 1;
343 if (ngx_test_config) {
344 if (!ngx_quiet_mode) {
345 ngx_log_stderr(0, "configuration file %s test is successful",
346 cycle->conf_file.data);
349 return 0;
352 if (ngx_signal) {
353 return ngx_signal_process(cycle, ngx_signal);
356 ngx_os_status(cycle->log);
358 ngx_cycle = cycle;
360 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
362 if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
363 ngx_process = NGX_PROCESS_MASTER;
366 #if !(NGX_WIN32)
368 if (ngx_init_signals(cycle->log) != NGX_OK) {
369 return 1;
372 if (!ngx_inherited && ccf->daemon) {
373 if (ngx_daemon(cycle->log) != NGX_OK) {
374 return 1;
377 ngx_daemonized = 1;
380 if (ngx_inherited) {
381 ngx_daemonized = 1;
384 #endif
386 if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
387 return 1;
390 if (cycle->log->file->fd != ngx_stderr) {
392 if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
393 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
394 ngx_set_stderr_n " failed");
395 return 1;
399 if (log->file->fd != ngx_stderr) {
400 if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
401 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
402 ngx_close_file_n " built-in log failed");
406 ngx_use_stderr = 0;
408 if (ngx_process == NGX_PROCESS_SINGLE) {
409 ngx_single_process_cycle(cycle);
411 } else {
412 ngx_master_process_cycle(cycle);
415 return 0;
419 static ngx_int_t
420 ngx_add_inherited_sockets(ngx_cycle_t *cycle)
422 u_char *p, *v, *inherited;
423 ngx_int_t s;
424 ngx_listening_t *ls;
426 inherited = (u_char *) getenv(NGINX_VAR);
428 if (inherited == NULL) {
429 return NGX_OK;
432 ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
433 "using inherited sockets from \"%s\"", inherited);
435 if (ngx_array_init(&cycle->listening, cycle->pool, 10,
436 sizeof(ngx_listening_t))
437 != NGX_OK)
439 return NGX_ERROR;
442 for (p = inherited, v = p; *p; p++) {
443 if (*p == ':' || *p == ';') {
444 s = ngx_atoi(v, p - v);
445 if (s == NGX_ERROR) {
446 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
447 "invalid socket number \"%s\" in " NGINX_VAR
448 " environment variable, ignoring the rest"
449 " of the variable", v);
450 break;
453 v = p + 1;
455 ls = ngx_array_push(&cycle->listening);
456 if (ls == NULL) {
457 return NGX_ERROR;
460 ngx_memzero(ls, sizeof(ngx_listening_t));
462 ls->fd = (ngx_socket_t) s;
466 ngx_inherited = 1;
468 return ngx_set_inherited_sockets(cycle);
472 char **
473 ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
475 char **p, **env;
476 ngx_str_t *var;
477 ngx_uint_t i, n;
478 ngx_core_conf_t *ccf;
480 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
482 if (last == NULL && ccf->environment) {
483 return ccf->environment;
486 var = ccf->env.elts;
488 for (i = 0; i < ccf->env.nelts; i++) {
489 if (ngx_strcmp(var[i].data, "TZ") == 0
490 || ngx_strncmp(var[i].data, "TZ=", 3) == 0)
492 goto tz_found;
496 var = ngx_array_push(&ccf->env);
497 if (var == NULL) {
498 return NULL;
501 var->len = 2;
502 var->data = (u_char *) "TZ";
504 var = ccf->env.elts;
506 tz_found:
508 n = 0;
510 for (i = 0; i < ccf->env.nelts; i++) {
512 if (var[i].data[var[i].len] == '=') {
513 n++;
514 continue;
517 for (p = ngx_os_environ; *p; p++) {
519 if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
520 && (*p)[var[i].len] == '=')
522 n++;
523 break;
528 if (last) {
529 env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log);
530 *last = n;
532 } else {
533 env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *));
536 if (env == NULL) {
537 return NULL;
540 n = 0;
542 for (i = 0; i < ccf->env.nelts; i++) {
544 if (var[i].data[var[i].len] == '=') {
545 env[n++] = (char *) var[i].data;
546 continue;
549 for (p = ngx_os_environ; *p; p++) {
551 if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
552 && (*p)[var[i].len] == '=')
554 env[n++] = *p;
555 break;
560 env[n] = NULL;
562 if (last == NULL) {
563 ccf->environment = env;
564 environ = env;
567 return env;
571 ngx_pid_t
572 ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
574 char **env, *var;
575 u_char *p;
576 ngx_uint_t i, n;
577 ngx_pid_t pid;
578 ngx_exec_ctx_t ctx;
579 ngx_core_conf_t *ccf;
580 ngx_listening_t *ls;
582 ngx_memzero(&ctx, sizeof(ngx_exec_ctx_t));
584 ctx.path = argv[0];
585 ctx.name = "new binary process";
586 ctx.argv = argv;
588 n = 2;
589 env = ngx_set_environment(cycle, &n);
590 if (env == NULL) {
591 return NGX_INVALID_PID;
594 var = ngx_alloc(sizeof(NGINX_VAR)
595 + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
596 cycle->log);
597 if (var == NULL) {
598 ngx_free(env);
599 return NGX_INVALID_PID;
602 p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR));
604 ls = cycle->listening.elts;
605 for (i = 0; i < cycle->listening.nelts; i++) {
606 p = ngx_sprintf(p, "%ud;", ls[i].fd);
609 *p = '\0';
611 env[n++] = var;
613 #if (NGX_SETPROCTITLE_USES_ENV)
615 /* allocate the spare 300 bytes for the new binary process title */
617 env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
618 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
619 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
620 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
621 "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
623 #endif
625 env[n] = NULL;
627 #if (NGX_DEBUG)
629 char **e;
630 for (e = env; *e; e++) {
631 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e);
634 #endif
636 ctx.envp = (char *const *) env;
638 ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
640 if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == NGX_FILE_ERROR) {
641 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
642 ngx_rename_file_n " %s to %s failed "
643 "before executing new binary process \"%s\"",
644 ccf->pid.data, ccf->oldpid.data, argv[0]);
646 ngx_free(env);
647 ngx_free(var);
649 return NGX_INVALID_PID;
652 pid = ngx_execute(cycle, &ctx);
654 if (pid == NGX_INVALID_PID) {
655 if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data)
656 == NGX_FILE_ERROR)
658 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
659 ngx_rename_file_n " %s back to %s failed after "
660 "an attempt to execute new binary process \"%s\"",
661 ccf->oldpid.data, ccf->pid.data, argv[0]);
665 ngx_free(env);
666 ngx_free(var);
668 return pid;
672 static ngx_int_t
673 ngx_get_options(int argc, char *const *argv)
675 u_char *p;
676 ngx_int_t i;
678 for (i = 1; i < argc; i++) {
680 p = (u_char *) argv[i];
682 if (*p++ != '-') {
683 ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
684 return NGX_ERROR;
687 while (*p) {
689 switch (*p++) {
691 case '?':
692 case 'h':
693 ngx_show_version = 1;
694 ngx_show_help = 1;
695 break;
697 case 'v':
698 ngx_show_version = 1;
699 break;
701 case 'V':
702 ngx_show_version = 1;
703 ngx_show_configure = 1;
704 break;
706 case 't':
707 ngx_test_config = 1;
708 break;
710 case 'q':
711 ngx_quiet_mode = 1;
712 break;
714 case 'p':
715 if (*p) {
716 ngx_prefix = p;
717 goto next;
720 if (argv[++i]) {
721 ngx_prefix = (u_char *) argv[i];
722 goto next;
725 ngx_log_stderr(0, "option \"-p\" requires directory name");
726 return NGX_ERROR;
728 case 'c':
729 if (*p) {
730 ngx_conf_file = p;
731 goto next;
734 if (argv[++i]) {
735 ngx_conf_file = (u_char *) argv[i];
736 goto next;
739 ngx_log_stderr(0, "option \"-c\" requires file name");
740 return NGX_ERROR;
742 case 'g':
743 if (*p) {
744 ngx_conf_params = p;
745 goto next;
748 if (argv[++i]) {
749 ngx_conf_params = (u_char *) argv[i];
750 goto next;
753 ngx_log_stderr(0, "option \"-g\" requires parameter");
754 return NGX_ERROR;
756 case 's':
757 if (*p) {
758 ngx_signal = (char *) p;
760 } else if (argv[++i]) {
761 ngx_signal = argv[i];
763 } else {
764 ngx_log_stderr(0, "option \"-s\" requires parameter");
765 return NGX_ERROR;
768 if (ngx_strcmp(ngx_signal, "stop") == 0
769 || ngx_strcmp(ngx_signal, "quit") == 0
770 || ngx_strcmp(ngx_signal, "reopen") == 0
771 || ngx_strcmp(ngx_signal, "reload") == 0)
773 ngx_process = NGX_PROCESS_SIGNALLER;
774 goto next;
777 ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
778 return NGX_ERROR;
780 default:
781 ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
782 return NGX_ERROR;
786 next:
788 continue;
791 return NGX_OK;
795 static ngx_int_t
796 ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
798 #if (NGX_FREEBSD)
800 ngx_os_argv = (char **) argv;
801 ngx_argc = argc;
802 ngx_argv = (char **) argv;
804 #else
805 size_t len;
806 ngx_int_t i;
808 ngx_os_argv = (char **) argv;
809 ngx_argc = argc;
811 ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
812 if (ngx_argv == NULL) {
813 return NGX_ERROR;
816 for (i = 0; i < argc; i++) {
817 len = ngx_strlen(argv[i]) + 1;
819 ngx_argv[i] = ngx_alloc(len, cycle->log);
820 if (ngx_argv[i] == NULL) {
821 return NGX_ERROR;
824 (void) ngx_cpystrn((u_char *) ngx_argv[i], (u_char *) argv[i], len);
827 ngx_argv[i] = NULL;
829 #endif
831 ngx_os_environ = environ;
833 return NGX_OK;
837 static ngx_int_t
838 ngx_process_options(ngx_cycle_t *cycle)
840 u_char *p;
841 size_t len;
843 if (ngx_prefix) {
844 len = ngx_strlen(ngx_prefix);
845 p = ngx_prefix;
847 if (len && !ngx_path_separator(p[len - 1])) {
848 p = ngx_pnalloc(cycle->pool, len + 1);
849 if (p == NULL) {
850 return NGX_ERROR;
853 ngx_memcpy(p, ngx_prefix, len);
854 p[len++] = '/';
857 cycle->conf_prefix.len = len;
858 cycle->conf_prefix.data = p;
859 cycle->prefix.len = len;
860 cycle->prefix.data = p;
862 } else {
864 #ifndef NGX_PREFIX
866 p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
867 if (p == NULL) {
868 return NGX_ERROR;
871 if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {
872 ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
873 return NGX_ERROR;
876 len = ngx_strlen(p);
878 p[len++] = '/';
880 cycle->conf_prefix.len = len;
881 cycle->conf_prefix.data = p;
882 cycle->prefix.len = len;
883 cycle->prefix.data = p;
885 #else
887 #ifdef NGX_CONF_PREFIX
888 ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
889 #else
890 ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
891 #endif
892 ngx_str_set(&cycle->prefix, NGX_PREFIX);
894 #endif
897 if (ngx_conf_file) {
898 cycle->conf_file.len = ngx_strlen(ngx_conf_file);
899 cycle->conf_file.data = ngx_conf_file;
901 } else {
902 ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
905 if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
906 return NGX_ERROR;
909 for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
910 p > cycle->conf_file.data;
911 p--)
913 if (ngx_path_separator(*p)) {
914 cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1;
915 cycle->conf_prefix.data = ngx_cycle->conf_file.data;
916 break;
920 if (ngx_conf_params) {
921 cycle->conf_param.len = ngx_strlen(ngx_conf_params);
922 cycle->conf_param.data = ngx_conf_params;
925 if (ngx_test_config) {
926 cycle->log->log_level = NGX_LOG_INFO;
929 return NGX_OK;
933 static void *
934 ngx_core_module_create_conf(ngx_cycle_t *cycle)
936 ngx_core_conf_t *ccf;
938 ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t));
939 if (ccf == NULL) {
940 return NULL;
944 * set by ngx_pcalloc()
946 * ccf->pid = NULL;
947 * ccf->oldpid = NULL;
948 * ccf->priority = 0;
949 * ccf->cpu_affinity_n = 0;
950 * ccf->cpu_affinity = NULL;
953 ccf->daemon = NGX_CONF_UNSET;
954 ccf->master = NGX_CONF_UNSET;
955 ccf->timer_resolution = NGX_CONF_UNSET_MSEC;
957 ccf->worker_processes = NGX_CONF_UNSET;
958 ccf->debug_points = NGX_CONF_UNSET;
960 ccf->rlimit_nofile = NGX_CONF_UNSET;
961 ccf->rlimit_core = NGX_CONF_UNSET;
962 ccf->rlimit_sigpending = NGX_CONF_UNSET;
964 ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;
965 ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT;
967 #if (NGX_THREADS)
968 ccf->worker_threads = NGX_CONF_UNSET;
969 ccf->thread_stack_size = NGX_CONF_UNSET_SIZE;
970 #endif
972 if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))
973 != NGX_OK)
975 return NULL;
978 return ccf;
982 static char *
983 ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
985 ngx_core_conf_t *ccf = conf;
987 ngx_conf_init_value(ccf->daemon, 1);
988 ngx_conf_init_value(ccf->master, 1);
989 ngx_conf_init_msec_value(ccf->timer_resolution, 0);
991 ngx_conf_init_value(ccf->worker_processes, 1);
992 ngx_conf_init_value(ccf->debug_points, 0);
994 #if (NGX_HAVE_CPU_AFFINITY)
996 if (ccf->cpu_affinity_n
997 && ccf->cpu_affinity_n != 1
998 && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)
1000 ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
1001 "the number of \"worker_processes\" is not equal to "
1002 "the number of \"worker_cpu_affinity\" masks, "
1003 "using last mask for remaining worker processes");
1006 #endif
1008 #if (NGX_THREADS)
1010 ngx_conf_init_value(ccf->worker_threads, 0);
1011 ngx_threads_n = ccf->worker_threads;
1012 ngx_conf_init_size_value(ccf->thread_stack_size, 2 * 1024 * 1024);
1014 #endif
1017 if (ccf->pid.len == 0) {
1018 ngx_str_set(&ccf->pid, NGX_PID_PATH);
1021 if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
1022 return NGX_CONF_ERROR;
1025 ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);
1027 ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
1028 if (ccf->oldpid.data == NULL) {
1029 return NGX_CONF_ERROR;
1032 ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len),
1033 NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT));
1036 #if !(NGX_WIN32)
1038 if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) {
1039 struct group *grp;
1040 struct passwd *pwd;
1042 ngx_set_errno(0);
1043 pwd = getpwnam(NGX_USER);
1044 if (pwd == NULL) {
1045 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1046 "getpwnam(\"" NGX_USER "\") failed");
1047 return NGX_CONF_ERROR;
1050 ccf->username = NGX_USER;
1051 ccf->user = pwd->pw_uid;
1053 ngx_set_errno(0);
1054 grp = getgrnam(NGX_GROUP);
1055 if (grp == NULL) {
1056 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1057 "getgrnam(\"" NGX_GROUP "\") failed");
1058 return NGX_CONF_ERROR;
1061 ccf->group = grp->gr_gid;
1065 if (ccf->lock_file.len == 0) {
1066 ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH);
1069 if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) {
1070 return NGX_CONF_ERROR;
1074 ngx_str_t lock_file;
1076 lock_file = cycle->old_cycle->lock_file;
1078 if (lock_file.len) {
1079 lock_file.len--;
1081 if (ccf->lock_file.len != lock_file.len
1082 || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len)
1083 != 0)
1085 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
1086 "\"lock_file\" could not be changed, ignored");
1089 cycle->lock_file.len = lock_file.len + 1;
1090 lock_file.len += sizeof(".accept");
1092 cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file);
1093 if (cycle->lock_file.data == NULL) {
1094 return NGX_CONF_ERROR;
1097 } else {
1098 cycle->lock_file.len = ccf->lock_file.len + 1;
1099 cycle->lock_file.data = ngx_pnalloc(cycle->pool,
1100 ccf->lock_file.len + sizeof(".accept"));
1101 if (cycle->lock_file.data == NULL) {
1102 return NGX_CONF_ERROR;
1105 ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data,
1106 ccf->lock_file.len),
1107 ".accept", sizeof(".accept"));
1111 #endif
1113 return NGX_CONF_OK;
1117 static char *
1118 ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1120 #if (NGX_WIN32)
1122 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1123 "\"user\" is not supported, ignored");
1125 return NGX_CONF_OK;
1127 #else
1129 ngx_core_conf_t *ccf = conf;
1131 char *group;
1132 struct passwd *pwd;
1133 struct group *grp;
1134 ngx_str_t *value;
1136 if (ccf->user != (uid_t) NGX_CONF_UNSET_UINT) {
1137 return "is duplicate";
1140 if (geteuid() != 0) {
1141 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1142 "the \"user\" directive makes sense only "
1143 "if the master process runs "
1144 "with super-user privileges, ignored");
1145 return NGX_CONF_OK;
1148 value = (ngx_str_t *) cf->args->elts;
1150 ccf->username = (char *) value[1].data;
1152 ngx_set_errno(0);
1153 pwd = getpwnam((const char *) value[1].data);
1154 if (pwd == NULL) {
1155 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1156 "getpwnam(\"%s\") failed", value[1].data);
1157 return NGX_CONF_ERROR;
1160 ccf->user = pwd->pw_uid;
1162 group = (char *) ((cf->args->nelts == 2) ? value[1].data : value[2].data);
1164 ngx_set_errno(0);
1165 grp = getgrnam(group);
1166 if (grp == NULL) {
1167 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1168 "getgrnam(\"%s\") failed", group);
1169 return NGX_CONF_ERROR;
1172 ccf->group = grp->gr_gid;
1174 return NGX_CONF_OK;
1176 #endif
1180 static char *
1181 ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1183 ngx_core_conf_t *ccf = conf;
1185 ngx_str_t *value, *var;
1186 ngx_uint_t i;
1188 var = ngx_array_push(&ccf->env);
1189 if (var == NULL) {
1190 return NGX_CONF_ERROR;
1193 value = cf->args->elts;
1194 *var = value[1];
1196 for (i = 0; i < value[1].len; i++) {
1198 if (value[1].data[i] == '=') {
1200 var->len = i;
1202 return NGX_CONF_OK;
1206 return NGX_CONF_OK;
1210 static char *
1211 ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1213 ngx_core_conf_t *ccf = conf;
1215 ngx_str_t *value;
1216 ngx_uint_t n, minus;
1218 if (ccf->priority != 0) {
1219 return "is duplicate";
1222 value = cf->args->elts;
1224 if (value[1].data[0] == '-') {
1225 n = 1;
1226 minus = 1;
1228 } else if (value[1].data[0] == '+') {
1229 n = 1;
1230 minus = 0;
1232 } else {
1233 n = 0;
1234 minus = 0;
1237 ccf->priority = ngx_atoi(&value[1].data[n], value[1].len - n);
1238 if (ccf->priority == NGX_ERROR) {
1239 return "invalid number";
1242 if (minus) {
1243 ccf->priority = -ccf->priority;
1246 return NGX_CONF_OK;
1250 static char *
1251 ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1253 #if (NGX_HAVE_CPU_AFFINITY)
1254 ngx_core_conf_t *ccf = conf;
1256 u_char ch;
1257 uint64_t *mask;
1258 ngx_str_t *value;
1259 ngx_uint_t i, n;
1261 if (ccf->cpu_affinity) {
1262 return "is duplicate";
1265 mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(uint64_t));
1266 if (mask == NULL) {
1267 return NGX_CONF_ERROR;
1270 ccf->cpu_affinity_n = cf->args->nelts - 1;
1271 ccf->cpu_affinity = mask;
1273 value = cf->args->elts;
1275 for (n = 1; n < cf->args->nelts; n++) {
1277 if (value[n].len > 64) {
1278 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1279 "\"worker_cpu_affinity\" supports up to 64 CPUs only");
1280 return NGX_CONF_ERROR;
1283 mask[n - 1] = 0;
1285 for (i = 0; i < value[n].len; i++) {
1287 ch = value[n].data[i];
1289 if (ch == ' ') {
1290 continue;
1293 mask[n - 1] <<= 1;
1295 if (ch == '0') {
1296 continue;
1299 if (ch == '1') {
1300 mask[n - 1] |= 1;
1301 continue;
1304 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1305 "invalid character \"%c\" in \"worker_cpu_affinity\"",
1306 ch);
1307 return NGX_CONF_ERROR;
1311 #else
1313 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1314 "\"worker_cpu_affinity\" is not supported "
1315 "on this platform, ignored");
1316 #endif
1318 return NGX_CONF_OK;
1322 uint64_t
1323 ngx_get_cpu_affinity(ngx_uint_t n)
1325 ngx_core_conf_t *ccf;
1327 ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
1328 ngx_core_module);
1330 if (ccf->cpu_affinity == NULL) {
1331 return 0;
1334 if (ccf->cpu_affinity_n > n) {
1335 return ccf->cpu_affinity[n];
1338 return ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
1342 static char *
1343 ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1345 ngx_str_t *value;
1346 ngx_core_conf_t *ccf;
1348 ccf = (ngx_core_conf_t *) conf;
1350 if (ccf->worker_processes != NGX_CONF_UNSET) {
1351 return "is duplicate";
1354 value = (ngx_str_t *) cf->args->elts;
1356 if (ngx_strcmp(value[1].data, "auto") == 0) {
1357 ccf->worker_processes = ngx_ncpu;
1358 return NGX_CONF_OK;
1361 ccf->worker_processes = ngx_atoi(value[1].data, value[1].len);
1363 if (ccf->worker_processes == NGX_ERROR) {
1364 return "invalid value";
1367 return NGX_CONF_OK;