Mercurial > hg > nginx-vendor-current
comparison src/core/ngx_conf_file.c @ 0:f0b350454894 NGINX_0_1_0
nginx 0.1.0
*) The first public version.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 04 Oct 2004 00:00:00 +0400 |
parents | |
children | 4b2dafa26fe2 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0b350454894 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 | |
10 | |
11 static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | |
12 | |
13 | |
14 static ngx_command_t ngx_conf_commands[] = { | |
15 | |
16 { ngx_string("include"), | |
17 NGX_ANY_CONF|NGX_CONF_TAKE1, | |
18 ngx_conf_include, | |
19 0, | |
20 0, | |
21 NULL }, | |
22 | |
23 ngx_null_command | |
24 }; | |
25 | |
26 | |
27 ngx_module_t ngx_conf_module = { | |
28 NGX_MODULE, | |
29 NULL, /* module context */ | |
30 ngx_conf_commands, /* module directives */ | |
31 NGX_CONF_MODULE, /* module type */ | |
32 NULL, /* init module */ | |
33 NULL /* init child */ | |
34 }; | |
35 | |
36 | |
37 | |
38 /* The ten fixed arguments */ | |
39 | |
40 static int argument_number[] = { | |
41 NGX_CONF_NOARGS, | |
42 NGX_CONF_TAKE1, | |
43 NGX_CONF_TAKE2, | |
44 NGX_CONF_TAKE3, | |
45 NGX_CONF_TAKE4, | |
46 NGX_CONF_TAKE5, | |
47 NGX_CONF_TAKE6, | |
48 NGX_CONF_TAKE7 | |
49 }; | |
50 | |
51 static int ngx_conf_read_token(ngx_conf_t *cf); | |
52 | |
53 | |
54 char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) | |
55 { | |
56 int m, rc, found, valid; | |
57 char *rv; | |
58 void *conf, **confp; | |
59 ngx_fd_t fd; | |
60 ngx_str_t *name; | |
61 ngx_conf_file_t *prev; | |
62 ngx_command_t *cmd; | |
63 | |
64 #if (NGX_SUPPRESS_WARN) | |
65 fd = NGX_INVALID_FILE; | |
66 prev = NULL; | |
67 #endif | |
68 | |
69 if (filename) { | |
70 | |
71 /* open configuration file */ | |
72 | |
73 fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN); | |
74 if (fd == NGX_INVALID_FILE) { | |
75 ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, | |
76 ngx_open_file_n " %s failed", filename->data); | |
77 return NGX_CONF_ERROR; | |
78 } | |
79 | |
80 prev = cf->conf_file; | |
81 if (!(cf->conf_file = ngx_palloc(cf->pool, sizeof(ngx_conf_file_t)))) { | |
82 return NGX_CONF_ERROR; | |
83 } | |
84 | |
85 if (ngx_fd_info(fd, &cf->conf_file->file.info) == -1) { | |
86 ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, | |
87 ngx_fd_info_n " %s failed", filename->data); | |
88 } | |
89 | |
90 if (!(cf->conf_file->buffer = ngx_create_temp_buf(cf->pool, 1024))) { | |
91 return NGX_CONF_ERROR; | |
92 } | |
93 | |
94 cf->conf_file->file.fd = fd; | |
95 cf->conf_file->file.name.len = filename->len; | |
96 cf->conf_file->file.name.data = filename->data; | |
97 cf->conf_file->file.offset = 0; | |
98 cf->conf_file->file.log = cf->log;; | |
99 cf->conf_file->line = 1; | |
100 } | |
101 | |
102 for ( ;; ) { | |
103 rc = ngx_conf_read_token(cf); | |
104 | |
105 /* | |
106 * ngx_conf_read_token() returns NGX_OK, NGX_ERROR, | |
107 * NGX_CONF_FILE_DONE or NGX_CONF_BLOCK_DONE | |
108 */ | |
109 | |
110 #if 0 | |
111 ngx_log_debug(cf->log, "token %d" _ rc); | |
112 #endif | |
113 | |
114 if (rc == NGX_ERROR) { | |
115 break; | |
116 } | |
117 | |
118 if (rc != NGX_OK) { | |
119 break; | |
120 } | |
121 | |
122 if (cf->handler) { | |
123 | |
124 /* custom handler, i.e. used in http "types { ... }" directive */ | |
125 | |
126 rv = (*cf->handler)(cf, NULL, cf->handler_conf); | |
127 if (rv == NGX_CONF_OK) { | |
128 continue; | |
129 | |
130 } else if (rv == NGX_CONF_ERROR) { | |
131 rc = NGX_ERROR; | |
132 break; | |
133 | |
134 } else { | |
135 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
136 "%s in %s:%d", | |
137 rv, | |
138 cf->conf_file->file.name.data, | |
139 cf->conf_file->line); | |
140 rc = NGX_ERROR; | |
141 break; | |
142 } | |
143 } | |
144 | |
145 name = (ngx_str_t *) cf->args->elts; | |
146 found = 0; | |
147 | |
148 for (m = 0; rc != NGX_ERROR && !found && ngx_modules[m]; m++) { | |
149 | |
150 /* look up the directive in the appropriate modules */ | |
151 | |
152 if (ngx_modules[m]->type != NGX_CONF_MODULE | |
153 && ngx_modules[m]->type != cf->module_type) | |
154 { | |
155 continue; | |
156 } | |
157 | |
158 cmd = ngx_modules[m]->commands; | |
159 if (cmd == NULL) { | |
160 continue; | |
161 } | |
162 | |
163 while (cmd->name.len) { | |
164 if (name->len == cmd->name.len | |
165 && ngx_strcmp(name->data, cmd->name.data) == 0) | |
166 { | |
167 | |
168 found = 1; | |
169 #if 0 | |
170 ngx_log_debug(cf->log, "command '%s'" _ cmd->name.data); | |
171 #endif | |
172 /* is the directive's location right ? */ | |
173 | |
174 if ((cmd->type & cf->cmd_type) == 0) { | |
175 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
176 "directive \"%s\" in %s:%d " | |
177 "is not allowed here", | |
178 name->data, | |
179 cf->conf_file->file.name.data, | |
180 cf->conf_file->line); | |
181 rc = NGX_ERROR; | |
182 break; | |
183 } | |
184 | |
185 /* is the directive's argument count right ? */ | |
186 | |
187 if (cmd->type & NGX_CONF_ANY) { | |
188 valid = 1; | |
189 | |
190 } else if (cmd->type & NGX_CONF_FLAG) { | |
191 | |
192 if (cf->args->nelts == 2) { | |
193 valid = 1; | |
194 } else { | |
195 valid = 0; | |
196 } | |
197 | |
198 } else if (cmd->type & NGX_CONF_1MORE) { | |
199 | |
200 if (cf->args->nelts > 1) { | |
201 valid = 1; | |
202 } else { | |
203 valid = 0; | |
204 } | |
205 | |
206 } else if (cmd->type & NGX_CONF_2MORE) { | |
207 | |
208 if (cf->args->nelts > 2) { | |
209 valid = 1; | |
210 } else { | |
211 valid = 0; | |
212 } | |
213 | |
214 } else if (cf->args->nelts <= 10 | |
215 && (cmd->type | |
216 & argument_number[cf->args->nelts - 1])) | |
217 { | |
218 valid = 1; | |
219 | |
220 } else { | |
221 valid = 0; | |
222 } | |
223 | |
224 if (!valid) { | |
225 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
226 "invalid number arguments in " | |
227 "directive \"%s\" in %s:%d", | |
228 name->data, | |
229 cf->conf_file->file.name.data, | |
230 cf->conf_file->line); | |
231 rc = NGX_ERROR; | |
232 break; | |
233 } | |
234 | |
235 /* set up the directive's configuration context */ | |
236 | |
237 conf = NULL; | |
238 | |
239 if (cmd->type & NGX_DIRECT_CONF) { | |
240 conf = ((void **) cf->ctx)[ngx_modules[m]->index]; | |
241 | |
242 } else if (cmd->type & NGX_MAIN_CONF) { | |
243 conf = &(((void **) cf->ctx)[ngx_modules[m]->index]); | |
244 | |
245 } else if (cf->ctx) { | |
246 confp = *(void **) ((char *) cf->ctx + cmd->conf); | |
247 | |
248 if (confp) { | |
249 conf = confp[ngx_modules[m]->ctx_index]; | |
250 } | |
251 } | |
252 | |
253 rv = cmd->set(cf, cmd, conf); | |
254 | |
255 #if 0 | |
256 ngx_log_debug(cf->log, "rv: %d" _ rv); | |
257 #endif | |
258 | |
259 if (rv == NGX_CONF_OK) { | |
260 break; | |
261 | |
262 } else if (rv == NGX_CONF_ERROR) { | |
263 rc = NGX_ERROR; | |
264 break; | |
265 | |
266 } else { | |
267 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
268 "the \"%s\" directive %s in %s:%d", | |
269 name->data, rv, | |
270 cf->conf_file->file.name.data, | |
271 cf->conf_file->line); | |
272 | |
273 rc = NGX_ERROR; | |
274 break; | |
275 } | |
276 } | |
277 | |
278 cmd++; | |
279 } | |
280 } | |
281 | |
282 if (!found) { | |
283 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
284 "unknown directive \"%s\" in %s:%d", | |
285 name->data, | |
286 cf->conf_file->file.name.data, | |
287 cf->conf_file->line); | |
288 | |
289 rc = NGX_ERROR; | |
290 break; | |
291 } | |
292 | |
293 if (rc == NGX_ERROR) { | |
294 break; | |
295 } | |
296 } | |
297 | |
298 if (filename) { | |
299 cf->conf_file = prev; | |
300 | |
301 if (ngx_close_file(fd) == NGX_FILE_ERROR) { | |
302 ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, | |
303 ngx_close_file_n " %s failed", | |
304 cf->conf_file->file.name.data); | |
305 return NGX_CONF_ERROR; | |
306 } | |
307 } | |
308 | |
309 if (rc == NGX_ERROR) { | |
310 return NGX_CONF_ERROR; | |
311 } | |
312 | |
313 return NGX_CONF_OK; | |
314 } | |
315 | |
316 | |
317 static int ngx_conf_read_token(ngx_conf_t *cf) | |
318 { | |
319 u_char *start, ch, *src, *dst; | |
320 int len; | |
321 int found, need_space, last_space, sharp_comment; | |
322 int quoted, s_quoted, d_quoted; | |
323 ssize_t n; | |
324 ngx_str_t *word; | |
325 ngx_buf_t *b; | |
326 | |
327 found = 0; | |
328 need_space = 0; | |
329 last_space = 1; | |
330 sharp_comment = 0; | |
331 quoted = s_quoted = d_quoted = 0; | |
332 | |
333 cf->args->nelts = 0; | |
334 b = cf->conf_file->buffer; | |
335 start = b->pos; | |
336 | |
337 #if 0 | |
338 ngx_log_debug(cf->log, "TOKEN START"); | |
339 #endif | |
340 | |
341 for ( ;; ) { | |
342 | |
343 if (b->pos >= b->last) { | |
344 if (cf->conf_file->file.offset | |
345 >= ngx_file_size(&cf->conf_file->file.info)) { | |
346 return NGX_CONF_FILE_DONE; | |
347 } | |
348 | |
349 if (b->pos - start) { | |
350 ngx_memcpy(b->start, start, b->pos - start); | |
351 } | |
352 | |
353 n = ngx_read_file(&cf->conf_file->file, | |
354 b->start + (b->pos - start), | |
355 b->end - (b->start + (b->pos - start)), | |
356 cf->conf_file->file.offset); | |
357 | |
358 if (n == NGX_ERROR) { | |
359 return NGX_ERROR; | |
360 } | |
361 | |
362 b->pos = b->start + (b->pos - start); | |
363 start = b->start; | |
364 b->last = b->pos + n; | |
365 } | |
366 | |
367 ch = *b->pos++; | |
368 | |
369 #if 0 | |
370 ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '%c'" _ | |
371 last_space _ need_space _ | |
372 quoted _ s_quoted _ d_quoted _ ch); | |
373 #endif | |
374 | |
375 if (ch == LF) { | |
376 cf->conf_file->line++; | |
377 | |
378 if (sharp_comment) { | |
379 sharp_comment = 0; | |
380 } | |
381 } | |
382 | |
383 if (sharp_comment) { | |
384 continue; | |
385 } | |
386 | |
387 if (quoted) { | |
388 quoted = 0; | |
389 continue; | |
390 } | |
391 | |
392 if (need_space) { | |
393 if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { | |
394 last_space = 1; | |
395 need_space = 0; | |
396 continue; | |
397 } | |
398 | |
399 if (ch == ';' || ch == '{') { | |
400 return NGX_OK; | |
401 } | |
402 | |
403 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
404 "unexpected '%c' in %s:%d", | |
405 ch, cf->conf_file->file.name.data, | |
406 cf->conf_file->line); | |
407 | |
408 return NGX_ERROR; | |
409 } | |
410 | |
411 if (last_space) { | |
412 if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { | |
413 continue; | |
414 } | |
415 | |
416 start = b->pos - 1; | |
417 | |
418 switch (ch) { | |
419 | |
420 case ';': | |
421 case '{': | |
422 if (cf->args->nelts == 0) { | |
423 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
424 "unexpected '%c' in %s:%d", | |
425 ch, cf->conf_file->file.name.data, | |
426 cf->conf_file->line); | |
427 return NGX_ERROR; | |
428 } | |
429 | |
430 return NGX_OK; | |
431 | |
432 case '}': | |
433 if (cf->args->nelts > 0) { | |
434 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
435 "unexpected '}' in %s:%d", | |
436 cf->conf_file->file.name.data, | |
437 cf->conf_file->line); | |
438 return NGX_ERROR; | |
439 } | |
440 | |
441 return NGX_CONF_BLOCK_DONE; | |
442 | |
443 case '#': | |
444 sharp_comment = 1; | |
445 continue; | |
446 | |
447 case '\\': | |
448 quoted = 1; | |
449 last_space = 0; | |
450 continue; | |
451 | |
452 case '"': | |
453 start++; | |
454 d_quoted = 1; | |
455 last_space = 0; | |
456 continue; | |
457 | |
458 case '\'': | |
459 start++; | |
460 s_quoted = 1; | |
461 last_space = 0; | |
462 continue; | |
463 | |
464 default: | |
465 last_space = 0; | |
466 } | |
467 | |
468 } else { | |
469 if (ch == '\\') { | |
470 quoted = 1; | |
471 continue; | |
472 } | |
473 | |
474 if (d_quoted) { | |
475 if (ch == '"') { | |
476 d_quoted = 0; | |
477 need_space = 1; | |
478 found = 1; | |
479 } | |
480 | |
481 } else if (s_quoted) { | |
482 if (ch == '\'') { | |
483 s_quoted = 0; | |
484 need_space = 1; | |
485 found = 1; | |
486 } | |
487 | |
488 } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF | |
489 || ch == ';' || ch == '{') { | |
490 last_space = 1; | |
491 found = 1; | |
492 } | |
493 | |
494 if (found) { | |
495 if (!(word = ngx_push_array(cf->args))) { | |
496 return NGX_ERROR; | |
497 } | |
498 | |
499 if (!(word->data = ngx_palloc(cf->pool, b->pos - start + 1))) { | |
500 return NGX_ERROR; | |
501 } | |
502 | |
503 for (dst = word->data, src = start, len = 0; | |
504 src < b->pos - 1; | |
505 len++) | |
506 { | |
507 if (*src == '\\') { | |
508 switch (src[1]) { | |
509 case '"': | |
510 case '\'': | |
511 case '\\': | |
512 src++; | |
513 break; | |
514 | |
515 case 't': | |
516 *dst++ = '\t'; | |
517 src += 2; | |
518 continue; | |
519 | |
520 case 'r': | |
521 *dst++ = '\r'; | |
522 src += 2; | |
523 continue; | |
524 | |
525 case 'n': | |
526 *dst++ = '\n'; | |
527 src += 2; | |
528 continue; | |
529 } | |
530 | |
531 } | |
532 *dst++ = *src++; | |
533 } | |
534 *dst = '\0'; | |
535 word->len = len; | |
536 | |
537 #if 0 | |
538 ngx_log_debug(cf->log, "FOUND %d:'%s'" _ word->len _ word->data); | |
539 #endif | |
540 | |
541 if (ch == ';' || ch == '{') { | |
542 return NGX_OK; | |
543 } | |
544 | |
545 found = 0; | |
546 } | |
547 } | |
548 } | |
549 } | |
550 | |
551 | |
552 static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
553 { | |
554 ngx_str_t *value, file; | |
555 | |
556 value = cf->args->elts; | |
557 file = value[1]; | |
558 | |
559 if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ | |
560 return NGX_CONF_ERROR; | |
561 } | |
562 | |
563 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); | |
564 | |
565 return ngx_conf_parse(cf, &file); | |
566 } | |
567 | |
568 | |
569 ngx_int_t ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name) | |
570 { | |
571 u_char *p; | |
572 ngx_str_t old; | |
573 | |
574 if (name->data[0] == '/') { | |
575 return NGX_OK; | |
576 } | |
577 | |
578 old = *name; | |
579 | |
580 name->len = cycle->root.len + old.len; | |
581 | |
582 if (!(name->data = ngx_palloc(cycle->pool, name->len + 1))) { | |
583 return NGX_ERROR; | |
584 } | |
585 | |
586 p = ngx_cpymem(name->data, cycle->root.data, cycle->root.len), | |
587 ngx_cpystrn(p, old.data, old.len + 1); | |
588 | |
589 return NGX_OK; | |
590 } | |
591 | |
592 | |
593 ngx_open_file_t *ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name) | |
594 { | |
595 ngx_str_t full; | |
596 ngx_uint_t i; | |
597 ngx_list_part_t *part; | |
598 ngx_open_file_t *file; | |
599 | |
600 #if (NGX_SUPPRESS_WARN) | |
601 full.len = 0; | |
602 full.data = NULL; | |
603 #endif | |
604 | |
605 if (name) { | |
606 full = *name; | |
607 | |
608 if (ngx_conf_full_name(cycle, &full) == NGX_ERROR) { | |
609 return NULL; | |
610 } | |
611 | |
612 part = &cycle->open_files.part; | |
613 file = part->elts; | |
614 | |
615 for (i = 0; /* void */ ; i++) { | |
616 | |
617 if (i >= part->nelts) { | |
618 if (part->next == NULL) { | |
619 break; | |
620 } | |
621 part = part->next; | |
622 file = part->elts; | |
623 i = 0; | |
624 } | |
625 | |
626 if (full.len != file[i].name.len) { | |
627 continue; | |
628 } | |
629 | |
630 if (ngx_strcmp(full.data, file[i].name.data) == 0) { | |
631 return &file[i]; | |
632 } | |
633 } | |
634 } | |
635 | |
636 if (!(file = ngx_list_push(&cycle->open_files))) { | |
637 return NULL; | |
638 } | |
639 | |
640 if (name) { | |
641 file->fd = NGX_INVALID_FILE; | |
642 file->name = full; | |
643 | |
644 } else { | |
645 file->fd = ngx_stderr_fileno; | |
646 file->name.len = 0; | |
647 file->name.data = NULL; | |
648 } | |
649 | |
650 return file; | |
651 } | |
652 | |
653 | |
654 void ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err, | |
655 char *fmt, ...) | |
656 { | |
657 int len; | |
658 char errstr[NGX_MAX_CONF_ERRSTR]; | |
659 va_list args; | |
660 | |
661 va_start(args, fmt); | |
662 len = ngx_vsnprintf(errstr, sizeof(errstr) - 1, fmt, args); | |
663 va_end(args); | |
664 | |
665 if (err) { | |
666 len += ngx_snprintf(errstr + len, sizeof(errstr) - len - 1, | |
667 " (%d: ", err); | |
668 len += ngx_strerror_r(err, errstr + len, sizeof(errstr) - len - 1); | |
669 errstr[len++] = ')'; | |
670 errstr[len] = '\0'; | |
671 } | |
672 | |
673 ngx_log_error(level, cf->log, 0, "%s in %s:%d", | |
674 errstr, cf->conf_file->file.name.data, cf->conf_file->line); | |
675 } | |
676 | |
677 | |
678 char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
679 { | |
680 char *p = conf; | |
681 | |
682 ngx_str_t *value; | |
683 ngx_flag_t *fp; | |
684 ngx_conf_post_t *post; | |
685 | |
686 fp = (ngx_flag_t *) (p + cmd->offset); | |
687 | |
688 if (*fp != NGX_CONF_UNSET) { | |
689 return "is duplicate"; | |
690 } | |
691 | |
692 value = cf->args->elts; | |
693 | |
694 if (ngx_strcasecmp(value[1].data, "on") == 0) { | |
695 *fp = 1; | |
696 | |
697 } else if (ngx_strcasecmp(value[1].data, "off") == 0) { | |
698 *fp = 0; | |
699 | |
700 } else { | |
701 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
702 "invalid value \"%s\" in \"%s\" directive, " | |
703 "it must be \"on\" or \"off\"", | |
704 value[1].data, cmd->name.data); | |
705 return NGX_CONF_ERROR; | |
706 } | |
707 | |
708 if (cmd->post) { | |
709 post = cmd->post; | |
710 return post->post_handler(cf, post, fp); | |
711 } | |
712 | |
713 return NGX_CONF_OK; | |
714 } | |
715 | |
716 | |
717 char *ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
718 { | |
719 char *p = conf; | |
720 | |
721 ngx_str_t *field, *value; | |
722 ngx_conf_post_t *post; | |
723 | |
724 field = (ngx_str_t *) (p + cmd->offset); | |
725 | |
726 if (field->data) { | |
727 return "is duplicate"; | |
728 } | |
729 | |
730 value = cf->args->elts; | |
731 | |
732 *field = value[1]; | |
733 | |
734 if (cmd->post) { | |
735 post = cmd->post; | |
736 return post->post_handler(cf, post, field); | |
737 } | |
738 | |
739 return NGX_CONF_OK; | |
740 } | |
741 | |
742 | |
743 char *ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
744 { | |
745 char *p = conf; | |
746 | |
747 ngx_int_t *np; | |
748 ngx_str_t *value; | |
749 ngx_conf_post_t *post; | |
750 | |
751 | |
752 np = (ngx_int_t *) (p + cmd->offset); | |
753 | |
754 if (*np != NGX_CONF_UNSET) { | |
755 return "is duplicate"; | |
756 } | |
757 | |
758 value = cf->args->elts; | |
759 *np = ngx_atoi(value[1].data, value[1].len); | |
760 if (*np == NGX_ERROR) { | |
761 return "invalid number"; | |
762 } | |
763 | |
764 if (cmd->post) { | |
765 post = cmd->post; | |
766 return post->post_handler(cf, post, np); | |
767 } | |
768 | |
769 return NGX_CONF_OK; | |
770 } | |
771 | |
772 | |
773 char *ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
774 { | |
775 char *p = conf; | |
776 | |
777 size_t *sp; | |
778 ngx_str_t *value; | |
779 ngx_conf_post_t *post; | |
780 | |
781 | |
782 sp = (size_t *) (p + cmd->offset); | |
783 if (*sp != NGX_CONF_UNSET_SIZE) { | |
784 return "is duplicate"; | |
785 } | |
786 | |
787 value = cf->args->elts; | |
788 | |
789 *sp = ngx_parse_size(&value[1]); | |
790 if (*sp == (size_t) NGX_ERROR) { | |
791 return "invalid value"; | |
792 } | |
793 | |
794 if (cmd->post) { | |
795 post = cmd->post; | |
796 return post->post_handler(cf, post, sp); | |
797 } | |
798 | |
799 return NGX_CONF_OK; | |
800 } | |
801 | |
802 | |
803 char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
804 { | |
805 char *p = conf; | |
806 | |
807 ngx_msec_t *msp; | |
808 ngx_str_t *value; | |
809 ngx_conf_post_t *post; | |
810 | |
811 | |
812 msp = (ngx_msec_t *) (p + cmd->offset); | |
813 if (*msp != NGX_CONF_UNSET_MSEC) { | |
814 return "is duplicate"; | |
815 } | |
816 | |
817 value = cf->args->elts; | |
818 | |
819 *msp = ngx_parse_time(&value[1], 0); | |
820 if (*msp == (ngx_msec_t) NGX_ERROR) { | |
821 return "invalid value"; | |
822 } | |
823 | |
824 if (*msp == (ngx_msec_t) NGX_PARSE_LARGE_TIME) { | |
825 return "value must be less than 597 hours"; | |
826 } | |
827 | |
828 if (cmd->post) { | |
829 post = cmd->post; | |
830 return post->post_handler(cf, post, msp); | |
831 } | |
832 | |
833 return NGX_CONF_OK; | |
834 } | |
835 | |
836 | |
837 char *ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
838 { | |
839 char *p = conf; | |
840 | |
841 time_t *sp; | |
842 ngx_str_t *value; | |
843 ngx_conf_post_t *post; | |
844 | |
845 | |
846 sp = (time_t *) (p + cmd->offset); | |
847 if (*sp != NGX_CONF_UNSET) { | |
848 return "is duplicate"; | |
849 } | |
850 | |
851 value = cf->args->elts; | |
852 | |
853 *sp = ngx_parse_time(&value[1], 1); | |
854 if (*sp == NGX_ERROR) { | |
855 return "invalid value"; | |
856 } | |
857 | |
858 if (*sp == NGX_PARSE_LARGE_TIME) { | |
859 return "value must be less than 68 years"; | |
860 } | |
861 | |
862 if (cmd->post) { | |
863 post = cmd->post; | |
864 return post->post_handler(cf, post, sp); | |
865 } | |
866 | |
867 return NGX_CONF_OK; | |
868 } | |
869 | |
870 | |
871 char *ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
872 { | |
873 char *p = conf; | |
874 | |
875 ngx_str_t *value; | |
876 ngx_bufs_t *bufs; | |
877 | |
878 | |
879 bufs = (ngx_bufs_t *) (p + cmd->offset); | |
880 if (bufs->num) { | |
881 return "is duplicate"; | |
882 } | |
883 | |
884 value = cf->args->elts; | |
885 | |
886 bufs->num = ngx_atoi(value[1].data, value[1].len); | |
887 if (bufs->num == NGX_ERROR || bufs->num == 0) { | |
888 return "invalid value"; | |
889 } | |
890 | |
891 bufs->size = ngx_parse_size(&value[2]); | |
892 if (bufs->size == (size_t) NGX_ERROR || bufs->size == 0) { | |
893 return "invalid value"; | |
894 } | |
895 | |
896 return NGX_CONF_OK; | |
897 } | |
898 | |
899 | |
900 char *ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
901 { | |
902 char *p = conf; | |
903 | |
904 ngx_uint_t *np, i; | |
905 ngx_str_t *value; | |
906 ngx_conf_enum_t *e; | |
907 | |
908 np = (ngx_uint_t *) (p + cmd->offset); | |
909 | |
910 if (*np != NGX_CONF_UNSET_UINT) { | |
911 return "is duplicate"; | |
912 } | |
913 | |
914 value = cf->args->elts; | |
915 e = cmd->post; | |
916 | |
917 for (i = 0; e[i].name.len != 0; i++) { | |
918 if (e[i].name.len != value[1].len | |
919 || ngx_strcasecmp(e[i].name.data, value[1].data) != 0) | |
920 { | |
921 continue; | |
922 } | |
923 | |
924 *np = e[i].value; | |
925 | |
926 return NGX_CONF_OK; | |
927 } | |
928 | |
929 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
930 "invalid value \"%s\"", value[1].data); | |
931 | |
932 return NGX_CONF_ERROR; | |
933 } | |
934 | |
935 | |
936 char *ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
937 { | |
938 char *p = conf; | |
939 | |
940 ngx_uint_t *np, i, m; | |
941 ngx_str_t *value; | |
942 ngx_conf_bitmask_t *mask; | |
943 | |
944 | |
945 np = (ngx_uint_t *) (p + cmd->offset); | |
946 value = cf->args->elts; | |
947 mask = cmd->post; | |
948 | |
949 for (i = 1; i < cf->args->nelts; i++) { | |
950 for (m = 0; mask[m].name.len != 0; m++) { | |
951 | |
952 if (mask[m].name.len != value[i].len | |
953 || ngx_strcasecmp(mask[m].name.data, value[i].data) != 0) | |
954 { | |
955 continue; | |
956 } | |
957 | |
958 if (*np & mask[m].mask) { | |
959 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
960 "duplicate value \"%s\"", value[i].data); | |
961 | |
962 } else { | |
963 *np |= mask[m].mask; | |
964 } | |
965 | |
966 break; | |
967 } | |
968 | |
969 if (mask[m].name.len == 0) { | |
970 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
971 "invalid value \"%s\"", value[i].data); | |
972 | |
973 return NGX_CONF_ERROR; | |
974 } | |
975 } | |
976 | |
977 return NGX_CONF_OK; | |
978 } | |
979 | |
980 | |
981 char *ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
982 { | |
983 return "unsupported on this platform"; | |
984 } | |
985 | |
986 | |
987 char *ngx_conf_check_num_bounds(ngx_conf_t *cf, void *post, void *data) | |
988 { | |
989 ngx_conf_num_bounds_t *bounds = post; | |
990 ngx_int_t *np = data; | |
991 | |
992 if (bounds->high == -1) { | |
993 if (*np >= bounds->low) { | |
994 return NGX_CONF_OK; | |
995 } | |
996 | |
997 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
998 "value must be equal or more than %d", bounds->low); | |
999 | |
1000 return NGX_CONF_ERROR; | |
1001 } | |
1002 | |
1003 if (*np >= bounds->low && *np <= bounds->high) { | |
1004 return NGX_CONF_OK; | |
1005 } | |
1006 | |
1007 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1008 "value must be between %d and %d", | |
1009 bounds->low, bounds->high); | |
1010 | |
1011 return NGX_CONF_ERROR; | |
1012 } |