1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9
10 #define NGX_CONF_BUFFER 4096
11
12 static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last);
13 static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf);
14 static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
15 static ngx_int_t ngx_conf_test_full_name(ngx_str_t *name);
16 static void ngx_conf_flush_files(ngx_cycle_t *cycle);
17
18
19 static ngx_command_t ngx_conf_commands[] = {
20
21 { ngx_string("include"),
22 NGX_ANY_CONF|NGX_CONF_TAKE1,
23 ngx_conf_include,
24 0,
25 0,
26 NULL },
27
28 ngx_null_command
29 };
30
31
32 ngx_module_t ngx_conf_module = {
33 NGX_MODULE_V1,
34 NULL, /* module context */
35 ngx_conf_commands, /* module directives */
36 NGX_CONF_MODULE, /* module type */
37 NULL, /* init master */
38 NULL, /* init module */
39 NULL, /* init process */
40 NULL, /* init thread */
41 NULL, /* exit thread */
42 ngx_conf_flush_files, /* exit process */
43 NULL, /* exit master */
44 NGX_MODULE_V1_PADDING
45 };
46
47
48 /* The eight fixed arguments */
49
50 static ngx_uint_t argument_number[] = {
51 NGX_CONF_NOARGS,
52 NGX_CONF_TAKE1,
53 NGX_CONF_TAKE2,
54 NGX_CONF_TAKE3,
55 NGX_CONF_TAKE4,
56 NGX_CONF_TAKE5,
57 NGX_CONF_TAKE6,
58 NGX_CONF_TAKE7
59 };
60
61
62 char *
63 ngx_conf_param(ngx_conf_t *cf)
64 {
65 char *rv;
66 ngx_str_t *param;
67 ngx_buf_t b;
68 ngx_conf_file_t conf_file;
69
70 param = &cf->cycle->conf_param;
71
72 if (param->len == 0) {
73 return NGX_CONF_OK;
74 }
75
76 ngx_memzero(&conf_file, sizeof(ngx_conf_file_t));
77
78 ngx_memzero(&b, sizeof(ngx_buf_t));
79
80 b.start = param->data;
81 b.pos = param->data;
82 b.last = param->data + param->len;
83 b.end = b.last;
84 b.temporary = 1;
85
86 conf_file.file.fd = NGX_INVALID_FILE;
87 conf_file.file.name.data = NULL;
88 conf_file.line = 0;
89
90 cf->conf_file = &conf_file;
91 cf->conf_file->buffer = &b;
92
93 rv = ngx_conf_parse(cf, NULL);
94
95 cf->conf_file = NULL;
96
97 return rv;
98 }
99
100
101 char *
102 ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
103 {
104 char *rv;
105 ngx_fd_t fd;
106 ngx_int_t rc;
107 ngx_buf_t buf;
108 ngx_conf_file_t *prev, conf_file;
109 enum {
110 parse_file = 0,
111 parse_block,
112 parse_param
113 } type;
114
115 #if (NGX_SUPPRESS_WARN)
116 fd = NGX_INVALID_FILE;
117 prev = NULL;
118 #endif
119
120 if (filename) {
121
122 /* open configuration file */
123
124 fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
125 if (fd == NGX_INVALID_FILE) {
126 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
127 ngx_open_file_n " \"%s\" failed",
128 filename->data);
129 return NGX_CONF_ERROR;
130 }
131
132 prev = cf->conf_file;
133
134 cf->conf_file = &conf_file;
135
136 if (ngx_fd_info(fd, &cf->conf_file->file.info) == -1) {
137 ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
138 ngx_fd_info_n " \"%s\" failed", filename->data);
139 }
140
141 cf->conf_file->buffer = &buf;
142
143 buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log);
144 if (buf.start == NULL) {
145 goto failed;
146 }
147
148 buf.pos = buf.start;
149 buf.last = buf.start;
150 buf.end = buf.last + NGX_CONF_BUFFER;
151 buf.temporary = 1;
152
153 cf->conf_file->file.fd = fd;
154 cf->conf_file->file.name.len = filename->len;
155 cf->conf_file->file.name.data = filename->data;
156 cf->conf_file->file.offset = 0;
157 cf->conf_file->file.log = cf->log;
158 cf->conf_file->line = 1;
159
160 type = parse_file;
161
162 } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {
163
164 type = parse_block;
165
166 } else {
167 type = parse_param;
168 }
169
170
171 for ( ;; ) {
172 rc = ngx_conf_read_token(cf);
173
174 /*
175 * ngx_conf_read_token() may return
176 *
177 * NGX_ERROR there is error
178 * NGX_OK the token terminated by ";" was found
179 * NGX_CONF_BLOCK_START the token terminated by "{" was found
180 * NGX_CONF_BLOCK_DONE the "}" was found
181 * NGX_CONF_FILE_DONE the configuration file is done
182 */
183
184 if (rc == NGX_ERROR) {
185 goto done;
186 }
187
188 if (rc == NGX_CONF_BLOCK_DONE) {
189
190 if (type != parse_block) {
191 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");
192 goto failed;
193 }
194
195 goto done;
196 }
197
198 if (rc == NGX_CONF_FILE_DONE) {
199
200 if (type == parse_block) {
201 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
202 "unexpected end of file, expecting \"}\"");
203 goto failed;
204 }
205
206 goto done;
207 }
208
209 if (rc == NGX_CONF_BLOCK_START) {
210
211 if (type == parse_param) {
212 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
213 "block directives are not supported "
214 "in -g option");
215 goto failed;
216 }
217 }
218
219 /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */
220
221 if (cf->handler) {
222
223 /*
224 * the custom handler, i.e., that is used in the http's
225 * "types { ... }" directive
226 */
227
228 rv = (*cf->handler)(cf, NULL, cf->handler_conf);
229 if (rv == NGX_CONF_OK) {
230 continue;
231 }
232
233 if (rv == NGX_CONF_ERROR) {
234 goto failed;
235 }
236
237 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);
238
239 goto failed;
240 }
241
242
243 rc = ngx_conf_handler(cf, rc);
244
245 if (rc == NGX_ERROR) {
246 goto failed;
247 }
248 }
249
250 failed:
251
252 rc = NGX_ERROR;
253
254 done:
255
256 if (filename) {
257 if (cf->conf_file->buffer->start) {
258 ngx_free(cf->conf_file->buffer->start);
259 }
260
261 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
262 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
263 ngx_close_file_n " %s failed",
264 cf->conf_file->file.name.data);
265 return NGX_CONF_ERROR;
266 }
267
268 cf->conf_file = prev;
269 }
270
271 if (rc == NGX_ERROR) {
272 return NGX_CONF_ERROR;
273 }
274
275 return NGX_CONF_OK;
276 }
277
278
279 static ngx_int_t
280 ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
281 {
282 char *rv;
283 void *conf, **confp;
284 ngx_uint_t i, multi;
285 ngx_str_t *name;
286 ngx_command_t *cmd;
287
288 name = cf->args->elts;
289
290 multi = 0;
291
292 for (i = 0; ngx_modules[i]; i++) {
293
294 /* look up the directive in the appropriate modules */
295
296 if (ngx_modules[i]->type != NGX_CONF_MODULE
297 && ngx_modules[i]->type != cf->module_type)
298 {
299 continue;
300 }
301
302 cmd = ngx_modules[i]->commands;
303 if (cmd == NULL) {
304 continue;
305 }
306
307 for ( /* void */ ; cmd->name.len; cmd++) {
308
309 if (name->len != cmd->name.len) {
310 continue;
311 }
312
313 if (ngx_strcmp(name->data, cmd->name.data) != 0) {
314 continue;
315 }
316
317
318 /* is the directive's location right ? */
319
320 if (!(cmd->type & cf->cmd_type)) {
321 if (cmd->type & NGX_CONF_MULTI) {
322 multi = 1;
323 continue;
324 }
325
326 goto not_allowed;
327 }
328
329 if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
330 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
331 "directive \"%s\" is not terminated by \";\"",
332 name->data);
333 return NGX_ERROR;
334 }
335
336 if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {
337 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
338 "directive \"%s\" has no opening \"{\"",
339 name->data);
340 return NGX_ERROR;
341 }
342
343 /* is the directive's argument count right ? */
344
345 if (!(cmd->type & NGX_CONF_ANY)) {
346
347 if (cmd->type & NGX_CONF_FLAG) {
348
349 if (cf->args->nelts != 2) {
350 goto invalid;
351 }
352
353 } else if (cmd->type & NGX_CONF_1MORE) {
354
355 if (cf->args->nelts < 2) {
356 goto invalid;
357 }
358
359 } else if (cmd->type & NGX_CONF_2MORE) {
360
361 if (cf->args->nelts < 3) {
362 goto invalid;
363 }
364
365 } else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {
366
367 goto invalid;
368
369 } else if (!(cmd->type & argument_number[cf->args->nelts - 1]))
370 {
371 goto invalid;
372 }
373 }
374
375 /* set up the directive's configuration context */
376
377 conf = NULL;
378
379 if (cmd->type & NGX_DIRECT_CONF) {
380 conf = ((void **) cf->ctx)[ngx_modules[i]->index];
381
382 } else if (cmd->type & NGX_MAIN_CONF) {
383 conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
384
385 } else if (cf->ctx) {
386 confp = *(void **) ((char *) cf->ctx + cmd->conf);
387
388 if (confp) {
389 conf = confp[ngx_modules[i]->ctx_index];
390 }
391 }
392
393 rv = cmd->set(cf, cmd, conf);
394
395 if (rv == NGX_CONF_OK) {
396 return NGX_OK;
397 }
398
399 if (rv == NGX_CONF_ERROR) {
400 return NGX_ERROR;
401 }
402
403 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
404 "\"%s\" directive %s", name->data, rv);
405
406 return NGX_ERROR;
407 }
408 }
409
410 if (multi == 0) {
411 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
412 "unknown directive \"%s\"", name->data);
413
414 return NGX_ERROR;
415 }
416
417 not_allowed:
418
419 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
420 "\"%s\" directive is not allowed here", name->data);
421 return NGX_ERROR;
422
423 invalid:
424
425 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
426 "invalid number of arguments in \"%s\" directive",
427 name->data);
428
429 return NGX_ERROR;
430 }
431
432
433 static ngx_int_t
434 ngx_conf_read_token(ngx_conf_t *cf)
435 {
436 u_char *start, ch, *src, *dst;
437 off_t file_size;
438 size_t len;
439 ssize_t n, size;
440 ngx_uint_t found, need_space, last_space, sharp_comment, variable;
441 ngx_uint_t quoted, s_quoted, d_quoted, start_line;
442 ngx_str_t *word;
443 ngx_buf_t *b;
444
445 found = 0;
446 need_space = 0;
447 last_space = 1;
448 sharp_comment = 0;
449 variable = 0;
450 quoted = 0;
451 s_quoted = 0;
452 d_quoted = 0;
453
454 cf->args->nelts = 0;
455 b = cf->conf_file->buffer;
456 start = b->pos;
457 start_line = cf->conf_file->line;
458
459 file_size = ngx_file_size(&cf->conf_file->file.info);
460
461 for ( ;; ) {
462
463 if (b->pos >= b->last) {
464
465 if (cf->conf_file->file.offset >= file_size) {
466
467 if (cf->args->nelts > 0) {
468
469 if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
470 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
471 "unexpected end of parameter, "
472 "expecting \";\"");
473 return NGX_ERROR;
474 }
475
476 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
477 "unexpected end of file, "
478 "expecting \";\" or \"}\"");
479 return NGX_ERROR;
480 }
481
482 return NGX_CONF_FILE_DONE;
483 }
484
485 len = b->pos - start;
486
487 if (len == NGX_CONF_BUFFER) {
488 cf->conf_file->line = start_line;
489
490 if (d_quoted) {
491 ch = '"';
492
493 } else if (s_quoted) {
494 ch = '\'';
495
496 } else {
497 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
498 "too long parameter \"%*s...\" started",
499 10, start);
500 return NGX_ERROR;
501 }
502
503 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
504 "too long parameter, probably "
505 "missing terminating \"%c\" character", ch);
506 return NGX_ERROR;
507 }
508
509 if (len) {
510 ngx_memcpy(b->start, start, len);
511 }
512
513 size = (ssize_t) (file_size - cf->conf_file->file.offset);
514
515 if (size > b->end - (b->start + len)) {
516 size = b->end - (b->start + len);
517 }
518
519 n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
520 cf->conf_file->file.offset);
521
522 if (n == NGX_ERROR) {
523 return NGX_ERROR;
524 }
525
526 if (n != size) {
527 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
528 ngx_read_file_n " returned "
529 "only %z bytes instead of %z",
530 n, size);
531 return NGX_ERROR;
532 }
533
534 b->pos = b->start + len;
535 b->last = b->pos + n;
536 start = b->start;
537 }
538
539 ch = *b->pos++;
540
541 if (ch == LF) {
542 cf->conf_file->line++;
543
544 if (sharp_comment) {
545 sharp_comment = 0;
546 }
547 }
548
549 if (sharp_comment) {
550 continue;
551 }
552
553 if (quoted) {
554 quoted = 0;
555 continue;
556 }
557
558 if (need_space) {
559 if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
560 last_space = 1;
561 need_space = 0;
562 continue;
563 }
564
565 if (ch == ';') {
566 return NGX_OK;
567 }
568
569 if (ch == '{') {
570 return NGX_CONF_BLOCK_START;
571 }
572
573 if (ch == ')') {
574 last_space = 1;
575 need_space = 0;
576
577 } else {
578 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
579 "unexpected \"%c\"", ch);
580 return NGX_ERROR;
581 }
582 }
583
584 if (last_space) {
585 if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
586 continue;
587 }
588
589 start = b->pos - 1;
590 start_line = cf->conf_file->line;
591
592 switch (ch) {
593
594 case ';':
595 case '{':
596 if (cf->args->nelts == 0) {
597 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
598 "unexpected \"%c\"", ch);
599 return NGX_ERROR;
600 }
601
602 if (ch == '{') {
603 return NGX_CONF_BLOCK_START;
604 }
605
606 return NGX_OK;
607
608 case '}':
609 if (cf->args->nelts != 0) {
610 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
611 "unexpected \"}\"");
612 return NGX_ERROR;
613 }
614
615 return NGX_CONF_BLOCK_DONE;
616
617 case '#':
618 sharp_comment = 1;
619 continue;
620
621 case '\\':
622 quoted = 1;
623 last_space = 0;
624 continue;
625
626 case '"':
627 start++;
628 d_quoted = 1;
629 last_space = 0;
630 continue;
631
632 case '\'':
633 start++;
634 s_quoted = 1;
635 last_space = 0;
636 continue;
637
638 default:
639 last_space = 0;
640 }
641
642 } else {
643 if (ch == '{' && variable) {
644 continue;
645 }
646
647 variable = 0;
648
649 if (ch == '\\') {
650 quoted = 1;
651 continue;
652 }
653
654 if (ch == '$') {
655 variable = 1;
656 continue;
657 }
658
659 if (d_quoted) {
660 if (ch == '"') {
661 d_quoted = 0;
662 need_space = 1;
663 found = 1;
664 }
665
666 } else if (s_quoted) {
667 if (ch == '\'') {
668 s_quoted = 0;
669 need_space = 1;
670 found = 1;
671 }
672
673 } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
674 || ch == ';' || ch == '{') {
675 last_space = 1;
676 found = 1;
677 }
678
679 if (found) {
680 word = ngx_array_push(cf->args);
681 if (word == NULL) {
682 return NGX_ERROR;
683 }
684
685 word->data = ngx_pnalloc(cf->pool, b->pos - start + 1);
686 if (word->data == NULL) {
687 return NGX_ERROR;
688 }
689
690 for (dst = word->data, src = start, len = 0;
691 src < b->pos - 1;
692 len++)
693 {
694 if (*src == '\\') {
695 switch (src[1]) {
696 case '"':
697 case '\'':
698 case '\\':
699 src++;
700 break;
701
702 case 't':
703 *dst++ = '\t';
704 src += 2;
705 continue;
706
707 case 'r':
708 *dst++ = '\r';
709 src += 2;
710 continue;
711
712 case 'n':
713 *dst++ = '\n';
714 src += 2;
715 continue;
716 }
717
718 }
719 *dst++ = *src++;
720 }
721 *dst = '\0';
722 word->len = len;
723
724 if (ch == ';') {
725 return NGX_OK;
726 }
727
728 if (ch == '{') {
729 return NGX_CONF_BLOCK_START;
730 }
731
732 found = 0;
733 }
734 }
735 }
736 }
737
738
739 static char *
740 ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
741 {
742 char *rv;
743 ngx_int_t n;
744 ngx_str_t *value, file, name;
745 ngx_glob_t gl;
746
747 value = cf->args->elts;
748 file = value[1];
749
750 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
751
752 if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
753 return NGX_CONF_ERROR;
754 }
755
756 if (strpbrk((char *) file.data, "*?[") == NULL) {
757
758 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
759
760 return ngx_conf_parse(cf, &file);
761 }
762
763 ngx_memzero(&gl, sizeof(ngx_glob_t));
764
765 gl.pattern = file.data;
766 gl.log = cf->log;
767 gl.test = 1;
768
769 if (ngx_open_glob(&gl) != NGX_OK) {
770 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
771 ngx_open_glob_n " \"%s\" failed", file.data);
772 return NGX_CONF_ERROR;
773 }
774
775 rv = NGX_CONF_OK;
776
777 for ( ;; ) {
778 n = ngx_read_glob(&gl, &name);
779
780 if (n != NGX_OK) {
781 break;
782 }
783
784 file.len = name.len++;
785 file.data = ngx_pstrdup(cf->pool, &name);
786
787 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
788
789 rv = ngx_conf_parse(cf, &file);
790
791 if (rv != NGX_CONF_OK) {
792 break;
793 }
794 }
795
796 ngx_close_glob(&gl);
797
798 return rv;
799 }
800
801
802 ngx_int_t
803 ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix)
804 {
805 size_t len;
806 u_char *p, *n, *prefix;
807 ngx_int_t rc;
808
809 rc = ngx_conf_test_full_name(name);
810
811 if (rc == NGX_OK) {
812 return rc;
813 }
814
815 if (conf_prefix) {
816 len = cycle->conf_prefix.len;
817 prefix = cycle->conf_prefix.data;
818
819 } else {
820 len = cycle->prefix.len;
821 prefix = cycle->prefix.data;
822 }
823
824 #if (NGX_WIN32)
825
826 if (rc == 2) {
827 len = rc;
828 }
829
830 #endif
831
832 n = ngx_pnalloc(cycle->pool, len + name->len + 1);
833 if (n == NULL) {
834 return NGX_ERROR;
835 }
836
837 p = ngx_cpymem(n, prefix, len);
838 ngx_cpystrn(p, name->data, name->len + 1);
839
840 name->len += len;
841 name->data = n;
842
843 return NGX_OK;
844 }
845
846
847 static ngx_int_t
848 ngx_conf_test_full_name(ngx_str_t *name)
849 {
850 #if (NGX_WIN32)
851 u_char c0, c1;
852
853 c0 = name->data[0];
854
855 if (name->len < 2) {
856 if (c0 == '/') {
857 return 2;
858 }
859
860 return NGX_DECLINED;
861 }
862
863 c1 = name->data[1];
864
865 if (c1 == ':') {
866 c0 |= 0x20;
867
868 if ((c0 >= 'a' && c0 <= 'z')) {
869 return NGX_OK;
870 }
871
872 return NGX_DECLINED;
873 }
874
875 if (c1 == '/') {
876 return NGX_OK;
877 }
878
879 if (c0 == '/') {
880 return 2;
881 }
882
883 return NGX_DECLINED;
884
885 #else
886
887 if (name->data[0] == '/') {
888 return NGX_OK;
889 }
890
891 return NGX_DECLINED;
892
893 #endif
894 }
895
896
897 ngx_open_file_t *
898 ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
899 {
900 ngx_str_t full;
901 ngx_uint_t i;
902 ngx_list_part_t *part;
903 ngx_open_file_t *file;
904
905 #if (NGX_SUPPRESS_WARN)
906 full.len = 0;
907 full.data = NULL;
908 #endif
909
910 if (name->len) {
911 full = *name;
912
913 if (ngx_conf_full_name(cycle, &full, 0) != NGX_OK) {
914 return NULL;
915 }
916
917 part = &cycle->open_files.part;
918 file = part->elts;
919
920 for (i = 0; /* void */ ; i++) {
921
922 if (i >= part->nelts) {
923 if (part->next == NULL) {
924 break;
925 }
926 part = part->next;
927 file = part->elts;
928 i = 0;
929 }
930
931 if (full.len != file[i].name.len) {
932 continue;
933 }
934
935 if (ngx_strcmp(full.data, file[i].name.data) == 0) {
936 return &file[i];
937 }
938 }
939 }
940
941 file = ngx_list_push(&cycle->open_files);
942 if (file == NULL) {
943 return NULL;
944 }
945
946 if (name->len) {
947 file->fd = NGX_INVALID_FILE;
948 file->name = full;
949
950 } else {
951 file->fd = ngx_stderr;
952 file->name = *name;
953 }
954
955 file->buffer = NULL;
956
957 return file;
958 }
959
960
961 static void
962 ngx_conf_flush_files(ngx_cycle_t *cycle)
963 {
964 ssize_t n, len;
965 ngx_uint_t i;
966 ngx_list_part_t *part;
967 ngx_open_file_t *file;
968
969 ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "flush files");
970
971 part = &cycle->open_files.part;
972 file = part->elts;
973
974 for (i = 0; /* void */ ; i++) {
975
976 if (i >= part->nelts) {
977 if (part->next == NULL) {
978 break;
979 }
980 part = part->next;
981 file = part->elts;
982 i = 0;
983 }
984
985 len = file[i].pos - file[i].buffer;
986
987 if (file[i].buffer == NULL || len == 0) {
988 continue;
989 }
990
991 n = ngx_write_fd(file[i].fd, file[i].buffer, len);
992
993 if (n == NGX_FILE_ERROR) {
994 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
995 ngx_write_fd_n " to \"%s\" failed",
996 file[i].name.data);
997
998 } else if (n != len) {
999 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
1000 ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
1001 file[i].name.data, n, len);
1002 }
1003 }
1004 }
1005
1006
1007 void ngx_cdecl
1008 ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
1009 char *fmt, ...)
1010 {
1011 u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last;
1012 va_list args;
1013
1014 last = errstr + NGX_MAX_CONF_ERRSTR;
1015
1016 va_start(args, fmt);
1017 p = ngx_vslprintf(errstr, last, fmt, args);
1018 va_end(args);
1019
1020 if (err) {
1021 p = ngx_log_errno(p, last, err);
1022 }
1023
1024 if (cf->conf_file == NULL) {
1025 ngx_log_error(level, cf->log, 0, "%*s", p - errstr, errstr);
1026 return;
1027 }
1028
1029 if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
1030 ngx_log_error(level, cf->log, 0, "%*s in command line",
1031 p - errstr, errstr);
1032 return;
1033 }
1034
1035 ngx_log_error(level, cf->log, 0, "%*s in %s:%ui",
1036 p - errstr, errstr,
1037 cf->conf_file->file.name.data, cf->conf_file->line);
1038 }
1039
1040
1041 char *
1042 ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1043 {
1044 char *p = conf;
1045
1046 ngx_str_t *value;
1047 ngx_flag_t *fp;
1048 ngx_conf_post_t *post;
1049
1050 fp = (ngx_flag_t *) (p + cmd->offset);
1051
1052 if (*fp != NGX_CONF_UNSET) {
1053 return "is duplicate";
1054 }
1055
1056 value = cf->args->elts;
1057
1058 if (ngx_strcasecmp(value[1].data, (u_char *) "on") == 0) {
1059 *fp = 1;
1060
1061 } else if (ngx_strcasecmp(value[1].data, (u_char *) "off") == 0) {
1062 *fp = 0;
1063
1064 } else {
1065 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1066 "invalid value \"%s\" in \"%s\" directive, "
1067 "it must be \"on\" or \"off\"",
1068 value[1].data, cmd->name.data);
1069 return NGX_CONF_ERROR;
1070 }
1071
1072 if (cmd->post) {
1073 post = cmd->post;
1074 return post->post_handler(cf, post, fp);
1075 }
1076
1077 return NGX_CONF_OK;
1078 }
1079
1080
1081 char *
1082 ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1083 {
1084 char *p = conf;
1085
1086 ngx_str_t *field, *value;
1087 ngx_conf_post_t *post;
1088
1089 field = (ngx_str_t *) (p + cmd->offset);
1090
1091 if (field->data) {
1092 return "is duplicate";
1093 }
1094
1095 value = cf->args->elts;
1096
1097 *field = value[1];
1098
1099 if (cmd->post) {
1100 post = cmd->post;
1101 return post->post_handler(cf, post, field);
1102 }
1103
1104 return NGX_CONF_OK;
1105 }
1106
1107
1108 char *
1109 ngx_conf_set_str_array_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1110 {
1111 char *p = conf;
1112
1113 ngx_str_t *value, *s;
1114 ngx_array_t **a;
1115 ngx_conf_post_t *post;
1116
1117 a = (ngx_array_t **) (p + cmd->offset);
1118
1119 if (*a == NGX_CONF_UNSET_PTR) {
1120 *a = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
1121 if (*a == NULL) {
1122 return NGX_CONF_ERROR;
1123 }
1124 }
1125
1126 s = ngx_array_push(*a);
1127 if (s == NULL) {
1128 return NGX_CONF_ERROR;
1129 }
1130
1131 value = cf->args->elts;
1132
1133 *s = value[1];
1134
1135 if (cmd->post) {
1136 post = cmd->post;
1137 return post->post_handler(cf, post, s);
1138 }
1139
1140 return NGX_CONF_OK;
1141 }
1142
1143
1144 char *
1145 ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1146 {
1147 char *p = conf;
1148
1149 ngx_str_t *value;
1150 ngx_array_t **a;
1151 ngx_keyval_t *kv;
1152 ngx_conf_post_t *post;
1153
1154 a = (ngx_array_t **) (p + cmd->offset);
1155
1156 if (*a == NULL) {
1157 *a = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t));
1158 if (*a == NULL) {
1159 return NGX_CONF_ERROR;
1160 }
1161 }
1162
1163 kv = ngx_array_push(*a);
1164 if (kv == NULL) {
1165 return NGX_CONF_ERROR;
1166 }
1167
1168 value = cf->args->elts;
1169
1170 kv->key = value[1];
1171 kv->value = value[2];
1172
1173 if (cmd->post) {
1174 post = cmd->post;
1175 return post->post_handler(cf, post, kv);
1176 }
1177
1178 return NGX_CONF_OK;
1179 }
1180
1181
1182 char *
1183 ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1184 {
1185 char *p = conf;
1186
1187 ngx_int_t *np;
1188 ngx_str_t *value;
1189 ngx_conf_post_t *post;
1190
1191
1192 np = (ngx_int_t *) (p + cmd->offset);
1193
1194 if (*np != NGX_CONF_UNSET) {
1195 return "is duplicate";
1196 }
1197
1198 value = cf->args->elts;
1199 *np = ngx_atoi(value[1].data, value[1].len);
1200 if (*np == NGX_ERROR) {
1201 return "invalid number";
1202 }
1203
1204 if (cmd->post) {
1205 post = cmd->post;
1206 return post->post_handler(cf, post, np);
1207 }
1208
1209 return NGX_CONF_OK;
1210 }
1211
1212
1213 char *
1214 ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1215 {
1216 char *p = conf;
1217
1218 size_t *sp;
1219 ngx_str_t *value;
1220 ngx_conf_post_t *post;
1221
1222
1223 sp = (size_t *) (p + cmd->offset);
1224 if (*sp != NGX_CONF_UNSET_SIZE) {
1225 return "is duplicate";
1226 }
1227
1228 value = cf->args->elts;
1229
1230 *sp = ngx_parse_size(&value[1]);
1231 if (*sp == (size_t) NGX_ERROR) {
1232 return "invalid value";
1233 }
1234
1235 if (cmd->post) {
1236 post = cmd->post;
1237 return post->post_handler(cf, post, sp);
1238 }
1239
1240 return NGX_CONF_OK;
1241 }
1242
1243
1244 char *
1245 ngx_conf_set_off_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1246 {
1247 char *p = conf;
1248
1249 off_t *op;
1250 ngx_str_t *value;
1251 ngx_conf_post_t *post;
1252
1253
1254 op = (off_t *) (p + cmd->offset);
1255 if (*op != NGX_CONF_UNSET) {
1256 return "is duplicate";
1257 }
1258
1259 value = cf->args->elts;
1260
1261 *op = ngx_parse_offset(&value[1]);
1262 if (*op == (off_t) NGX_ERROR) {
1263 return "invalid value";
1264 }
1265
1266 if (cmd->post) {
1267 post = cmd->post;
1268 return post->post_handler(cf, post, op);
1269 }
1270
1271 return NGX_CONF_OK;
1272 }
1273
1274
1275 char *
1276 ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1277 {
1278 char *p = conf;
1279
1280 ngx_msec_t *msp;
1281 ngx_str_t *value;
1282 ngx_conf_post_t *post;
1283
1284
1285 msp = (ngx_msec_t *) (p + cmd->offset);
1286 if (*msp != NGX_CONF_UNSET_MSEC) {
1287 return "is duplicate";
1288 }
1289
1290 value = cf->args->elts;
1291
1292 *msp = ngx_parse_time(&value[1], 0);
1293 if (*msp == (ngx_msec_t) NGX_ERROR) {
1294 return "invalid value";
1295 }
1296
1297 if (*msp == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
1298 return "value must be less than 597 hours";
1299 }
1300
1301 if (cmd->post) {
1302 post = cmd->post;
1303 return post->post_handler(cf, post, msp);
1304 }
1305
1306 return NGX_CONF_OK;
1307 }
1308
1309
1310 char *
1311 ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1312 {
1313 char *p = conf;
1314
1315 time_t *sp;
1316 ngx_str_t *value;
1317 ngx_conf_post_t *post;
1318
1319
1320 sp = (time_t *) (p + cmd->offset);
1321 if (*sp != NGX_CONF_UNSET) {
1322 return "is duplicate";
1323 }
1324
1325 value = cf->args->elts;
1326
1327 *sp = ngx_parse_time(&value[1], 1);
1328 if (*sp == NGX_ERROR) {
1329 return "invalid value";
1330 }
1331
1332 if (*sp == NGX_PARSE_LARGE_TIME) {
1333 return "value must be less than 68 years";
1334 }
1335
1336 if (cmd->post) {
1337 post = cmd->post;
1338 return post->post_handler(cf, post, sp);
1339 }
1340
1341 return NGX_CONF_OK;
1342 }
1343
1344
1345 char *
1346 ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1347 {
1348 char *p = conf;
1349
1350 ngx_str_t *value;
1351 ngx_bufs_t *bufs;
1352
1353
1354 bufs = (ngx_bufs_t *) (p + cmd->offset);
1355 if (bufs->num) {
1356 return "is duplicate";
1357 }
1358
1359 value = cf->args->elts;
1360
1361 bufs->num = ngx_atoi(value[1].data, value[1].len);
1362 if (bufs->num == NGX_ERROR || bufs->num == 0) {
1363 return "invalid value";
1364 }
1365
1366 bufs->size = ngx_parse_size(&value[2]);
1367 if (bufs->size == (size_t) NGX_ERROR || bufs->size == 0) {
1368 return "invalid value";
1369 }
1370
1371 return NGX_CONF_OK;
1372 }
1373
1374
1375 char *
1376 ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1377 {
1378 char *p = conf;
1379
1380 ngx_uint_t *np, i;
1381 ngx_str_t *value;
1382 ngx_conf_enum_t *e;
1383
1384 np = (ngx_uint_t *) (p + cmd->offset);
1385
1386 if (*np != NGX_CONF_UNSET_UINT) {
1387 return "is duplicate";
1388 }
1389
1390 value = cf->args->elts;
1391 e = cmd->post;
1392
1393 for (i = 0; e[i].name.len != 0; i++) {
1394 if (e[i].name.len != value[1].len
1395 || ngx_strcasecmp(e[i].name.data, value[1].data) != 0)
1396 {
1397 continue;
1398 }
1399
1400 *np = e[i].value;
1401
1402 return NGX_CONF_OK;
1403 }
1404
1405 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1406 "invalid value \"%s\"", value[1].data);
1407
1408 return NGX_CONF_ERROR;
1409 }
1410
1411
1412 char *
1413 ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1414 {
1415 char *p = conf;
1416
1417 ngx_uint_t *np, i, m;
1418 ngx_str_t *value;
1419 ngx_conf_bitmask_t *mask;
1420
1421
1422 np = (ngx_uint_t *) (p + cmd->offset);
1423 value = cf->args->elts;
1424 mask = cmd->post;
1425
1426 for (i = 1; i < cf->args->nelts; i++) {
1427 for (m = 0; mask[m].name.len != 0; m++) {
1428
1429 if (mask[m].name.len != value[i].len
1430 || ngx_strcasecmp(mask[m].name.data, value[i].data) != 0)
1431 {
1432 continue;
1433 }
1434
1435 if (*np & mask[m].mask) {
1436 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1437 "duplicate value \"%s\"", value[i].data);
1438
1439 } else {
1440 *np |= mask[m].mask;
1441 }
1442
1443 break;
1444 }
1445
1446 if (mask[m].name.len == 0) {
1447 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1448 "invalid value \"%s\"", value[i].data);
1449
1450 return NGX_CONF_ERROR;
1451 }
1452 }
1453
1454 return NGX_CONF_OK;
1455 }
1456
1457
1458 char *
1459 ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1460 {
1461 return "unsupported on this platform";
1462 }
1463
1464
1465 char *
1466 ngx_conf_deprecated(ngx_conf_t *cf, void *post, void *data)
1467 {
1468 ngx_conf_deprecated_t *d = post;
1469
1470 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1471 "the \"%s\" directive is deprecated, "
1472 "use the \"%s\" directive instead",
1473 d->old_name, d->new_name);
1474
1475 return NGX_CONF_OK;
1476 }
1477
1478
1479 char *
1480 ngx_conf_check_num_bounds(ngx_conf_t *cf, void *post, void *data)
1481 {
1482 ngx_conf_num_bounds_t *bounds = post;
1483 ngx_int_t *np = data;
1484
1485 if (bounds->high == -1) {
1486 if (*np >= bounds->low) {
1487 return NGX_CONF_OK;
1488 }
1489
1490 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1491 "value must be equal or more than %i", bounds->low);
1492
1493 return NGX_CONF_ERROR;
1494 }
1495
1496 if (*np >= bounds->low && *np <= bounds->high) {
1497 return NGX_CONF_OK;
1498 }
1499
1500 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1501 "value must be between %i and %i",
1502 bounds->low, bounds->high);
1503
1504 return NGX_CONF_ERROR;
1505 }
1506
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.