Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 
0011 #define NGX_CONF_BUFFER  4096
0012 
0013 static ngx_int_t ngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename);
0014 static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last);
0015 static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf);
0016 static void ngx_conf_flush_files(ngx_cycle_t *cycle);
0017 
0018 
0019 static ngx_command_t  ngx_conf_commands[] = {
0020 
0021     { ngx_string("include"),
0022       NGX_ANY_CONF|NGX_CONF_TAKE1,
0023       ngx_conf_include,
0024       0,
0025       0,
0026       NULL },
0027 
0028       ngx_null_command
0029 };
0030 
0031 
0032 ngx_module_t  ngx_conf_module = {
0033     NGX_MODULE_V1,
0034     NULL,                                  /* module context */
0035     ngx_conf_commands,                     /* module directives */
0036     NGX_CONF_MODULE,                       /* module type */
0037     NULL,                                  /* init master */
0038     NULL,                                  /* init module */
0039     NULL,                                  /* init process */
0040     NULL,                                  /* init thread */
0041     NULL,                                  /* exit thread */
0042     ngx_conf_flush_files,                  /* exit process */
0043     NULL,                                  /* exit master */
0044     NGX_MODULE_V1_PADDING
0045 };
0046 
0047 
0048 /* The eight fixed arguments */
0049 
0050 static ngx_uint_t argument_number[] = {
0051     NGX_CONF_NOARGS,
0052     NGX_CONF_TAKE1,
0053     NGX_CONF_TAKE2,
0054     NGX_CONF_TAKE3,
0055     NGX_CONF_TAKE4,
0056     NGX_CONF_TAKE5,
0057     NGX_CONF_TAKE6,
0058     NGX_CONF_TAKE7
0059 };
0060 
0061 
0062 char *
0063 ngx_conf_param(ngx_conf_t *cf)
0064 {
0065     char             *rv;
0066     ngx_str_t        *param;
0067     ngx_buf_t         b;
0068     ngx_conf_file_t   conf_file;
0069 
0070     param = &cf->cycle->conf_param;
0071 
0072     if (param->len == 0) {
0073         return NGX_CONF_OK;
0074     }
0075 
0076     ngx_memzero(&conf_file, sizeof(ngx_conf_file_t));
0077 
0078     ngx_memzero(&b, sizeof(ngx_buf_t));
0079 
0080     b.start = param->data;
0081     b.pos = param->data;
0082     b.last = param->data + param->len;
0083     b.end = b.last;
0084     b.temporary = 1;
0085 
0086     conf_file.file.fd = NGX_INVALID_FILE;
0087     conf_file.file.name.data = NULL;
0088     conf_file.line = 0;
0089 
0090     cf->conf_file = &conf_file;
0091     cf->conf_file->buffer = &b;
0092 
0093     rv = ngx_conf_parse(cf, NULL);
0094 
0095     cf->conf_file = NULL;
0096 
0097     return rv;
0098 }
0099 
0100 
0101 static ngx_int_t
0102 ngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename)
0103 {
0104     off_t             size;
0105     u_char           *p;
0106     uint32_t          hash;
0107     ngx_buf_t        *buf;
0108     ngx_str_node_t   *sn;
0109     ngx_conf_dump_t  *cd;
0110 
0111     hash = ngx_crc32_long(filename->data, filename->len);
0112 
0113     sn = ngx_str_rbtree_lookup(&cf->cycle->config_dump_rbtree, filename, hash);
0114 
0115     if (sn) {
0116         cf->conf_file->dump = NULL;
0117         return NGX_OK;
0118     }
0119 
0120     p = ngx_pstrdup(cf->cycle->pool, filename);
0121     if (p == NULL) {
0122         return NGX_ERROR;
0123     }
0124 
0125     cd = ngx_array_push(&cf->cycle->config_dump);
0126     if (cd == NULL) {
0127         return NGX_ERROR;
0128     }
0129 
0130     size = ngx_file_size(&cf->conf_file->file.info);
0131 
0132     buf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size);
0133     if (buf == NULL) {
0134         return NGX_ERROR;
0135     }
0136 
0137     cd->name.data = p;
0138     cd->name.len = filename->len;
0139     cd->buffer = buf;
0140 
0141     cf->conf_file->dump = buf;
0142 
0143     sn = ngx_palloc(cf->temp_pool, sizeof(ngx_str_node_t));
0144     if (sn == NULL) {
0145         return NGX_ERROR;
0146     }
0147 
0148     sn->node.key = hash;
0149     sn->str = cd->name;
0150 
0151     ngx_rbtree_insert(&cf->cycle->config_dump_rbtree, &sn->node);
0152 
0153     return NGX_OK;
0154 }
0155 
0156 
0157 char *
0158 ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
0159 {
0160     char             *rv;
0161     ngx_fd_t          fd;
0162     ngx_int_t         rc;
0163     ngx_buf_t         buf;
0164     ngx_conf_file_t  *prev, conf_file;
0165     enum {
0166         parse_file = 0,
0167         parse_block,
0168         parse_param
0169     } type;
0170 
0171 #if (NGX_SUPPRESS_WARN)
0172     fd = NGX_INVALID_FILE;
0173     prev = NULL;
0174 #endif
0175 
0176     if (filename) {
0177 
0178         /* open configuration file */
0179 
0180         fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
0181         if (fd == NGX_INVALID_FILE) {
0182             ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
0183                                ngx_open_file_n " \"%s\" failed",
0184                                filename->data);
0185             return NGX_CONF_ERROR;
0186         }
0187 
0188         prev = cf->conf_file;
0189 
0190         cf->conf_file = &conf_file;
0191 
0192         if (ngx_fd_info(fd, &cf->conf_file->file.info) == NGX_FILE_ERROR) {
0193             ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
0194                           ngx_fd_info_n " \"%s\" failed", filename->data);
0195         }
0196 
0197         cf->conf_file->buffer = &buf;
0198 
0199         buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log);
0200         if (buf.start == NULL) {
0201             goto failed;
0202         }
0203 
0204         buf.pos = buf.start;
0205         buf.last = buf.start;
0206         buf.end = buf.last + NGX_CONF_BUFFER;
0207         buf.temporary = 1;
0208 
0209         cf->conf_file->file.fd = fd;
0210         cf->conf_file->file.name.len = filename->len;
0211         cf->conf_file->file.name.data = filename->data;
0212         cf->conf_file->file.offset = 0;
0213         cf->conf_file->file.log = cf->log;
0214         cf->conf_file->line = 1;
0215 
0216         type = parse_file;
0217 
0218         if (ngx_dump_config
0219 #if (NGX_DEBUG)
0220             || 1
0221 #endif
0222            )
0223         {
0224             if (ngx_conf_add_dump(cf, filename) != NGX_OK) {
0225                 goto failed;
0226             }
0227 
0228         } else {
0229             cf->conf_file->dump = NULL;
0230         }
0231 
0232     } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {
0233 
0234         type = parse_block;
0235 
0236     } else {
0237         type = parse_param;
0238     }
0239 
0240 
0241     for ( ;; ) {
0242         rc = ngx_conf_read_token(cf);
0243 
0244         /*
0245          * ngx_conf_read_token() may return
0246          *
0247          *    NGX_ERROR             there is error
0248          *    NGX_OK                the token terminated by ";" was found
0249          *    NGX_CONF_BLOCK_START  the token terminated by "{" was found
0250          *    NGX_CONF_BLOCK_DONE   the "}" was found
0251          *    NGX_CONF_FILE_DONE    the configuration file is done
0252          */
0253 
0254         if (rc == NGX_ERROR) {
0255             goto done;
0256         }
0257 
0258         if (rc == NGX_CONF_BLOCK_DONE) {
0259 
0260             if (type != parse_block) {
0261                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");
0262                 goto failed;
0263             }
0264 
0265             goto done;
0266         }
0267 
0268         if (rc == NGX_CONF_FILE_DONE) {
0269 
0270             if (type == parse_block) {
0271                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0272                                    "unexpected end of file, expecting \"}\"");
0273                 goto failed;
0274             }
0275 
0276             goto done;
0277         }
0278 
0279         if (rc == NGX_CONF_BLOCK_START) {
0280 
0281             if (type == parse_param) {
0282                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0283                                    "block directives are not supported "
0284                                    "in -g option");
0285                 goto failed;
0286             }
0287         }
0288 
0289         /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */
0290 
0291         if (cf->handler) {
0292 
0293             /*
0294              * the custom handler, i.e., that is used in the http's
0295              * "types { ... }" directive
0296              */
0297 
0298             if (rc == NGX_CONF_BLOCK_START) {
0299                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"{\"");
0300                 goto failed;
0301             }
0302 
0303             rv = (*cf->handler)(cf, NULL, cf->handler_conf);
0304             if (rv == NGX_CONF_OK) {
0305                 continue;
0306             }
0307 
0308             if (rv == NGX_CONF_ERROR) {
0309                 goto failed;
0310             }
0311 
0312             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);
0313 
0314             goto failed;
0315         }
0316 
0317 
0318         rc = ngx_conf_handler(cf, rc);
0319 
0320         if (rc == NGX_ERROR) {
0321             goto failed;
0322         }
0323     }
0324 
0325 failed:
0326 
0327     rc = NGX_ERROR;
0328 
0329 done:
0330 
0331     if (filename) {
0332         if (cf->conf_file->buffer->start) {
0333             ngx_free(cf->conf_file->buffer->start);
0334         }
0335 
0336         if (ngx_close_file(fd) == NGX_FILE_ERROR) {
0337             ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
0338                           ngx_close_file_n " %s failed",
0339                           filename->data);
0340             rc = NGX_ERROR;
0341         }
0342 
0343         cf->conf_file = prev;
0344     }
0345 
0346     if (rc == NGX_ERROR) {
0347         return NGX_CONF_ERROR;
0348     }
0349 
0350     return NGX_CONF_OK;
0351 }
0352 
0353 
0354 static ngx_int_t
0355 ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
0356 {
0357     char           *rv;
0358     void           *conf, **confp;
0359     ngx_uint_t      i, found;
0360     ngx_str_t      *name;
0361     ngx_command_t  *cmd;
0362 
0363     name = cf->args->elts;
0364 
0365     found = 0;
0366 
0367     for (i = 0; cf->cycle->modules[i]; i++) {
0368 
0369         cmd = cf->cycle->modules[i]->commands;
0370         if (cmd == NULL) {
0371             continue;
0372         }
0373 
0374         for ( /* void */ ; cmd->name.len; cmd++) {
0375 
0376             if (name->len != cmd->name.len) {
0377                 continue;
0378             }
0379 
0380             if (ngx_strcmp(name->data, cmd->name.data) != 0) {
0381                 continue;
0382             }
0383 
0384             found = 1;
0385 
0386             if (cf->cycle->modules[i]->type != NGX_CONF_MODULE
0387                 && cf->cycle->modules[i]->type != cf->module_type)
0388             {
0389                 continue;
0390             }
0391 
0392             /* is the directive's location right ? */
0393 
0394             if (!(cmd->type & cf->cmd_type)) {
0395                 continue;
0396             }
0397 
0398             if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
0399                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0400                                   "directive \"%s\" is not terminated by \";\"",
0401                                   name->data);
0402                 return NGX_ERROR;
0403             }
0404 
0405             if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {
0406                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0407                                    "directive \"%s\" has no opening \"{\"",
0408                                    name->data);
0409                 return NGX_ERROR;
0410             }
0411 
0412             /* is the directive's argument count right ? */
0413 
0414             if (!(cmd->type & NGX_CONF_ANY)) {
0415 
0416                 if (cmd->type & NGX_CONF_FLAG) {
0417 
0418                     if (cf->args->nelts != 2) {
0419                         goto invalid;
0420                     }
0421 
0422                 } else if (cmd->type & NGX_CONF_1MORE) {
0423 
0424                     if (cf->args->nelts < 2) {
0425                         goto invalid;
0426                     }
0427 
0428                 } else if (cmd->type & NGX_CONF_2MORE) {
0429 
0430                     if (cf->args->nelts < 3) {
0431                         goto invalid;
0432                     }
0433 
0434                 } else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {
0435 
0436                     goto invalid;
0437 
0438                 } else if (!(cmd->type & argument_number[cf->args->nelts - 1]))
0439                 {
0440                     goto invalid;
0441                 }
0442             }
0443 
0444             /* set up the directive's configuration context */
0445 
0446             conf = NULL;
0447 
0448             if (cmd->type & NGX_DIRECT_CONF) {
0449                 conf = ((void **) cf->ctx)[cf->cycle->modules[i]->index];
0450 
0451             } else if (cmd->type & NGX_MAIN_CONF) {
0452                 conf = &(((void **) cf->ctx)[cf->cycle->modules[i]->index]);
0453 
0454             } else if (cf->ctx) {
0455                 confp = *(void **) ((char *) cf->ctx + cmd->conf);
0456 
0457                 if (confp) {
0458                     conf = confp[cf->cycle->modules[i]->ctx_index];
0459                 }
0460             }
0461 
0462             rv = cmd->set(cf, cmd, conf);
0463 
0464             if (rv == NGX_CONF_OK) {
0465                 return NGX_OK;
0466             }
0467 
0468             if (rv == NGX_CONF_ERROR) {
0469                 return NGX_ERROR;
0470             }
0471 
0472             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0473                                "\"%s\" directive %s", name->data, rv);
0474 
0475             return NGX_ERROR;
0476         }
0477     }
0478 
0479     if (found) {
0480         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0481                            "\"%s\" directive is not allowed here", name->data);
0482 
0483         return NGX_ERROR;
0484     }
0485 
0486     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0487                        "unknown directive \"%s\"", name->data);
0488 
0489     return NGX_ERROR;
0490 
0491 invalid:
0492 
0493     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0494                        "invalid number of arguments in \"%s\" directive",
0495                        name->data);
0496 
0497     return NGX_ERROR;
0498 }
0499 
0500 
0501 static ngx_int_t
0502 ngx_conf_read_token(ngx_conf_t *cf)
0503 {
0504     u_char      *start, ch, *src, *dst;
0505     off_t        file_size;
0506     size_t       len;
0507     ssize_t      n, size;
0508     ngx_uint_t   found, need_space, last_space, sharp_comment, variable;
0509     ngx_uint_t   quoted, s_quoted, d_quoted, start_line;
0510     ngx_str_t   *word;
0511     ngx_buf_t   *b, *dump;
0512 
0513     found = 0;
0514     need_space = 0;
0515     last_space = 1;
0516     sharp_comment = 0;
0517     variable = 0;
0518     quoted = 0;
0519     s_quoted = 0;
0520     d_quoted = 0;
0521 
0522     cf->args->nelts = 0;
0523     b = cf->conf_file->buffer;
0524     dump = cf->conf_file->dump;
0525     start = b->pos;
0526     start_line = cf->conf_file->line;
0527 
0528     file_size = ngx_file_size(&cf->conf_file->file.info);
0529 
0530     for ( ;; ) {
0531 
0532         if (b->pos >= b->last) {
0533 
0534             if (cf->conf_file->file.offset >= file_size) {
0535 
0536                 if (cf->args->nelts > 0 || !last_space) {
0537 
0538                     if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
0539                         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0540                                            "unexpected end of parameter, "
0541                                            "expecting \";\"");
0542                         return NGX_ERROR;
0543                     }
0544 
0545                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0546                                   "unexpected end of file, "
0547                                   "expecting \";\" or \"}\"");
0548                     return NGX_ERROR;
0549                 }
0550 
0551                 return NGX_CONF_FILE_DONE;
0552             }
0553 
0554             len = b->pos - start;
0555 
0556             if (len == NGX_CONF_BUFFER) {
0557                 cf->conf_file->line = start_line;
0558 
0559                 if (d_quoted) {
0560                     ch = '"';
0561 
0562                 } else if (s_quoted) {
0563                     ch = '\'';
0564 
0565                 } else {
0566                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0567                                        "too long parameter \"%*s...\" started",
0568                                        10, start);
0569                     return NGX_ERROR;
0570                 }
0571 
0572                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0573                                    "too long parameter, probably "
0574                                    "missing terminating \"%c\" character", ch);
0575                 return NGX_ERROR;
0576             }
0577 
0578             if (len) {
0579                 ngx_memmove(b->start, start, len);
0580             }
0581 
0582             size = (ssize_t) (file_size - cf->conf_file->file.offset);
0583 
0584             if (size > b->end - (b->start + len)) {
0585                 size = b->end - (b->start + len);
0586             }
0587 
0588             n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
0589                               cf->conf_file->file.offset);
0590 
0591             if (n == NGX_ERROR) {
0592                 return NGX_ERROR;
0593             }
0594 
0595             if (n != size) {
0596                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0597                                    ngx_read_file_n " returned "
0598                                    "only %z bytes instead of %z",
0599                                    n, size);
0600                 return NGX_ERROR;
0601             }
0602 
0603             b->pos = b->start + len;
0604             b->last = b->pos + n;
0605             start = b->start;
0606 
0607             if (dump) {
0608                 dump->last = ngx_cpymem(dump->last, b->pos, size);
0609             }
0610         }
0611 
0612         ch = *b->pos++;
0613 
0614         if (ch == LF) {
0615             cf->conf_file->line++;
0616 
0617             if (sharp_comment) {
0618                 sharp_comment = 0;
0619             }
0620         }
0621 
0622         if (sharp_comment) {
0623             continue;
0624         }
0625 
0626         if (quoted) {
0627             quoted = 0;
0628             continue;
0629         }
0630 
0631         if (need_space) {
0632             if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
0633                 last_space = 1;
0634                 need_space = 0;
0635                 continue;
0636             }
0637 
0638             if (ch == ';') {
0639                 return NGX_OK;
0640             }
0641 
0642             if (ch == '{') {
0643                 return NGX_CONF_BLOCK_START;
0644             }
0645 
0646             if (ch == ')') {
0647                 last_space = 1;
0648                 need_space = 0;
0649 
0650             } else {
0651                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0652                                    "unexpected \"%c\"", ch);
0653                 return NGX_ERROR;
0654             }
0655         }
0656 
0657         if (last_space) {
0658             if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
0659                 continue;
0660             }
0661 
0662             start = b->pos - 1;
0663             start_line = cf->conf_file->line;
0664 
0665             switch (ch) {
0666 
0667             case ';':
0668             case '{':
0669                 if (cf->args->nelts == 0) {
0670                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0671                                        "unexpected \"%c\"", ch);
0672                     return NGX_ERROR;
0673                 }
0674 
0675                 if (ch == '{') {
0676                     return NGX_CONF_BLOCK_START;
0677                 }
0678 
0679                 return NGX_OK;
0680 
0681             case '}':
0682                 if (cf->args->nelts != 0) {
0683                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0684                                        "unexpected \"}\"");
0685                     return NGX_ERROR;
0686                 }
0687 
0688                 return NGX_CONF_BLOCK_DONE;
0689 
0690             case '#':
0691                 sharp_comment = 1;
0692                 continue;
0693 
0694             case '\\':
0695                 quoted = 1;
0696                 last_space = 0;
0697                 continue;
0698 
0699             case '"':
0700                 start++;
0701                 d_quoted = 1;
0702                 last_space = 0;
0703                 continue;
0704 
0705             case '\'':
0706                 start++;
0707                 s_quoted = 1;
0708                 last_space = 0;
0709                 continue;
0710 
0711             default:
0712                 last_space = 0;
0713             }
0714 
0715         } else {
0716             if (ch == '{' && variable) {
0717                 continue;
0718             }
0719 
0720             variable = 0;
0721 
0722             if (ch == '\\') {
0723                 quoted = 1;
0724                 continue;
0725             }
0726 
0727             if (ch == '$') {
0728                 variable = 1;
0729                 continue;
0730             }
0731 
0732             if (d_quoted) {
0733                 if (ch == '"') {
0734                     d_quoted = 0;
0735                     need_space = 1;
0736                     found = 1;
0737                 }
0738 
0739             } else if (s_quoted) {
0740                 if (ch == '\'') {
0741                     s_quoted = 0;
0742                     need_space = 1;
0743                     found = 1;
0744                 }
0745 
0746             } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
0747                        || ch == ';' || ch == '{')
0748             {
0749                 last_space = 1;
0750                 found = 1;
0751             }
0752 
0753             if (found) {
0754                 word = ngx_array_push(cf->args);
0755                 if (word == NULL) {
0756                     return NGX_ERROR;
0757                 }
0758 
0759                 word->data = ngx_pnalloc(cf->pool, b->pos - 1 - start + 1);
0760                 if (word->data == NULL) {
0761                     return NGX_ERROR;
0762                 }
0763 
0764                 for (dst = word->data, src = start, len = 0;
0765                      src < b->pos - 1;
0766                      len++)
0767                 {
0768                     if (*src == '\\') {
0769                         switch (src[1]) {
0770                         case '"':
0771                         case '\'':
0772                         case '\\':
0773                             src++;
0774                             break;
0775 
0776                         case 't':
0777                             *dst++ = '\t';
0778                             src += 2;
0779                             continue;
0780 
0781                         case 'r':
0782                             *dst++ = '\r';
0783                             src += 2;
0784                             continue;
0785 
0786                         case 'n':
0787                             *dst++ = '\n';
0788                             src += 2;
0789                             continue;
0790                         }
0791 
0792                     }
0793                     *dst++ = *src++;
0794                 }
0795                 *dst = '\0';
0796                 word->len = len;
0797 
0798                 if (ch == ';') {
0799                     return NGX_OK;
0800                 }
0801 
0802                 if (ch == '{') {
0803                     return NGX_CONF_BLOCK_START;
0804                 }
0805 
0806                 found = 0;
0807             }
0808         }
0809     }
0810 }
0811 
0812 
0813 char *
0814 ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0815 {
0816     char        *rv;
0817     ngx_int_t    n;
0818     ngx_str_t   *value, file, name;
0819     ngx_glob_t   gl;
0820 
0821     value = cf->args->elts;
0822     file = value[1];
0823 
0824     ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
0825 
0826     if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
0827         return NGX_CONF_ERROR;
0828     }
0829 
0830     if (strpbrk((char *) file.data, "*?[") == NULL) {
0831 
0832         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
0833 
0834         return ngx_conf_parse(cf, &file);
0835     }
0836 
0837     ngx_memzero(&gl, sizeof(ngx_glob_t));
0838 
0839     gl.pattern = file.data;
0840     gl.log = cf->log;
0841     gl.test = 1;
0842 
0843     if (ngx_open_glob(&gl) != NGX_OK) {
0844         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
0845                            ngx_open_glob_n " \"%s\" failed", file.data);
0846         return NGX_CONF_ERROR;
0847     }
0848 
0849     rv = NGX_CONF_OK;
0850 
0851     for ( ;; ) {
0852         n = ngx_read_glob(&gl, &name);
0853 
0854         if (n != NGX_OK) {
0855             break;
0856         }
0857 
0858         file.len = name.len++;
0859         file.data = ngx_pstrdup(cf->pool, &name);
0860         if (file.data == NULL) {
0861             return NGX_CONF_ERROR;
0862         }
0863 
0864         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
0865 
0866         rv = ngx_conf_parse(cf, &file);
0867 
0868         if (rv != NGX_CONF_OK) {
0869             break;
0870         }
0871     }
0872 
0873     ngx_close_glob(&gl);
0874 
0875     return rv;
0876 }
0877 
0878 
0879 ngx_int_t
0880 ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix)
0881 {
0882     ngx_str_t  *prefix;
0883 
0884     prefix = conf_prefix ? &cycle->conf_prefix : &cycle->prefix;
0885 
0886     return ngx_get_full_name(cycle->pool, prefix, name);
0887 }
0888 
0889 
0890 ngx_open_file_t *
0891 ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
0892 {
0893     ngx_str_t         full;
0894     ngx_uint_t        i;
0895     ngx_list_part_t  *part;
0896     ngx_open_file_t  *file;
0897 
0898 #if (NGX_SUPPRESS_WARN)
0899     ngx_str_null(&full);
0900 #endif
0901 
0902     if (name->len) {
0903         full = *name;
0904 
0905         if (ngx_conf_full_name(cycle, &full, 0) != NGX_OK) {
0906             return NULL;
0907         }
0908 
0909         part = &cycle->open_files.part;
0910         file = part->elts;
0911 
0912         for (i = 0; /* void */ ; i++) {
0913 
0914             if (i >= part->nelts) {
0915                 if (part->next == NULL) {
0916                     break;
0917                 }
0918                 part = part->next;
0919                 file = part->elts;
0920                 i = 0;
0921             }
0922 
0923             if (full.len != file[i].name.len) {
0924                 continue;
0925             }
0926 
0927             if (ngx_strcmp(full.data, file[i].name.data) == 0) {
0928                 return &file[i];
0929             }
0930         }
0931     }
0932 
0933     file = ngx_list_push(&cycle->open_files);
0934     if (file == NULL) {
0935         return NULL;
0936     }
0937 
0938     if (name->len) {
0939         file->fd = NGX_INVALID_FILE;
0940         file->name = full;
0941 
0942     } else {
0943         file->fd = ngx_stderr;
0944         file->name = *name;
0945     }
0946 
0947     file->flush = NULL;
0948     file->data = NULL;
0949 
0950     return file;
0951 }
0952 
0953 
0954 static void
0955 ngx_conf_flush_files(ngx_cycle_t *cycle)
0956 {
0957     ngx_uint_t        i;
0958     ngx_list_part_t  *part;
0959     ngx_open_file_t  *file;
0960 
0961     ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "flush files");
0962 
0963     part = &cycle->open_files.part;
0964     file = part->elts;
0965 
0966     for (i = 0; /* void */ ; i++) {
0967 
0968         if (i >= part->nelts) {
0969             if (part->next == NULL) {
0970                 break;
0971             }
0972             part = part->next;
0973             file = part->elts;
0974             i = 0;
0975         }
0976 
0977         if (file[i].flush) {
0978             file[i].flush(&file[i], cycle->log);
0979         }
0980     }
0981 }
0982 
0983 
0984 void ngx_cdecl
0985 ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
0986     const char *fmt, ...)
0987 {
0988     u_char   errstr[NGX_MAX_CONF_ERRSTR], *p, *last;
0989     va_list  args;
0990 
0991     last = errstr + NGX_MAX_CONF_ERRSTR;
0992 
0993     va_start(args, fmt);
0994     p = ngx_vslprintf(errstr, last, fmt, args);
0995     va_end(args);
0996 
0997     if (err) {
0998         p = ngx_log_errno(p, last, err);
0999     }
1000 
1001     if (cf->conf_file == NULL) {
1002         ngx_log_error(level, cf->log, 0, "%*s", p - errstr, errstr);
1003         return;
1004     }
1005 
1006     if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
1007         ngx_log_error(level, cf->log, 0, "%*s in command line",
1008                       p - errstr, errstr);
1009         return;
1010     }
1011 
1012     ngx_log_error(level, cf->log, 0, "%*s in %s:%ui",
1013                   p - errstr, errstr,
1014                   cf->conf_file->file.name.data, cf->conf_file->line);
1015 }
1016 
1017 
1018 char *
1019 ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1020 {
1021     char  *p = conf;
1022 
1023     ngx_str_t        *value;
1024     ngx_flag_t       *fp;
1025     ngx_conf_post_t  *post;
1026 
1027     fp = (ngx_flag_t *) (p + cmd->offset);
1028 
1029     if (*fp != NGX_CONF_UNSET) {
1030         return "is duplicate";
1031     }
1032 
1033     value = cf->args->elts;
1034 
1035     if (ngx_strcasecmp(value[1].data, (u_char *) "on") == 0) {
1036         *fp = 1;
1037 
1038     } else if (ngx_strcasecmp(value[1].data, (u_char *) "off") == 0) {
1039         *fp = 0;
1040 
1041     } else {
1042         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1043                      "invalid value \"%s\" in \"%s\" directive, "
1044                      "it must be \"on\" or \"off\"",
1045                      value[1].data, cmd->name.data);
1046         return NGX_CONF_ERROR;
1047     }
1048 
1049     if (cmd->post) {
1050         post = cmd->post;
1051         return post->post_handler(cf, post, fp);
1052     }
1053 
1054     return NGX_CONF_OK;
1055 }
1056 
1057 
1058 char *
1059 ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1060 {
1061     char  *p = conf;
1062 
1063     ngx_str_t        *field, *value;
1064     ngx_conf_post_t  *post;
1065 
1066     field = (ngx_str_t *) (p + cmd->offset);
1067 
1068     if (field->data) {
1069         return "is duplicate";
1070     }
1071 
1072     value = cf->args->elts;
1073 
1074     *field = value[1];
1075 
1076     if (cmd->post) {
1077         post = cmd->post;
1078         return post->post_handler(cf, post, field);
1079     }
1080 
1081     return NGX_CONF_OK;
1082 }
1083 
1084 
1085 char *
1086 ngx_conf_set_str_array_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1087 {
1088     char  *p = conf;
1089 
1090     ngx_str_t         *value, *s;
1091     ngx_array_t      **a;
1092     ngx_conf_post_t   *post;
1093 
1094     a = (ngx_array_t **) (p + cmd->offset);
1095 
1096     if (*a == NGX_CONF_UNSET_PTR) {
1097         *a = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
1098         if (*a == NULL) {
1099             return NGX_CONF_ERROR;
1100         }
1101     }
1102 
1103     s = ngx_array_push(*a);
1104     if (s == NULL) {
1105         return NGX_CONF_ERROR;
1106     }
1107 
1108     value = cf->args->elts;
1109 
1110     *s = value[1];
1111 
1112     if (cmd->post) {
1113         post = cmd->post;
1114         return post->post_handler(cf, post, s);
1115     }
1116 
1117     return NGX_CONF_OK;
1118 }
1119 
1120 
1121 char *
1122 ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1123 {
1124     char  *p = conf;
1125 
1126     ngx_str_t         *value;
1127     ngx_array_t      **a;
1128     ngx_keyval_t      *kv;
1129     ngx_conf_post_t   *post;
1130 
1131     a = (ngx_array_t **) (p + cmd->offset);
1132 
1133     if (*a == NULL) {
1134         *a = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t));
1135         if (*a == NULL) {
1136             return NGX_CONF_ERROR;
1137         }
1138     }
1139 
1140     kv = ngx_array_push(*a);
1141     if (kv == NULL) {
1142         return NGX_CONF_ERROR;
1143     }
1144 
1145     value = cf->args->elts;
1146 
1147     kv->key = value[1];
1148     kv->value = value[2];
1149 
1150     if (cmd->post) {
1151         post = cmd->post;
1152         return post->post_handler(cf, post, kv);
1153     }
1154 
1155     return NGX_CONF_OK;
1156 }
1157 
1158 
1159 char *
1160 ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1161 {
1162     char  *p = conf;
1163 
1164     ngx_int_t        *np;
1165     ngx_str_t        *value;
1166     ngx_conf_post_t  *post;
1167 
1168 
1169     np = (ngx_int_t *) (p + cmd->offset);
1170 
1171     if (*np != NGX_CONF_UNSET) {
1172         return "is duplicate";
1173     }
1174 
1175     value = cf->args->elts;
1176     *np = ngx_atoi(value[1].data, value[1].len);
1177     if (*np == NGX_ERROR) {
1178         return "invalid number";
1179     }
1180 
1181     if (cmd->post) {
1182         post = cmd->post;
1183         return post->post_handler(cf, post, np);
1184     }
1185 
1186     return NGX_CONF_OK;
1187 }
1188 
1189 
1190 char *
1191 ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1192 {
1193     char  *p = conf;
1194 
1195     size_t           *sp;
1196     ngx_str_t        *value;
1197     ngx_conf_post_t  *post;
1198 
1199 
1200     sp = (size_t *) (p + cmd->offset);
1201     if (*sp != NGX_CONF_UNSET_SIZE) {
1202         return "is duplicate";
1203     }
1204 
1205     value = cf->args->elts;
1206 
1207     *sp = ngx_parse_size(&value[1]);
1208     if (*sp == (size_t) NGX_ERROR) {
1209         return "invalid value";
1210     }
1211 
1212     if (cmd->post) {
1213         post = cmd->post;
1214         return post->post_handler(cf, post, sp);
1215     }
1216 
1217     return NGX_CONF_OK;
1218 }
1219 
1220 
1221 char *
1222 ngx_conf_set_off_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1223 {
1224     char  *p = conf;
1225 
1226     off_t            *op;
1227     ngx_str_t        *value;
1228     ngx_conf_post_t  *post;
1229 
1230 
1231     op = (off_t *) (p + cmd->offset);
1232     if (*op != NGX_CONF_UNSET) {
1233         return "is duplicate";
1234     }
1235 
1236     value = cf->args->elts;
1237 
1238     *op = ngx_parse_offset(&value[1]);
1239     if (*op == (off_t) NGX_ERROR) {
1240         return "invalid value";
1241     }
1242 
1243     if (cmd->post) {
1244         post = cmd->post;
1245         return post->post_handler(cf, post, op);
1246     }
1247 
1248     return NGX_CONF_OK;
1249 }
1250 
1251 
1252 char *
1253 ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1254 {
1255     char  *p = conf;
1256 
1257     ngx_msec_t       *msp;
1258     ngx_str_t        *value;
1259     ngx_conf_post_t  *post;
1260 
1261 
1262     msp = (ngx_msec_t *) (p + cmd->offset);
1263     if (*msp != NGX_CONF_UNSET_MSEC) {
1264         return "is duplicate";
1265     }
1266 
1267     value = cf->args->elts;
1268 
1269     *msp = ngx_parse_time(&value[1], 0);
1270     if (*msp == (ngx_msec_t) NGX_ERROR) {
1271         return "invalid value";
1272     }
1273 
1274     if (cmd->post) {
1275         post = cmd->post;
1276         return post->post_handler(cf, post, msp);
1277     }
1278 
1279     return NGX_CONF_OK;
1280 }
1281 
1282 
1283 char *
1284 ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1285 {
1286     char  *p = conf;
1287 
1288     time_t           *sp;
1289     ngx_str_t        *value;
1290     ngx_conf_post_t  *post;
1291 
1292 
1293     sp = (time_t *) (p + cmd->offset);
1294     if (*sp != NGX_CONF_UNSET) {
1295         return "is duplicate";
1296     }
1297 
1298     value = cf->args->elts;
1299 
1300     *sp = ngx_parse_time(&value[1], 1);
1301     if (*sp == (time_t) NGX_ERROR) {
1302         return "invalid value";
1303     }
1304 
1305     if (cmd->post) {
1306         post = cmd->post;
1307         return post->post_handler(cf, post, sp);
1308     }
1309 
1310     return NGX_CONF_OK;
1311 }
1312 
1313 
1314 char *
1315 ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1316 {
1317     char *p = conf;
1318 
1319     ngx_str_t   *value;
1320     ngx_bufs_t  *bufs;
1321 
1322 
1323     bufs = (ngx_bufs_t *) (p + cmd->offset);
1324     if (bufs->num) {
1325         return "is duplicate";
1326     }
1327 
1328     value = cf->args->elts;
1329 
1330     bufs->num = ngx_atoi(value[1].data, value[1].len);
1331     if (bufs->num == NGX_ERROR || bufs->num == 0) {
1332         return "invalid value";
1333     }
1334 
1335     bufs->size = ngx_parse_size(&value[2]);
1336     if (bufs->size == (size_t) NGX_ERROR || bufs->size == 0) {
1337         return "invalid value";
1338     }
1339 
1340     return NGX_CONF_OK;
1341 }
1342 
1343 
1344 char *
1345 ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1346 {
1347     char  *p = conf;
1348 
1349     ngx_uint_t       *np, i;
1350     ngx_str_t        *value;
1351     ngx_conf_enum_t  *e;
1352 
1353     np = (ngx_uint_t *) (p + cmd->offset);
1354 
1355     if (*np != NGX_CONF_UNSET_UINT) {
1356         return "is duplicate";
1357     }
1358 
1359     value = cf->args->elts;
1360     e = cmd->post;
1361 
1362     for (i = 0; e[i].name.len != 0; i++) {
1363         if (e[i].name.len != value[1].len
1364             || ngx_strcasecmp(e[i].name.data, value[1].data) != 0)
1365         {
1366             continue;
1367         }
1368 
1369         *np = e[i].value;
1370 
1371         return NGX_CONF_OK;
1372     }
1373 
1374     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1375                        "invalid value \"%s\"", value[1].data);
1376 
1377     return NGX_CONF_ERROR;
1378 }
1379 
1380 
1381 char *
1382 ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1383 {
1384     char  *p = conf;
1385 
1386     ngx_uint_t          *np, i, m;
1387     ngx_str_t           *value;
1388     ngx_conf_bitmask_t  *mask;
1389 
1390 
1391     np = (ngx_uint_t *) (p + cmd->offset);
1392     value = cf->args->elts;
1393     mask = cmd->post;
1394 
1395     for (i = 1; i < cf->args->nelts; i++) {
1396         for (m = 0; mask[m].name.len != 0; m++) {
1397 
1398             if (mask[m].name.len != value[i].len
1399                 || ngx_strcasecmp(mask[m].name.data, value[i].data) != 0)
1400             {
1401                 continue;
1402             }
1403 
1404             if (*np & mask[m].mask) {
1405                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1406                                    "duplicate value \"%s\"", value[i].data);
1407 
1408             } else {
1409                 *np |= mask[m].mask;
1410             }
1411 
1412             break;
1413         }
1414 
1415         if (mask[m].name.len == 0) {
1416             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1417                                "invalid value \"%s\"", value[i].data);
1418 
1419             return NGX_CONF_ERROR;
1420         }
1421     }
1422 
1423     return NGX_CONF_OK;
1424 }
1425 
1426 
1427 #if 0
1428 
1429 char *
1430 ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1431 {
1432     return "unsupported on this platform";
1433 }
1434 
1435 #endif
1436 
1437 
1438 char *
1439 ngx_conf_deprecated(ngx_conf_t *cf, void *post, void *data)
1440 {
1441     ngx_conf_deprecated_t  *d = post;
1442 
1443     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1444                        "the \"%s\" directive is deprecated, "
1445                        "use the \"%s\" directive instead",
1446                        d->old_name, d->new_name);
1447 
1448     return NGX_CONF_OK;
1449 }
1450 
1451 
1452 char *
1453 ngx_conf_check_num_bounds(ngx_conf_t *cf, void *post, void *data)
1454 {
1455     ngx_conf_num_bounds_t  *bounds = post;
1456     ngx_int_t  *np = data;
1457 
1458     if (bounds->high == -1) {
1459         if (*np >= bounds->low) {
1460             return NGX_CONF_OK;
1461         }
1462 
1463         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1464                            "value must be equal to or greater than %i",
1465                            bounds->low);
1466 
1467         return NGX_CONF_ERROR;
1468     }
1469 
1470     if (*np >= bounds->low && *np <= bounds->high) {
1471         return NGX_CONF_OK;
1472     }
1473 
1474     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1475                        "value must be between %i and %i",
1476                        bounds->low, bounds->high);
1477 
1478     return NGX_CONF_ERROR;
1479 }