1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev
11e18a033bSKonstantin Ananyev#define NGX_CONF_BUFFER  4096
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename);
14e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last);
15e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_conf_read_token(ngx_conf_t *cf);
16e18a033bSKonstantin Ananyevstatic void ngx_conf_flush_files(ngx_cycle_t *cycle);
17e18a033bSKonstantin Ananyev
18e18a033bSKonstantin Ananyev
19e18a033bSKonstantin Ananyevstatic ngx_command_t  ngx_conf_commands[] = {
20e18a033bSKonstantin Ananyev
21e18a033bSKonstantin Ananyev    { ngx_string("include"),
22e18a033bSKonstantin Ananyev      NGX_ANY_CONF|NGX_CONF_TAKE1,
23e18a033bSKonstantin Ananyev      ngx_conf_include,
24e18a033bSKonstantin Ananyev      0,
25e18a033bSKonstantin Ananyev      0,
26e18a033bSKonstantin Ananyev      NULL },
27e18a033bSKonstantin Ananyev
28e18a033bSKonstantin Ananyev      ngx_null_command
29e18a033bSKonstantin Ananyev};
30e18a033bSKonstantin Ananyev
31e18a033bSKonstantin Ananyev
32e18a033bSKonstantin Ananyevngx_module_t  ngx_conf_module = {
33e18a033bSKonstantin Ananyev    NGX_MODULE_V1,
34e18a033bSKonstantin Ananyev    NULL,                                  /* module context */
35e18a033bSKonstantin Ananyev    ngx_conf_commands,                     /* module directives */
36e18a033bSKonstantin Ananyev    NGX_CONF_MODULE,                       /* module type */
37e18a033bSKonstantin Ananyev    NULL,                                  /* init master */
38e18a033bSKonstantin Ananyev    NULL,                                  /* init module */
39e18a033bSKonstantin Ananyev    NULL,                                  /* init process */
40e18a033bSKonstantin Ananyev    NULL,                                  /* init thread */
41e18a033bSKonstantin Ananyev    NULL,                                  /* exit thread */
42e18a033bSKonstantin Ananyev    ngx_conf_flush_files,                  /* exit process */
43e18a033bSKonstantin Ananyev    NULL,                                  /* exit master */
44e18a033bSKonstantin Ananyev    NGX_MODULE_V1_PADDING
45e18a033bSKonstantin Ananyev};
46e18a033bSKonstantin Ananyev
47e18a033bSKonstantin Ananyev
48e18a033bSKonstantin Ananyev/* The eight fixed arguments */
49e18a033bSKonstantin Ananyev
50e18a033bSKonstantin Ananyevstatic ngx_uint_t argument_number[] = {
51e18a033bSKonstantin Ananyev    NGX_CONF_NOARGS,
52e18a033bSKonstantin Ananyev    NGX_CONF_TAKE1,
53e18a033bSKonstantin Ananyev    NGX_CONF_TAKE2,
54e18a033bSKonstantin Ananyev    NGX_CONF_TAKE3,
55e18a033bSKonstantin Ananyev    NGX_CONF_TAKE4,
56e18a033bSKonstantin Ananyev    NGX_CONF_TAKE5,
57e18a033bSKonstantin Ananyev    NGX_CONF_TAKE6,
58e18a033bSKonstantin Ananyev    NGX_CONF_TAKE7
59e18a033bSKonstantin Ananyev};
60e18a033bSKonstantin Ananyev
61e18a033bSKonstantin Ananyev
62e18a033bSKonstantin Ananyevchar *
63e18a033bSKonstantin Ananyevngx_conf_param(ngx_conf_t *cf)
64e18a033bSKonstantin Ananyev{
65e18a033bSKonstantin Ananyev    char             *rv;
66e18a033bSKonstantin Ananyev    ngx_str_t        *param;
67e18a033bSKonstantin Ananyev    ngx_buf_t         b;
68e18a033bSKonstantin Ananyev    ngx_conf_file_t   conf_file;
69e18a033bSKonstantin Ananyev
70e18a033bSKonstantin Ananyev    param = &cf->cycle->conf_param;
71e18a033bSKonstantin Ananyev
72e18a033bSKonstantin Ananyev    if (param->len == 0) {
73e18a033bSKonstantin Ananyev        return NGX_CONF_OK;
74e18a033bSKonstantin Ananyev    }
75e18a033bSKonstantin Ananyev
76e18a033bSKonstantin Ananyev    ngx_memzero(&conf_file, sizeof(ngx_conf_file_t));
77e18a033bSKonstantin Ananyev
78e18a033bSKonstantin Ananyev    ngx_memzero(&b, sizeof(ngx_buf_t));
79e18a033bSKonstantin Ananyev
80e18a033bSKonstantin Ananyev    b.start = param->data;
81e18a033bSKonstantin Ananyev    b.pos = param->data;
82e18a033bSKonstantin Ananyev    b.last = param->data + param->len;
83e18a033bSKonstantin Ananyev    b.end = b.last;
84e18a033bSKonstantin Ananyev    b.temporary = 1;
85e18a033bSKonstantin Ananyev
86e18a033bSKonstantin Ananyev    conf_file.file.fd = NGX_INVALID_FILE;
87e18a033bSKonstantin Ananyev    conf_file.file.name.data = NULL;
88e18a033bSKonstantin Ananyev    conf_file.line = 0;
89e18a033bSKonstantin Ananyev
90e18a033bSKonstantin Ananyev    cf->conf_file = &conf_file;
91e18a033bSKonstantin Ananyev    cf->conf_file->buffer = &b;
92e18a033bSKonstantin Ananyev
93e18a033bSKonstantin Ananyev    rv = ngx_conf_parse(cf, NULL);
94e18a033bSKonstantin Ananyev
95e18a033bSKonstantin Ananyev    cf->conf_file = NULL;
96e18a033bSKonstantin Ananyev
97e18a033bSKonstantin Ananyev    return rv;
98e18a033bSKonstantin Ananyev}
99e18a033bSKonstantin Ananyev
100e18a033bSKonstantin Ananyev
101e18a033bSKonstantin Ananyevstatic ngx_int_t
102e18a033bSKonstantin Ananyevngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename)
103e18a033bSKonstantin Ananyev{
104e18a033bSKonstantin Ananyev    off_t             size;
105e18a033bSKonstantin Ananyev    u_char           *p;
106e18a033bSKonstantin Ananyev    uint32_t          hash;
107e18a033bSKonstantin Ananyev    ngx_buf_t        *buf;
108e18a033bSKonstantin Ananyev    ngx_str_node_t   *sn;
109e18a033bSKonstantin Ananyev    ngx_conf_dump_t  *cd;
110e18a033bSKonstantin Ananyev
111e18a033bSKonstantin Ananyev    hash = ngx_crc32_long(filename->data, filename->len);
112e18a033bSKonstantin Ananyev
113e18a033bSKonstantin Ananyev    sn = ngx_str_rbtree_lookup(&cf->cycle->config_dump_rbtree, filename, hash);
114e18a033bSKonstantin Ananyev
115e18a033bSKonstantin Ananyev    if (sn) {
116e18a033bSKonstantin Ananyev        cf->conf_file->dump = NULL;
117e18a033bSKonstantin Ananyev        return NGX_OK;
118e18a033bSKonstantin Ananyev    }
119e18a033bSKonstantin Ananyev
120e18a033bSKonstantin Ananyev    p = ngx_pstrdup(cf->cycle->pool, filename);
121e18a033bSKonstantin Ananyev    if (p == NULL) {
122e18a033bSKonstantin Ananyev        return NGX_ERROR;
123e18a033bSKonstantin Ananyev    }
124e18a033bSKonstantin Ananyev
125e18a033bSKonstantin Ananyev    cd = ngx_array_push(&cf->cycle->config_dump);
126e18a033bSKonstantin Ananyev    if (cd == NULL) {
127e18a033bSKonstantin Ananyev        return NGX_ERROR;
128e18a033bSKonstantin Ananyev    }
129e18a033bSKonstantin Ananyev
130e18a033bSKonstantin Ananyev    size = ngx_file_size(&cf->conf_file->file.info);
131e18a033bSKonstantin Ananyev
132e18a033bSKonstantin Ananyev    buf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size);
133e18a033bSKonstantin Ananyev    if (buf == NULL) {
134e18a033bSKonstantin Ananyev        return NGX_ERROR;
135e18a033bSKonstantin Ananyev    }
136e18a033bSKonstantin Ananyev
137e18a033bSKonstantin Ananyev    cd->name.data = p;
138e18a033bSKonstantin Ananyev    cd->name.len = filename->len;
139e18a033bSKonstantin Ananyev    cd->buffer = buf;
140e18a033bSKonstantin Ananyev
141e18a033bSKonstantin Ananyev    cf->conf_file->dump = buf;
142e18a033bSKonstantin Ananyev
143e18a033bSKonstantin Ananyev    sn = ngx_palloc(cf->temp_pool, sizeof(ngx_str_node_t));
144e18a033bSKonstantin Ananyev    if (sn == NULL) {
145e18a033bSKonstantin Ananyev        return NGX_ERROR;
146e18a033bSKonstantin Ananyev    }
147e18a033bSKonstantin Ananyev
148e18a033bSKonstantin Ananyev    sn->node.key = hash;
149e18a033bSKonstantin Ananyev    sn->str = cd->name;
150e18a033bSKonstantin Ananyev
151e18a033bSKonstantin Ananyev    ngx_rbtree_insert(&cf->cycle->config_dump_rbtree, &sn->node);
152e18a033bSKonstantin Ananyev
153e18a033bSKonstantin Ananyev    return NGX_OK;
154e18a033bSKonstantin Ananyev}
155e18a033bSKonstantin Ananyev
156e18a033bSKonstantin Ananyev
157e18a033bSKonstantin Ananyevchar *
158e18a033bSKonstantin Ananyevngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
159e18a033bSKonstantin Ananyev{
160e18a033bSKonstantin Ananyev    char             *rv;
161e18a033bSKonstantin Ananyev    ngx_fd_t          fd;
162e18a033bSKonstantin Ananyev    ngx_int_t         rc;
163e18a033bSKonstantin Ananyev    ngx_buf_t         buf;
164e18a033bSKonstantin Ananyev    ngx_conf_file_t  *prev, conf_file;
165e18a033bSKonstantin Ananyev    enum {
166e18a033bSKonstantin Ananyev        parse_file = 0,
167e18a033bSKonstantin Ananyev        parse_block,
168e18a033bSKonstantin Ananyev        parse_param
169e18a033bSKonstantin Ananyev    } type;
170e18a033bSKonstantin Ananyev
171e18a033bSKonstantin Ananyev#if (NGX_SUPPRESS_WARN)
172e18a033bSKonstantin Ananyev    fd = NGX_INVALID_FILE;
173e18a033bSKonstantin Ananyev    prev = NULL;
174e18a033bSKonstantin Ananyev#endif
175e18a033bSKonstantin Ananyev
176e18a033bSKonstantin Ananyev    if (filename) {
177e18a033bSKonstantin Ananyev
178e18a033bSKonstantin Ananyev        /* open configuration file */
179e18a033bSKonstantin Ananyev
180e18a033bSKonstantin Ananyev        fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
181e18a033bSKonstantin Ananyev        if (fd == NGX_INVALID_FILE) {
182e18a033bSKonstantin Ananyev            ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
183e18a033bSKonstantin Ananyev                               ngx_open_file_n " \"%s\" failed",
184e18a033bSKonstantin Ananyev                               filename->data);
185e18a033bSKonstantin Ananyev            return NGX_CONF_ERROR;
186e18a033bSKonstantin Ananyev        }
187e18a033bSKonstantin Ananyev
188e18a033bSKonstantin Ananyev        prev = cf->conf_file;
189e18a033bSKonstantin Ananyev
190e18a033bSKonstantin Ananyev        cf->conf_file = &conf_file;
191e18a033bSKonstantin Ananyev
192e18a033bSKonstantin Ananyev        if (ngx_fd_info(fd, &cf->conf_file->file.info) == NGX_FILE_ERROR) {
193e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
194e18a033bSKonstantin Ananyev                          ngx_fd_info_n " \"%s\" failed", filename->data);
195e18a033bSKonstantin Ananyev        }
196e18a033bSKonstantin Ananyev
197e18a033bSKonstantin Ananyev        cf->conf_file->buffer = &buf;
198e18a033bSKonstantin Ananyev
199e18a033bSKonstantin Ananyev        buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log);
200e18a033bSKonstantin Ananyev        if (buf.start == NULL) {
201e18a033bSKonstantin Ananyev            goto failed;
202e18a033bSKonstantin Ananyev        }
203e18a033bSKonstantin Ananyev
204e18a033bSKonstantin Ananyev        buf.pos = buf.start;
205e18a033bSKonstantin Ananyev        buf.last = buf.start;
206e18a033bSKonstantin Ananyev        buf.end = buf.last + NGX_CONF_BUFFER;
207e18a033bSKonstantin Ananyev        buf.temporary = 1;
208e18a033bSKonstantin Ananyev
209e18a033bSKonstantin Ananyev        cf->conf_file->file.fd = fd;
210e18a033bSKonstantin Ananyev        cf->conf_file->file.name.len = filename->len;
211e18a033bSKonstantin Ananyev        cf->conf_file->file.name.data = filename->data;
212e18a033bSKonstantin Ananyev        cf->conf_file->file.offset = 0;
213e18a033bSKonstantin Ananyev        cf->conf_file->file.log = cf->log;
214e18a033bSKonstantin Ananyev        cf->conf_file->line = 1;
215e18a033bSKonstantin Ananyev
216e18a033bSKonstantin Ananyev        type = parse_file;
217e18a033bSKonstantin Ananyev
218e18a033bSKonstantin Ananyev        if (ngx_dump_config
219e18a033bSKonstantin Ananyev#if (NGX_DEBUG)
220e18a033bSKonstantin Ananyev            || 1
221e18a033bSKonstantin Ananyev#endif
222e18a033bSKonstantin Ananyev           )
223e18a033bSKonstantin Ananyev        {
224e18a033bSKonstantin Ananyev            if (ngx_conf_add_dump(cf, filename) != NGX_OK) {
225e18a033bSKonstantin Ananyev                goto failed;
226e18a033bSKonstantin Ananyev            }
227e18a033bSKonstantin Ananyev
228e18a033bSKonstantin Ananyev        } else {
229e18a033bSKonstantin Ananyev            cf->conf_file->dump = NULL;
230e18a033bSKonstantin Ananyev        }
231e18a033bSKonstantin Ananyev
232e18a033bSKonstantin Ananyev    } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {
233e18a033bSKonstantin Ananyev
234e18a033bSKonstantin Ananyev        type = parse_block;
235e18a033bSKonstantin Ananyev
236e18a033bSKonstantin Ananyev    } else {
237e18a033bSKonstantin Ananyev        type = parse_param;
238e18a033bSKonstantin Ananyev    }
239e18a033bSKonstantin Ananyev
240e18a033bSKonstantin Ananyev
241e18a033bSKonstantin Ananyev    for ( ;; ) {
242e18a033bSKonstantin Ananyev        rc = ngx_conf_read_token(cf);
243e18a033bSKonstantin Ananyev
244e18a033bSKonstantin Ananyev        /*
245e18a033bSKonstantin Ananyev         * ngx_conf_read_token() may return
246e18a033bSKonstantin Ananyev         *
247e18a033bSKonstantin Ananyev         *    NGX_ERROR             there is error
248e18a033bSKonstantin Ananyev         *    NGX_OK                the token terminated by ";" was found
249e18a033bSKonstantin Ananyev         *    NGX_CONF_BLOCK_START  the token terminated by "{" was found
250e18a033bSKonstantin Ananyev         *    NGX_CONF_BLOCK_DONE   the "}" was found
251e18a033bSKonstantin Ananyev         *    NGX_CONF_FILE_DONE    the configuration file is done
252e18a033bSKonstantin Ananyev         */
253e18a033bSKonstantin Ananyev
254e18a033bSKonstantin Ananyev        if (rc == NGX_ERROR) {
255e18a033bSKonstantin Ananyev            goto done;
256e18a033bSKonstantin Ananyev        }
257e18a033bSKonstantin Ananyev
258e18a033bSKonstantin Ananyev        if (rc == NGX_CONF_BLOCK_DONE) {
259e18a033bSKonstantin Ananyev
260e18a033bSKonstantin Ananyev            if (type != parse_block) {
261e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");
262e18a033bSKonstantin Ananyev                goto failed;
263e18a033bSKonstantin Ananyev            }
264e18a033bSKonstantin Ananyev
265e18a033bSKonstantin Ananyev            goto done;
266e18a033bSKonstantin Ananyev        }
267e18a033bSKonstantin Ananyev
268e18a033bSKonstantin Ananyev        if (rc == NGX_CONF_FILE_DONE) {
269e18a033bSKonstantin Ananyev
270e18a033bSKonstantin Ananyev            if (type == parse_block) {
271e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
272e18a033bSKonstantin Ananyev                                   "unexpected end of file, expecting \"}\"");
273e18a033bSKonstantin Ananyev                goto failed;
274e18a033bSKonstantin Ananyev            }
275e18a033bSKonstantin Ananyev
276e18a033bSKonstantin Ananyev            goto done;
277e18a033bSKonstantin Ananyev        }
278e18a033bSKonstantin Ananyev
279e18a033bSKonstantin Ananyev        if (rc == NGX_CONF_BLOCK_START) {
280e18a033bSKonstantin Ananyev
281e18a033bSKonstantin Ananyev            if (type == parse_param) {
282e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
283e18a033bSKonstantin Ananyev                                   "block directives are not supported "
284e18a033bSKonstantin Ananyev                                   "in -g option");
285e18a033bSKonstantin Ananyev                goto failed;
286e18a033bSKonstantin Ananyev            }
287e18a033bSKonstantin Ananyev        }
288e18a033bSKonstantin Ananyev
289e18a033bSKonstantin Ananyev        /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */
290e18a033bSKonstantin Ananyev
291e18a033bSKonstantin Ananyev        if (cf->handler) {
292e18a033bSKonstantin Ananyev
293e18a033bSKonstantin Ananyev            /*
294e18a033bSKonstantin Ananyev             * the custom handler, i.e., that is used in the http's
295e18a033bSKonstantin Ananyev             * "types { ... }" directive
296e18a033bSKonstantin Ananyev             */
297e18a033bSKonstantin Ananyev
298e18a033bSKonstantin Ananyev            if (rc == NGX_CONF_BLOCK_START) {
299e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"{\"");
300e18a033bSKonstantin Ananyev                goto failed;
301e18a033bSKonstantin Ananyev            }
302e18a033bSKonstantin Ananyev
303e18a033bSKonstantin Ananyev            rv = (*cf->handler)(cf, NULL, cf->handler_conf);
304e18a033bSKonstantin Ananyev            if (rv == NGX_CONF_OK) {
305e18a033bSKonstantin Ananyev                continue;
306e18a033bSKonstantin Ananyev            }
307e18a033bSKonstantin Ananyev
308e18a033bSKonstantin Ananyev            if (rv == NGX_CONF_ERROR) {
309e18a033bSKonstantin Ananyev                goto failed;
310e18a033bSKonstantin Ananyev            }
311e18a033bSKonstantin Ananyev
312e18a033bSKonstantin Ananyev            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);
313e18a033bSKonstantin Ananyev
314e18a033bSKonstantin Ananyev            goto failed;
315e18a033bSKonstantin Ananyev        }
316e18a033bSKonstantin Ananyev
317e18a033bSKonstantin Ananyev
318e18a033bSKonstantin Ananyev        rc = ngx_conf_handler(cf, rc);
319e18a033bSKonstantin Ananyev
320e18a033bSKonstantin Ananyev        if (rc == NGX_ERROR) {
321e18a033bSKonstantin Ananyev            goto failed;
322e18a033bSKonstantin Ananyev        }
323e18a033bSKonstantin Ananyev    }
324e18a033bSKonstantin Ananyev
325e18a033bSKonstantin Ananyevfailed:
326e18a033bSKonstantin Ananyev
327e18a033bSKonstantin Ananyev    rc = NGX_ERROR;
328e18a033bSKonstantin Ananyev
329e18a033bSKonstantin Ananyevdone:
330e18a033bSKonstantin Ananyev
331e18a033bSKonstantin Ananyev    if (filename) {
332e18a033bSKonstantin Ananyev        if (cf->conf_file->buffer->start) {
333e18a033bSKonstantin Ananyev            ngx_free(cf->conf_file->buffer->start);
334e18a033bSKonstantin Ananyev        }
335e18a033bSKonstantin Ananyev
336e18a033bSKonstantin Ananyev        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
337e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
338e18a033bSKonstantin Ananyev                          ngx_close_file_n " %s failed",
339e18a033bSKonstantin Ananyev                          filename->data);
340e18a033bSKonstantin Ananyev            rc = NGX_ERROR;
341e18a033bSKonstantin Ananyev        }
342e18a033bSKonstantin Ananyev
343e18a033bSKonstantin Ananyev        cf->conf_file = prev;
344e18a033bSKonstantin Ananyev    }
345e18a033bSKonstantin Ananyev
346e18a033bSKonstantin Ananyev    if (rc == NGX_ERROR) {
347e18a033bSKonstantin Ananyev        return NGX_CONF_ERROR;
348e18a033bSKonstantin Ananyev    }
349e18a033bSKonstantin Ananyev
350e18a033bSKonstantin Ananyev    return NGX_CONF_OK;
351e18a033bSKonstantin Ananyev}
352e18a033bSKonstantin Ananyev
353e18a033bSKonstantin Ananyev
354e18a033bSKonstantin Ananyevstatic ngx_int_t
355e18a033bSKonstantin Ananyevngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
356e18a033bSKonstantin Ananyev{
357e18a033bSKonstantin Ananyev    char           *rv;
358e18a033bSKonstantin Ananyev    void           *conf, **confp;
359e18a033bSKonstantin Ananyev    ngx_uint_t      i, found;
360e18a033bSKonstantin Ananyev    ngx_str_t      *name;
361e18a033bSKonstantin Ananyev    ngx_command_t  *cmd;
362e18a033bSKonstantin Ananyev
363e18a033bSKonstantin Ananyev    name = cf->args->elts;
364e18a033bSKonstantin Ananyev
365e18a033bSKonstantin Ananyev    found = 0;
366e18a033bSKonstantin Ananyev
367e18a033bSKonstantin Ananyev    for (i = 0; cf->cycle->modules[i]; i++) {
368e18a033bSKonstantin Ananyev
369e18a033bSKonstantin Ananyev        cmd = cf->cycle->modules[i]->commands;
370e18a033bSKonstantin Ananyev        if (cmd == NULL) {
371e18a033bSKonstantin Ananyev            continue;
372e18a033bSKonstantin Ananyev        }
373e18a033bSKonstantin Ananyev
374e18a033bSKonstantin Ananyev        for ( /* void */ ; cmd->name.len; cmd++) {
375e18a033bSKonstantin Ananyev
376e18a033bSKonstantin Ananyev            if (name->len != cmd->name.len) {
377e18a033bSKonstantin Ananyev                continue;
378e18a033bSKonstantin Ananyev            }
379e18a033bSKonstantin Ananyev
380e18a033bSKonstantin Ananyev            if (ngx_strcmp(name->data, cmd->name.data) != 0) {
381e18a033bSKonstantin Ananyev                continue;
382e18a033bSKonstantin Ananyev            }
383e18a033bSKonstantin Ananyev
384e18a033bSKonstantin Ananyev            found = 1;
385e18a033bSKonstantin Ananyev
386e18a033bSKonstantin Ananyev            if (cf->cycle->modules[i]->type != NGX_CONF_MODULE
387e18a033bSKonstantin Ananyev                && cf->cycle->modules[i]->type != cf->module_type)
388e18a033bSKonstantin Ananyev            {
389e18a033bSKonstantin Ananyev                continue;
390e18a033bSKonstantin Ananyev            }
391e18a033bSKonstantin Ananyev
392e18a033bSKonstantin Ananyev            /* is the directive's location right ? */
393e18a033bSKonstantin Ananyev
394e18a033bSKonstantin Ananyev            if (!(cmd->type & cf->cmd_type)) {
395e18a033bSKonstantin Ananyev                continue;
396e18a033bSKonstantin Ananyev            }
397e18a033bSKonstantin Ananyev
398e18a033bSKonstantin Ananyev            if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
399e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
400e18a033bSKonstantin Ananyev                                  "directive \"%s\" is not terminated by \";\"",
401e18a033bSKonstantin Ananyev                                  name->data);
402e18a033bSKonstantin Ananyev                return NGX_ERROR;
403e18a033bSKonstantin Ananyev            }
404e18a033bSKonstantin Ananyev
405e18a033bSKonstantin Ananyev            if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {
406e18a033bSKonstantin Ananyev                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
407e18a033bSKonstantin Ananyev                                   "directive \"%s\" has no opening \"{\"",
408e18a033bSKonstantin Ananyev                                   name->data);
409e18a033bSKonstantin Ananyev                return NGX_ERROR;
410e18a033bSKonstantin Ananyev            }
411e18a033bSKonstantin Ananyev
412e18a033bSKonstantin Ananyev            /* is the directive's argument count right ? */
413e18a033bSKonstantin Ananyev
414e18a033bSKonstantin Ananyev            if (!(cmd->type & NGX_CONF_ANY)) {
415e18a033bSKonstantin Ananyev
416e18a033bSKonstantin Ananyev                if (cmd->type & NGX_CONF_FLAG) {
417e18a033bSKonstantin Ananyev
418e18a033bSKonstantin Ananyev                    if (cf->args->nelts != 2) {
419e18a033bSKonstantin Ananyev                        goto invalid;
420