comparison src/core/ngx_conf_file.c @ 0:f0b350454894 NGINX_0_1_0

nginx 0.1.0 *) The first public version.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Oct 2004 00:00:00 +0400
parents
children 4b2dafa26fe2
comparison
equal deleted inserted replaced
-1:000000000000 0:f0b350454894
1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9
10
11 static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
12
13
14 static ngx_command_t ngx_conf_commands[] = {
15
16 { ngx_string("include"),
17 NGX_ANY_CONF|NGX_CONF_TAKE1,
18 ngx_conf_include,
19 0,
20 0,
21 NULL },
22
23 ngx_null_command
24 };
25
26
27 ngx_module_t ngx_conf_module = {
28 NGX_MODULE,
29 NULL, /* module context */
30 ngx_conf_commands, /* module directives */
31 NGX_CONF_MODULE, /* module type */
32 NULL, /* init module */
33 NULL /* init child */
34 };
35
36
37
38 /* The ten fixed arguments */
39
40 static int argument_number[] = {
41 NGX_CONF_NOARGS,
42 NGX_CONF_TAKE1,
43 NGX_CONF_TAKE2,
44 NGX_CONF_TAKE3,
45 NGX_CONF_TAKE4,
46 NGX_CONF_TAKE5,
47 NGX_CONF_TAKE6,
48 NGX_CONF_TAKE7
49 };
50
51 static int ngx_conf_read_token(ngx_conf_t *cf);
52
53
54 char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
55 {
56 int m, rc, found, valid;
57 char *rv;
58 void *conf, **confp;
59 ngx_fd_t fd;
60 ngx_str_t *name;
61 ngx_conf_file_t *prev;
62 ngx_command_t *cmd;
63
64 #if (NGX_SUPPRESS_WARN)
65 fd = NGX_INVALID_FILE;
66 prev = NULL;
67 #endif
68
69 if (filename) {
70
71 /* open configuration file */
72
73 fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN);
74 if (fd == NGX_INVALID_FILE) {
75 ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
76 ngx_open_file_n " %s failed", filename->data);
77 return NGX_CONF_ERROR;
78 }
79
80 prev = cf->conf_file;
81 if (!(cf->conf_file = ngx_palloc(cf->pool, sizeof(ngx_conf_file_t)))) {
82 return NGX_CONF_ERROR;
83 }
84
85 if (ngx_fd_info(fd, &cf->conf_file->file.info) == -1) {
86 ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
87 ngx_fd_info_n " %s failed", filename->data);
88 }
89
90 if (!(cf->conf_file->buffer = ngx_create_temp_buf(cf->pool, 1024))) {
91 return NGX_CONF_ERROR;
92 }
93
94 cf->conf_file->file.fd = fd;
95 cf->conf_file->file.name.len = filename->len;
96 cf->conf_file->file.name.data = filename->data;
97 cf->conf_file->file.offset = 0;
98 cf->conf_file->file.log = cf->log;;
99 cf->conf_file->line = 1;
100 }
101
102 for ( ;; ) {
103 rc = ngx_conf_read_token(cf);
104
105 /*
106 * ngx_conf_read_token() returns NGX_OK, NGX_ERROR,
107 * NGX_CONF_FILE_DONE or NGX_CONF_BLOCK_DONE
108 */
109
110 #if 0
111 ngx_log_debug(cf->log, "token %d" _ rc);
112 #endif
113
114 if (rc == NGX_ERROR) {
115 break;
116 }
117
118 if (rc != NGX_OK) {
119 break;
120 }
121
122 if (cf->handler) {
123
124 /* custom handler, i.e. used in http "types { ... }" directive */
125
126 rv = (*cf->handler)(cf, NULL, cf->handler_conf);
127 if (rv == NGX_CONF_OK) {
128 continue;
129
130 } else if (rv == NGX_CONF_ERROR) {
131 rc = NGX_ERROR;
132 break;
133
134 } else {
135 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
136 "%s in %s:%d",
137 rv,
138 cf->conf_file->file.name.data,
139 cf->conf_file->line);
140 rc = NGX_ERROR;
141 break;
142 }
143 }
144
145 name = (ngx_str_t *) cf->args->elts;
146 found = 0;
147
148 for (m = 0; rc != NGX_ERROR && !found && ngx_modules[m]; m++) {
149
150 /* look up the directive in the appropriate modules */
151
152 if (ngx_modules[m]->type != NGX_CONF_MODULE
153 && ngx_modules[m]->type != cf->module_type)
154 {
155 continue;
156 }
157
158 cmd = ngx_modules[m]->commands;
159 if (cmd == NULL) {
160 continue;
161 }
162
163 while (cmd->name.len) {
164 if (name->len == cmd->name.len
165 && ngx_strcmp(name->data, cmd->name.data) == 0)
166 {
167
168 found = 1;
169 #if 0
170 ngx_log_debug(cf->log, "command '%s'" _ cmd->name.data);
171 #endif
172 /* is the directive's location right ? */
173
174 if ((cmd->type & cf->cmd_type) == 0) {
175 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
176 "directive \"%s\" in %s:%d "
177 "is not allowed here",
178 name->data,
179 cf->conf_file->file.name.data,
180 cf->conf_file->line);
181 rc = NGX_ERROR;
182 break;
183 }
184
185 /* is the directive's argument count right ? */
186
187 if (cmd->type & NGX_CONF_ANY) {
188 valid = 1;
189
190 } else if (cmd->type & NGX_CONF_FLAG) {
191
192 if (cf->args->nelts == 2) {
193 valid = 1;
194 } else {
195 valid = 0;
196 }
197
198 } else if (cmd->type & NGX_CONF_1MORE) {
199
200 if (cf->args->nelts > 1) {
201 valid = 1;
202 } else {
203 valid = 0;
204 }
205
206 } else if (cmd->type & NGX_CONF_2MORE) {
207
208 if (cf->args->nelts > 2) {
209 valid = 1;
210 } else {
211 valid = 0;
212 }
213
214 } else if (cf->args->nelts <= 10
215 && (cmd->type
216 & argument_number[cf->args->nelts - 1]))
217 {
218 valid = 1;
219
220 } else {
221 valid = 0;
222 }
223
224 if (!valid) {
225 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
226 "invalid number arguments in "
227 "directive \"%s\" in %s:%d",
228 name->data,
229 cf->conf_file->file.name.data,
230 cf->conf_file->line);
231 rc = NGX_ERROR;
232 break;
233 }
234
235 /* set up the directive's configuration context */
236
237 conf = NULL;
238
239 if (cmd->type & NGX_DIRECT_CONF) {
240 conf = ((void **) cf->ctx)[ngx_modules[m]->index];
241
242 } else if (cmd->type & NGX_MAIN_CONF) {
243 conf = &(((void **) cf->ctx)[ngx_modules[m]->index]);
244
245 } else if (cf->ctx) {
246 confp = *(void **) ((char *) cf->ctx + cmd->conf);
247
248 if (confp) {
249 conf = confp[ngx_modules[m]->ctx_index];
250 }
251 }
252
253 rv = cmd->set(cf, cmd, conf);
254
255 #if 0
256 ngx_log_debug(cf->log, "rv: %d" _ rv);
257 #endif
258
259 if (rv == NGX_CONF_OK) {
260 break;
261
262 } else if (rv == NGX_CONF_ERROR) {
263 rc = NGX_ERROR;
264 break;
265
266 } else {
267 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
268 "the \"%s\" directive %s in %s:%d",
269 name->data, rv,
270 cf->conf_file->file.name.data,
271 cf->conf_file->line);
272
273 rc = NGX_ERROR;
274 break;
275 }
276 }
277
278 cmd++;
279 }
280 }
281
282 if (!found) {
283 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
284 "unknown directive \"%s\" in %s:%d",
285 name->data,
286 cf->conf_file->file.name.data,
287 cf->conf_file->line);
288
289 rc = NGX_ERROR;
290 break;
291 }
292
293 if (rc == NGX_ERROR) {
294 break;
295 }
296 }
297
298 if (filename) {
299 cf->conf_file = prev;
300
301 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
302 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
303 ngx_close_file_n " %s failed",
304 cf->conf_file->file.name.data);
305 return NGX_CONF_ERROR;
306 }
307 }
308
309 if (rc == NGX_ERROR) {
310 return NGX_CONF_ERROR;
311 }
312
313 return NGX_CONF_OK;
314 }
315
316
317 static int ngx_conf_read_token(ngx_conf_t *cf)
318 {
319 u_char *start, ch, *src, *dst;
320 int len;
321 int found, need_space, last_space, sharp_comment;
322 int quoted, s_quoted, d_quoted;
323 ssize_t n;
324 ngx_str_t *word;
325 ngx_buf_t *b;
326
327 found = 0;
328 need_space = 0;
329 last_space = 1;
330 sharp_comment = 0;
331 quoted = s_quoted = d_quoted = 0;
332
333 cf->args->nelts = 0;
334 b = cf->conf_file->buffer;
335 start = b->pos;
336
337 #if 0
338 ngx_log_debug(cf->log, "TOKEN START");
339 #endif
340
341 for ( ;; ) {
342
343 if (b->pos >= b->last) {
344 if (cf->conf_file->file.offset
345 >= ngx_file_size(&cf->conf_file->file.info)) {
346 return NGX_CONF_FILE_DONE;
347 }
348
349 if (b->pos - start) {
350 ngx_memcpy(b->start, start, b->pos - start);
351 }
352
353 n = ngx_read_file(&cf->conf_file->file,
354 b->start + (b->pos - start),
355 b->end - (b->start + (b->pos - start)),
356 cf->conf_file->file.offset);
357
358 if (n == NGX_ERROR) {
359 return NGX_ERROR;
360 }
361
362 b->pos = b->start + (b->pos - start);
363 start = b->start;
364 b->last = b->pos + n;
365 }
366
367 ch = *b->pos++;
368
369 #if 0
370 ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '%c'" _
371 last_space _ need_space _
372 quoted _ s_quoted _ d_quoted _ ch);
373 #endif
374
375 if (ch == LF) {
376 cf->conf_file->line++;
377
378 if (sharp_comment) {
379 sharp_comment = 0;
380 }
381 }
382
383 if (sharp_comment) {
384 continue;
385 }
386
387 if (quoted) {
388 quoted = 0;
389 continue;
390 }
391
392 if (need_space) {
393 if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
394 last_space = 1;
395 need_space = 0;
396 continue;
397 }
398
399 if (ch == ';' || ch == '{') {
400 return NGX_OK;
401 }
402
403 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
404 "unexpected '%c' in %s:%d",
405 ch, cf->conf_file->file.name.data,
406 cf->conf_file->line);
407
408 return NGX_ERROR;
409 }
410
411 if (last_space) {
412 if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
413 continue;
414 }
415
416 start = b->pos - 1;
417
418 switch (ch) {
419
420 case ';':
421 case '{':
422 if (cf->args->nelts == 0) {
423 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
424 "unexpected '%c' in %s:%d",
425 ch, cf->conf_file->file.name.data,
426 cf->conf_file->line);
427 return NGX_ERROR;
428 }
429
430 return NGX_OK;
431
432 case '}':
433 if (cf->args->nelts > 0) {
434 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
435 "unexpected '}' in %s:%d",
436 cf->conf_file->file.name.data,
437 cf->conf_file->line);
438 return NGX_ERROR;
439 }
440
441 return NGX_CONF_BLOCK_DONE;
442
443 case '#':
444 sharp_comment = 1;
445 continue;
446
447 case '\\':
448 quoted = 1;
449 last_space = 0;
450 continue;
451
452 case '"':
453 start++;
454 d_quoted = 1;
455 last_space = 0;
456 continue;
457
458 case '\'':
459 start++;
460 s_quoted = 1;
461 last_space = 0;
462 continue;
463
464 default:
465 last_space = 0;
466 }
467
468 } else {
469 if (ch == '\\') {
470 quoted = 1;
471 continue;
472 }
473
474 if (d_quoted) {
475 if (ch == '"') {
476 d_quoted = 0;
477 need_space = 1;
478 found = 1;
479 }
480
481 } else if (s_quoted) {
482 if (ch == '\'') {
483 s_quoted = 0;
484 need_space = 1;
485 found = 1;
486 }
487
488 } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
489 || ch == ';' || ch == '{') {
490 last_space = 1;
491 found = 1;
492 }
493
494 if (found) {
495 if (!(word = ngx_push_array(cf->args))) {
496 return NGX_ERROR;
497 }
498
499 if (!(word->data = ngx_palloc(cf->pool, b->pos - start + 1))) {
500 return NGX_ERROR;
501 }
502
503 for (dst = word->data, src = start, len = 0;
504 src < b->pos - 1;
505 len++)
506 {
507 if (*src == '\\') {
508 switch (src[1]) {
509 case '"':
510 case '\'':
511 case '\\':
512 src++;
513 break;
514
515 case 't':
516 *dst++ = '\t';
517 src += 2;
518 continue;
519
520 case 'r':
521 *dst++ = '\r';
522 src += 2;
523 continue;
524
525 case 'n':
526 *dst++ = '\n';
527 src += 2;
528 continue;
529 }
530
531 }
532 *dst++ = *src++;
533 }
534 *dst = '\0';
535 word->len = len;
536
537 #if 0
538 ngx_log_debug(cf->log, "FOUND %d:'%s'" _ word->len _ word->data);
539 #endif
540
541 if (ch == ';' || ch == '{') {
542 return NGX_OK;
543 }
544
545 found = 0;
546 }
547 }
548 }
549 }
550
551
552 static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
553 {
554 ngx_str_t *value, file;
555
556 value = cf->args->elts;
557 file = value[1];
558
559 if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){
560 return NGX_CONF_ERROR;
561 }
562
563 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
564
565 return ngx_conf_parse(cf, &file);
566 }
567
568
569 ngx_int_t ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name)
570 {
571 u_char *p;
572 ngx_str_t old;
573
574 if (name->data[0] == '/') {
575 return NGX_OK;
576 }
577
578 old = *name;
579
580 name->len = cycle->root.len + old.len;
581
582 if (!(name->data = ngx_palloc(cycle->pool, name->len + 1))) {
583 return NGX_ERROR;
584 }
585
586 p = ngx_cpymem(name->data, cycle->root.data, cycle->root.len),
587 ngx_cpystrn(p, old.data, old.len + 1);
588
589 return NGX_OK;
590 }
591
592
593 ngx_open_file_t *ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
594 {
595 ngx_str_t full;
596 ngx_uint_t i;
597 ngx_list_part_t *part;
598 ngx_open_file_t *file;
599
600 #if (NGX_SUPPRESS_WARN)
601 full.len = 0;
602 full.data = NULL;
603 #endif
604
605 if (name) {
606 full = *name;
607
608 if (ngx_conf_full_name(cycle, &full) == NGX_ERROR) {
609 return NULL;
610 }
611
612 part = &cycle->open_files.part;
613 file = part->elts;
614
615 for (i = 0; /* void */ ; i++) {
616
617 if (i >= part->nelts) {
618 if (part->next == NULL) {
619 break;
620 }
621 part = part->next;
622 file = part->elts;
623 i = 0;
624 }
625
626 if (full.len != file[i].name.len) {
627 continue;
628 }
629
630 if (ngx_strcmp(full.data, file[i].name.data) == 0) {
631 return &file[i];
632 }
633 }
634 }
635
636 if (!(file = ngx_list_push(&cycle->open_files))) {
637 return NULL;
638 }
639
640 if (name) {
641 file->fd = NGX_INVALID_FILE;
642 file->name = full;
643
644 } else {
645 file->fd = ngx_stderr_fileno;
646 file->name.len = 0;
647 file->name.data = NULL;
648 }
649
650 return file;
651 }
652
653
654 void ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
655 char *fmt, ...)
656 {
657 int len;
658 char errstr[NGX_MAX_CONF_ERRSTR];
659 va_list args;
660
661 va_start(args, fmt);
662 len = ngx_vsnprintf(errstr, sizeof(errstr) - 1, fmt, args);
663 va_end(args);
664
665 if (err) {
666 len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1,
667 " (%d: ", err);
668 len += ngx_strerror_r(err, errstr + len, sizeof(errstr) - len - 1);
669 errstr[len++] = ')';
670 errstr[len] = '\0';
671 }
672
673 ngx_log_error(level, cf->log, 0, "%s in %s:%d",
674 errstr, cf->conf_file->file.name.data, cf->conf_file->line);
675 }
676
677
678 char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
679 {
680 char *p = conf;
681
682 ngx_str_t *value;
683 ngx_flag_t *fp;
684 ngx_conf_post_t *post;
685
686 fp = (ngx_flag_t *) (p + cmd->offset);
687
688 if (*fp != NGX_CONF_UNSET) {
689 return "is duplicate";
690 }
691
692 value = cf->args->elts;
693
694 if (ngx_strcasecmp(value[1].data, "on") == 0) {
695 *fp = 1;
696
697 } else if (ngx_strcasecmp(value[1].data, "off") == 0) {
698 *fp = 0;
699
700 } else {
701 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
702 "invalid value \"%s\" in \"%s\" directive, "
703 "it must be \"on\" or \"off\"",
704 value[1].data, cmd->name.data);
705 return NGX_CONF_ERROR;
706 }
707
708 if (cmd->post) {
709 post = cmd->post;
710 return post->post_handler(cf, post, fp);
711 }
712
713 return NGX_CONF_OK;
714 }
715
716
717 char *ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
718 {
719 char *p = conf;
720
721 ngx_str_t *field, *value;
722 ngx_conf_post_t *post;
723
724 field = (ngx_str_t *) (p + cmd->offset);
725
726 if (field->data) {
727 return "is duplicate";
728 }
729
730 value = cf->args->elts;
731
732 *field = value[1];
733
734 if (cmd->post) {
735 post = cmd->post;
736 return post->post_handler(cf, post, field);
737 }
738
739 return NGX_CONF_OK;
740 }
741
742
743 char *ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
744 {
745 char *p = conf;
746
747 ngx_int_t *np;
748 ngx_str_t *value;
749 ngx_conf_post_t *post;
750
751
752 np = (ngx_int_t *) (p + cmd->offset);
753
754 if (*np != NGX_CONF_UNSET) {
755 return "is duplicate";
756 }
757
758 value = cf->args->elts;
759 *np = ngx_atoi(value[1].data, value[1].len);
760 if (*np == NGX_ERROR) {
761 return "invalid number";
762 }
763
764 if (cmd->post) {
765 post = cmd->post;
766 return post->post_handler(cf, post, np);
767 }
768
769 return NGX_CONF_OK;
770 }
771
772
773 char *ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
774 {
775 char *p = conf;
776
777 size_t *sp;
778 ngx_str_t *value;
779 ngx_conf_post_t *post;
780
781
782 sp = (size_t *) (p + cmd->offset);
783 if (*sp != NGX_CONF_UNSET_SIZE) {
784 return "is duplicate";
785 }
786
787 value = cf->args->elts;
788
789 *sp = ngx_parse_size(&value[1]);
790 if (*sp == (size_t) NGX_ERROR) {
791 return "invalid value";
792 }
793
794 if (cmd->post) {
795 post = cmd->post;
796 return post->post_handler(cf, post, sp);
797 }
798
799 return NGX_CONF_OK;
800 }
801
802
803 char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
804 {
805 char *p = conf;
806
807 ngx_msec_t *msp;
808 ngx_str_t *value;
809 ngx_conf_post_t *post;
810
811
812 msp = (ngx_msec_t *) (p + cmd->offset);
813 if (*msp != NGX_CONF_UNSET_MSEC) {
814 return "is duplicate";
815 }
816
817 value = cf->args->elts;
818
819 *msp = ngx_parse_time(&value[1], 0);
820 if (*msp == (ngx_msec_t) NGX_ERROR) {
821 return "invalid value";
822 }
823
824 if (*msp == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
825 return "value must be less than 597 hours";
826 }
827
828 if (cmd->post) {
829 post = cmd->post;
830 return post->post_handler(cf, post, msp);
831 }
832
833 return NGX_CONF_OK;
834 }
835
836
837 char *ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
838 {
839 char *p = conf;
840
841 time_t *sp;
842 ngx_str_t *value;
843 ngx_conf_post_t *post;
844
845
846 sp = (time_t *) (p + cmd->offset);
847 if (*sp != NGX_CONF_UNSET) {
848 return "is duplicate";
849 }
850
851 value = cf->args->elts;
852
853 *sp = ngx_parse_time(&value[1], 1);
854 if (*sp == NGX_ERROR) {
855 return "invalid value";
856 }
857
858 if (*sp == NGX_PARSE_LARGE_TIME) {
859 return "value must be less than 68 years";
860 }
861
862 if (cmd->post) {
863 post = cmd->post;
864 return post->post_handler(cf, post, sp);
865 }
866
867 return NGX_CONF_OK;
868 }
869
870
871 char *ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
872 {
873 char *p = conf;
874
875 ngx_str_t *value;
876 ngx_bufs_t *bufs;
877
878
879 bufs = (ngx_bufs_t *) (p + cmd->offset);
880 if (bufs->num) {
881 return "is duplicate";
882 }
883
884 value = cf->args->elts;
885
886 bufs->num = ngx_atoi(value[1].data, value[1].len);
887 if (bufs->num == NGX_ERROR || bufs->num == 0) {
888 return "invalid value";
889 }
890
891 bufs->size = ngx_parse_size(&value[2]);
892 if (bufs->size == (size_t) NGX_ERROR || bufs->size == 0) {
893 return "invalid value";
894 }
895
896 return NGX_CONF_OK;
897 }
898
899
900 char *ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
901 {
902 char *p = conf;
903
904 ngx_uint_t *np, i;
905 ngx_str_t *value;
906 ngx_conf_enum_t *e;
907
908 np = (ngx_uint_t *) (p + cmd->offset);
909
910 if (*np != NGX_CONF_UNSET_UINT) {
911 return "is duplicate";
912 }
913
914 value = cf->args->elts;
915 e = cmd->post;
916
917 for (i = 0; e[i].name.len != 0; i++) {
918 if (e[i].name.len != value[1].len
919 || ngx_strcasecmp(e[i].name.data, value[1].data) != 0)
920 {
921 continue;
922 }
923
924 *np = e[i].value;
925
926 return NGX_CONF_OK;
927 }
928
929 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
930 "invalid value \"%s\"", value[1].data);
931
932 return NGX_CONF_ERROR;
933 }
934
935
936 char *ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
937 {
938 char *p = conf;
939
940 ngx_uint_t *np, i, m;
941 ngx_str_t *value;
942 ngx_conf_bitmask_t *mask;
943
944
945 np = (ngx_uint_t *) (p + cmd->offset);
946 value = cf->args->elts;
947 mask = cmd->post;
948
949 for (i = 1; i < cf->args->nelts; i++) {
950 for (m = 0; mask[m].name.len != 0; m++) {
951
952 if (mask[m].name.len != value[i].len
953 || ngx_strcasecmp(mask[m].name.data, value[i].data) != 0)
954 {
955 continue;
956 }
957
958 if (*np & mask[m].mask) {
959 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
960 "duplicate value \"%s\"", value[i].data);
961
962 } else {
963 *np |= mask[m].mask;
964 }
965
966 break;
967 }
968
969 if (mask[m].name.len == 0) {
970 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
971 "invalid value \"%s\"", value[i].data);
972
973 return NGX_CONF_ERROR;
974 }
975 }
976
977 return NGX_CONF_OK;
978 }
979
980
981 char *ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
982 {
983 return "unsupported on this platform";
984 }
985
986
987 char *ngx_conf_check_num_bounds(ngx_conf_t *cf, void *post, void *data)
988 {
989 ngx_conf_num_bounds_t *bounds = post;
990 ngx_int_t *np = data;
991
992 if (bounds->high == -1) {
993 if (*np >= bounds->low) {
994 return NGX_CONF_OK;
995 }
996
997 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
998 "value must be equal or more than %d", bounds->low);
999
1000 return NGX_CONF_ERROR;
1001 }
1002
1003 if (*np >= bounds->low && *np <= bounds->high) {
1004 return NGX_CONF_OK;
1005 }
1006
1007 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1008 "value must be between %d and %d",
1009 bounds->low, bounds->high);
1010
1011 return NGX_CONF_ERROR;
1012 }