ngx_conf_file.c

来自「Nginx是一个高性能的HTTP和反向代理服务器」· C语言 代码 · 共 1,335 行 · 第 1/2 页

C
1,335
字号
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last);static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf);static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static void ngx_conf_flush_files(ngx_cycle_t *cycle);static ngx_command_t  ngx_conf_commands[] = {    { ngx_string("include"),      NGX_ANY_CONF|NGX_CONF_TAKE1,      ngx_conf_include,      0,      0,      NULL },      ngx_null_command};ngx_module_t  ngx_conf_module = {    NGX_MODULE_V1,    NULL,                                  /* module context */    ngx_conf_commands,                     /* module directives */    NGX_CONF_MODULE,                       /* module type */    NULL,                                  /* init master */    NULL,                                  /* init module */    NULL,                                  /* init process */    NULL,                                  /* init thread */    NULL,                                  /* exit thread */    ngx_conf_flush_files,                  /* exit process */    NULL,                                  /* exit master */    NGX_MODULE_V1_PADDING};/* The ten fixed arguments */static int argument_number[] = {    NGX_CONF_NOARGS,    NGX_CONF_TAKE1,    NGX_CONF_TAKE2,    NGX_CONF_TAKE3,    NGX_CONF_TAKE4,    NGX_CONF_TAKE5,    NGX_CONF_TAKE6,    NGX_CONF_TAKE7};char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename){    char             *rv;    ngx_fd_t          fd;    ngx_int_t         rc;    ngx_buf_t        *b;    ngx_uint_t        block;    ngx_conf_file_t  *prev;#if (NGX_SUPPRESS_WARN)    fd = NGX_INVALID_FILE;    prev = NULL;#endif    if (filename) {        /* open configuration file */        fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);        if (fd == NGX_INVALID_FILE) {            ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,                               ngx_open_file_n " \"%s\" failed",                               filename->data);            return NGX_CONF_ERROR;        }        prev = cf->conf_file;        cf->conf_file = ngx_palloc(cf->pool, sizeof(ngx_conf_file_t));        if (cf->conf_file == NULL) {            return NGX_CONF_ERROR;        }        if (ngx_fd_info(fd, &cf->conf_file->file.info) == -1) {            ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,                          ngx_fd_info_n " \"%s\" failed", filename->data);        }        b = ngx_calloc_buf(cf->pool);        if (b == NULL) {            return NGX_CONF_ERROR;        }        cf->conf_file->buffer = b;        b->start = ngx_alloc(ngx_pagesize, cf->log);        if (b->start == NULL) {            return NGX_CONF_ERROR;        }        b->pos = b->start;        b->last = b->start;        b->end = b->last + ngx_pagesize;        b->temporary = 1;        cf->conf_file->file.fd = fd;        cf->conf_file->file.name.len = filename->len;        cf->conf_file->file.name.data = filename->data;        cf->conf_file->file.offset = 0;        cf->conf_file->file.log = cf->log;        cf->conf_file->line = 1;        block = 0;    } else {        block = 1;    }    for ( ;; ) {        rc = ngx_conf_read_token(cf);        /*         * ngx_conf_read_token() may return         *         *    NGX_ERROR             there is error         *    NGX_OK                the token terminated by ";" was found         *    NGX_CONF_BLOCK_START  the token terminated by "{" was found         *    NGX_CONF_BLOCK_DONE   the "}" was found         *    NGX_CONF_FILE_DONE    the configuration file is done         */        if (rc == NGX_ERROR) {            goto done;        }        if (rc == NGX_CONF_BLOCK_DONE) {            if (!block) {                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");                goto failed;            }            block = 0;        }        if (rc == NGX_CONF_FILE_DONE && block) {            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                               "unexpected end of file, expecting \"}\"");            goto failed;        }        if (rc != NGX_OK && rc != NGX_CONF_BLOCK_START) {            goto done;        }        if (cf->handler) {            /*             * the custom handler, i.e., that is used in the http's             * "types { ... }" directive             */            rv = (*cf->handler)(cf, NULL, cf->handler_conf);            if (rv == NGX_CONF_OK) {                continue;            }            if (rv == NGX_CONF_ERROR) {                goto failed;            }            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);            goto failed;        }        rc = ngx_conf_handler(cf, rc);        if (rc == NGX_ERROR) {            goto failed;        }    }failed:    rc = NGX_ERROR;done:    if (filename) {        ngx_free(cf->conf_file->buffer->start);        cf->conf_file = prev;        if (ngx_close_file(fd) == NGX_FILE_ERROR) {            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,                          ngx_close_file_n " %s failed",                          cf->conf_file->file.name.data);            return NGX_CONF_ERROR;        }    }    if (rc == NGX_ERROR) {        return NGX_CONF_ERROR;    }    return NGX_CONF_OK;}static ngx_int_tngx_conf_handler(ngx_conf_t *cf, ngx_int_t last){    char           *rv;    void           *conf, **confp;    ngx_uint_t      i, multi;    ngx_str_t      *name;    ngx_command_t  *cmd;    name = cf->args->elts;    multi = 0;    for (i = 0; ngx_modules[i]; i++) {        /* look up the directive in the appropriate modules */        if (ngx_modules[i]->type != NGX_CONF_MODULE            && ngx_modules[i]->type != cf->module_type)        {            continue;        }        cmd = ngx_modules[i]->commands;        if (cmd == NULL) {            continue;        }        for ( /* void */ ; cmd->name.len; cmd++) {            if (name->len != cmd->name.len) {                continue;            }            if (ngx_strcmp(name->data, cmd->name.data) != 0) {                continue;            }            /* is the directive's location right ? */            if (!(cmd->type & cf->cmd_type)) {                if (cmd->type & NGX_CONF_MULTI) {                    multi = 1;                    continue;                }                goto not_allowed;            }            if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                                  "directive \"%s\" is not terminated by \";\"",                                  name->data);                return NGX_ERROR;            }            if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                                   "directive \"%s\" has no opening \"{\"",                                   name->data);                return NGX_ERROR;            }            /* is the directive's argument count right ? */            if (!(cmd->type & NGX_CONF_ANY)) {                if (cmd->type & NGX_CONF_FLAG) {                    if (cf->args->nelts != 2) {                        goto invalid;                    }                } else if (cmd->type & NGX_CONF_1MORE) {                    if (cf->args->nelts < 2) {                        goto invalid;                    }                } else if (cmd->type & NGX_CONF_2MORE) {                    if (cf->args->nelts < 3) {                        goto invalid;                    }                } else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {                    goto invalid;                } else if (!(cmd->type & argument_number[cf->args->nelts - 1]))                {                    goto invalid;                }            }            /* set up the directive's configuration context */            conf = NULL;            if (cmd->type & NGX_DIRECT_CONF) {                conf = ((void **) cf->ctx)[ngx_modules[i]->index];            } else if (cmd->type & NGX_MAIN_CONF) {                conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);            } else if (cf->ctx) {                confp = *(void **) ((char *) cf->ctx + cmd->conf);                if (confp) {                    conf = confp[ngx_modules[i]->ctx_index];                }            }            rv = cmd->set(cf, cmd, conf);            if (rv == NGX_CONF_OK) {                return NGX_OK;            }            if (rv == NGX_CONF_ERROR) {                return NGX_ERROR;            }            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                               "\"%s\" directive %s", name->data, rv);            return NGX_ERROR;        }    }    if (multi == 0) {        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                           "unknown directive \"%s\"", name->data);        return NGX_ERROR;    }not_allowed:    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                       "\"%s\" directive is not allowed here", name->data);    return NGX_ERROR;invalid:    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                       "invalid number of arguments in \"%s\" directive",                       name->data);    return NGX_ERROR;}static ngx_int_tngx_conf_read_token(ngx_conf_t *cf){    u_char      *start, ch, *src, *dst;    int          len;    int          found, need_space, last_space, sharp_comment, variable;    int          quoted, s_quoted, d_quoted;    ssize_t      n;    ngx_str_t   *word;    ngx_buf_t   *b;    found = 0;    need_space = 0;    last_space = 1;    sharp_comment = 0;    variable = 0;    quoted = s_quoted = d_quoted = 0;    cf->args->nelts = 0;    b = cf->conf_file->buffer;    start = b->pos;    for ( ;; ) {        if (b->pos >= b->last) {            if (cf->conf_file->file.offset                                 >= ngx_file_size(&cf->conf_file->file.info))            {                if (cf->args->nelts > 0) {                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                                  "unexpected end of file, "                                  "expecting \";\" or \"}\"");                    return NGX_ERROR;                }                return NGX_CONF_FILE_DONE;            }            if (b->pos - start) {                ngx_memcpy(b->start, start, b->pos - start);            }            n = ngx_read_file(&cf->conf_file->file,                              b->start + (b->pos - start),                              b->end - (b->start + (b->pos - start)),                              cf->conf_file->file.offset);            if (n == NGX_ERROR) {                return NGX_ERROR;            }            b->pos = b->start + (b->pos - start);            start = b->start;            b->last = b->pos + n;        }        ch = *b->pos++;        if (ch == LF) {            cf->conf_file->line++;            if (sharp_comment) {                sharp_comment = 0;            }        }        if (sharp_comment) {            continue;        }        if (quoted) {            quoted = 0;            continue;        }        if (need_space) {            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {                last_space = 1;                need_space = 0;                continue;            }            if (ch == ';') {                return NGX_OK;            }            if (ch == '{') {                return NGX_CONF_BLOCK_START;            }            if (ch == ')') {                last_space = 1;                need_space = 0;            } else {                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                                    "unexpected \"%c\"", ch);                 return NGX_ERROR;            }        }        if (last_space) {            if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {                continue;            }            start = b->pos - 1;            switch (ch) {            case ';':            case '{':                if (cf->args->nelts == 0) {                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                                       "unexpected \"%c\"", ch);                    return NGX_ERROR;                }                if (ch == '{') {                    return NGX_CONF_BLOCK_START;                }                return NGX_OK;            case '}':                if (cf->args->nelts != 0) {                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,                                       "unexpected \"}\"");                    return NGX_ERROR;                }                return NGX_CONF_BLOCK_DONE;            case '#':                sharp_comment = 1;                continue;            case '\\':                quoted = 1;                last_space = 0;                continue;            case '"':                start++;                d_quoted = 1;                last_space = 0;                continue;            case '\'':                start++;                s_quoted = 1;                last_space = 0;                continue;            default:                last_space = 0;            }        } else {            if (ch == '{' && variable) {                continue;            }            variable = 0;            if (ch == '\\') {                quoted = 1;                continue;            }            if (ch == '$') {                variable = 1;                continue;            }            if (d_quoted) {                if (ch == '"') {                    d_quoted = 0;                    need_space = 1;                    found = 1;                }            } else if (s_quoted) {                if (ch == '\'') {                    s_quoted = 0;                    need_space = 1;                    found = 1;                }            } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF                       || ch == ';' || ch == '{') {                last_space = 1;                found = 1;            }            if (found) {                word = ngx_array_push(cf->args);                if (word == NULL) {                    return NGX_ERROR;                }                word->data = ngx_palloc(cf->pool, b->pos - start + 1);                if (word->data == NULL) {                    return NGX_ERROR;                }                for (dst = word->data, src = start, len = 0;                     src < b->pos - 1;                     len++)                {                    if (*src == '\\') {                        switch (src[1]) {                        case '"':                        case '\'':                        case '\\':                            src++;                            break;                        case 't':                            *dst++ = '\t';                            src += 2;                            continue;                        case 'r':                            *dst++ = '\r';                            src += 2;                            continue;                        case 'n':                            *dst++ = '\n';                            src += 2;                            continue;                        }                    }                    *dst++ = *src++;                }                *dst = '\0';                word->len = len;                if (ch == ';') {                    return NGX_OK;                }                if (ch == '{') {                    return NGX_CONF_BLOCK_START;                }                found = 0;            }        }    }}static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){    char        *rv;    ngx_int_t    n;    ngx_str_t   *value, file, name;    ngx_glob_t   gl;    value = cf->args->elts;    file = value[1];    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);    if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR) {        return NGX_CONF_ERROR;    }    if (strpbrk((char *) file.data, "*?[") == NULL) {        ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);        return ngx_conf_parse(cf, &file);    }    ngx_memzero(&gl, sizeof(ngx_glob_t));    gl.pattern = file.data;    gl.log = cf->log;    gl.test = 1;    if (ngx_open_glob(&gl) != NGX_OK) {        ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,                           ngx_open_glob_n " \"%s\" failed", file.data);        return NGX_CONF_ERROR;    }    rv = NGX_CONF_OK;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?