Annotation of embedaddon/nginx/src/core/ngx_conf_file.c, revision 1.1.1.1
1.1 misho 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:
11: #define NGX_CONF_BUFFER 4096
12:
13: static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last);
14: static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf);
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) == NGX_FILE_ERROR) {
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: filename->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, found;
285: ngx_str_t *name;
286: ngx_command_t *cmd;
287:
288: name = cf->args->elts;
289:
290: found = 0;
291:
292: for (i = 0; ngx_modules[i]; i++) {
293:
294: cmd = ngx_modules[i]->commands;
295: if (cmd == NULL) {
296: continue;
297: }
298:
299: for ( /* void */ ; cmd->name.len; cmd++) {
300:
301: if (name->len != cmd->name.len) {
302: continue;
303: }
304:
305: if (ngx_strcmp(name->data, cmd->name.data) != 0) {
306: continue;
307: }
308:
309: found = 1;
310:
311: if (ngx_modules[i]->type != NGX_CONF_MODULE
312: && ngx_modules[i]->type != cf->module_type)
313: {
314: continue;
315: }
316:
317: /* is the directive's location right ? */
318:
319: if (!(cmd->type & cf->cmd_type)) {
320: continue;
321: }
322:
323: if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
324: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
325: "directive \"%s\" is not terminated by \";\"",
326: name->data);
327: return NGX_ERROR;
328: }
329:
330: if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {
331: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
332: "directive \"%s\" has no opening \"{\"",
333: name->data);
334: return NGX_ERROR;
335: }
336:
337: /* is the directive's argument count right ? */
338:
339: if (!(cmd->type & NGX_CONF_ANY)) {
340:
341: if (cmd->type & NGX_CONF_FLAG) {
342:
343: if (cf->args->nelts != 2) {
344: goto invalid;
345: }
346:
347: } else if (cmd->type & NGX_CONF_1MORE) {
348:
349: if (cf->args->nelts < 2) {
350: goto invalid;
351: }
352:
353: } else if (cmd->type & NGX_CONF_2MORE) {
354:
355: if (cf->args->nelts < 3) {
356: goto invalid;
357: }
358:
359: } else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {
360:
361: goto invalid;
362:
363: } else if (!(cmd->type & argument_number[cf->args->nelts - 1]))
364: {
365: goto invalid;
366: }
367: }
368:
369: /* set up the directive's configuration context */
370:
371: conf = NULL;
372:
373: if (cmd->type & NGX_DIRECT_CONF) {
374: conf = ((void **) cf->ctx)[ngx_modules[i]->index];
375:
376: } else if (cmd->type & NGX_MAIN_CONF) {
377: conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
378:
379: } else if (cf->ctx) {
380: confp = *(void **) ((char *) cf->ctx + cmd->conf);
381:
382: if (confp) {
383: conf = confp[ngx_modules[i]->ctx_index];
384: }
385: }
386:
387: rv = cmd->set(cf, cmd, conf);
388:
389: if (rv == NGX_CONF_OK) {
390: return NGX_OK;
391: }
392:
393: if (rv == NGX_CONF_ERROR) {
394: return NGX_ERROR;
395: }
396:
397: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
398: "\"%s\" directive %s", name->data, rv);
399:
400: return NGX_ERROR;
401: }
402: }
403:
404: if (found) {
405: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
406: "\"%s\" directive is not allowed here", name->data);
407:
408: return NGX_ERROR;
409: }
410:
411: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
412: "unknown directive \"%s\"", name->data);
413:
414: return NGX_ERROR;
415:
416: invalid:
417:
418: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
419: "invalid number of arguments in \"%s\" directive",
420: name->data);
421:
422: return NGX_ERROR;
423: }
424:
425:
426: static ngx_int_t
427: ngx_conf_read_token(ngx_conf_t *cf)
428: {
429: u_char *start, ch, *src, *dst;
430: off_t file_size;
431: size_t len;
432: ssize_t n, size;
433: ngx_uint_t found, need_space, last_space, sharp_comment, variable;
434: ngx_uint_t quoted, s_quoted, d_quoted, start_line;
435: ngx_str_t *word;
436: ngx_buf_t *b;
437:
438: found = 0;
439: need_space = 0;
440: last_space = 1;
441: sharp_comment = 0;
442: variable = 0;
443: quoted = 0;
444: s_quoted = 0;
445: d_quoted = 0;
446:
447: cf->args->nelts = 0;
448: b = cf->conf_file->buffer;
449: start = b->pos;
450: start_line = cf->conf_file->line;
451:
452: file_size = ngx_file_size(&cf->conf_file->file.info);
453:
454: for ( ;; ) {
455:
456: if (b->pos >= b->last) {
457:
458: if (cf->conf_file->file.offset >= file_size) {
459:
460: if (cf->args->nelts > 0 || !last_space) {
461:
462: if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
463: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
464: "unexpected end of parameter, "
465: "expecting \";\"");
466: return NGX_ERROR;
467: }
468:
469: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
470: "unexpected end of file, "
471: "expecting \";\" or \"}\"");
472: return NGX_ERROR;
473: }
474:
475: return NGX_CONF_FILE_DONE;
476: }
477:
478: len = b->pos - start;
479:
480: if (len == NGX_CONF_BUFFER) {
481: cf->conf_file->line = start_line;
482:
483: if (d_quoted) {
484: ch = '"';
485:
486: } else if (s_quoted) {
487: ch = '\'';
488:
489: } else {
490: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
491: "too long parameter \"%*s...\" started",
492: 10, start);
493: return NGX_ERROR;
494: }
495:
496: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
497: "too long parameter, probably "
498: "missing terminating \"%c\" character", ch);
499: return NGX_ERROR;
500: }
501:
502: if (len) {
503: ngx_memmove(b->start, start, len);
504: }
505:
506: size = (ssize_t) (file_size - cf->conf_file->file.offset);
507:
508: if (size > b->end - (b->start + len)) {
509: size = b->end - (b->start + len);
510: }
511:
512: n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
513: cf->conf_file->file.offset);
514:
515: if (n == NGX_ERROR) {
516: return NGX_ERROR;
517: }
518:
519: if (n != size) {
520: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
521: ngx_read_file_n " returned "
522: "only %z bytes instead of %z",
523: n, size);
524: return NGX_ERROR;
525: }
526:
527: b->pos = b->start + len;
528: b->last = b->pos + n;
529: start = b->start;
530: }
531:
532: ch = *b->pos++;
533:
534: if (ch == LF) {
535: cf->conf_file->line++;
536:
537: if (sharp_comment) {
538: sharp_comment = 0;
539: }
540: }
541:
542: if (sharp_comment) {
543: continue;
544: }
545:
546: if (quoted) {
547: quoted = 0;
548: continue;
549: }
550:
551: if (need_space) {
552: if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
553: last_space = 1;
554: need_space = 0;
555: continue;
556: }
557:
558: if (ch == ';') {
559: return NGX_OK;
560: }
561:
562: if (ch == '{') {
563: return NGX_CONF_BLOCK_START;
564: }
565:
566: if (ch == ')') {
567: last_space = 1;
568: need_space = 0;
569:
570: } else {
571: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
572: "unexpected \"%c\"", ch);
573: return NGX_ERROR;
574: }
575: }
576:
577: if (last_space) {
578: if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
579: continue;
580: }
581:
582: start = b->pos - 1;
583: start_line = cf->conf_file->line;
584:
585: switch (ch) {
586:
587: case ';':
588: case '{':
589: if (cf->args->nelts == 0) {
590: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
591: "unexpected \"%c\"", ch);
592: return NGX_ERROR;
593: }
594:
595: if (ch == '{') {
596: return NGX_CONF_BLOCK_START;
597: }
598:
599: return NGX_OK;
600:
601: case '}':
602: if (cf->args->nelts != 0) {
603: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
604: "unexpected \"}\"");
605: return NGX_ERROR;
606: }
607:
608: return NGX_CONF_BLOCK_DONE;
609:
610: case '#':
611: sharp_comment = 1;
612: continue;
613:
614: case '\\':
615: quoted = 1;
616: last_space = 0;
617: continue;
618:
619: case '"':
620: start++;
621: d_quoted = 1;
622: last_space = 0;
623: continue;
624:
625: case '\'':
626: start++;
627: s_quoted = 1;
628: last_space = 0;
629: continue;
630:
631: default:
632: last_space = 0;
633: }
634:
635: } else {
636: if (ch == '{' && variable) {
637: continue;
638: }
639:
640: variable = 0;
641:
642: if (ch == '\\') {
643: quoted = 1;
644: continue;
645: }
646:
647: if (ch == '$') {
648: variable = 1;
649: continue;
650: }
651:
652: if (d_quoted) {
653: if (ch == '"') {
654: d_quoted = 0;
655: need_space = 1;
656: found = 1;
657: }
658:
659: } else if (s_quoted) {
660: if (ch == '\'') {
661: s_quoted = 0;
662: need_space = 1;
663: found = 1;
664: }
665:
666: } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
667: || ch == ';' || ch == '{')
668: {
669: last_space = 1;
670: found = 1;
671: }
672:
673: if (found) {
674: word = ngx_array_push(cf->args);
675: if (word == NULL) {
676: return NGX_ERROR;
677: }
678:
679: word->data = ngx_pnalloc(cf->pool, b->pos - start + 1);
680: if (word->data == NULL) {
681: return NGX_ERROR;
682: }
683:
684: for (dst = word->data, src = start, len = 0;
685: src < b->pos - 1;
686: len++)
687: {
688: if (*src == '\\') {
689: switch (src[1]) {
690: case '"':
691: case '\'':
692: case '\\':
693: src++;
694: break;
695:
696: case 't':
697: *dst++ = '\t';
698: src += 2;
699: continue;
700:
701: case 'r':
702: *dst++ = '\r';
703: src += 2;
704: continue;
705:
706: case 'n':
707: *dst++ = '\n';
708: src += 2;
709: continue;
710: }
711:
712: }
713: *dst++ = *src++;
714: }
715: *dst = '\0';
716: word->len = len;
717:
718: if (ch == ';') {
719: return NGX_OK;
720: }
721:
722: if (ch == '{') {
723: return NGX_CONF_BLOCK_START;
724: }
725:
726: found = 0;
727: }
728: }
729: }
730: }
731:
732:
733: char *
734: ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
735: {
736: char *rv;
737: ngx_int_t n;
738: ngx_str_t *value, file, name;
739: ngx_glob_t gl;
740:
741: value = cf->args->elts;
742: file = value[1];
743:
744: ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
745:
746: if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
747: return NGX_CONF_ERROR;
748: }
749:
750: if (strpbrk((char *) file.data, "*?[") == NULL) {
751:
752: ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
753:
754: return ngx_conf_parse(cf, &file);
755: }
756:
757: ngx_memzero(&gl, sizeof(ngx_glob_t));
758:
759: gl.pattern = file.data;
760: gl.log = cf->log;
761: gl.test = 1;
762:
763: if (ngx_open_glob(&gl) != NGX_OK) {
764: ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
765: ngx_open_glob_n " \"%s\" failed", file.data);
766: return NGX_CONF_ERROR;
767: }
768:
769: rv = NGX_CONF_OK;
770:
771: for ( ;; ) {
772: n = ngx_read_glob(&gl, &name);
773:
774: if (n != NGX_OK) {
775: break;
776: }
777:
778: file.len = name.len++;
779: file.data = ngx_pstrdup(cf->pool, &name);
780:
781: ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
782:
783: rv = ngx_conf_parse(cf, &file);
784:
785: if (rv != NGX_CONF_OK) {
786: break;
787: }
788: }
789:
790: ngx_close_glob(&gl);
791:
792: return rv;
793: }
794:
795:
796: ngx_int_t
797: ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix)
798: {
799: size_t len;
800: u_char *p, *n, *prefix;
801: ngx_int_t rc;
802:
803: rc = ngx_conf_test_full_name(name);
804:
805: if (rc == NGX_OK) {
806: return rc;
807: }
808:
809: if (conf_prefix) {
810: len = cycle->conf_prefix.len;
811: prefix = cycle->conf_prefix.data;
812:
813: } else {
814: len = cycle->prefix.len;
815: prefix = cycle->prefix.data;
816: }
817:
818: #if (NGX_WIN32)
819:
820: if (rc == 2) {
821: len = rc;
822: }
823:
824: #endif
825:
826: n = ngx_pnalloc(cycle->pool, len + name->len + 1);
827: if (n == NULL) {
828: return NGX_ERROR;
829: }
830:
831: p = ngx_cpymem(n, prefix, len);
832: ngx_cpystrn(p, name->data, name->len + 1);
833:
834: name->len += len;
835: name->data = n;
836:
837: return NGX_OK;
838: }
839:
840:
841: static ngx_int_t
842: ngx_conf_test_full_name(ngx_str_t *name)
843: {
844: #if (NGX_WIN32)
845: u_char c0, c1;
846:
847: c0 = name->data[0];
848:
849: if (name->len < 2) {
850: if (c0 == '/') {
851: return 2;
852: }
853:
854: return NGX_DECLINED;
855: }
856:
857: c1 = name->data[1];
858:
859: if (c1 == ':') {
860: c0 |= 0x20;
861:
862: if ((c0 >= 'a' && c0 <= 'z')) {
863: return NGX_OK;
864: }
865:
866: return NGX_DECLINED;
867: }
868:
869: if (c1 == '/') {
870: return NGX_OK;
871: }
872:
873: if (c0 == '/') {
874: return 2;
875: }
876:
877: return NGX_DECLINED;
878:
879: #else
880:
881: if (name->data[0] == '/') {
882: return NGX_OK;
883: }
884:
885: return NGX_DECLINED;
886:
887: #endif
888: }
889:
890:
891: ngx_open_file_t *
892: ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
893: {
894: ngx_str_t full;
895: ngx_uint_t i;
896: ngx_list_part_t *part;
897: ngx_open_file_t *file;
898:
899: #if (NGX_SUPPRESS_WARN)
900: ngx_str_null(&full);
901: #endif
902:
903: if (name->len) {
904: full = *name;
905:
906: if (ngx_conf_full_name(cycle, &full, 0) != NGX_OK) {
907: return NULL;
908: }
909:
910: part = &cycle->open_files.part;
911: file = part->elts;
912:
913: for (i = 0; /* void */ ; i++) {
914:
915: if (i >= part->nelts) {
916: if (part->next == NULL) {
917: break;
918: }
919: part = part->next;
920: file = part->elts;
921: i = 0;
922: }
923:
924: if (full.len != file[i].name.len) {
925: continue;
926: }
927:
928: if (ngx_strcmp(full.data, file[i].name.data) == 0) {
929: return &file[i];
930: }
931: }
932: }
933:
934: file = ngx_list_push(&cycle->open_files);
935: if (file == NULL) {
936: return NULL;
937: }
938:
939: if (name->len) {
940: file->fd = NGX_INVALID_FILE;
941: file->name = full;
942:
943: } else {
944: file->fd = ngx_stderr;
945: file->name = *name;
946: }
947:
948: file->flush = NULL;
949: file->data = NULL;
950:
951: return file;
952: }
953:
954:
955: static void
956: ngx_conf_flush_files(ngx_cycle_t *cycle)
957: {
958: ngx_uint_t i;
959: ngx_list_part_t *part;
960: ngx_open_file_t *file;
961:
962: ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "flush files");
963:
964: part = &cycle->open_files.part;
965: file = part->elts;
966:
967: for (i = 0; /* void */ ; i++) {
968:
969: if (i >= part->nelts) {
970: if (part->next == NULL) {
971: break;
972: }
973: part = part->next;
974: file = part->elts;
975: i = 0;
976: }
977:
978: if (file[i].flush) {
979: file[i].flush(&file[i], cycle->log);
980: }
981: }
982: }
983:
984:
985: void ngx_cdecl
986: ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
987: const char *fmt, ...)
988: {
989: u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last;
990: va_list args;
991:
992: last = errstr + NGX_MAX_CONF_ERRSTR;
993:
994: va_start(args, fmt);
995: p = ngx_vslprintf(errstr, last, fmt, args);
996: va_end(args);
997:
998: if (err) {
999: p = ngx_log_errno(p, last, err);
1000: }
1001:
1002: if (cf->conf_file == NULL) {
1003: ngx_log_error(level, cf->log, 0, "%*s", p - errstr, errstr);
1004: return;
1005: }
1006:
1007: if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
1008: ngx_log_error(level, cf->log, 0, "%*s in command line",
1009: p - errstr, errstr);
1010: return;
1011: }
1012:
1013: ngx_log_error(level, cf->log, 0, "%*s in %s:%ui",
1014: p - errstr, errstr,
1015: cf->conf_file->file.name.data, cf->conf_file->line);
1016: }
1017:
1018:
1019: char *
1020: ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1021: {
1022: char *p = conf;
1023:
1024: ngx_str_t *value;
1025: ngx_flag_t *fp;
1026: ngx_conf_post_t *post;
1027:
1028: fp = (ngx_flag_t *) (p + cmd->offset);
1029:
1030: if (*fp != NGX_CONF_UNSET) {
1031: return "is duplicate";
1032: }
1033:
1034: value = cf->args->elts;
1035:
1036: if (ngx_strcasecmp(value[1].data, (u_char *) "on") == 0) {
1037: *fp = 1;
1038:
1039: } else if (ngx_strcasecmp(value[1].data, (u_char *) "off") == 0) {
1040: *fp = 0;
1041:
1042: } else {
1043: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1044: "invalid value \"%s\" in \"%s\" directive, "
1045: "it must be \"on\" or \"off\"",
1046: value[1].data, cmd->name.data);
1047: return NGX_CONF_ERROR;
1048: }
1049:
1050: if (cmd->post) {
1051: post = cmd->post;
1052: return post->post_handler(cf, post, fp);
1053: }
1054:
1055: return NGX_CONF_OK;
1056: }
1057:
1058:
1059: char *
1060: ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1061: {
1062: char *p = conf;
1063:
1064: ngx_str_t *field, *value;
1065: ngx_conf_post_t *post;
1066:
1067: field = (ngx_str_t *) (p + cmd->offset);
1068:
1069: if (field->data) {
1070: return "is duplicate";
1071: }
1072:
1073: value = cf->args->elts;
1074:
1075: *field = value[1];
1076:
1077: if (cmd->post) {
1078: post = cmd->post;
1079: return post->post_handler(cf, post, field);
1080: }
1081:
1082: return NGX_CONF_OK;
1083: }
1084:
1085:
1086: char *
1087: ngx_conf_set_str_array_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1088: {
1089: char *p = conf;
1090:
1091: ngx_str_t *value, *s;
1092: ngx_array_t **a;
1093: ngx_conf_post_t *post;
1094:
1095: a = (ngx_array_t **) (p + cmd->offset);
1096:
1097: if (*a == NGX_CONF_UNSET_PTR) {
1098: *a = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
1099: if (*a == NULL) {
1100: return NGX_CONF_ERROR;
1101: }
1102: }
1103:
1104: s = ngx_array_push(*a);
1105: if (s == NULL) {
1106: return NGX_CONF_ERROR;
1107: }
1108:
1109: value = cf->args->elts;
1110:
1111: *s = value[1];
1112:
1113: if (cmd->post) {
1114: post = cmd->post;
1115: return post->post_handler(cf, post, s);
1116: }
1117:
1118: return NGX_CONF_OK;
1119: }
1120:
1121:
1122: char *
1123: ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1124: {
1125: char *p = conf;
1126:
1127: ngx_str_t *value;
1128: ngx_array_t **a;
1129: ngx_keyval_t *kv;
1130: ngx_conf_post_t *post;
1131:
1132: a = (ngx_array_t **) (p + cmd->offset);
1133:
1134: if (*a == NULL) {
1135: *a = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t));
1136: if (*a == NULL) {
1137: return NGX_CONF_ERROR;
1138: }
1139: }
1140:
1141: kv = ngx_array_push(*a);
1142: if (kv == NULL) {
1143: return NGX_CONF_ERROR;
1144: }
1145:
1146: value = cf->args->elts;
1147:
1148: kv->key = value[1];
1149: kv->value = value[2];
1150:
1151: if (cmd->post) {
1152: post = cmd->post;
1153: return post->post_handler(cf, post, kv);
1154: }
1155:
1156: return NGX_CONF_OK;
1157: }
1158:
1159:
1160: char *
1161: ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1162: {
1163: char *p = conf;
1164:
1165: ngx_int_t *np;
1166: ngx_str_t *value;
1167: ngx_conf_post_t *post;
1168:
1169:
1170: np = (ngx_int_t *) (p + cmd->offset);
1171:
1172: if (*np != NGX_CONF_UNSET) {
1173: return "is duplicate";
1174: }
1175:
1176: value = cf->args->elts;
1177: *np = ngx_atoi(value[1].data, value[1].len);
1178: if (*np == NGX_ERROR) {
1179: return "invalid number";
1180: }
1181:
1182: if (cmd->post) {
1183: post = cmd->post;
1184: return post->post_handler(cf, post, np);
1185: }
1186:
1187: return NGX_CONF_OK;
1188: }
1189:
1190:
1191: char *
1192: ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1193: {
1194: char *p = conf;
1195:
1196: size_t *sp;
1197: ngx_str_t *value;
1198: ngx_conf_post_t *post;
1199:
1200:
1201: sp = (size_t *) (p + cmd->offset);
1202: if (*sp != NGX_CONF_UNSET_SIZE) {
1203: return "is duplicate";
1204: }
1205:
1206: value = cf->args->elts;
1207:
1208: *sp = ngx_parse_size(&value[1]);
1209: if (*sp == (size_t) NGX_ERROR) {
1210: return "invalid value";
1211: }
1212:
1213: if (cmd->post) {
1214: post = cmd->post;
1215: return post->post_handler(cf, post, sp);
1216: }
1217:
1218: return NGX_CONF_OK;
1219: }
1220:
1221:
1222: char *
1223: ngx_conf_set_off_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1224: {
1225: char *p = conf;
1226:
1227: off_t *op;
1228: ngx_str_t *value;
1229: ngx_conf_post_t *post;
1230:
1231:
1232: op = (off_t *) (p + cmd->offset);
1233: if (*op != NGX_CONF_UNSET) {
1234: return "is duplicate";
1235: }
1236:
1237: value = cf->args->elts;
1238:
1239: *op = ngx_parse_offset(&value[1]);
1240: if (*op == (off_t) NGX_ERROR) {
1241: return "invalid value";
1242: }
1243:
1244: if (cmd->post) {
1245: post = cmd->post;
1246: return post->post_handler(cf, post, op);
1247: }
1248:
1249: return NGX_CONF_OK;
1250: }
1251:
1252:
1253: char *
1254: ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1255: {
1256: char *p = conf;
1257:
1258: ngx_msec_t *msp;
1259: ngx_str_t *value;
1260: ngx_conf_post_t *post;
1261:
1262:
1263: msp = (ngx_msec_t *) (p + cmd->offset);
1264: if (*msp != NGX_CONF_UNSET_MSEC) {
1265: return "is duplicate";
1266: }
1267:
1268: value = cf->args->elts;
1269:
1270: *msp = ngx_parse_time(&value[1], 0);
1271: if (*msp == (ngx_msec_t) NGX_ERROR) {
1272: return "invalid value";
1273: }
1274:
1275: if (cmd->post) {
1276: post = cmd->post;
1277: return post->post_handler(cf, post, msp);
1278: }
1279:
1280: return NGX_CONF_OK;
1281: }
1282:
1283:
1284: char *
1285: ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1286: {
1287: char *p = conf;
1288:
1289: time_t *sp;
1290: ngx_str_t *value;
1291: ngx_conf_post_t *post;
1292:
1293:
1294: sp = (time_t *) (p + cmd->offset);
1295: if (*sp != NGX_CONF_UNSET) {
1296: return "is duplicate";
1297: }
1298:
1299: value = cf->args->elts;
1300:
1301: *sp = ngx_parse_time(&value[1], 1);
1302: if (*sp == (time_t) NGX_ERROR) {
1303: return "invalid value";
1304: }
1305:
1306: if (cmd->post) {
1307: post = cmd->post;
1308: return post->post_handler(cf, post, sp);
1309: }
1310:
1311: return NGX_CONF_OK;
1312: }
1313:
1314:
1315: char *
1316: ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1317: {
1318: char *p = conf;
1319:
1320: ngx_str_t *value;
1321: ngx_bufs_t *bufs;
1322:
1323:
1324: bufs = (ngx_bufs_t *) (p + cmd->offset);
1325: if (bufs->num) {
1326: return "is duplicate";
1327: }
1328:
1329: value = cf->args->elts;
1330:
1331: bufs->num = ngx_atoi(value[1].data, value[1].len);
1332: if (bufs->num == NGX_ERROR || bufs->num == 0) {
1333: return "invalid value";
1334: }
1335:
1336: bufs->size = ngx_parse_size(&value[2]);
1337: if (bufs->size == (size_t) NGX_ERROR || bufs->size == 0) {
1338: return "invalid value";
1339: }
1340:
1341: return NGX_CONF_OK;
1342: }
1343:
1344:
1345: char *
1346: ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1347: {
1348: char *p = conf;
1349:
1350: ngx_uint_t *np, i;
1351: ngx_str_t *value;
1352: ngx_conf_enum_t *e;
1353:
1354: np = (ngx_uint_t *) (p + cmd->offset);
1355:
1356: if (*np != NGX_CONF_UNSET_UINT) {
1357: return "is duplicate";
1358: }
1359:
1360: value = cf->args->elts;
1361: e = cmd->post;
1362:
1363: for (i = 0; e[i].name.len != 0; i++) {
1364: if (e[i].name.len != value[1].len
1365: || ngx_strcasecmp(e[i].name.data, value[1].data) != 0)
1366: {
1367: continue;
1368: }
1369:
1370: *np = e[i].value;
1371:
1372: return NGX_CONF_OK;
1373: }
1374:
1375: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1376: "invalid value \"%s\"", value[1].data);
1377:
1378: return NGX_CONF_ERROR;
1379: }
1380:
1381:
1382: char *
1383: ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1384: {
1385: char *p = conf;
1386:
1387: ngx_uint_t *np, i, m;
1388: ngx_str_t *value;
1389: ngx_conf_bitmask_t *mask;
1390:
1391:
1392: np = (ngx_uint_t *) (p + cmd->offset);
1393: value = cf->args->elts;
1394: mask = cmd->post;
1395:
1396: for (i = 1; i < cf->args->nelts; i++) {
1397: for (m = 0; mask[m].name.len != 0; m++) {
1398:
1399: if (mask[m].name.len != value[i].len
1400: || ngx_strcasecmp(mask[m].name.data, value[i].data) != 0)
1401: {
1402: continue;
1403: }
1404:
1405: if (*np & mask[m].mask) {
1406: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1407: "duplicate value \"%s\"", value[i].data);
1408:
1409: } else {
1410: *np |= mask[m].mask;
1411: }
1412:
1413: break;
1414: }
1415:
1416: if (mask[m].name.len == 0) {
1417: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1418: "invalid value \"%s\"", value[i].data);
1419:
1420: return NGX_CONF_ERROR;
1421: }
1422: }
1423:
1424: return NGX_CONF_OK;
1425: }
1426:
1427:
1428: #if 0
1429:
1430: char *
1431: ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1432: {
1433: return "unsupported on this platform";
1434: }
1435:
1436: #endif
1437:
1438:
1439: char *
1440: ngx_conf_deprecated(ngx_conf_t *cf, void *post, void *data)
1441: {
1442: ngx_conf_deprecated_t *d = post;
1443:
1444: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1445: "the \"%s\" directive is deprecated, "
1446: "use the \"%s\" directive instead",
1447: d->old_name, d->new_name);
1448:
1449: return NGX_CONF_OK;
1450: }
1451:
1452:
1453: char *
1454: ngx_conf_check_num_bounds(ngx_conf_t *cf, void *post, void *data)
1455: {
1456: ngx_conf_num_bounds_t *bounds = post;
1457: ngx_int_t *np = data;
1458:
1459: if (bounds->high == -1) {
1460: if (*np >= bounds->low) {
1461: return NGX_CONF_OK;
1462: }
1463:
1464: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1465: "value must be equal to or greater than %i",
1466: bounds->low);
1467:
1468: return NGX_CONF_ERROR;
1469: }
1470:
1471: if (*np >= bounds->low && *np <= bounds->high) {
1472: return NGX_CONF_OK;
1473: }
1474:
1475: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1476: "value must be between %i and %i",
1477: bounds->low, bounds->high);
1478:
1479: return NGX_CONF_ERROR;
1480: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>