nginx.c revision e18a033b
1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
10#include <nginx.h>
11
12
13static void ngx_show_version_info(void);
14static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
15static void ngx_cleanup_environment(void *data);
16static ngx_int_t ngx_get_options(int argc, char *const *argv);
17static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
18static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
19static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
20static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
21static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
22static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
23static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
24static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd,
25    void *conf);
26static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd,
27    void *conf);
28static char *ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
29#if (NGX_HAVE_DLOPEN)
30static void ngx_unload_module(void *data);
31#endif
32
33
34static ngx_conf_enum_t  ngx_debug_points[] = {
35    { ngx_string("stop"), NGX_DEBUG_POINTS_STOP },
36    { ngx_string("abort"), NGX_DEBUG_POINTS_ABORT },
37    { ngx_null_string, 0 }
38};
39
40
41static ngx_command_t  ngx_core_commands[] = {
42
43    { ngx_string("daemon"),
44      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
45      ngx_conf_set_flag_slot,
46      0,
47      offsetof(ngx_core_conf_t, daemon),
48      NULL },
49
50    { ngx_string("master_process"),
51      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
52      ngx_conf_set_flag_slot,
53      0,
54      offsetof(ngx_core_conf_t, master),
55      NULL },
56
57    { ngx_string("timer_resolution"),
58      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
59      ngx_conf_set_msec_slot,
60      0,
61      offsetof(ngx_core_conf_t, timer_resolution),
62      NULL },
63
64    { ngx_string("pid"),
65      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
66      ngx_conf_set_str_slot,
67      0,
68      offsetof(ngx_core_conf_t, pid),
69      NULL },
70
71    { ngx_string("lock_file"),
72      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
73      ngx_conf_set_str_slot,
74      0,
75      offsetof(ngx_core_conf_t, lock_file),
76      NULL },
77
78    { ngx_string("worker_processes"),
79      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
80      ngx_set_worker_processes,
81      0,
82      0,
83      NULL },
84
85    { ngx_string("debug_points"),
86      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
87      ngx_conf_set_enum_slot,
88      0,
89      offsetof(ngx_core_conf_t, debug_points),
90      &ngx_debug_points },
91
92    { ngx_string("user"),
93      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
94      ngx_set_user,
95      0,
96      0,
97      NULL },
98
99    { ngx_string("worker_priority"),
100      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
101      ngx_set_priority,
102      0,
103      0,
104      NULL },
105
106    { ngx_string("worker_cpu_affinity"),
107      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
108      ngx_set_cpu_affinity,
109      0,
110      0,
111      NULL },
112
113    { ngx_string("worker_rlimit_nofile"),
114      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
115      ngx_conf_set_num_slot,
116      0,
117      offsetof(ngx_core_conf_t, rlimit_nofile),
118      NULL },
119
120    { ngx_string("worker_rlimit_core"),
121      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
122      ngx_conf_set_off_slot,
123      0,
124      offsetof(ngx_core_conf_t, rlimit_core),
125      NULL },
126
127    { ngx_string("worker_shutdown_timeout"),
128      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
129      ngx_conf_set_msec_slot,
130      0,
131      offsetof(ngx_core_conf_t, shutdown_timeout),
132      NULL },
133
134    { ngx_string("working_directory"),
135      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
136      ngx_conf_set_str_slot,
137      0,
138      offsetof(ngx_core_conf_t, working_directory),
139      NULL },
140
141    { ngx_string("env"),
142      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
143      ngx_set_env,
144      0,
145      0,
146      NULL },
147
148    { ngx_string("load_module"),
149      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
150      ngx_load_module,
151      0,
152      0,
153      NULL },
154
155      ngx_null_command
156};
157
158
159static ngx_core_module_t  ngx_core_module_ctx = {
160    ngx_string("core"),
161    ngx_core_module_create_conf,
162    ngx_core_module_init_conf
163};
164
165
166ngx_module_t  ngx_core_module = {
167    NGX_MODULE_V1,
168    &ngx_core_module_ctx,                  /* module context */
169    ngx_core_commands,                     /* module directives */
170    NGX_CORE_MODULE,                       /* module type */
171    NULL,                                  /* init master */
172    NULL,                                  /* init module */
173    NULL,                                  /* init process */
174    NULL,                                  /* init thread */
175    NULL,                                  /* exit thread */
176    NULL,                                  /* exit process */
177    NULL,                                  /* exit master */
178    NGX_MODULE_V1_PADDING
179};
180
181
182static ngx_uint_t   ngx_show_help;
183static ngx_uint_t   ngx_show_version;
184static ngx_uint_t   ngx_show_configure;
185static u_char      *ngx_prefix;
186static u_char      *ngx_conf_file;
187static u_char      *ngx_conf_params;
188static char        *ngx_signal;
189
190
191static char **ngx_os_environ;
192
193
194int ngx_cdecl
195main(int argc, char *const *argv)
196{
197    ngx_buf_t        *b;
198    ngx_log_t        *log;
199    ngx_uint_t        i;
200    ngx_cycle_t      *cycle, init_cycle;
201    ngx_conf_dump_t  *cd;
202    ngx_core_conf_t  *ccf;
203
204    ngx_debug_init();
205
206    if (ngx_strerror_init() != NGX_OK) {
207        return 1;
208    }
209
210    if (ngx_get_options(argc, argv) != NGX_OK) {
211        return 1;
212    }
213
214    if (ngx_show_version) {
215        ngx_show_version_info();
216
217        if (!ngx_test_config) {
218            return 0;
219        }
220    }
221
222    /* TODO */ ngx_max_sockets = -1;
223
224    ngx_time_init();
225
226#if (NGX_PCRE)
227    ngx_regex_init();
228#endif
229
230    ngx_pid = ngx_getpid();
231
232    log = ngx_log_init(ngx_prefix);
233    if (log == NULL) {
234        return 1;
235    }
236
237    /* STUB */
238#if (NGX_OPENSSL)
239    ngx_ssl_init(log);
240#endif
241
242    /*
243     * init_cycle->log is required for signal handlers and
244     * ngx_process_options()
245     */
246
247    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
248    init_cycle.log = log;
249    ngx_cycle = &init_cycle;
250
251    init_cycle.pool = ngx_create_pool(1024, log);
252    if (init_cycle.pool == NULL) {
253        return 1;
254    }
255
256    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
257        return 1;
258    }
259
260    if (ngx_process_options(&init_cycle) != NGX_OK) {
261        return 1;
262    }
263
264    if (ngx_os_init(log) != NGX_OK) {
265        return 1;
266    }
267
268    /*
269     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
270     */
271
272    if (ngx_crc32_table_init() != NGX_OK) {
273        return 1;
274    }
275
276    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
277        return 1;
278    }
279
280    if (ngx_preinit_modules() != NGX_OK) {
281        return 1;
282    }
283
284    cycle = ngx_init_cycle(&init_cycle);
285    if (cycle == NULL) {
286        if (ngx_test_config) {
287            ngx_log_stderr(0, "configuration file %s test failed",
288                           init_cycle.conf_file.data);
289        }
290
291        return 1;
292    }
293
294    if (ngx_test_config) {
295        if (!ngx_quiet_mode) {
296            ngx_log_stderr(0, "configuration file %s test is successful",
297                           cycle->conf_file.data);
298        }
299
300        if (ngx_dump_config) {
301            cd = cycle->config_dump.elts;
302
303            for (i = 0; i < cycle->config_dump.nelts; i++) {
304
305                ngx_write_stdout("# configuration file ");
306                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
307                                    cd[i].name.len);
308                ngx_write_stdout(":" NGX_LINEFEED);
309
310                b = cd[i].buffer;
311
312                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
313                ngx_write_stdout(NGX_LINEFEED);
314            }
315        }
316
317        return 0;
318    }
319
320    if (ngx_signal) {
321        return ngx_signal_process(cycle, ngx_signal);
322    }
323
324    ngx_os_status(cycle->log);
325
326    ngx_cycle = cycle;
327
328    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
329
330    if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
331        ngx_process = NGX_PROCESS_MASTER;
332    }
333
334#if !(NGX_WIN32)
335
336    if (ngx_init_signals(cycle->log) != NGX_OK) {
337        return 1;
338    }
339
340    if (!ngx_inherited && ccf->daemon) {
341        if (ngx_daemon(cycle->log) != NGX_OK) {
342            return 1;
343        }
344
345        ngx_daemonized = 1;
346    }
347
348    if (ngx_inherited) {
349        ngx_daemonized = 1;
350    }
351
352#endif
353
354    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
355        return 1;
356    }
357
358    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
359        return 1;
360    }
361
362    if (log->file->fd != ngx_stderr) {
363        if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
364            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
365                          ngx_close_file_n " built-in log failed");
366        }
367    }
368
369    ngx_use_stderr = 0;
370
371    if (ngx_process == NGX_PROCESS_SINGLE) {
372        ngx_single_process_cycle(cycle);
373
374    } else {
375        ngx_master_process_cycle(cycle);
376    }
377
378    return 0;
379}
380
381
382static void
383ngx_show_version_info(void)
384{
385    ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);
386
387    if (ngx_show_help) {
388        ngx_write_stderr(
389            "Usage: nginx [-?hvVtTq] [-s signal] [-c filename] "
390                         "[-p prefix] [-g directives]" NGX_LINEFEED
391                         NGX_LINEFEED
392            "Options:" NGX_LINEFEED
393            "  -?,-h         : this help" NGX_LINEFEED
394            "  -v            : show version and exit" NGX_LINEFEED
395            "  -V            : show version and configure options then exit"
396                               NGX_LINEFEED
397            "  -t            : test configuration and exit" NGX_LINEFEED
398            "  -T            : test configuration, dump it and exit"
399                               NGX_LINEFEED
400            "  -q            : suppress non-error messages "
401                               "during configuration testing" NGX_LINEFEED
402            "  -s signal     : send signal to a master process: "
403                               "stop, quit, reopen, reload" NGX_LINEFEED
404#ifdef NGX_PREFIX
405            "  -p prefix     : set prefix path (default: " NGX_PREFIX ")"
406                               NGX_LINEFEED
407#else
408            "  -p prefix     : set prefix path (default: NONE)" NGX_LINEFEED
409#endif
410            "  -c filename   : set configuration file (default: " NGX_CONF_PATH
411                               ")" NGX_LINEFEED
412            "  -g directives : set global directives out of configuration "
413                               "file" NGX_LINEFEED NGX_LINEFEED
414        );
415    }
416
417    if (ngx_show_configure) {
418
419#ifdef NGX_COMPILER
420        ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED);
421#endif
422
423#if (NGX_SSL)
424        if (ngx_strcmp(ngx_ssl_version(), OPENSSL_VERSION_TEXT) == 0) {
425            ngx_write_stderr("built with " OPENSSL_VERSION_TEXT NGX_LINEFEED);
426        } else {
427            ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
428                             " (running with ");
429            ngx_write_stderr((char *) (uintptr_t) ngx_ssl_version());
430            ngx_write_stderr(")" NGX_LINEFEED);
431        }
432#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
433        ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED);
434#else
435        ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED);
436#endif
437#endif
438
439        ngx_write_stderr("configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
440    }
441}
442
443
444static ngx_int_t
445ngx_add_inherited_sockets(ngx_cycle_t *cycle)
446{
447    u_char           *p, *v, *inherited;
448    ngx_int_t         s;
449    ngx_listening_t  *ls;
450
451    inherited = (u_char *) getenv(NGINX_VAR);
452
453    if (inherited == NULL) {
454        return NGX_OK;
455    }
456
457    ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
458                  "using inherited sockets from \"%s\"", inherited);
459
460    if (ngx_array_init(&cycle->listening, cycle->pool, 10,
461                       sizeof(ngx_listening_t))
462        != NGX_OK)
463    {
464        return NGX_ERROR;
465    }
466
467    for (p = inherited, v = p; *p; p++) {
468        if (*p == ':' || *p == ';') {
469            s = ngx_atoi(v, p - v);
470            if (s == NGX_ERROR) {
471                ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
472                              "invalid socket number \"%s\" in " NGINX_VAR
473                              " environment variable, ignoring the rest"
474                              " of the variable", v);
475                break;
476            }
477
478            v = p + 1;
479
480            ls = ngx_array_push(&cycle->listening);
481            if (ls == NULL) {
482                return NGX_ERROR;
483            }
484
485            ngx_memzero(ls, sizeof(ngx_listening_t));
486
487            ls->fd = (ngx_socket_t) s;
488        }
489    }
490
491    if (v != p) {
492        ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
493                      "invalid socket number \"%s\" in " NGINX_VAR
494                      " environment variable, ignoring", v);
495    }
496
497    ngx_inherited = 1;
498
499    return ngx_set_inherited_sockets(cycle);
500}
501
502
503char **
504ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
505{
506    char                **p, **env;
507    ngx_str_t            *var;
508    ngx_uint_t            i, n;
509    ngx_core_conf_t      *ccf;
510    ngx_pool_cleanup_t   *cln;
511
512    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
513
514    if (last == NULL && ccf->environment) {
515        return ccf->environment;
516    }
517
518    var = ccf->env.elts;
519
520    for (i = 0; i < ccf->env.nelts; i++) {
521        if (ngx_strcmp(var[i].data, "TZ") == 0
522            || ngx_strncmp(var[i].data, "TZ=", 3) == 0)
523        {
524            goto tz_found;
525        }
526    }
527
528    var = ngx_array_push(&ccf->env);
529    if (var == NULL) {
530        return NULL;
531    }
532
533    var->len = 2;
534    var->data = (u_char *) "TZ";
535
536    var = ccf->env.elts;
537
538tz_found:
539
540    n = 0;
541
542    for (i = 0; i < ccf->env.nelts; i++) {
543
544        if (var[i].data[var[i].len] == '=') {
545            n++;
546            continue;
547        }
548
549        for (p = ngx_os_environ; *p; p++) {
550
551            if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
552                && (*p)[var[i].len] == '=')
553            {
554                n++;
555                break;
556            }
557        }
558    }
559
560    if (last) {
561        env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log);
562        if (env == NULL) {
563            return NULL;
564        }
565
566        *last = n;
567
568    } else {
569        cln = ngx_pool_cleanup_add(cycle->pool, 0);
570        if (cln == NULL) {
571            return NULL;
572        }
573
574        env = ngx_alloc((n + 1) * sizeof(char *), cycle->log);
575        if (env == NULL) {
576            return NULL;
577        }
578
579        cln->handler = ngx_cleanup_environment;
580        cln->data = env;
581    }
582
583    n = 0;
584
585    for (i = 0; i < ccf->env.nelts; i++) {
586
587        if (var[i].data[var[i].len] == '=') {
588            env[n++] = (char *) var[i].data;
589            continue;
590        }
591
592        for (p = ngx_os_environ; *p; p++) {
593
594            if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
595                && (*p)[var[i].len] == '=')
596            {
597                env[n++] = *p;
598                break;
599            }
600        }
601    }
602
603    env[n] = NULL;
604
605    if (last == NULL) {
606        ccf->environment = env;
607        environ = env;
608    }
609
610    return env;
611}
612
613
614static void
615ngx_cleanup_environment(void *data)
616{
617    char  **env = data;
618
619    if (environ == env) {
620
621        /*
622         * if the environment is still used, as it happens on exit,
623         * the only option is to leak it
624         */
625
626        return;
627    }
628
629    ngx_free(env);
630}
631
632
633ngx_pid_t
634ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
635{
636    char             **env, *var;
637    u_char            *p;
638    ngx_uint_t         i, n;
639    ngx_pid_t          pid;
640    ngx_exec_ctx_t     ctx;
641    ngx_core_conf_t   *ccf;
642    ngx_listening_t   *ls;
643
644    ngx_memzero(&ctx, sizeof(ngx_exec_ctx_t));
645
646    ctx.path = argv[0];
647    ctx.name = "new binary process";
648    ctx.argv = argv;
649
650    n = 2;
651    env = ngx_set_environment(cycle, &n);
652    if (env == NULL) {
653        return NGX_INVALID_PID;
654    }
655
656    var = ngx_alloc(sizeof(NGINX_VAR)
657                    + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
658                    cycle->log);
659    if (var == NULL) {
660        ngx_free(env);
661        return NGX_INVALID_PID;
662    }
663
664    p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR));
665
666    ls = cycle->listening.elts;
667    for (i = 0; i < cycle->listening.nelts; i++) {
668        p = ngx_sprintf(p, "%ud;", ls[i].fd);
669    }
670
671    *p = '\0';
672
673    env[n++] = var;
674
675#if (NGX_SETPROCTITLE_USES_ENV)
676
677    /* allocate the spare 300 bytes for the new binary process title */
678
679    env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
680               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
681               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
682               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
683               "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
684
685#endif
686
687    env[n] = NULL;
688
689#if (NGX_DEBUG)
690    {
691    char  **e;
692    for (e = env; *e; e++) {
693        ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e);
694    }
695    }
696#endif
697
698    ctx.envp = (char *const *) env;
699
700    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
701
702    if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == NGX_FILE_ERROR) {
703        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
704                      ngx_rename_file_n " %s to %s failed "
705                      "before executing new binary process \"%s\"",
706                      ccf->pid.data, ccf->oldpid.data, argv[0]);
707
708        ngx_free(env);
709        ngx_free(var);
710
711        return NGX_INVALID_PID;
712    }
713
714    pid = ngx_execute(cycle, &ctx);
715
716    if (pid == NGX_INVALID_PID) {
717        if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data)
718            == NGX_FILE_ERROR)
719        {
720            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
721                          ngx_rename_file_n " %s back to %s failed after "
722                          "an attempt to execute new binary process \"%s\"",
723                          ccf->oldpid.data, ccf->pid.data, argv[0]);
724        }
725    }
726
727    ngx_free(env);
728    ngx_free(var);
729
730    return pid;
731}
732
733
734static ngx_int_t
735ngx_get_options(int argc, char *const *argv)
736{
737    u_char     *p;
738    ngx_int_t   i;
739
740    for (i = 1; i < argc; i++) {
741
742        p = (u_char *) argv[i];
743
744        if (*p++ != '-') {
745            ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
746            return NGX_ERROR;
747        }
748
749        while (*p) {
750
751            switch (*p++) {
752
753            case '?':
754            case 'h':
755                ngx_show_version = 1;
756                ngx_show_help = 1;
757                break;
758
759            case 'v':
760                ngx_show_version = 1;
761                break;
762
763            case 'V':
764                ngx_show_version = 1;
765                ngx_show_configure = 1;
766                break;
767
768            case 't':
769                ngx_test_config = 1;
770                break;
771
772            case 'T':
773                ngx_test_config = 1;
774                ngx_dump_config = 1;
775                break;
776
777            case 'q':
778                ngx_quiet_mode = 1;
779                break;
780
781            case 'p':
782                if (*p) {
783                    ngx_prefix = p;
784                    goto next;
785                }
786
787                if (argv[++i]) {
788                    ngx_prefix = (u_char *) argv[i];
789                    goto next;
790                }
791
792                ngx_log_stderr(0, "option \"-p\" requires directory name");
793                return NGX_ERROR;
794
795            case 'c':
796                if (*p) {
797                    ngx_conf_file = p;
798                    goto next;
799                }
800
801                if (argv[++i]) {
802                    ngx_conf_file = (u_char *) argv[i];
803                    goto next;
804                }
805
806                ngx_log_stderr(0, "option \"-c\" requires file name");
807                return NGX_ERROR;
808
809            case 'g':
810                if (*p) {
811                    ngx_conf_params = p;
812                    goto next;
813                }
814
815                if (argv[++i]) {
816                    ngx_conf_params = (u_char *) argv[i];
817                    goto next;
818                }
819
820                ngx_log_stderr(0, "option \"-g\" requires parameter");
821                return NGX_ERROR;
822
823            case 's':
824                if (*p) {
825                    ngx_signal = (char *) p;
826
827                } else if (argv[++i]) {
828                    ngx_signal = argv[i];
829
830                } else {
831                    ngx_log_stderr(0, "option \"-s\" requires parameter");
832                    return NGX_ERROR;
833                }
834
835                if (ngx_strcmp(ngx_signal, "stop") == 0
836                    || ngx_strcmp(ngx_signal, "quit") == 0
837                    || ngx_strcmp(ngx_signal, "reopen") == 0
838                    || ngx_strcmp(ngx_signal, "reload") == 0)
839                {
840                    ngx_process = NGX_PROCESS_SIGNALLER;
841                    goto next;
842                }
843
844                ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
845                return NGX_ERROR;
846
847            default:
848                ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
849                return NGX_ERROR;
850            }
851        }
852
853    next:
854
855        continue;
856    }
857
858    return NGX_OK;
859}
860
861
862static ngx_int_t
863ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
864{
865#if (NGX_FREEBSD)
866
867    ngx_os_argv = (char **) argv;
868    ngx_argc = argc;
869    ngx_argv = (char **) argv;
870
871#else
872    size_t     len;
873    ngx_int_t  i;
874
875    ngx_os_argv = (char **) argv;
876    ngx_argc = argc;
877
878    ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
879    if (ngx_argv == NULL) {
880        return NGX_ERROR;
881    }
882
883    for (i = 0; i < argc; i++) {
884        len = ngx_strlen(argv[i]) + 1;
885
886        ngx_argv[i] = ngx_alloc(len, cycle->log);
887        if (ngx_argv[i] == NULL) {
888            return NGX_ERROR;
889        }
890
891        (void) ngx_cpystrn((u_char *) ngx_argv[i], (u_char *) argv[i], len);
892    }
893
894    ngx_argv[i] = NULL;
895
896#endif
897
898    ngx_os_environ = environ;
899
900    return NGX_OK;
901}
902
903
904static ngx_int_t
905ngx_process_options(ngx_cycle_t *cycle)
906{
907    u_char  *p;
908    size_t   len;
909
910    if (ngx_prefix) {
911        len = ngx_strlen(ngx_prefix);
912        p = ngx_prefix;
913
914        if (len && !ngx_path_separator(p[len - 1])) {
915            p = ngx_pnalloc(cycle->pool, len + 1);
916            if (p == NULL) {
917                return NGX_ERROR;
918            }
919
920            ngx_memcpy(p, ngx_prefix, len);
921            p[len++] = '/';
922        }
923
924        cycle->conf_prefix.len = len;
925        cycle->conf_prefix.data = p;
926        cycle->prefix.len = len;
927        cycle->prefix.data = p;
928
929    } else {
930
931#ifndef NGX_PREFIX
932
933        p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
934        if (p == NULL) {
935            return NGX_ERROR;
936        }
937
938        if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {
939            ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
940            return NGX_ERROR;
941        }
942
943        len = ngx_strlen(p);
944
945        p[len++] = '/';
946
947        cycle->conf_prefix.len = len;
948        cycle->conf_prefix.data = p;
949        cycle->prefix.len = len;
950        cycle->prefix.data = p;
951
952#else
953
954#ifdef NGX_CONF_PREFIX
955        ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
956#else
957        ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
958#endif
959        ngx_str_set(&cycle->prefix, NGX_PREFIX);
960
961#endif
962    }
963
964    if (ngx_conf_file) {
965        cycle->conf_file.len = ngx_strlen(ngx_conf_file);
966        cycle->conf_file.data = ngx_conf_file;
967
968    } else {
969        ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
970    }
971
972    if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
973        return NGX_ERROR;
974    }
975
976    for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
977         p > cycle->conf_file.data;
978         p--)
979    {
980        if (ngx_path_separator(*p)) {
981            cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1;
982            cycle->conf_prefix.data = ngx_cycle->conf_file.data;
983            break;
984        }
985    }
986
987    if (ngx_conf_params) {
988        cycle->conf_param.len = ngx_strlen(ngx_conf_params);
989        cycle->conf_param.data = ngx_conf_params;
990    }
991
992    if (ngx_test_config) {
993        cycle->log->log_level = NGX_LOG_INFO;
994    }
995
996    return NGX_OK;
997}
998
999
1000static void *
1001ngx_core_module_create_conf(ngx_cycle_t *cycle)
1002{
1003    ngx_core_conf_t  *ccf;
1004
1005    ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t));
1006    if (ccf == NULL) {
1007        return NULL;
1008    }
1009
1010    /*
1011     * set by ngx_pcalloc()
1012     *
1013     *     ccf->pid = NULL;
1014     *     ccf->oldpid = NULL;
1015     *     ccf->priority = 0;
1016     *     ccf->cpu_affinity_auto = 0;
1017     *     ccf->cpu_affinity_n = 0;
1018     *     ccf->cpu_affinity = NULL;
1019     */
1020
1021    ccf->daemon = NGX_CONF_UNSET;
1022    ccf->master = NGX_CONF_UNSET;
1023    ccf->timer_resolution = NGX_CONF_UNSET_MSEC;
1024    ccf->shutdown_timeout = NGX_CONF_UNSET_MSEC;
1025
1026    ccf->worker_processes = NGX_CONF_UNSET;
1027    ccf->debug_points = NGX_CONF_UNSET;
1028
1029    ccf->rlimit_nofile = NGX_CONF_UNSET;
1030    ccf->rlimit_core = NGX_CONF_UNSET;
1031
1032    ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;
1033    ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT;
1034
1035    if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))
1036        != NGX_OK)
1037    {
1038        return NULL;
1039    }
1040
1041    return ccf;
1042}
1043
1044
1045static char *
1046ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
1047{
1048    ngx_core_conf_t  *ccf = conf;
1049
1050    ngx_conf_init_value(ccf->daemon, 1);
1051    ngx_conf_init_value(ccf->master, 1);
1052    ngx_conf_init_msec_value(ccf->timer_resolution, 0);
1053    ngx_conf_init_msec_value(ccf->shutdown_timeout, 0);
1054
1055    ngx_conf_init_value(ccf->worker_processes, 1);
1056    ngx_conf_init_value(ccf->debug_points, 0);
1057
1058#if (NGX_HAVE_CPU_AFFINITY)
1059
1060    if (!ccf->cpu_affinity_auto
1061        && ccf->cpu_affinity_n
1062        && ccf->cpu_affinity_n != 1
1063        && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)
1064    {
1065        ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
1066                      "the number of \"worker_processes\" is not equal to "
1067                      "the number of \"worker_cpu_affinity\" masks, "
1068                      "using last mask for remaining worker processes");
1069    }
1070
1071#endif
1072
1073
1074    if (ccf->pid.len == 0) {
1075        ngx_str_set(&ccf->pid, NGX_PID_PATH);
1076    }
1077
1078    if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
1079        return NGX_CONF_ERROR;
1080    }
1081
1082    ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);
1083
1084    ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
1085    if (ccf->oldpid.data == NULL) {
1086        return NGX_CONF_ERROR;
1087    }
1088
1089    ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len),
1090               NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT));
1091
1092
1093#if !(NGX_WIN32)
1094
1095    if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) {
1096        struct group   *grp;
1097        struct passwd  *pwd;
1098
1099        ngx_set_errno(0);
1100        pwd = getpwnam(NGX_USER);
1101        if (pwd == NULL) {
1102            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1103                          "getpwnam(\"" NGX_USER "\") failed");
1104            return NGX_CONF_ERROR;
1105        }
1106
1107        ccf->username = NGX_USER;
1108        ccf->user = pwd->pw_uid;
1109
1110        ngx_set_errno(0);
1111        grp = getgrnam(NGX_GROUP);
1112        if (grp == NULL) {
1113            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
1114                          "getgrnam(\"" NGX_GROUP "\") failed");
1115            return NGX_CONF_ERROR;
1116        }
1117
1118        ccf->group = grp->gr_gid;
1119    }
1120
1121
1122    if (ccf->lock_file.len == 0) {
1123        ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH);
1124    }
1125
1126    if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) {
1127        return NGX_CONF_ERROR;
1128    }
1129
1130    {
1131    ngx_str_t  lock_file;
1132
1133    lock_file = cycle->old_cycle->lock_file;
1134
1135    if (lock_file.len) {
1136        lock_file.len--;
1137
1138        if (ccf->lock_file.len != lock_file.len
1139            || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len)
1140               != 0)
1141        {
1142            ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
1143                          "\"lock_file\" could not be changed, ignored");
1144        }
1145
1146        cycle->lock_file.len = lock_file.len + 1;
1147        lock_file.len += sizeof(".accept");
1148
1149        cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file);
1150        if (cycle->lock_file.data == NULL) {
1151            return NGX_CONF_ERROR;
1152        }
1153
1154    } else {
1155        cycle->lock_file.len = ccf->lock_file.len + 1;
1156        cycle->lock_file.data = ngx_pnalloc(cycle->pool,
1157                                      ccf->lock_file.len + sizeof(".accept"));
1158        if (cycle->lock_file.data == NULL) {
1159            return NGX_CONF_ERROR;
1160        }
1161
1162        ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data,
1163                              ccf->lock_file.len),
1164                   ".accept", sizeof(".accept"));
1165    }
1166    }
1167
1168#endif
1169
1170    return NGX_CONF_OK;
1171}
1172
1173
1174static char *
1175ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1176{
1177#if (NGX_WIN32)
1178
1179    ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1180                       "\"user\" is not supported, ignored");
1181
1182    return NGX_CONF_OK;
1183
1184#else
1185
1186    ngx_core_conf_t  *ccf = conf;
1187
1188    char             *group;
1189    struct passwd    *pwd;
1190    struct group     *grp;
1191    ngx_str_t        *value;
1192
1193    if (ccf->user != (uid_t) NGX_CONF_UNSET_UINT) {
1194        return "is duplicate";
1195    }
1196
1197    if (geteuid() != 0) {
1198        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1199                           "the \"user\" directive makes sense only "
1200                           "if the master process runs "
1201                           "with super-user privileges, ignored");
1202        return NGX_CONF_OK;
1203    }
1204
1205    value = cf->args->elts;
1206
1207    ccf->username = (char *) value[1].data;
1208
1209    ngx_set_errno(0);
1210    pwd = getpwnam((const char *) value[1].data);
1211    if (pwd == NULL) {
1212        ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1213                           "getpwnam(\"%s\") failed", value[1].data);
1214        return NGX_CONF_ERROR;
1215    }
1216
1217    ccf->user = pwd->pw_uid;
1218
1219    group = (char *) ((cf->args->nelts == 2) ? value[1].data : value[2].data);
1220
1221    ngx_set_errno(0);
1222    grp = getgrnam(group);
1223    if (grp == NULL) {
1224        ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1225                           "getgrnam(\"%s\") failed", group);
1226        return NGX_CONF_ERROR;
1227    }
1228
1229    ccf->group = grp->gr_gid;
1230
1231    return NGX_CONF_OK;
1232
1233#endif
1234}
1235
1236
1237static char *
1238ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1239{
1240    ngx_core_conf_t  *ccf = conf;
1241
1242    ngx_str_t   *value, *var;
1243    ngx_uint_t   i;
1244
1245    var = ngx_array_push(&ccf->env);
1246    if (var == NULL) {
1247        return NGX_CONF_ERROR;
1248    }
1249
1250    value = cf->args->elts;
1251    *var = value[1];
1252
1253    for (i = 0; i < value[1].len; i++) {
1254
1255        if (value[1].data[i] == '=') {
1256
1257            var->len = i;
1258
1259            return NGX_CONF_OK;
1260        }
1261    }
1262
1263    return NGX_CONF_OK;
1264}
1265
1266
1267static char *
1268ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1269{
1270    ngx_core_conf_t  *ccf = conf;
1271
1272    ngx_str_t        *value;
1273    ngx_uint_t        n, minus;
1274
1275    if (ccf->priority != 0) {
1276        return "is duplicate";
1277    }
1278
1279    value = cf->args->elts;
1280
1281    if (value[1].data[0] == '-') {
1282        n = 1;
1283        minus = 1;
1284
1285    } else if (value[1].data[0] == '+') {
1286        n = 1;
1287        minus = 0;
1288
1289    } else {
1290        n = 0;
1291        minus = 0;
1292    }
1293
1294    ccf->priority = ngx_atoi(&value[1].data[n], value[1].len - n);
1295    if (ccf->priority == NGX_ERROR) {
1296        return "invalid number";
1297    }
1298
1299    if (minus) {
1300        ccf->priority = -ccf->priority;
1301    }
1302
1303    return NGX_CONF_OK;
1304}
1305
1306
1307static char *
1308ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1309{
1310#if (NGX_HAVE_CPU_AFFINITY)
1311    ngx_core_conf_t  *ccf = conf;
1312
1313    u_char            ch, *p;
1314    ngx_str_t        *value;
1315    ngx_uint_t        i, n;
1316    ngx_cpuset_t     *mask;
1317
1318    if (ccf->cpu_affinity) {
1319        return "is duplicate";
1320    }
1321
1322    mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(ngx_cpuset_t));
1323    if (mask == NULL) {
1324        return NGX_CONF_ERROR;
1325    }
1326
1327    ccf->cpu_affinity_n = cf->args->nelts - 1;
1328    ccf->cpu_affinity = mask;
1329
1330    value = cf->args->elts;
1331
1332    if (ngx_strcmp(value[1].data, "auto") == 0) {
1333
1334        if (cf->args->nelts > 3) {
1335            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1336                               "invalid number of arguments in "
1337                               "\"worker_cpu_affinity\" directive");
1338            return NGX_CONF_ERROR;
1339        }
1340
1341        ccf->cpu_affinity_auto = 1;
1342
1343        CPU_ZERO(&mask[0]);
1344        for (i = 0; i < (ngx_uint_t) ngx_min(ngx_ncpu, CPU_SETSIZE); i++) {
1345            CPU_SET(i, &mask[0]);
1346        }
1347
1348        n = 2;
1349
1350    } else {
1351        n = 1;
1352    }
1353
1354    for ( /* void */ ; n < cf->args->nelts; n++) {
1355
1356        if (value[n].len > CPU_SETSIZE) {
1357            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1358                         "\"worker_cpu_affinity\" supports up to %d CPUs only",
1359                         CPU_SETSIZE);
1360            return NGX_CONF_ERROR;
1361        }
1362
1363        i = 0;
1364        CPU_ZERO(&mask[n - 1]);
1365
1366        for (p = value[n].data + value[n].len - 1;
1367             p >= value[n].data;
1368             p--)
1369        {
1370            ch = *p;
1371
1372            if (ch == ' ') {
1373                continue;
1374            }
1375
1376            i++;
1377
1378            if (ch == '0') {
1379                continue;
1380            }
1381
1382            if (ch == '1') {
1383                CPU_SET(i - 1, &mask[n - 1]);
1384                continue;
1385            }
1386
1387            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1388                          "invalid character \"%c\" in \"worker_cpu_affinity\"",
1389                          ch);
1390            return NGX_CONF_ERROR;
1391        }
1392    }
1393
1394#else
1395
1396    ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1397                       "\"worker_cpu_affinity\" is not supported "
1398                       "on this platform, ignored");
1399#endif
1400
1401    return NGX_CONF_OK;
1402}
1403
1404
1405ngx_cpuset_t *
1406ngx_get_cpu_affinity(ngx_uint_t n)
1407{
1408#if (NGX_HAVE_CPU_AFFINITY)
1409    ngx_uint_t        i, j;
1410    ngx_cpuset_t     *mask;
1411    ngx_core_conf_t  *ccf;
1412
1413    static ngx_cpuset_t  result;
1414
1415    ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
1416                                           ngx_core_module);
1417
1418    if (ccf->cpu_affinity == NULL) {
1419        return NULL;
1420    }
1421
1422    if (ccf->cpu_affinity_auto) {
1423        mask = &ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
1424
1425        for (i = 0, j = n; /* void */ ; i++) {
1426
1427            if (CPU_ISSET(i % CPU_SETSIZE, mask) && j-- == 0) {
1428                break;
1429            }
1430
1431            if (i == CPU_SETSIZE && j == n) {
1432                /* empty mask */
1433                return NULL;
1434            }
1435
1436            /* void */
1437        }
1438
1439        CPU_ZERO(&result);
1440        CPU_SET(i % CPU_SETSIZE, &result);
1441
1442        return &result;
1443    }
1444
1445    if (ccf->cpu_affinity_n > n) {
1446        return &ccf->cpu_affinity[n];
1447    }
1448
1449    return &ccf->cpu_affinity[ccf->cpu_affinity_n - 1];
1450
1451#else
1452
1453    return NULL;
1454
1455#endif
1456}
1457
1458
1459static char *
1460ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1461{
1462    ngx_str_t        *value;
1463    ngx_core_conf_t  *ccf;
1464
1465    ccf = (ngx_core_conf_t *) conf;
1466
1467    if (ccf->worker_processes != NGX_CONF_UNSET) {
1468        return "is duplicate";
1469    }
1470
1471    value = cf->args->elts;
1472
1473    if (ngx_strcmp(value[1].data, "auto") == 0) {
1474        ccf->worker_processes = ngx_ncpu;
1475        return NGX_CONF_OK;
1476    }
1477
1478    ccf->worker_processes = ngx_atoi(value[1].data, value[1].len);
1479
1480    if (ccf->worker_processes == NGX_ERROR) {
1481        return "invalid value";
1482    }
1483
1484    return NGX_CONF_OK;
1485}
1486
1487
1488static char *
1489ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1490{
1491#if (NGX_HAVE_DLOPEN)
1492    void                *handle;
1493    char               **names, **order;
1494    ngx_str_t           *value, file;
1495    ngx_uint_t           i;
1496    ngx_module_t        *module, **modules;
1497    ngx_pool_cleanup_t  *cln;
1498
1499    if (cf->cycle->modules_used) {
1500        return "is specified too late";
1501    }
1502
1503    value = cf->args->elts;
1504
1505    file = value[1];
1506
1507    if (ngx_conf_full_name(cf->cycle, &file, 0) != NGX_OK) {
1508        return NGX_CONF_ERROR;
1509    }
1510
1511    cln = ngx_pool_cleanup_add(cf->cycle->pool, 0);
1512    if (cln == NULL) {
1513        return NGX_CONF_ERROR;
1514    }
1515
1516    handle = ngx_dlopen(file.data);
1517    if (handle == NULL) {
1518        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1519                           ngx_dlopen_n " \"%s\" failed (%s)",
1520                           file.data, ngx_dlerror());
1521        return NGX_CONF_ERROR;
1522    }
1523
1524    cln->handler = ngx_unload_module;
1525    cln->data = handle;
1526
1527    modules = ngx_dlsym(handle, "ngx_modules");
1528    if (modules == NULL) {
1529        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1530                           ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
1531                           &value[1], "ngx_modules", ngx_dlerror());
1532        return NGX_CONF_ERROR;
1533    }
1534
1535    names = ngx_dlsym(handle, "ngx_module_names");
1536    if (names == NULL) {
1537        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1538                           ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
1539                           &value[1], "ngx_module_names", ngx_dlerror());
1540        return NGX_CONF_ERROR;
1541    }
1542
1543    order = ngx_dlsym(handle, "ngx_module_order");
1544
1545    for (i = 0; modules[i]; i++) {
1546        module = modules[i];
1547        module->name = names[i];
1548
1549        if (ngx_add_module(cf, &file, module, order) != NGX_OK) {
1550            return NGX_CONF_ERROR;
1551        }
1552
1553        ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, "module: %s i:%ui",
1554                       module->name, module->index);
1555    }
1556
1557    return NGX_CONF_OK;
1558
1559#else
1560
1561    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1562                       "\"load_module\" is not supported "
1563                       "on this platform");
1564    return NGX_CONF_ERROR;
1565
1566#endif
1567}
1568
1569
1570#if (NGX_HAVE_DLOPEN)
1571
1572static void
1573ngx_unload_module(void *data)
1574{
1575    void  *handle = data;
1576
1577    if (ngx_dlclose(handle) != 0) {
1578        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
1579                      ngx_dlclose_n " failed (%s)", ngx_dlerror());
1580    }
1581}
1582
1583#endif
1584