Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / core / ngx_conf_file.c
bloba262672139c9e543a83f270519fb7ffb11961384
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
11 #define NGX_CONF_BUFFER 4096
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);
19 static ngx_command_t ngx_conf_commands[] = {
21 { ngx_string("include"),
22 NGX_ANY_CONF|NGX_CONF_TAKE1,
23 ngx_conf_include,
26 NULL },
28 ngx_null_command
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
48 /* The eight fixed arguments */
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
62 char *
63 ngx_conf_param(ngx_conf_t *cf)
65 char *rv;
66 ngx_str_t *param;
67 ngx_buf_t b;
68 ngx_conf_file_t conf_file;
70 param = &cf->cycle->conf_param;
72 if (param->len == 0) {
73 return NGX_CONF_OK;
76 ngx_memzero(&conf_file, sizeof(ngx_conf_file_t));
78 ngx_memzero(&b, sizeof(ngx_buf_t));
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;
86 conf_file.file.fd = NGX_INVALID_FILE;
87 conf_file.file.name.data = NULL;
88 conf_file.line = 0;
90 cf->conf_file = &conf_file;
91 cf->conf_file->buffer = &b;
93 rv = ngx_conf_parse(cf, NULL);
95 cf->conf_file = NULL;
97 return rv;
101 char *
102 ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
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;
115 #if (NGX_SUPPRESS_WARN)
116 fd = NGX_INVALID_FILE;
117 prev = NULL;
118 #endif
120 if (filename) {
122 /* open configuration file */
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;
132 prev = cf->conf_file;
134 cf->conf_file = &conf_file;
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);
141 cf->conf_file->buffer = &buf;
143 buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log);
144 if (buf.start == NULL) {
145 goto failed;
148 buf.pos = buf.start;
149 buf.last = buf.start;
150 buf.end = buf.last + NGX_CONF_BUFFER;
151 buf.temporary = 1;
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;
160 type = parse_file;
162 } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {
164 type = parse_block;
166 } else {
167 type = parse_param;
171 for ( ;; ) {
172 rc = ngx_conf_read_token(cf);
175 * ngx_conf_read_token() may return
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
184 if (rc == NGX_ERROR) {
185 goto done;
188 if (rc == NGX_CONF_BLOCK_DONE) {
190 if (type != parse_block) {
191 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");
192 goto failed;
195 goto done;
198 if (rc == NGX_CONF_FILE_DONE) {
200 if (type == parse_block) {
201 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
202 "unexpected end of file, expecting \"}\"");
203 goto failed;
206 goto done;
209 if (rc == NGX_CONF_BLOCK_START) {
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;
219 /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */
221 if (cf->handler) {
224 * the custom handler, i.e., that is used in the http's
225 * "types { ... }" directive
228 rv = (*cf->handler)(cf, NULL, cf->handler_conf);
229 if (rv == NGX_CONF_OK) {
230 continue;
233 if (rv == NGX_CONF_ERROR) {
234 goto failed;
237 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);
239 goto failed;
243 rc = ngx_conf_handler(cf, rc);
245 if (rc == NGX_ERROR) {
246 goto failed;
250 failed:
252 rc = NGX_ERROR;
254 done:
256 if (filename) {
257 if (cf->conf_file->buffer->start) {
258 ngx_free(cf->conf_file->buffer->start);
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;
268 cf->conf_file = prev;
271 if (rc == NGX_ERROR) {
272 return NGX_CONF_ERROR;
275 return NGX_CONF_OK;
279 static ngx_int_t
280 ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
282 char *rv;
283 void *conf, **confp;
284 ngx_uint_t i, found;
285 ngx_str_t *name;
286 ngx_command_t *cmd;
288 name = cf->args->elts;
290 found = 0;
292 for (i = 0; ngx_modules[i]; i++) {
294 cmd = ngx_modules[i]->commands;
295 if (cmd == NULL) {
296 continue;
299 for ( /* void */ ; cmd->name.len; cmd++) {
301 if (name->len != cmd->name.len) {
302 continue;
305 if (ngx_strcmp(name->data, cmd->name.data) != 0) {
306 continue;
309 found = 1;
311 if (ngx_modules[i]->type != NGX_CONF_MODULE
312 && ngx_modules[i]->type != cf->module_type)
314 continue;
317 /* is the directive's location right ? */
319 if (!(cmd->type & cf->cmd_type)) {
320 continue;
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;
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;
337 /* is the directive's argument count right ? */
339 if (!(cmd->type & NGX_CONF_ANY)) {
341 if (cmd->type & NGX_CONF_FLAG) {
343 if (cf->args->nelts != 2) {
344 goto invalid;
347 } else if (cmd->type & NGX_CONF_1MORE) {
349 if (cf->args->nelts < 2) {
350 goto invalid;
353 } else if (cmd->type & NGX_CONF_2MORE) {
355 if (cf->args->nelts < 3) {
356 goto invalid;
359 } else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {
361 goto invalid;
363 } else if (!(cmd->type & argument_number[cf->args->nelts - 1]))
365 goto invalid;
369 /* set up the directive's configuration context */
371 conf = NULL;
373 if (cmd->type & NGX_DIRECT_CONF) {
374 conf = ((void **) cf->ctx)[ngx_modules[i]->index];
376 } else if (cmd->type & NGX_MAIN_CONF) {
377 conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
379 } else if (cf->ctx) {
380 confp = *(void **) ((char *) cf->ctx + cmd->conf);
382 if (confp) {
383 conf = confp[ngx_modules[i]->ctx_index];
387 rv = cmd->set(cf, cmd, conf);
389 if (rv == NGX_CONF_OK) {
390 return NGX_OK;
393 if (rv == NGX_CONF_ERROR) {
394 return NGX_ERROR;
397 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
398 "\"%s\" directive %s", name->data, rv);
400 return NGX_ERROR;
404 if (found) {
405 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
406 "\"%s\" directive is not allowed here", name->data);
408 return NGX_ERROR;
411 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
412 "unknown directive \"%s\"", name->data);
414 return NGX_ERROR;
416 invalid:
418 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
419 "invalid number of arguments in \"%s\" directive",
420 name->data);
422 return NGX_ERROR;
426 static ngx_int_t
427 ngx_conf_read_token(ngx_conf_t *cf)
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;
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;
447 cf->args->nelts = 0;
448 b = cf->conf_file->buffer;
449 start = b->pos;
450 start_line = cf->conf_file->line;
452 file_size = ngx_file_size(&cf->conf_file->file.info);
454 for ( ;; ) {
456 if (b->pos >= b->last) {
458 if (cf->conf_file->file.offset >= file_size) {
460 if (cf->args->nelts > 0 || !last_space) {
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;
469 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
470 "unexpected end of file, "
471 "expecting \";\" or \"}\"");
472 return NGX_ERROR;
475 return NGX_CONF_FILE_DONE;
478 len = b->pos - start;
480 if (len == NGX_CONF_BUFFER) {
481 cf->conf_file->line = start_line;
483 if (d_quoted) {
484 ch = '"';
486 } else if (s_quoted) {
487 ch = '\'';
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;
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;
502 if (len) {
503 ngx_memmove(b->start, start, len);
506 size = (ssize_t) (file_size - cf->conf_file->file.offset);
508 if (size > b->end - (b->start + len)) {
509 size = b->end - (b->start + len);
512 n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
513 cf->conf_file->file.offset);
515 if (n == NGX_ERROR) {
516 return NGX_ERROR;
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;
527 b->pos = b->start + len;
528 b->last = b->pos + n;
529 start = b->start;
532 ch = *b->pos++;
534 if (ch == LF) {
535 cf->conf_file->line++;
537 if (sharp_comment) {
538 sharp_comment = 0;
542 if (sharp_comment) {
543 continue;
546 if (quoted) {
547 quoted = 0;
548 continue;
551 if (need_space) {
552 if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
553 last_space = 1;
554 need_space = 0;
555 continue;
558 if (ch == ';') {
559 return NGX_OK;
562 if (ch == '{') {
563 return NGX_CONF_BLOCK_START;
566 if (ch == ')') {
567 last_space = 1;
568 need_space = 0;
570 } else {
571 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
572 "unexpected \"%c\"", ch);
573 return NGX_ERROR;
577 if (last_space) {
578 if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
579 continue;
582 start = b->pos - 1;
583 start_line = cf->conf_file->line;
585 switch (ch) {
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;
595 if (ch == '{') {
596 return NGX_CONF_BLOCK_START;
599 return NGX_OK;
601 case '}':
602 if (cf->args->nelts != 0) {
603 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
604 "unexpected \"}\"");
605 return NGX_ERROR;
608 return NGX_CONF_BLOCK_DONE;
610 case '#':
611 sharp_comment = 1;
612 continue;
614 case '\\':
615 quoted = 1;
616 last_space = 0;
617 continue;
619 case '"':
620 start++;
621 d_quoted = 1;
622 last_space = 0;
623 continue;
625 case '\'':
626 start++;
627 s_quoted = 1;
628 last_space = 0;
629 continue;
631 default:
632 last_space = 0;
635 } else {
636 if (ch == '{' && variable) {
637 continue;
640 variable = 0;
642 if (ch == '\\') {
643 quoted = 1;
644 continue;
647 if (ch == '$') {
648 variable = 1;
649 continue;
652 if (d_quoted) {
653 if (ch == '"') {
654 d_quoted = 0;
655 need_space = 1;
656 found = 1;
659 } else if (s_quoted) {
660 if (ch == '\'') {
661 s_quoted = 0;
662 need_space = 1;
663 found = 1;
666 } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
667 || ch == ';' || ch == '{')
669 last_space = 1;
670 found = 1;
673 if (found) {
674 word = ngx_array_push(cf->args);
675 if (word == NULL) {
676 return NGX_ERROR;
679 word->data = ngx_pnalloc(cf->pool, b->pos - start + 1);
680 if (word->data == NULL) {
681 return NGX_ERROR;
684 for (dst = word->data, src = start, len = 0;
685 src < b->pos - 1;
686 len++)
688 if (*src == '\\') {
689 switch (src[1]) {
690 case '"':
691 case '\'':
692 case '\\':
693 src++;
694 break;
696 case 't':
697 *dst++ = '\t';
698 src += 2;
699 continue;
701 case 'r':
702 *dst++ = '\r';
703 src += 2;
704 continue;
706 case 'n':
707 *dst++ = '\n';
708 src += 2;
709 continue;
713 *dst++ = *src++;
715 *dst = '\0';
716 word->len = len;
718 if (ch == ';') {
719 return NGX_OK;
722 if (ch == '{') {
723 return NGX_CONF_BLOCK_START;
726 found = 0;
733 char *
734 ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
736 char *rv;
737 ngx_int_t n;
738 ngx_str_t *value, file, name;
739 ngx_glob_t gl;
741 value = cf->args->elts;
742 file = value[1];
744 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
746 if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
747 return NGX_CONF_ERROR;
750 if (strpbrk((char *) file.data, "*?[") == NULL) {
752 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
754 return ngx_conf_parse(cf, &file);
757 ngx_memzero(&gl, sizeof(ngx_glob_t));
759 gl.pattern = file.data;
760 gl.log = cf->log;
761 gl.test = 1;
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;
769 rv = NGX_CONF_OK;
771 for ( ;; ) {
772 n = ngx_read_glob(&gl, &name);
774 if (n != NGX_OK) {
775 break;
778 file.len = name.len++;
779 file.data = ngx_pstrdup(cf->pool, &name);
781 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
783 rv = ngx_conf_parse(cf, &file);
785 if (rv != NGX_CONF_OK) {
786 break;
790 ngx_close_glob(&gl);
792 return rv;
796 ngx_int_t
797 ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix)
799 size_t len;
800 u_char *p, *n, *prefix;
801 ngx_int_t rc;
803 rc = ngx_conf_test_full_name(name);
805 if (rc == NGX_OK) {
806 return rc;
809 if (conf_prefix) {
810 len = cycle->conf_prefix.len;
811 prefix = cycle->conf_prefix.data;
813 } else {
814 len = cycle->prefix.len;
815 prefix = cycle->prefix.data;
818 #if (NGX_WIN32)
820 if (rc == 2) {
821 len = rc;
824 #endif
826 n = ngx_pnalloc(cycle->pool, len + name->len + 1);
827 if (n == NULL) {
828 return NGX_ERROR;
831 p = ngx_cpymem(n, prefix, len);
832 ngx_cpystrn(p, name->data, name->len + 1);
834 name->len += len;
835 name->data = n;
837 return NGX_OK;
841 static ngx_int_t
842 ngx_conf_test_full_name(ngx_str_t *name)
844 #if (NGX_WIN32)
845 u_char c0, c1;
847 c0 = name->data[0];
849 if (name->len < 2) {
850 if (c0 == '/') {
851 return 2;
854 return NGX_DECLINED;
857 c1 = name->data[1];
859 if (c1 == ':') {
860 c0 |= 0x20;
862 if ((c0 >= 'a' && c0 <= 'z')) {
863 return NGX_OK;
866 return NGX_DECLINED;
869 if (c1 == '/') {
870 return NGX_OK;
873 if (c0 == '/') {
874 return 2;
877 return NGX_DECLINED;
879 #else
881 if (name->data[0] == '/') {
882 return NGX_OK;
885 return NGX_DECLINED;
887 #endif
891 ngx_open_file_t *
892 ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
894 ngx_str_t full;
895 ngx_uint_t i;
896 ngx_list_part_t *part;
897 ngx_open_file_t *file;
899 #if (NGX_SUPPRESS_WARN)
900 ngx_str_null(&full);
901 #endif
903 if (name->len) {
904 full = *name;
906 if (ngx_conf_full_name(cycle, &full, 0) != NGX_OK) {
907 return NULL;
910 part = &cycle->open_files.part;
911 file = part->elts;
913 for (i = 0; /* void */ ; i++) {
915 if (i >= part->nelts) {
916 if (part->next == NULL) {
917 break;
919 part = part->next;
920 file = part->elts;
921 i = 0;
924 if (full.len != file[i].name.len) {
925 continue;
928 if (ngx_strcmp(full.data, file[i].name.data) == 0) {
929 return &file[i];
934 file = ngx_list_push(&cycle->open_files);
935 if (file == NULL) {
936 return NULL;
939 if (name->len) {
940 file->fd = NGX_INVALID_FILE;
941 file->name = full;
943 } else {
944 file->fd = ngx_stderr;
945 file->name = *name;
948 file->flush = NULL;
949 file->data = NULL;
951 return file;
955 static void
956 ngx_conf_flush_files(ngx_cycle_t *cycle)
958 ngx_uint_t i;
959 ngx_list_part_t *part;
960 ngx_open_file_t *file;
962 ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "flush files");
964 part = &cycle->open_files.part;
965 file = part->elts;
967 for (i = 0; /* void */ ; i++) {
969 if (i >= part->nelts) {
970 if (part->next == NULL) {
971 break;
973 part = part->next;
974 file = part->elts;
975 i = 0;
978 if (file[i].flush) {
979 file[i].flush(&file[i], cycle->log);
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, ...)
989 u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last;
990 va_list args;
992 last = errstr + NGX_MAX_CONF_ERRSTR;
994 va_start(args, fmt);
995 p = ngx_vslprintf(errstr, last, fmt, args);
996 va_end(args);
998 if (err) {
999 p = ngx_log_errno(p, last, err);
1002 if (cf->conf_file == NULL) {
1003 ngx_log_error(level, cf->log, 0, "%*s", p - errstr, errstr);
1004 return;
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;
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);
1019 char *
1020 ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1022 char *p = conf;
1024 ngx_str_t *value;
1025 ngx_flag_t *fp;
1026 ngx_conf_post_t *post;
1028 fp = (ngx_flag_t *) (p + cmd->offset);
1030 if (*fp != NGX_CONF_UNSET) {
1031 return "is duplicate";
1034 value = cf->args->elts;
1036 if (ngx_strcasecmp(value[1].data, (u_char *) "on") == 0) {
1037 *fp = 1;
1039 } else if (ngx_strcasecmp(value[1].data, (u_char *) "off") == 0) {
1040 *fp = 0;
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;
1050 if (cmd->post) {
1051 post = cmd->post;
1052 return post->post_handler(cf, post, fp);
1055 return NGX_CONF_OK;
1059 char *
1060 ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1062 char *p = conf;
1064 ngx_str_t *field, *value;
1065 ngx_conf_post_t *post;
1067 field = (ngx_str_t *) (p + cmd->offset);
1069 if (field->data) {
1070 return "is duplicate";
1073 value = cf->args->elts;
1075 *field = value[1];
1077 if (cmd->post) {
1078 post = cmd->post;
1079 return post->post_handler(cf, post, field);
1082 return NGX_CONF_OK;
1086 char *
1087 ngx_conf_set_str_array_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1089 char *p = conf;
1091 ngx_str_t *value, *s;
1092 ngx_array_t **a;
1093 ngx_conf_post_t *post;
1095 a = (ngx_array_t **) (p + cmd->offset);
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;
1104 s = ngx_array_push(*a);
1105 if (s == NULL) {
1106 return NGX_CONF_ERROR;
1109 value = cf->args->elts;
1111 *s = value[1];
1113 if (cmd->post) {
1114 post = cmd->post;
1115 return post->post_handler(cf, post, s);
1118 return NGX_CONF_OK;
1122 char *
1123 ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1125 char *p = conf;
1127 ngx_str_t *value;
1128 ngx_array_t **a;
1129 ngx_keyval_t *kv;
1130 ngx_conf_post_t *post;
1132 a = (ngx_array_t **) (p + cmd->offset);
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;
1141 kv = ngx_array_push(*a);
1142 if (kv == NULL) {
1143 return NGX_CONF_ERROR;
1146 value = cf->args->elts;
1148 kv->key = value[1];
1149 kv->value = value[2];
1151 if (cmd->post) {
1152 post = cmd->post;
1153 return post->post_handler(cf, post, kv);
1156 return NGX_CONF_OK;
1160 char *
1161 ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1163 char *p = conf;
1165 ngx_int_t *np;
1166 ngx_str_t *value;
1167 ngx_conf_post_t *post;
1170 np = (ngx_int_t *) (p + cmd->offset);
1172 if (*np != NGX_CONF_UNSET) {
1173 return "is duplicate";
1176 value = cf->args->elts;
1177 *np = ngx_atoi(value[1].data, value[1].len);
1178 if (*np == NGX_ERROR) {
1179 return "invalid number";
1182 if (cmd->post) {
1183 post = cmd->post;
1184 return post->post_handler(cf, post, np);
1187 return NGX_CONF_OK;
1191 char *
1192 ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1194 char *p = conf;
1196 size_t *sp;
1197 ngx_str_t *value;
1198 ngx_conf_post_t *post;
1201 sp = (size_t *) (p + cmd->offset);
1202 if (*sp != NGX_CONF_UNSET_SIZE) {
1203 return "is duplicate";
1206 value = cf->args->elts;
1208 *sp = ngx_parse_size(&value[1]);
1209 if (*sp == (size_t) NGX_ERROR) {
1210 return "invalid value";
1213 if (cmd->post) {
1214 post = cmd->post;
1215 return post->post_handler(cf, post, sp);
1218 return NGX_CONF_OK;
1222 char *
1223 ngx_conf_set_off_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1225 char *p = conf;
1227 off_t *op;
1228 ngx_str_t *value;
1229 ngx_conf_post_t *post;
1232 op = (off_t *) (p + cmd->offset);
1233 if (*op != NGX_CONF_UNSET) {
1234 return "is duplicate";
1237 value = cf->args->elts;
1239 *op = ngx_parse_offset(&value[1]);
1240 if (*op == (off_t) NGX_ERROR) {
1241 return "invalid value";
1244 if (cmd->post) {
1245 post = cmd->post;
1246 return post->post_handler(cf, post, op);
1249 return NGX_CONF_OK;
1253 char *
1254 ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1256 char *p = conf;
1258 ngx_msec_t *msp;
1259 ngx_str_t *value;
1260 ngx_conf_post_t *post;
1263 msp = (ngx_msec_t *) (p + cmd->offset);
1264 if (*msp != NGX_CONF_UNSET_MSEC) {
1265 return "is duplicate";
1268 value = cf->args->elts;
1270 *msp = ngx_parse_time(&value[1], 0);
1271 if (*msp == (ngx_msec_t) NGX_ERROR) {
1272 return "invalid value";
1275 if (cmd->post) {
1276 post = cmd->post;
1277 return post->post_handler(cf, post, msp);
1280 return NGX_CONF_OK;
1284 char *
1285 ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1287 char *p = conf;
1289 time_t *sp;
1290 ngx_str_t *value;
1291 ngx_conf_post_t *post;
1294 sp = (time_t *) (p + cmd->offset);
1295 if (*sp != NGX_CONF_UNSET) {
1296 return "is duplicate";
1299 value = cf->args->elts;
1301 *sp = ngx_parse_time(&value[1], 1);
1302 if (*sp == (time_t) NGX_ERROR) {
1303 return "invalid value";
1306 if (cmd->post) {
1307 post = cmd->post;
1308 return post->post_handler(cf, post, sp);
1311 return NGX_CONF_OK;
1315 char *
1316 ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1318 char *p = conf;
1320 ngx_str_t *value;
1321 ngx_bufs_t *bufs;
1324 bufs = (ngx_bufs_t *) (p + cmd->offset);
1325 if (bufs->num) {
1326 return "is duplicate";
1329 value = cf->args->elts;
1331 bufs->num = ngx_atoi(value[1].data, value[1].len);
1332 if (bufs->num == NGX_ERROR || bufs->num == 0) {
1333 return "invalid value";
1336 bufs->size = ngx_parse_size(&value[2]);
1337 if (bufs->size == (size_t) NGX_ERROR || bufs->size == 0) {
1338 return "invalid value";
1341 return NGX_CONF_OK;
1345 char *
1346 ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1348 char *p = conf;
1350 ngx_uint_t *np, i;
1351 ngx_str_t *value;
1352 ngx_conf_enum_t *e;
1354 np = (ngx_uint_t *) (p + cmd->offset);
1356 if (*np != NGX_CONF_UNSET_UINT) {
1357 return "is duplicate";
1360 value = cf->args->elts;
1361 e = cmd->post;
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)
1367 continue;
1370 *np = e[i].value;
1372 return NGX_CONF_OK;
1375 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1376 "invalid value \"%s\"", value[1].data);
1378 return NGX_CONF_ERROR;
1382 char *
1383 ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1385 char *p = conf;
1387 ngx_uint_t *np, i, m;
1388 ngx_str_t *value;
1389 ngx_conf_bitmask_t *mask;
1392 np = (ngx_uint_t *) (p + cmd->offset);
1393 value = cf->args->elts;
1394 mask = cmd->post;
1396 for (i = 1; i < cf->args->nelts; i++) {
1397 for (m = 0; mask[m].name.len != 0; m++) {
1399 if (mask[m].name.len != value[i].len
1400 || ngx_strcasecmp(mask[m].name.data, value[i].data) != 0)
1402 continue;
1405 if (*np & mask[m].mask) {
1406 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1407 "duplicate value \"%s\"", value[i].data);
1409 } else {
1410 *np |= mask[m].mask;
1413 break;
1416 if (mask[m].name.len == 0) {
1417 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1418 "invalid value \"%s\"", value[i].data);
1420 return NGX_CONF_ERROR;
1424 return NGX_CONF_OK;
1428 #if 0
1430 char *
1431 ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1433 return "unsupported on this platform";
1436 #endif
1439 char *
1440 ngx_conf_deprecated(ngx_conf_t *cf, void *post, void *data)
1442 ngx_conf_deprecated_t *d = post;
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);
1449 return NGX_CONF_OK;
1453 char *
1454 ngx_conf_check_num_bounds(ngx_conf_t *cf, void *post, void *data)
1456 ngx_conf_num_bounds_t *bounds = post;
1457 ngx_int_t *np = data;
1459 if (bounds->high == -1) {
1460 if (*np >= bounds->low) {
1461 return NGX_CONF_OK;
1464 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1465 "value must be equal to or greater than %i",
1466 bounds->low);
1468 return NGX_CONF_ERROR;
1471 if (*np >= bounds->low && *np <= bounds->high) {
1472 return NGX_CONF_OK;
1475 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1476 "value must be between %i and %i",
1477 bounds->low, bounds->high);
1479 return NGX_CONF_ERROR;