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 
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, 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             if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
0660                 continue;
0661             }
0662 
0663             start = b->pos - 1;
0664             start_line = cf->conf_file->line;
0665 
0666             switch (ch) {
0667 
0668             case ';':
0669             case '{':
0670                 if (cf->args->nelts == 0) {
0671                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0672                                        "unexpected \"%c\"", ch);
0673                     return NGX_ERROR;
0674                 }
0675 
0676                 if (ch == '{') {
0677                     return NGX_CONF_BLOCK_START;
0678                 }
0679 
0680                 return NGX_OK;
0681 
0682             case '}':
0683                 if (cf->args->nelts != 0) {
0684                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0685                                        "unexpected \"}\"");
0686                     return NGX_ERROR;
0687                 }
0688 
0689                 return NGX_CONF_BLOCK_DONE;
0690 
0691             case '#':
0692                 sharp_comment = 1;
0693                 continue;
0694 
0695             case '\\':
0696                 quoted = 1;
0697                 last_space = 0;
0698                 continue;
0699 
0700             case '"':
0701                 start++;
0702                 d_quoted = 1;
0703                 last_space = 0;
0704                 continue;
0705 
0706             case '\'':
0707                 start++;
0708                 s_quoted = 1;
0709                 last_space = 0;
0710                 continue;
0711 
0712             case '$':
0713                 variable = 1;
0714                 last_space = 0;
0715                 continue;
0716 
0717             default:
0718                 last_space = 0;
0719             }
0720 
0721         } else {
0722             if (ch == '{' && variable) {
0723                 continue;
0724             }
0725 
0726             variable = 0;
0727 
0728             if (ch == '\\') {
0729                 quoted = 1;
0730                 continue;
0731             }
0732 
0733             if (ch == '$') {
0734                 variable = 1;
0735                 continue;
0736             }
0737 
0738             if (d_quoted) {
0739                 if (ch == '"') {
0740                     d_quoted = 0;
0741                     need_space = 1;
0742                     found = 1;
0743                 }
0744 
0745             } else if (s_quoted) {
0746                 if (ch == '\'') {
0747                     s_quoted = 0;
0748                     need_space = 1;
0749                     found = 1;
0750                 }
0751 
0752             } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
0753                        || ch == ';' || ch == '{')
0754             {
0755                 last_space = 1;
0756                 found = 1;
0757             }
0758 
0759             if (found) {
0760                 word = ngx_array_push(cf->args);
0761                 if (word == NULL) {
0762                     return NGX_ERROR;
0763                 }
0764 
0765                 word->data = ngx_pnalloc(cf->pool, b->pos - 1 - start + 1);
0766                 if (word->data == NULL) {
0767                     return NGX_ERROR;
0768                 }
0769 
0770                 for (dst = word->data, src = start, len = 0;
0771                      src < b->pos - 1;
0772                      len++)
0773                 {
0774                     if (*src == '\\') {
0775                         switch (src[1]) {
0776                         case '"':
0777                         case '\'':
0778                         case '\\':
0779                             src++;
0780                             break;
0781 
0782                         case 't':
0783                             *dst++ = '\t';
0784                             src += 2;
0785                             continue;
0786 
0787                         case 'r':
0788                             *dst++ = '\r';
0789                             src += 2;
0790                             continue;
0791 
0792                         case 'n':
0793                             *dst++ = '\n';
0794                             src += 2;
0795                             continue;
0796                         }
0797 
0798                     }
0799                     *dst++ = *src++;
0800                 }
0801                 *dst = '\0';
0802                 word->len = len;
0803 
0804                 if (ch == ';') {
0805                     return NGX_OK;
0806                 }
0807 
0808                 if (ch == '{') {
0809                     return NGX_CONF_BLOCK_START;
0810                 }
0811 
0812                 found = 0;
0813             }
0814         }
0815     }
0816 }
0817 
0818 
0819 char *
0820 ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0821 {
0822     char        *rv;
0823     ngx_int_t    n;
0824     ngx_str_t   *value, file, name;
0825     ngx_glob_t   gl;
0826 
0827     value = cf->args->elts;
0828     file = value[1];
0829 
0830     ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
0831 
0832     if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
0833         return NGX_CONF_ERROR;
0834     }
0835 
0836     if (strpbrk((char *) file.data, "*?[") == NULL) {
0837 
0838         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
0839 
0840         return ngx_conf_parse(cf, &file);
0841     }
0842 
0843     ngx_memzero(&gl, sizeof(ngx_glob_t));
0844 
0845     gl.pattern = file.data;
0846     gl.log = cf->log;
0847     gl.test = 1;
0848 
0849     if (ngx_open_glob(&gl) != NGX_OK) {
0850         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
0851                            ngx_open_glob_n " \"%s\" failed", file.data);
0852         return NGX_CONF_ERROR;
0853     }
0854 
0855     rv = NGX_CONF_OK;
0856 
0857     for ( ;; ) {
0858         n = ngx_read_glob(&gl, &name);
0859 
0860         if (n != NGX_OK) {
0861             break;
0862         }
0863 
0864         file.len = name.len++;
0865         file.data = ngx_pstrdup(cf->pool, &name);
0866         if (file.data == NULL) {
0867             return NGX_CONF_ERROR;
0868         }
0869 
0870         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
0871 
0872         rv = ngx_conf_parse(cf, &file);
0873 
0874         if (rv != NGX_CONF_OK) {
0875             break;
0876         }
0877     }
0878 
0879     ngx_close_glob(&gl);
0880 
0881     return rv;
0882 }
0883 
0884 
0885 ngx_int_t
0886 ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix)
0887 {
0888     ngx_str_t  *prefix;
0889 
0890     prefix = conf_prefix ? &cycle->conf_prefix : &cycle->prefix;
0891 
0892     return ngx_get_full_name(cycle->pool, prefix, name);
0893 }
0894 
0895 
0896 ngx_open_file_t *
0897 ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
0898 {
0899     ngx_str_t         full;
0900     ngx_uint_t        i;
0901     ngx_list_part_t  *part;
0902     ngx_open_file_t  *file;
0903 
0904 #if (NGX_SUPPRESS_WARN)
0905     ngx_str_null(&full);
0906 #endif
0907 
0908     if (name->len) {
0909         full = *name;
0910 
0911         if (ngx_conf_full_name(cycle, &full, 0) != NGX_OK) {
0912             return NULL;
0913         }
0914 
0915         part = &cycle->open_files.part;
0916         file = part->elts;
0917 
0918         for (i = 0; /* void */ ; i++) {
0919 
0920             if (i >= part->nelts) {
0921                 if (part->next == NULL) {
0922                     break;
0923                 }
0924                 part = part->next;
0925                 file = part->elts;
0926                 i = 0;
0927             }
0928 
0929             if (full.len != file[i].name.len) {
0930                 continue;
0931             }
0932 
0933             if (ngx_strcmp(full.data, file[i].name.data) == 0) {
0934                 return &file[i];
0935             }
0936         }
0937     }
0938 
0939     file = ngx_list_push(&cycle->open_files);
0940     if (file == NULL) {
0941         return NULL;
0942     }
0943 
0944     if (name->len) {
0945         file->fd = NGX_INVALID_FILE;
0946         file->name = full;
0947 
0948     } else {
0949         file->fd = ngx_stderr;
0950         file->name = *name;
0951     }
0952 
0953     file->flush = NULL;
0954     file->data = NULL;
0955 
0956     return file;
0957 }
0958 
0959 
0960 static void
0961 ngx_conf_flush_files(ngx_cycle_t *cycle)
0962 {
0963     ngx_uint_t        i;
0964     ngx_list_part_t  *part;
0965     ngx_open_file_t  *file;
0966 
0967     ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "flush files");
0968 
0969     part = &cycle->open_files.part;
0970     file = part->elts;
0971 
0972     for (i = 0; /* void */ ; i++) {
0973 
0974         if (i >= part->nelts) {
0975             if (part->next == NULL) {
0976                 break;
0977             }
0978             part = part->next;
0979             file = part->elts;
0980             i = 0;
0981         }
0982 
0983         if (file[i].flush) {
0984             file[i].flush(&file[i], cycle->log);
0985         }
0986     }
0987 }
0988 
0989 
0990 void ngx_cdecl
0991 ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
0992     const char *fmt, ...)
0993 {
0994     u_char   errstr[NGX_MAX_CONF_ERRSTR], *p, *last;
0995     va_list  args;
0996 
0997     last = errstr + NGX_MAX_CONF_ERRSTR;
0998 
0999     va_start(args, fmt);
1000     p = ngx_vslprintf(errstr, last, fmt, args);
1001     va_end(args);
1002 
1003     if (err) {
1004         p = ngx_log_errno(p, last, err);
1005     }
1006 
1007     if (cf->conf_file == NULL) {
1008         ngx_log_error(level, cf->log, 0, "%*s", p - errstr, errstr);
1009         return;
1010     }
1011 
1012     if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
1013         ngx_log_error(level, cf->log, 0, "%*s in command line",
1014                       p - errstr, errstr);
1015         return;
1016     }
1017 
1018     ngx_log_error(level, cf->log, 0, "%*s in %s:%ui",
1019                   p - errstr, errstr,
1020                   cf->conf_file->file.name.data, cf->conf_file->line);
1021 }
1022 
1023 
1024 char *
1025 ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1026 {
1027     char  *p = conf;
1028 
1029     ngx_str_t        *value;
1030     ngx_flag_t       *fp;
1031     ngx_conf_post_t  *post;
1032 
1033     fp = (ngx_flag_t *) (p + cmd->offset);
1034 
1035     if (*fp != NGX_CONF_UNSET) {
1036         return "is duplicate";
1037     }
1038 
1039     value = cf->args->elts;
1040 
1041     if (ngx_strcasecmp(value[1].data, (u_char *) "on") == 0) {
1042         *fp = 1;
1043 
1044     } else if (ngx_strcasecmp(value[1].data, (u_char *) "off") == 0) {
1045         *fp = 0;
1046 
1047     } else {
1048         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1049                      "invalid value \"%s\" in \"%s\" directive, "
1050                      "it must be \"on\" or \"off\"",
1051                      value[1].data, cmd->name.data);
1052         return NGX_CONF_ERROR;
1053     }
1054 
1055     if (cmd->post) {
1056         post = cmd->post;
1057         return post->post_handler(cf, post, fp);
1058     }
1059 
1060     return NGX_CONF_OK;
1061 }
1062 
1063 
1064 char *
1065 ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1066 {
1067     char  *p = conf;
1068 
1069     ngx_str_t        *field, *value;
1070     ngx_conf_post_t  *post;
1071 
1072     field = (ngx_str_t *) (p + cmd->offset);
1073 
1074     if (field->data) {
1075         return "is duplicate";
1076     }
1077 
1078     value = cf->args->elts;
1079 
1080     *field = value[1];
1081 
1082     if (cmd->post) {
1083         post = cmd->post;
1084         return post->post_handler(cf, post, field);
1085     }
1086 
1087     return NGX_CONF_OK;
1088 }
1089 
1090 
1091 char *
1092 ngx_conf_set_str_array_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1093 {
1094     char  *p = conf;
1095 
1096     ngx_str_t         *value, *s;
1097     ngx_array_t      **a;
1098     ngx_conf_post_t   *post;
1099 
1100     a = (ngx_array_t **) (p + cmd->offset);
1101 
1102     if (*a == NGX_CONF_UNSET_PTR) {
1103         *a = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
1104         if (*a == NULL) {
1105             return NGX_CONF_ERROR;
1106         }
1107     }
1108 
1109     s = ngx_array_push(*a);
1110     if (s == NULL) {
1111         return NGX_CONF_ERROR;
1112     }
1113 
1114     value = cf->args->elts;
1115 
1116     *s = value[1];
1117 
1118     if (cmd->post) {
1119         post = cmd->post;
1120         return post->post_handler(cf, post, s);
1121     }
1122 
1123     return NGX_CONF_OK;
1124 }
1125 
1126 
1127 char *
1128 ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1129 {
1130     char  *p = conf;
1131 
1132     ngx_str_t         *value;
1133     ngx_array_t      **a;
1134     ngx_keyval_t      *kv;
1135     ngx_conf_post_t   *post;
1136 
1137     a = (ngx_array_t **) (p + cmd->offset);
1138 
1139     if (*a == NULL) {
1140         *a = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t));
1141         if (*a == NULL) {
1142             return NGX_CONF_ERROR;
1143         }
1144     }
1145 
1146     kv = ngx_array_push(*a);
1147     if (kv == NULL) {
1148         return NGX_CONF_ERROR;
1149     }
1150 
1151     value = cf->args->elts;
1152 
1153     kv->key = value[1];
1154     kv->value = value[2];
1155 
1156     if (cmd->post) {
1157         post = cmd->post;
1158         return post->post_handler(cf, post, kv);
1159     }
1160 
1161     return NGX_CONF_OK;
1162 }
1163 
1164 
1165 char *
1166 ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1167 {
1168     char  *p = conf;
1169 
1170     ngx_int_t        *np;
1171     ngx_str_t        *value;
1172     ngx_conf_post_t  *post;
1173 
1174 
1175     np = (ngx_int_t *) (p + cmd->offset);
1176 
1177     if (*np != NGX_CONF_UNSET) {
1178         return "is duplicate";
1179     }
1180 
1181     value = cf->args->elts;
1182     *np = ngx_atoi(value[1].data, value[1].len);
1183     if (*np == NGX_ERROR) {
1184         return "invalid number";
1185     }
1186 
1187     if (cmd->post) {
1188         post = cmd->post;
1189         return post->post_handler(cf, post, np);
1190     }
1191 
1192     return NGX_CONF_OK;
1193 }
1194 
1195 
1196 char *
1197 ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1198 {
1199     char  *p = conf;
1200 
1201     size_t           *sp;
1202     ngx_str_t        *value;
1203     ngx_conf_post_t  *post;
1204 
1205 
1206     sp = (size_t *) (p + cmd->offset);
1207     if (*sp != NGX_CONF_UNSET_SIZE) {
1208         return "is duplicate";
1209     }
1210 
1211     value = cf->args->elts;
1212 
1213     *sp = ngx_parse_size(&value[1]);
1214     if (*sp == (size_t) NGX_ERROR) {
1215         return "invalid value";
1216     }
1217 
1218     if (cmd->post) {
1219         post = cmd->post;
1220         return post->post_handler(cf, post, sp);
1221     }
1222 
1223     return NGX_CONF_OK;
1224 }
1225 
1226 
1227 char *
1228 ngx_conf_set_off_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1229 {
1230     char  *p = conf;
1231 
1232     off_t            *op;
1233     ngx_str_t        *value;
1234     ngx_conf_post_t  *post;
1235 
1236 
1237     op = (off_t *) (p + cmd->offset);
1238     if (*op != NGX_CONF_UNSET) {
1239         return "is duplicate";
1240     }
1241 
1242     value = cf->args->elts;
1243 
1244     *op = ngx_parse_offset(&value[1]);
1245     if (*op == (off_t) NGX_ERROR) {
1246         return "invalid value";
1247     }
1248 
1249     if (cmd->post) {
1250         post = cmd->post;
1251         return post->post_handler(cf, post, op);
1252     }
1253 
1254     return NGX_CONF_OK;
1255 }
1256 
1257 
1258 char *
1259 ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1260 {
1261     char  *p = conf;
1262 
1263     ngx_msec_t       *msp;
1264     ngx_str_t        *value;
1265     ngx_conf_post_t  *post;
1266 
1267 
1268     msp = (ngx_msec_t *) (p + cmd->offset);
1269     if (*msp != NGX_CONF_UNSET_MSEC) {
1270         return "is duplicate";
1271     }
1272 
1273     value = cf->args->elts;
1274 
1275     *msp = ngx_parse_time(&value[1], 0);
1276     if (*msp == (ngx_msec_t) NGX_ERROR) {
1277         return "invalid value";
1278     }
1279 
1280     if (cmd->post) {
1281         post = cmd->post;
1282         return post->post_handler(cf, post, msp);
1283     }
1284 
1285     return NGX_CONF_OK;
1286 }
1287 
1288 
1289 char *
1290 ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1291 {
1292     char  *p = conf;
1293 
1294     time_t           *sp;
1295     ngx_str_t        *value;
1296     ngx_conf_post_t  *post;
1297 
1298 
1299     sp = (time_t *) (p + cmd->offset);
1300     if (*sp != NGX_CONF_UNSET) {
1301         return "is duplicate";
1302     }
1303 
1304     value = cf->args->elts;
1305 
1306     *sp = ngx_parse_time(&value[1], 1);
1307     if (*sp == (time_t) NGX_ERROR) {
1308         return "invalid value";
1309     }
1310 
1311     if (cmd->post) {
1312         post = cmd->post;
1313         return post->post_handler(cf, post, sp);
1314     }
1315 
1316     return NGX_CONF_OK;
1317 }
1318 
1319 
1320 char *
1321 ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1322 {
1323     char *p = conf;
1324 
1325     ngx_str_t   *value;
1326     ngx_bufs_t  *bufs;
1327 
1328 
1329     bufs = (ngx_bufs_t *) (p + cmd->offset);
1330     if (bufs->num) {
1331         return "is duplicate";
1332     }
1333 
1334     value = cf->args->elts;
1335 
1336     bufs->num = ngx_atoi(value[1].data, value[1].len);
1337     if (bufs->num == NGX_ERROR || bufs->num == 0) {
1338         return "invalid value";
1339     }
1340 
1341     bufs->size = ngx_parse_size(&value[2]);
1342     if (bufs->size == (size_t) NGX_ERROR || bufs->size == 0) {
1343         return "invalid value";
1344     }
1345 
1346     return NGX_CONF_OK;
1347 }
1348 
1349 
1350 char *
1351 ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1352 {
1353     char  *p = conf;
1354 
1355     ngx_uint_t       *np, i;
1356     ngx_str_t        *value;
1357     ngx_conf_enum_t  *e;
1358 
1359     np = (ngx_uint_t *) (p + cmd->offset);
1360 
1361     if (*np != NGX_CONF_UNSET_UINT) {
1362         return "is duplicate";
1363     }
1364 
1365     value = cf->args->elts;
1366     e = cmd->post;
1367 
1368     for (i = 0; e[i].name.len != 0; i++) {
1369         if (e[i].name.len != value[1].len
1370             || ngx_strcasecmp(e[i].name.data, value[1].data) != 0)
1371         {
1372             continue;
1373         }
1374 
1375         *np = e[i].value;
1376 
1377         return NGX_CONF_OK;
1378     }
1379 
1380     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1381                        "invalid value \"%s\"", value[1].data);
1382 
1383     return NGX_CONF_ERROR;
1384 }
1385 
1386 
1387 char *
1388 ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1389 {
1390     char  *p = conf;
1391 
1392     ngx_uint_t          *np, i, m;
1393     ngx_str_t           *value;
1394     ngx_conf_bitmask_t  *mask;
1395 
1396 
1397     np = (ngx_uint_t *) (p + cmd->offset);
1398     value = cf->args->elts;
1399     mask = cmd->post;
1400 
1401     for (i = 1; i < cf->args->nelts; i++) {
1402         for (m = 0; mask[m].name.len != 0; m++) {
1403 
1404             if (mask[m].name.len != value[i].len
1405                 || ngx_strcasecmp(mask[m].name.data, value[i].data) != 0)
1406             {
1407                 continue;
1408             }
1409 
1410             if (*np & mask[m].mask) {
1411                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1412                                    "duplicate value \"%s\"", value[i].data);
1413 
1414             } else {
1415                 *np |= mask[m].mask;
1416             }
1417 
1418             break;
1419         }
1420 
1421         if (mask[m].name.len == 0) {
1422             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1423                                "invalid value \"%s\"", value[i].data);
1424 
1425             return NGX_CONF_ERROR;
1426         }
1427     }
1428 
1429     return NGX_CONF_OK;
1430 }
1431 
1432 
1433 #if 0
1434 
1435 char *
1436 ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1437 {
1438     return "unsupported on this platform";
1439 }
1440 
1441 #endif
1442 
1443 
1444 char *
1445 ngx_conf_deprecated(ngx_conf_t *cf, void *post, void *data)
1446 {
1447     ngx_conf_deprecated_t  *d = post;
1448 
1449     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1450                        "the \"%s\" directive is deprecated, "
1451                        "use the \"%s\" directive instead",
1452                        d->old_name, d->new_name);
1453 
1454     return NGX_CONF_OK;
1455 }
1456 
1457 
1458 char *
1459 ngx_conf_check_num_bounds(ngx_conf_t *cf, void *post, void *data)
1460 {
1461     ngx_conf_num_bounds_t  *bounds = post;
1462     ngx_int_t  *np = data;
1463 
1464     if (bounds->high == -1) {
1465         if (*np >= bounds->low) {
1466             return NGX_CONF_OK;
1467         }
1468 
1469         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1470                            "value must be equal to or greater than %i",
1471                            bounds->low);
1472 
1473         return NGX_CONF_ERROR;
1474     }
1475 
1476     if (*np >= bounds->low && *np <= bounds->high) {
1477         return NGX_CONF_OK;
1478     }
1479 
1480     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1481                        "value must be between %i and %i",
1482                        bounds->low, bounds->high);
1483 
1484     return NGX_CONF_ERROR;
1485 }