Back to home page

Nginx displayed by LXR

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