~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/core/ngx_conf_file.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

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