fix extension
[nginx.git] / nginx / src / core / nginx.c
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <nginx.h>
10
11
12 static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
13 static ngx_int_t ngx_getopt(ngx_cycle_t *cycle, int argc, char *const *argv);
14 static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
15 static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
16 static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
17 static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
18 static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
19 static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
20 static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd,
21     void *conf);
22
23
24 static ngx_conf_enum_t  ngx_debug_points[] = {
25     { ngx_string("stop"), NGX_DEBUG_POINTS_STOP },
26     { ngx_string("abort"), NGX_DEBUG_POINTS_ABORT },
27     { ngx_null_string, 0 }
28 };
29
30
31 static ngx_command_t  ngx_core_commands[] = {
32
33     { ngx_string("daemon"),
34       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
35       ngx_conf_set_flag_slot,
36       0,
37       offsetof(ngx_core_conf_t, daemon),
38       NULL },
39
40     { ngx_string("master_process"),
41       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
42       ngx_conf_set_flag_slot,
43       0,
44       offsetof(ngx_core_conf_t, master),
45       NULL },
46
47     { ngx_string("timer_resolution"),
48       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
49       ngx_conf_set_msec_slot,
50       0,
51       offsetof(ngx_core_conf_t, timer_resolution),
52       NULL },
53
54     { ngx_string("pid"),
55       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
56       ngx_conf_set_str_slot,
57       0,
58       offsetof(ngx_core_conf_t, pid),
59       NULL },
60
61     { ngx_string("lock_file"),
62       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
63       ngx_conf_set_str_slot,
64       0,
65       offsetof(ngx_core_conf_t, lock_file),
66       NULL },
67
68     { ngx_string("worker_processes"),
69       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
70       ngx_conf_set_num_slot,
71       0,
72       offsetof(ngx_core_conf_t, worker_processes),
73       NULL },
74
75     { ngx_string("debug_points"),
76       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
77       ngx_conf_set_enum_slot,
78       0,
79       offsetof(ngx_core_conf_t, debug_points),
80       &ngx_debug_points },
81
82     { ngx_string("user"),
83       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
84       ngx_set_user,
85       0,
86       0,
87       NULL },
88
89     { ngx_string("worker_priority"),
90       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
91       ngx_set_priority,
92       0,
93       0,
94       NULL },
95
96     { ngx_string("worker_cpu_affinity"),
97       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
98       ngx_set_cpu_affinity,
99       0,
100       0,
101       NULL },
102
103     { ngx_string("worker_rlimit_nofile"),
104       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
105       ngx_conf_set_num_slot,
106       0,
107       offsetof(ngx_core_conf_t, rlimit_nofile),
108       NULL },
109
110     { ngx_string("worker_rlimit_core"),
111       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
112       ngx_conf_set_size_slot,
113       0,
114       offsetof(ngx_core_conf_t, rlimit_core),
115       NULL },
116
117     { ngx_string("worker_rlimit_sigpending"),
118       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
119       ngx_conf_set_num_slot,
120       0,
121       offsetof(ngx_core_conf_t, rlimit_sigpending),
122       NULL },
123
124     { ngx_string("working_directory"),
125       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
126       ngx_conf_set_str_slot,
127       0,
128       offsetof(ngx_core_conf_t, working_directory),
129       NULL },
130
131     { ngx_string("env"),
132       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
133       ngx_set_env,
134       0,
135       0,
136       NULL },
137
138 #if (NGX_THREADS)
139
140     { ngx_string("worker_threads"),
141       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
142       ngx_conf_set_num_slot,
143       0,
144       offsetof(ngx_core_conf_t, worker_threads),
145       NULL },
146
147     { ngx_string("thread_stack_size"),
148       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
149       ngx_conf_set_size_slot,
150       0,
151       offsetof(ngx_core_conf_t, thread_stack_size),
152       NULL },
153
154 #endif
155
156       ngx_null_command
157 };
158
159
160 static ngx_core_module_t  ngx_core_module_ctx = {
161     ngx_string("core"),
162     ngx_core_module_create_conf,
163     ngx_core_module_init_conf
164 };
165
166
167 ngx_module_t  ngx_core_module = {
168     NGX_MODULE_V1,
169     &ngx_core_module_ctx,                  /* module context */
170     ngx_core_commands,                     /* module directives */
171     NGX_CORE_MODULE,                       /* module type */
172     NULL,                                  /* init master */
173     NULL,                                  /* init module */
174     NULL,                                  /* init process */
175     NULL,                                  /* init thread */
176     NULL,                                  /* exit thread */
177     NULL,                                  /* exit process */
178     NULL,                                  /* exit master */
179     NGX_MODULE_V1_PADDING
180 };
181
182
183 ngx_uint_t  ngx_max_module;
184
185 static ngx_uint_t  ngx_show_version;
186 static ngx_uint_t  ngx_show_configure;
187
188 static char **ngx_os_environ;
189
190
191 int ngx_cdecl
192 main(int argc, char *const *argv)
193 {
194     char             *p;
195     ssize_t           n;
196     ngx_int_t         i;
197     ngx_log_t        *log;
198     ngx_cycle_t      *cycle, init_cycle;
199     ngx_core_conf_t  *ccf;
200
201 #if (NGX_FREEBSD)
202     ngx_debug_init();
203 #endif
204
205     /* TODO */ ngx_max_sockets = -1;
206
207     ngx_time_init();
208
209 #if (NGX_PCRE)
210     ngx_regex_init();
211 #endif
212
213     ngx_pid = ngx_getpid();
214
215     log = ngx_log_init();
216     if (log == NULL) {
217         return 1;
218     }
219
220     /* STUB */
221 #if (NGX_OPENSSL)
222     ngx_ssl_init(log);
223 #endif
224
225     /* init_cycle->log is required for signal handlers and ngx_getopt() */
226
227     ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
228     init_cycle.log = log;
229     ngx_cycle = &init_cycle;
230
231     init_cycle.pool = ngx_create_pool(1024, log);
232     if (init_cycle.pool == NULL) {
233         return 1;
234     }
235
236     if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
237         return 1;
238     }
239
240     if (ngx_getopt(&init_cycle, argc, ngx_argv) != NGX_OK) {
241         return 1;
242     }
243
244     if (ngx_show_version) {
245
246         p = "nginx version: " NGINX_VER CRLF;
247         n = sizeof("nginx version: " NGINX_VER CRLF) - 1;
248
249         if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
250             return 1;
251         }
252
253         if (ngx_show_configure) {
254 #ifdef NGX_COMPILER
255             p = "built by " NGX_COMPILER CRLF;
256             n = sizeof("built by " NGX_COMPILER CRLF) - 1;
257
258             if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
259                 return 1;
260             }
261 #endif
262
263             p = "configure arguments: " NGX_CONFIGURE CRLF;
264             n = sizeof("configure arguments :" NGX_CONFIGURE CRLF) - 1;
265
266             if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
267                 return 1;
268             }
269         }
270
271         if (!ngx_test_config) {
272             return 0;
273         }
274     }
275
276     if (ngx_test_config) {
277         log->log_level = NGX_LOG_INFO;
278     }
279
280     if (ngx_os_init(log) != NGX_OK) {
281         return 1;
282     }
283
284     /*
285      * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
286      */
287
288     if (ngx_crc32_table_init() != NGX_OK) {
289         return 1;
290     }
291
292     if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
293         return 1;
294     }
295
296     ngx_max_module = 0;
297     for (i = 0; ngx_modules[i]; i++) {
298         ngx_modules[i]->index = ngx_max_module++;
299     }
300
301     cycle = ngx_init_cycle(&init_cycle);
302     if (cycle == NULL) {
303         if (ngx_test_config) {
304             ngx_log_error(NGX_LOG_EMERG, log, 0,
305                           "the configuration file %s test failed",
306                           init_cycle.conf_file.data);
307         }
308
309         return 1;
310     }
311
312     if (ngx_test_config) {
313         ngx_log_error(NGX_LOG_INFO, log, 0,
314                       "the configuration file %s was tested successfully",
315                       cycle->conf_file.data);
316         return 0;
317     }
318
319     ngx_os_status(cycle->log);
320
321     ngx_cycle = cycle;
322
323     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
324
325     ngx_process = ccf->master ? NGX_PROCESS_MASTER : NGX_PROCESS_SINGLE;
326
327 #if (NGX_WIN32)
328
329 #if 0
330
331     TODO:
332
333     if (ccf->run_as_service) {
334         if (ngx_service(cycle->log) != NGX_OK) {
335             return 1;
336         }
337
338         return 0;
339     }
340 #endif
341
342 #else
343
344     if (ngx_init_signals(cycle->log) != NGX_OK) {
345         return 1;
346     }
347
348     if (!ngx_inherited && ccf->daemon) {
349         if (ngx_daemon(cycle->log) != NGX_OK) {
350             return 1;
351         }
352
353         ngx_daemonized = 1;
354     }
355
356     if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
357         return 1;
358     }
359
360 #endif
361
362     if (ngx_process == NGX_PROCESS_MASTER) {
363         ngx_master_process_cycle(cycle);
364
365     } else {
366         ngx_single_process_cycle(cycle);
367     }
368
369     return 0;
370 }
371
372
373 static ngx_int_t
374 ngx_add_inherited_sockets(ngx_cycle_t *cycle)
375 {
376     u_char           *p, *v, *inherited;
377     ngx_int_t         s;
378     ngx_listening_t  *ls;
379
380     inherited = (u_char *) getenv(NGINX_VAR);
381
382     if (inherited == NULL) {
383         return NGX_OK;
384     }
385
386     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
387                   "using inherited sockets from \"%s\"", inherited);
388
389     if (ngx_array_init(&cycle->listening, cycle->pool, 10,
390                        sizeof(ngx_listening_t))
391         == NGX_ERROR)
392     {
393         return NGX_ERROR;
394     }
395
396     for (p = inherited, v = p; *p; p++) {
397         if (*p == ':' || *p == ';') {
398             s = ngx_atoi(v, p - v);
399             if (s == NGX_ERROR) {
400                 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
401                               "invalid socket number \"%s\" in " NGINX_VAR
402                               " environment variable, ignoring the rest"
403                               " of the variable", v);
404                 break;
405             }
406
407             v = p + 1;
408
409             ls = ngx_array_push(&cycle->listening);
410             if (ls == NULL) {
411                 return NGX_ERROR;
412             }
413
414             ngx_memzero(ls, sizeof(ngx_listening_t));
415
416             ls->fd = (ngx_socket_t) s;
417         }
418     }
419
420     ngx_inherited = 1;
421
422     return ngx_set_inherited_sockets(cycle);
423 }
424
425
426 char **
427 ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
428 {
429     char             **p, **env;
430     ngx_str_t         *var;
431     ngx_uint_t         i, n;
432     ngx_core_conf_t   *ccf;
433
434     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
435
436     if (last == NULL && ccf->environment) {
437         return ccf->environment;
438     }
439
440     var = ccf->env.elts;
441
442     for (i = 0; i < ccf->env.nelts; i++) {
443         if (ngx_strcmp(var[i].data, "TZ") == 0
444             || ngx_strncmp(var[i].data, "TZ=", 3) == 0)
445         {
446             goto tz_found;
447         }
448     }
449
450     var = ngx_array_push(&ccf->env);
451     if (var == NULL) {
452         return NULL;
453     }
454
455     var->len = 2;
456     var->data = (u_char *) "TZ";
457
458     var = ccf->env.elts;
459
460 tz_found:
461
462     n = 0;
463
464     for (i = 0; i < ccf->env.nelts; i++) {
465
466         if (var[i].data[var[i].len] == '=') {
467             n++;
468             continue;
469         }
470
471         for (p = ngx_os_environ; *p; p++) {
472
473             if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
474                 && (*p)[var[i].len] == '=')
475             {
476                 n++;
477                 break;
478             }
479         }
480     }
481
482     if (last) {
483         env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log);
484         *last = n;
485
486     } else {
487         env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *));
488     }
489
490     if (env == NULL) {
491         return NULL;
492     }
493
494     n = 0;
495
496     for (i = 0; i < ccf->env.nelts; i++) {
497
498         if (var[i].data[var[i].len] == '=') {
499             env[n++] = (char *) var[i].data;
500             continue;
501         }
502
503         for (p = ngx_os_environ; *p; p++) {
504
505             if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
506                 && (*p)[var[i].len] == '=')
507             {
508                 env[n++] = *p;
509                 break;
510             }
511         }
512     }
513
514     env[n] = NULL;
515
516     if (last == NULL) {
517         ccf->environment = env;
518         environ = env;
519     }
520
521     return env;
522 }
523
524
525 ngx_pid_t
526 ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
527 {
528     char             **env, *var;
529     u_char            *p;
530     ngx_uint_t         i, n;
531     ngx_pid_t          pid;
532     ngx_exec_ctx_t     ctx;
533     ngx_core_conf_t   *ccf;
534     ngx_listening_t   *ls;
535
536     ctx.path = argv[0];
537     ctx.name = "new binary process";
538     ctx.argv = argv;
539
540     n = 2;
541     env = ngx_set_environment(cycle, &n);
542     if (env == NULL) {
543         return NGX_INVALID_PID;
544     }
545
546     var = ngx_alloc(sizeof(NGINX_VAR)
547                     + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
548                     cycle->log);
549
550     p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR));
551
552     ls = cycle->listening.elts;
553     for (i = 0; i < cycle->listening.nelts; i++) {
554         p = ngx_sprintf(p, "%ud;", ls[i].fd);
555     }
556
557     *p = '\0';
558
559     env[n++] = var;
560
561 #if (NGX_SETPROCTITLE_USES_ENV)
562
563     /* allocate the spare 300 bytes for the new binary process title */
564
565     env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
566                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
567                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
568                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
569                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
570
571 #endif
572
573     env[n] = NULL;
574
575 #if (NGX_DEBUG)
576     {
577     char  **e;
578     for (e = env; *e; e++) {
579         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e);
580     }
581     }
582 #endif
583
584     ctx.envp = (char *const *) env;
585
586     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
587
588     if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) != NGX_OK) {
589         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
590                       ngx_rename_file_n " %s to %s failed "
591                       "before executing new binary process \"%s\"",
592                       ccf->pid.data, ccf->oldpid.data, argv[0]);
593
594         ngx_free(env);
595         ngx_free(var);
596
597         return NGX_INVALID_PID;
598     }
599
600     pid = ngx_execute(cycle, &ctx);
601
602     if (pid == NGX_INVALID_PID) {
603         if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data) != NGX_OK) {
604             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
605                           ngx_rename_file_n " %s back to %s failed after "
606                           "the try to execute the new binary process \"%s\"",
607                           ccf->oldpid.data, ccf->pid.data, argv[0]);
608         }
609     }
610
611     ngx_free(env);
612     ngx_free(var);
613
614     return pid;
615 }
616
617
618 static ngx_int_t
619 ngx_getopt(ngx_cycle_t *cycle, int argc, char *const *argv)
620 {
621     ngx_int_t  i;
622
623     for (i = 1; i < argc; i++) {
624         if (argv[i][0] != '-') {
625             ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
626                           "invalid option: \"%s\"", argv[i]);
627             return NGX_ERROR;
628         }
629
630         switch (argv[i][1]) {
631
632         case 'v':
633             ngx_show_version = 1;
634             break;
635
636         case 'V':
637             ngx_show_version = 1;
638             ngx_show_configure = 1;
639             break;
640
641         case 't':
642             ngx_test_config = 1;
643             break;
644
645         case 'c':
646             if (argv[i + 1] == NULL) {
647                 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
648                               "the option \"-c\" requires file name");
649                 return NGX_ERROR;
650             }
651
652             cycle->conf_file.data = (u_char *) argv[++i];
653             cycle->conf_file.len = ngx_strlen(cycle->conf_file.data);
654             break;
655
656         case 'g':
657             if (argv[i + 1] == NULL) {
658                 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
659                               "the option \"-g\" requires parameter");
660                 return NGX_ERROR;
661             }
662
663             cycle->conf_param.data = (u_char *) argv[++i];
664             cycle->conf_param.len = ngx_strlen(cycle->conf_param.data);
665             break;
666
667         default:
668             ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
669                           "invalid option: \"%s\"", argv[i]);
670             return NGX_ERROR;
671         }
672     }
673
674     if (cycle->conf_file.data == NULL) {
675         cycle->conf_file.len = sizeof(NGX_CONF_PATH) - 1;
676         cycle->conf_file.data = (u_char *) NGX_CONF_PATH;
677     }
678
679     return NGX_OK;
680 }
681
682
683 static ngx_int_t
684 ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
685 {
686 #if (NGX_FREEBSD)
687
688     ngx_os_argv = (char **) argv;
689     ngx_argc = argc;
690     ngx_argv = (char **) argv;
691
692 #else
693     size_t     len;
694     ngx_int_t  i;
695
696     ngx_os_argv = (char **) argv;
697     ngx_argc = argc;
698
699     ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
700     if (ngx_argv == NULL) {
701         return NGX_ERROR;
702     }
703
704     for (i = 0; i < argc; i++) {
705         len = ngx_strlen(argv[i]) + 1;
706
707         ngx_argv[i] = ngx_alloc(len, cycle->log);
708         if (ngx_argv[i] == NULL) {
709             return NGX_ERROR;
710         }
711
712         (void) ngx_cpystrn((u_char *) ngx_argv[i], (u_char *) argv[i], len);
713     }
714
715     ngx_argv[i] = NULL;
716
717 #endif
718
719     ngx_os_environ = environ;
720
721     return NGX_OK;
722 }
723
724
725 static void *
726 ngx_core_module_create_conf(ngx_cycle_t *cycle)
727 {
728     ngx_core_conf_t  *ccf;
729
730     ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t));
731     if (ccf == NULL) {
732         return NULL;
733     }
734
735     /*
736      * set by pcalloc()
737      *
738      *     ccf->pid = NULL;
739      *     ccf->oldpid = NULL;
740      *     ccf->priority = 0;
741      *     ccf->cpu_affinity_n = 0;
742      *     ccf->cpu_affinity = NULL;
743      */
744
745     ccf->daemon = NGX_CONF_UNSET;
746     ccf->master = NGX_CONF_UNSET;
747     ccf->timer_resolution = NGX_CONF_UNSET_MSEC;
748
749     ccf->worker_processes = NGX_CONF_UNSET;
750     ccf->debug_points = NGX_CONF_UNSET;
751
752     ccf->rlimit_nofile = NGX_CONF_UNSET;
753     ccf->rlimit_core = NGX_CONF_UNSET_SIZE;
754     ccf->rlimit_sigpending = NGX_CONF_UNSET;
755
756     ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;
757     ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT;
758
759 #if (NGX_THREADS)
760     ccf->worker_threads = NGX_CONF_UNSET;
761     ccf->thread_stack_size = NGX_CONF_UNSET_SIZE;
762 #endif
763
764     if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))
765         != NGX_OK)
766     {
767         return NULL;
768     }
769
770     return ccf;
771 }
772
773
774 static char *
775 ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
776 {
777     ngx_core_conf_t  *ccf = conf;
778
779     ngx_conf_init_value(ccf->daemon, 1);
780     ngx_conf_init_value(ccf->master, 1);
781     ngx_conf_init_msec_value(ccf->timer_resolution, 0);
782
783     ngx_conf_init_value(ccf->worker_processes, 1);
784     ngx_conf_init_value(ccf->debug_points, 0);
785
786 #if (NGX_HAVE_SCHED_SETAFFINITY)
787
788     if (ccf->cpu_affinity_n
789         && ccf->cpu_affinity_n != 1
790         && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)
791     {
792         ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
793                       "number of the \"worker_processes\" is not equal to "
794                       "the number of the \"worker_cpu_affinity\" mask, "
795                       "using last mask for remaining worker processes");
796     }
797
798 #endif
799
800 #if (NGX_THREADS)
801
802     ngx_conf_init_value(ccf->worker_threads, 0);
803     ngx_threads_n = ccf->worker_threads;
804     ngx_conf_init_size_value(ccf->thread_stack_size, 2 * 1024 * 1024);
805
806 #endif
807
808 #if !(NGX_WIN32)
809
810     if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) {
811         struct group   *grp;
812         struct passwd  *pwd;
813
814         ngx_set_errno(0);
815         pwd = getpwnam(NGX_USER);
816         if (pwd == NULL) {
817             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
818                           "getpwnam(\"" NGX_USER "\") failed");
819             return NGX_CONF_ERROR;
820         }
821
822         ccf->username = NGX_USER;
823         ccf->user = pwd->pw_uid;
824
825         ngx_set_errno(0);
826         grp = getgrnam(NGX_GROUP);
827         if (grp == NULL) {
828             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
829                           "getgrnam(\"" NGX_GROUP "\") failed");
830             return NGX_CONF_ERROR;
831         }
832
833         ccf->group = grp->gr_gid;
834     }
835
836     if (ccf->pid.len == 0) {
837         ccf->pid.len = sizeof(NGX_PID_PATH) - 1;
838         ccf->pid.data = (u_char *) NGX_PID_PATH;
839     }
840
841     if (ngx_conf_full_name(cycle, &ccf->pid, 0) == NGX_ERROR) {
842         return NGX_CONF_ERROR;
843     }
844
845     ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);
846
847     ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
848     if (ccf->oldpid.data == NULL) {
849         return NGX_CONF_ERROR;
850     }
851
852     ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len),
853                NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT));
854
855
856     if (ccf->lock_file.len == 0) {
857         ccf->lock_file.len = sizeof(NGX_LOCK_PATH) - 1;
858         ccf->lock_file.data = (u_char *) NGX_LOCK_PATH;
859     }
860
861     if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) == NGX_ERROR) {
862         return NGX_CONF_ERROR;
863     }
864
865     {
866     ngx_str_t  lock_file;
867
868     lock_file = cycle->old_cycle->lock_file;
869
870     if (lock_file.len) {
871         lock_file.len--;
872
873         if (ccf->lock_file.len != lock_file.len
874             || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len)
875                != 0)
876         {
877             ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
878                           "\"lock_file\" could not be changed, ignored");
879         }
880
881         cycle->lock_file.len = lock_file.len + 1;
882         lock_file.len += sizeof(".accept");
883
884         cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file);
885         if (cycle->lock_file.data == NULL) {
886             return NGX_CONF_ERROR;
887         }
888
889     } else {
890         cycle->lock_file.len = ccf->lock_file.len + 1;
891         cycle->lock_file.data = ngx_pnalloc(cycle->pool,
892                                       ccf->lock_file.len + sizeof(".accept"));
893         if (cycle->lock_file.data == NULL) {
894             return NGX_CONF_ERROR;
895         }
896
897         ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data,
898                               ccf->lock_file.len),
899                    ".accept", sizeof(".accept"));
900     }
901     }
902
903 #endif
904
905     return NGX_CONF_OK;
906 }
907
908
909 static char *
910 ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
911 {
912 #if (NGX_WIN32)
913
914     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
915                        "\"user\" is not supported, ignored");
916
917     return NGX_CONF_OK;
918
919 #else
920
921     ngx_core_conf_t  *ccf = conf;
922
923     char             *group;
924     struct passwd    *pwd;
925     struct group     *grp;
926     ngx_str_t        *value;
927
928     if (ccf->user != (uid_t) NGX_CONF_UNSET_UINT) {
929         return "is duplicate";
930     }
931
932     if (geteuid() != 0) {
933         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
934                            "the \"user\" directive makes sense only "
935                            "if the master process runs "
936                            "with super-user privileges, ignored");
937         return NGX_CONF_OK;
938     }
939
940     value = (ngx_str_t *) cf->args->elts;
941
942     ccf->username = (char *) value[1].data;
943
944     ngx_set_errno(0);
945     pwd = getpwnam((const char *) value[1].data);
946     if (pwd == NULL) {
947         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
948                            "getpwnam(\"%s\") failed", value[1].data);
949         return NGX_CONF_ERROR;
950     }
951
952     ccf->user = pwd->pw_uid;
953
954     group = (char *) ((cf->args->nelts == 2) ? value[1].data : value[2].data);
955
956     ngx_set_errno(0);
957     grp = getgrnam(group);
958     if (grp == NULL) {
959         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
960                            "getgrnam(\"%s\") failed", group);
961         return NGX_CONF_ERROR;
962     }
963
964     ccf->group = grp->gr_gid;
965
966     return NGX_CONF_OK;
967
968 #endif
969 }
970
971
972 static char *
973 ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
974 {
975     ngx_core_conf_t  *ccf = conf;
976
977     ngx_str_t   *value, *var;
978     ngx_uint_t   i;
979
980     var = ngx_array_push(&ccf->env);
981     if (var == NULL) {
982         return NGX_CONF_ERROR;
983     }
984
985     value = cf->args->elts;
986     *var = value[1];
987
988     for (i = 0; i < value[1].len; i++) {
989
990         if (value[1].data[i] == '=') {
991
992             var->len = i;
993
994             return NGX_CONF_OK;
995         }
996     }
997
998     return NGX_CONF_OK;
999 }
1000
1001
1002 static char *
1003 ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1004 {
1005     ngx_core_conf_t  *ccf = conf;
1006
1007     ngx_str_t        *value;
1008     ngx_uint_t        n, minus;
1009
1010     if (ccf->priority != 0) {
1011         return "is duplicate";
1012     }
1013
1014     value = cf->args->elts;
1015
1016     if (value[1].data[0] == '-') {
1017         n = 1;
1018         minus = 1;
1019
1020     } else if (value[1].data[0] == '+') {
1021         n = 1;
1022         minus = 0;
1023
1024     } else {
1025         n = 0;
1026         minus = 0;
1027     }
1028
1029     ccf->priority = ngx_atoi(&value[1].data[n], value[1].len - n);
1030     if (ccf->priority == NGX_ERROR) {
1031         return "invalid number";
1032     }
1033
1034     if (minus) {
1035         ccf->priority = -ccf->priority;
1036     }
1037
1038     return NGX_CONF_OK;
1039 }
1040
1041
1042 static char *
1043 ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1044 {
1045 #if (NGX_HAVE_SCHED_SETAFFINITY)
1046     ngx_core_conf_t  *ccf = conf;
1047
1048     u_char            ch;
1049     u_long           *mask;
1050     ngx_str_t        *value;
1051     ngx_uint_t        i, n;
1052
1053     if (ccf->cpu_affinity) {
1054         return "is duplicate";
1055     }
1056
1057     mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(long));
1058     if (mask == NULL) {
1059         return NGX_CONF_ERROR;
1060     }
1061
1062     ccf->cpu_affinity_n = cf->args->nelts - 1;
1063     ccf->cpu_affinity = mask;
1064
1065     value = cf->args->elts;
1066
1067     for (n = 1; n < cf->args->nelts; n++) {
1068
1069         if (value[n].len > 32) {
1070             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1071                          "\"worker_cpu_affinity\" supports up to 32 CPU only");
1072             return NGX_CONF_ERROR;
1073         }
1074
1075         mask[n - 1] = 0;
1076
1077         for (i = 0; i < value[n].len; i++) {
1078
1079             ch = value[n].data[i];
1080
1081             if (ch == ' ') {
1082                 continue;
1083             }
1084
1085             mask[n - 1] <<= 1;
1086
1087             if (ch == '0') {
1088                 continue;
1089             }
1090
1091             if (ch == '1') {
1092                 mask[n - 1] |= 1;
1093                 continue;
1094             }
1095
1096             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1097                           "invalid character \"%c\" in \"worker_cpu_affinity\"",
1098                           ch);
1099             return NGX_CONF_ERROR;
1100         }
1101     }
1102
1103 #else
1104
1105     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1106                        "\"worker_cpu_affinity\" is not supported "
1107                        "on this platform, ignored");
1108 #endif
1109
1110     return NGX_CONF_OK;
1111 }
1112
1113
1114 u_long
1115 ngx_get_cpu_affinity(ngx_uint_t n)
1116 {
1117     ngx_core_conf_t  *ccf;
1118
1119     ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
1120                                            ngx_core_module);
1121
1122     if (ccf->cpu_affinity == NULL) {
1123         return 0;
1124     }
1125
1126     if (ccf->cpu_affinity_n > n) {
1127         return ccf->cpu_affinity[n];
1128     }
1129
1130     return ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
1131 }