Annotation of embedaddon/nginx/src/core/ngx_conf_file.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7:
! 8: #include <ngx_config.h>
! 9: #include <ngx_core.h>
! 10:
! 11: #define NGX_CONF_BUFFER 4096
! 12:
! 13: static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last);
! 14: static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf);
! 15: static ngx_int_t ngx_conf_test_full_name(ngx_str_t *name);
! 16: static void ngx_conf_flush_files(ngx_cycle_t *cycle);
! 17:
! 18:
! 19: static ngx_command_t ngx_conf_commands[] = {
! 20:
! 21: { ngx_string("include"),
! 22: NGX_ANY_CONF|NGX_CONF_TAKE1,
! 23: ngx_conf_include,
! 24: 0,
! 25: 0,
! 26: NULL },
! 27:
! 28: ngx_null_command
! 29: };
! 30:
! 31:
! 32: ngx_module_t ngx_conf_module = {
! 33: NGX_MODULE_V1,
! 34: NULL, /* module context */
! 35: ngx_conf_commands, /* module directives */
! 36: NGX_CONF_MODULE, /* module type */
! 37: NULL, /* init master */
! 38: NULL, /* init module */
! 39: NULL, /* init process */
! 40: NULL, /* init thread */
! 41: NULL, /* exit thread */
! 42: ngx_conf_flush_files, /* exit process */
! 43: NULL, /* exit master */
! 44: NGX_MODULE_V1_PADDING
! 45: };
! 46:
! 47:
! 48: /* The eight fixed arguments */
! 49:
! 50: static ngx_uint_t argument_number[] = {
! 51: NGX_CONF_NOARGS,
! 52: NGX_CONF_TAKE1,
! 53: NGX_CONF_TAKE2,
! 54: NGX_CONF_TAKE3,
! 55: NGX_CONF_TAKE4,
! 56: NGX_CONF_TAKE5,
! 57: NGX_CONF_TAKE6,
! 58: NGX_CONF_TAKE7
! 59: };
! 60:
! 61:
! 62: char *
! 63: ngx_conf_param(ngx_conf_t *cf)
! 64: {
! 65: char *rv;
! 66: ngx_str_t *param;
! 67: ngx_buf_t b;
! 68: ngx_conf_file_t conf_file;
! 69:
! 70: param = &cf->cycle->conf_param;
! 71:
! 72: if (param->len == 0) {
! 73: return NGX_CONF_OK;
! 74: }
! 75:
! 76: ngx_memzero(&conf_file, sizeof(ngx_conf_file_t));
! 77:
! 78: ngx_memzero(&b, sizeof(ngx_buf_t));
! 79:
! 80: b.start = param->data;
! 81: b.pos = param->data;
! 82: b.last = param->data + param->len;
! 83: b.end = b.last;
! 84: b.temporary = 1;
! 85:
! 86: conf_file.file.fd = NGX_INVALID_FILE;
! 87: conf_file.file.name.data = NULL;
! 88: conf_file.line = 0;
! 89:
! 90: cf->conf_file = &conf_file;
! 91: cf->conf_file->buffer = &b;
! 92:
! 93: rv = ngx_conf_parse(cf, NULL);
! 94:
! 95: cf->conf_file = NULL;
! 96:
! 97: return rv;
! 98: }
! 99:
! 100:
! 101: char *
! 102: ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
! 103: {
! 104: char *rv;
! 105: ngx_fd_t fd;
! 106: ngx_int_t rc;
! 107: ngx_buf_t buf;
! 108: ngx_conf_file_t *prev, conf_file;
! 109: enum {
! 110: parse_file = 0,
! 111: parse_block,
! 112: parse_param
! 113: } type;
! 114:
! 115: #if (NGX_SUPPRESS_WARN)
! 116: fd = NGX_INVALID_FILE;
! 117: prev = NULL;
! 118: #endif
! 119:
! 120: if (filename) {
! 121:
! 122: /* open configuration file */
! 123:
! 124: fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
! 125: if (fd == NGX_INVALID_FILE) {
! 126: ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
! 127: ngx_open_file_n " \"%s\" failed",
! 128: filename->data);
! 129: return NGX_CONF_ERROR;
! 130: }
! 131:
! 132: prev = cf->conf_file;
! 133:
! 134: cf->conf_file = &conf_file;
! 135:
! 136: if (ngx_fd_info(fd, &cf->conf_file->file.info) == NGX_FILE_ERROR) {
! 137: ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
! 138: ngx_fd_info_n " \"%s\" failed", filename->data);
! 139: }
! 140:
! 141: cf->conf_file->buffer = &buf;
! 142:
! 143: buf.start = ngx_alloc(NGX_CONF_BUFFER, cf->log);
! 144: if (buf.start == NULL) {
! 145: goto failed;
! 146: }
! 147:
! 148: buf.pos = buf.start;
! 149: buf.last = buf.start;
! 150: buf.end = buf.last + NGX_CONF_BUFFER;
! 151: buf.temporary = 1;
! 152:
! 153: cf->conf_file->file.fd = fd;
! 154: cf->conf_file->file.name.len = filename->len;
! 155: cf->conf_file->file.name.data = filename->data;
! 156: cf->conf_file->file.offset = 0;
! 157: cf->conf_file->file.log = cf->log;
! 158: cf->conf_file->line = 1;
! 159:
! 160: type = parse_file;
! 161:
! 162: } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {
! 163:
! 164: type = parse_block;
! 165:
! 166: } else {
! 167: type = parse_param;
! 168: }
! 169:
! 170:
! 171: for ( ;; ) {
! 172: rc = ngx_conf_read_token(cf);
! 173:
! 174: /*
! 175: * ngx_conf_read_token() may return
! 176: *
! 177: * NGX_ERROR there is error
! 178: * NGX_OK the token terminated by ";" was found
! 179: * NGX_CONF_BLOCK_START the token terminated by "{" was found
! 180: * NGX_CONF_BLOCK_DONE the "}" was found
! 181: * NGX_CONF_FILE_DONE the configuration file is done
! 182: */
! 183:
! 184: if (rc == NGX_ERROR) {
! 185: goto done;
! 186: }
! 187:
! 188: if (rc == NGX_CONF_BLOCK_DONE) {
! 189:
! 190: if (type != parse_block) {
! 191: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");
! 192: goto failed;
! 193: }
! 194:
! 195: goto done;
! 196: }
! 197:
! 198: if (rc == NGX_CONF_FILE_DONE) {
! 199:
! 200: if (type == parse_block) {
! 201: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 202: "unexpected end of file, expecting \"}\"");
! 203: goto failed;
! 204: }
! 205:
! 206: goto done;
! 207: }
! 208:
! 209: if (rc == NGX_CONF_BLOCK_START) {
! 210:
! 211: if (type == parse_param) {
! 212: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 213: "block directives are not supported "
! 214: "in -g option");
! 215: goto failed;
! 216: }
! 217: }
! 218:
! 219: /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */
! 220:
! 221: if (cf->handler) {
! 222:
! 223: /*
! 224: * the custom handler, i.e., that is used in the http's
! 225: * "types { ... }" directive
! 226: */
! 227:
! 228: rv = (*cf->handler)(cf, NULL, cf->handler_conf);
! 229: if (rv == NGX_CONF_OK) {
! 230: continue;
! 231: }
! 232:
! 233: if (rv == NGX_CONF_ERROR) {
! 234: goto failed;
! 235: }
! 236:
! 237: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, rv);
! 238:
! 239: goto failed;
! 240: }
! 241:
! 242:
! 243: rc = ngx_conf_handler(cf, rc);
! 244:
! 245: if (rc == NGX_ERROR) {
! 246: goto failed;
! 247: }
! 248: }
! 249:
! 250: failed:
! 251:
! 252: rc = NGX_ERROR;
! 253:
! 254: done:
! 255:
! 256: if (filename) {
! 257: if (cf->conf_file->buffer->start) {
! 258: ngx_free(cf->conf_file->buffer->start);
! 259: }
! 260:
! 261: if (ngx_close_file(fd) == NGX_FILE_ERROR) {
! 262: ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
! 263: ngx_close_file_n " %s failed",
! 264: filename->data);
! 265: return NGX_CONF_ERROR;
! 266: }
! 267:
! 268: cf->conf_file = prev;
! 269: }
! 270:
! 271: if (rc == NGX_ERROR) {
! 272: return NGX_CONF_ERROR;
! 273: }
! 274:
! 275: return NGX_CONF_OK;
! 276: }
! 277:
! 278:
! 279: static ngx_int_t
! 280: ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
! 281: {
! 282: char *rv;
! 283: void *conf, **confp;
! 284: ngx_uint_t i, found;
! 285: ngx_str_t *name;
! 286: ngx_command_t *cmd;
! 287:
! 288: name = cf->args->elts;
! 289:
! 290: found = 0;
! 291:
! 292: for (i = 0; ngx_modules[i]; i++) {
! 293:
! 294: cmd = ngx_modules[i]->commands;
! 295: if (cmd == NULL) {
! 296: continue;
! 297: }
! 298:
! 299: for ( /* void */ ; cmd->name.len; cmd++) {
! 300:
! 301: if (name->len != cmd->name.len) {
! 302: continue;
! 303: }
! 304:
! 305: if (ngx_strcmp(name->data, cmd->name.data) != 0) {
! 306: continue;
! 307: }
! 308:
! 309: found = 1;
! 310:
! 311: if (ngx_modules[i]->type != NGX_CONF_MODULE
! 312: && ngx_modules[i]->type != cf->module_type)
! 313: {
! 314: continue;
! 315: }
! 316:
! 317: /* is the directive's location right ? */
! 318:
! 319: if (!(cmd->type & cf->cmd_type)) {
! 320: continue;
! 321: }
! 322:
! 323: if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
! 324: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 325: "directive \"%s\" is not terminated by \";\"",
! 326: name->data);
! 327: return NGX_ERROR;
! 328: }
! 329:
! 330: if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {
! 331: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 332: "directive \"%s\" has no opening \"{\"",
! 333: name->data);
! 334: return NGX_ERROR;
! 335: }
! 336:
! 337: /* is the directive's argument count right ? */
! 338:
! 339: if (!(cmd->type & NGX_CONF_ANY)) {
! 340:
! 341: if (cmd->type & NGX_CONF_FLAG) {
! 342:
! 343: if (cf->args->nelts != 2) {
! 344: goto invalid;
! 345: }
! 346:
! 347: } else if (cmd->type & NGX_CONF_1MORE) {
! 348:
! 349: if (cf->args->nelts < 2) {
! 350: goto invalid;
! 351: }
! 352:
! 353: } else if (cmd->type & NGX_CONF_2MORE) {
! 354:
! 355: if (cf->args->nelts < 3) {
! 356: goto invalid;
! 357: }
! 358:
! 359: } else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {
! 360:
! 361: goto invalid;
! 362:
! 363: } else if (!(cmd->type & argument_number[cf->args->nelts - 1]))
! 364: {
! 365: goto invalid;
! 366: }
! 367: }
! 368:
! 369: /* set up the directive's configuration context */
! 370:
! 371: conf = NULL;
! 372:
! 373: if (cmd->type & NGX_DIRECT_CONF) {
! 374: conf = ((void **) cf->ctx)[ngx_modules[i]->index];
! 375:
! 376: } else if (cmd->type & NGX_MAIN_CONF) {
! 377: conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
! 378:
! 379: } else if (cf->ctx) {
! 380: confp = *(void **) ((char *) cf->ctx + cmd->conf);
! 381:
! 382: if (confp) {
! 383: conf = confp[ngx_modules[i]->ctx_index];
! 384: }
! 385: }
! 386:
! 387: rv = cmd->set(cf, cmd, conf);
! 388:
! 389: if (rv == NGX_CONF_OK) {
! 390: return NGX_OK;
! 391: }
! 392:
! 393: if (rv == NGX_CONF_ERROR) {
! 394: return NGX_ERROR;
! 395: }
! 396:
! 397: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 398: "\"%s\" directive %s", name->data, rv);
! 399:
! 400: return NGX_ERROR;
! 401: }
! 402: }
! 403:
! 404: if (found) {
! 405: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 406: "\"%s\" directive is not allowed here", name->data);
! 407:
! 408: return NGX_ERROR;
! 409: }
! 410:
! 411: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 412: "unknown directive \"%s\"", name->data);
! 413:
! 414: return NGX_ERROR;
! 415:
! 416: invalid:
! 417:
! 418: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 419: "invalid number of arguments in \"%s\" directive",
! 420: name->data);
! 421:
! 422: return NGX_ERROR;
! 423: }
! 424:
! 425:
! 426: static ngx_int_t
! 427: ngx_conf_read_token(ngx_conf_t *cf)
! 428: {
! 429: u_char *start, ch, *src, *dst;
! 430: off_t file_size;
! 431: size_t len;
! 432: ssize_t n, size;
! 433: ngx_uint_t found, need_space, last_space, sharp_comment, variable;
! 434: ngx_uint_t quoted, s_quoted, d_quoted, start_line;
! 435: ngx_str_t *word;
! 436: ngx_buf_t *b;
! 437:
! 438: found = 0;
! 439: need_space = 0;
! 440: last_space = 1;
! 441: sharp_comment = 0;
! 442: variable = 0;
! 443: quoted = 0;
! 444: s_quoted = 0;
! 445: d_quoted = 0;
! 446:
! 447: cf->args->nelts = 0;
! 448: b = cf->conf_file->buffer;
! 449: start = b->pos;
! 450: start_line = cf->conf_file->line;
! 451:
! 452: file_size = ngx_file_size(&cf->conf_file->file.info);
! 453:
! 454: for ( ;; ) {
! 455:
! 456: if (b->pos >= b->last) {
! 457:
! 458: if (cf->conf_file->file.offset >= file_size) {
! 459:
! 460: if (cf->args->nelts > 0 || !last_space) {
! 461:
! 462: if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
! 463: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 464: "unexpected end of parameter, "
! 465: "expecting \";\"");
! 466: return NGX_ERROR;
! 467: }
! 468:
! 469: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 470: "unexpected end of file, "
! 471: "expecting \";\" or \"}\"");
! 472: return NGX_ERROR;
! 473: }
! 474:
! 475: return NGX_CONF_FILE_DONE;
! 476: }
! 477:
! 478: len = b->pos - start;
! 479:
! 480: if (len == NGX_CONF_BUFFER) {
! 481: cf->conf_file->line = start_line;
! 482:
! 483: if (d_quoted) {
! 484: ch = '"';
! 485:
! 486: } else if (s_quoted) {
! 487: ch = '\'';
! 488:
! 489: } else {
! 490: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 491: "too long parameter \"%*s...\" started",
! 492: 10, start);
! 493: return NGX_ERROR;
! 494: }
! 495:
! 496: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 497: "too long parameter, probably "
! 498: "missing terminating \"%c\" character", ch);
! 499: return NGX_ERROR;
! 500: }
! 501:
! 502: if (len) {
! 503: ngx_memmove(b->start, start, len);
! 504: }
! 505:
! 506: size = (ssize_t) (file_size - cf->conf_file->file.offset);
! 507:
! 508: if (size > b->end - (b->start + len)) {
! 509: size = b->end - (b->start + len);
! 510: }
! 511:
! 512: n = ngx_read_file(&cf->conf_file->file, b->start + len, size,
! 513: cf->conf_file->file.offset);
! 514:
! 515: if (n == NGX_ERROR) {
! 516: return NGX_ERROR;
! 517: }
! 518:
! 519: if (n != size) {
! 520: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 521: ngx_read_file_n " returned "
! 522: "only %z bytes instead of %z",
! 523: n, size);
! 524: return NGX_ERROR;
! 525: }
! 526:
! 527: b->pos = b->start + len;
! 528: b->last = b->pos + n;
! 529: start = b->start;
! 530: }
! 531:
! 532: ch = *b->pos++;
! 533:
! 534: if (ch == LF) {
! 535: cf->conf_file->line++;
! 536:
! 537: if (sharp_comment) {
! 538: sharp_comment = 0;
! 539: }
! 540: }
! 541:
! 542: if (sharp_comment) {
! 543: continue;
! 544: }
! 545:
! 546: if (quoted) {
! 547: quoted = 0;
! 548: continue;
! 549: }
! 550:
! 551: if (need_space) {
! 552: if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
! 553: last_space = 1;
! 554: need_space = 0;
! 555: continue;
! 556: }
! 557:
! 558: if (ch == ';') {
! 559: return NGX_OK;
! 560: }
! 561:
! 562: if (ch == '{') {
! 563: return NGX_CONF_BLOCK_START;
! 564: }
! 565:
! 566: if (ch == ')') {
! 567: last_space = 1;
! 568: need_space = 0;
! 569:
! 570: } else {
! 571: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 572: "unexpected \"%c\"", ch);
! 573: return NGX_ERROR;
! 574: }
! 575: }
! 576:
! 577: if (last_space) {
! 578: if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) {
! 579: continue;
! 580: }
! 581:
! 582: start = b->pos - 1;
! 583: start_line = cf->conf_file->line;
! 584:
! 585: switch (ch) {
! 586:
! 587: case ';':
! 588: case '{':
! 589: if (cf->args->nelts == 0) {
! 590: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 591: "unexpected \"%c\"", ch);
! 592: return NGX_ERROR;
! 593: }
! 594:
! 595: if (ch == '{') {
! 596: return NGX_CONF_BLOCK_START;
! 597: }
! 598:
! 599: return NGX_OK;
! 600:
! 601: case '}':
! 602: if (cf->args->nelts != 0) {
! 603: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 604: "unexpected \"}\"");
! 605: return NGX_ERROR;
! 606: }
! 607:
! 608: return NGX_CONF_BLOCK_DONE;
! 609:
! 610: case '#':
! 611: sharp_comment = 1;
! 612: continue;
! 613:
! 614: case '\\':
! 615: quoted = 1;
! 616: last_space = 0;
! 617: continue;
! 618:
! 619: case '"':
! 620: start++;
! 621: d_quoted = 1;
! 622: last_space = 0;
! 623: continue;
! 624:
! 625: case '\'':
! 626: start++;
! 627: s_quoted = 1;
! 628: last_space = 0;
! 629: continue;
! 630:
! 631: default:
! 632: last_space = 0;
! 633: }
! 634:
! 635: } else {
! 636: if (ch == '{' && variable) {
! 637: continue;
! 638: }
! 639:
! 640: variable = 0;
! 641:
! 642: if (ch == '\\') {
! 643: quoted = 1;
! 644: continue;
! 645: }
! 646:
! 647: if (ch == '$') {
! 648: variable = 1;
! 649: continue;
! 650: }
! 651:
! 652: if (d_quoted) {
! 653: if (ch == '"') {
! 654: d_quoted = 0;
! 655: need_space = 1;
! 656: found = 1;
! 657: }
! 658:
! 659: } else if (s_quoted) {
! 660: if (ch == '\'') {
! 661: s_quoted = 0;
! 662: need_space = 1;
! 663: found = 1;
! 664: }
! 665:
! 666: } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
! 667: || ch == ';' || ch == '{')
! 668: {
! 669: last_space = 1;
! 670: found = 1;
! 671: }
! 672:
! 673: if (found) {
! 674: word = ngx_array_push(cf->args);
! 675: if (word == NULL) {
! 676: return NGX_ERROR;
! 677: }
! 678:
! 679: word->data = ngx_pnalloc(cf->pool, b->pos - start + 1);
! 680: if (word->data == NULL) {
! 681: return NGX_ERROR;
! 682: }
! 683:
! 684: for (dst = word->data, src = start, len = 0;
! 685: src < b->pos - 1;
! 686: len++)
! 687: {
! 688: if (*src == '\\') {
! 689: switch (src[1]) {
! 690: case '"':
! 691: case '\'':
! 692: case '\\':
! 693: src++;
! 694: break;
! 695:
! 696: case 't':
! 697: *dst++ = '\t';
! 698: src += 2;
! 699: continue;
! 700:
! 701: case 'r':
! 702: *dst++ = '\r';
! 703: src += 2;
! 704: continue;
! 705:
! 706: case 'n':
! 707: *dst++ = '\n';
! 708: src += 2;
! 709: continue;
! 710: }
! 711:
! 712: }
! 713: *dst++ = *src++;
! 714: }
! 715: *dst = '\0';
! 716: word->len = len;
! 717:
! 718: if (ch == ';') {
! 719: return NGX_OK;
! 720: }
! 721:
! 722: if (ch == '{') {
! 723: return NGX_CONF_BLOCK_START;
! 724: }
! 725:
! 726: found = 0;
! 727: }
! 728: }
! 729: }
! 730: }
! 731:
! 732:
! 733: char *
! 734: ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 735: {
! 736: char *rv;
! 737: ngx_int_t n;
! 738: ngx_str_t *value, file, name;
! 739: ngx_glob_t gl;
! 740:
! 741: value = cf->args->elts;
! 742: file = value[1];
! 743:
! 744: ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
! 745:
! 746: if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
! 747: return NGX_CONF_ERROR;
! 748: }
! 749:
! 750: if (strpbrk((char *) file.data, "*?[") == NULL) {
! 751:
! 752: ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
! 753:
! 754: return ngx_conf_parse(cf, &file);
! 755: }
! 756:
! 757: ngx_memzero(&gl, sizeof(ngx_glob_t));
! 758:
! 759: gl.pattern = file.data;
! 760: gl.log = cf->log;
! 761: gl.test = 1;
! 762:
! 763: if (ngx_open_glob(&gl) != NGX_OK) {
! 764: ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
! 765: ngx_open_glob_n " \"%s\" failed", file.data);
! 766: return NGX_CONF_ERROR;
! 767: }
! 768:
! 769: rv = NGX_CONF_OK;
! 770:
! 771: for ( ;; ) {
! 772: n = ngx_read_glob(&gl, &name);
! 773:
! 774: if (n != NGX_OK) {
! 775: break;
! 776: }
! 777:
! 778: file.len = name.len++;
! 779: file.data = ngx_pstrdup(cf->pool, &name);
! 780:
! 781: ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
! 782:
! 783: rv = ngx_conf_parse(cf, &file);
! 784:
! 785: if (rv != NGX_CONF_OK) {
! 786: break;
! 787: }
! 788: }
! 789:
! 790: ngx_close_glob(&gl);
! 791:
! 792: return rv;
! 793: }
! 794:
! 795:
! 796: ngx_int_t
! 797: ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix)
! 798: {
! 799: size_t len;
! 800: u_char *p, *n, *prefix;
! 801: ngx_int_t rc;
! 802:
! 803: rc = ngx_conf_test_full_name(name);
! 804:
! 805: if (rc == NGX_OK) {
! 806: return rc;
! 807: }
! 808:
! 809: if (conf_prefix) {
! 810: len = cycle->conf_prefix.len;
! 811: prefix = cycle->conf_prefix.data;
! 812:
! 813: } else {
! 814: len = cycle->prefix.len;
! 815: prefix = cycle->prefix.data;
! 816: }
! 817:
! 818: #if (NGX_WIN32)
! 819:
! 820: if (rc == 2) {
! 821: len = rc;
! 822: }
! 823:
! 824: #endif
! 825:
! 826: n = ngx_pnalloc(cycle->pool, len + name->len + 1);
! 827: if (n == NULL) {
! 828: return NGX_ERROR;
! 829: }
! 830:
! 831: p = ngx_cpymem(n, prefix, len);
! 832: ngx_cpystrn(p, name->data, name->len + 1);
! 833:
! 834: name->len += len;
! 835: name->data = n;
! 836:
! 837: return NGX_OK;
! 838: }
! 839:
! 840:
! 841: static ngx_int_t
! 842: ngx_conf_test_full_name(ngx_str_t *name)
! 843: {
! 844: #if (NGX_WIN32)
! 845: u_char c0, c1;
! 846:
! 847: c0 = name->data[0];
! 848:
! 849: if (name->len < 2) {
! 850: if (c0 == '/') {
! 851: return 2;
! 852: }
! 853:
! 854: return NGX_DECLINED;
! 855: }
! 856:
! 857: c1 = name->data[1];
! 858:
! 859: if (c1 == ':') {
! 860: c0 |= 0x20;
! 861:
! 862: if ((c0 >= 'a' && c0 <= 'z')) {
! 863: return NGX_OK;
! 864: }
! 865:
! 866: return NGX_DECLINED;
! 867: }
! 868:
! 869: if (c1 == '/') {
! 870: return NGX_OK;
! 871: }
! 872:
! 873: if (c0 == '/') {
! 874: return 2;
! 875: }
! 876:
! 877: return NGX_DECLINED;
! 878:
! 879: #else
! 880:
! 881: if (name->data[0] == '/') {
! 882: return NGX_OK;
! 883: }
! 884:
! 885: return NGX_DECLINED;
! 886:
! 887: #endif
! 888: }
! 889:
! 890:
! 891: ngx_open_file_t *
! 892: ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
! 893: {
! 894: ngx_str_t full;
! 895: ngx_uint_t i;
! 896: ngx_list_part_t *part;
! 897: ngx_open_file_t *file;
! 898:
! 899: #if (NGX_SUPPRESS_WARN)
! 900: ngx_str_null(&full);
! 901: #endif
! 902:
! 903: if (name->len) {
! 904: full = *name;
! 905:
! 906: if (ngx_conf_full_name(cycle, &full, 0) != NGX_OK) {
! 907: return NULL;
! 908: }
! 909:
! 910: part = &cycle->open_files.part;
! 911: file = part->elts;
! 912:
! 913: for (i = 0; /* void */ ; i++) {
! 914:
! 915: if (i >= part->nelts) {
! 916: if (part->next == NULL) {
! 917: break;
! 918: }
! 919: part = part->next;
! 920: file = part->elts;
! 921: i = 0;
! 922: }
! 923:
! 924: if (full.len != file[i].name.len) {
! 925: continue;
! 926: }
! 927:
! 928: if (ngx_strcmp(full.data, file[i].name.data) == 0) {
! 929: return &file[i];
! 930: }
! 931: }
! 932: }
! 933:
! 934: file = ngx_list_push(&cycle->open_files);
! 935: if (file == NULL) {
! 936: return NULL;
! 937: }
! 938:
! 939: if (name->len) {
! 940: file->fd = NGX_INVALID_FILE;
! 941: file->name = full;
! 942:
! 943: } else {
! 944: file->fd = ngx_stderr;
! 945: file->name = *name;
! 946: }
! 947:
! 948: file->flush = NULL;
! 949: file->data = NULL;
! 950:
! 951: return file;
! 952: }
! 953:
! 954:
! 955: static void
! 956: ngx_conf_flush_files(ngx_cycle_t *cycle)
! 957: {
! 958: ngx_uint_t i;
! 959: ngx_list_part_t *part;
! 960: ngx_open_file_t *file;
! 961:
! 962: ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "flush files");
! 963:
! 964: part = &cycle->open_files.part;
! 965: file = part->elts;
! 966:
! 967: for (i = 0; /* void */ ; i++) {
! 968:
! 969: if (i >= part->nelts) {
! 970: if (part->next == NULL) {
! 971: break;
! 972: }
! 973: part = part->next;
! 974: file = part->elts;
! 975: i = 0;
! 976: }
! 977:
! 978: if (file[i].flush) {
! 979: file[i].flush(&file[i], cycle->log);
! 980: }
! 981: }
! 982: }
! 983:
! 984:
! 985: void ngx_cdecl
! 986: ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
! 987: const char *fmt, ...)
! 988: {
! 989: u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last;
! 990: va_list args;
! 991:
! 992: last = errstr + NGX_MAX_CONF_ERRSTR;
! 993:
! 994: va_start(args, fmt);
! 995: p = ngx_vslprintf(errstr, last, fmt, args);
! 996: va_end(args);
! 997:
! 998: if (err) {
! 999: p = ngx_log_errno(p, last, err);
! 1000: }
! 1001:
! 1002: if (cf->conf_file == NULL) {
! 1003: ngx_log_error(level, cf->log, 0, "%*s", p - errstr, errstr);
! 1004: return;
! 1005: }
! 1006:
! 1007: if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
! 1008: ngx_log_error(level, cf->log, 0, "%*s in command line",
! 1009: p - errstr, errstr);
! 1010: return;
! 1011: }
! 1012:
! 1013: ngx_log_error(level, cf->log, 0, "%*s in %s:%ui",
! 1014: p - errstr, errstr,
! 1015: cf->conf_file->file.name.data, cf->conf_file->line);
! 1016: }
! 1017:
! 1018:
! 1019: char *
! 1020: ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1021: {
! 1022: char *p = conf;
! 1023:
! 1024: ngx_str_t *value;
! 1025: ngx_flag_t *fp;
! 1026: ngx_conf_post_t *post;
! 1027:
! 1028: fp = (ngx_flag_t *) (p + cmd->offset);
! 1029:
! 1030: if (*fp != NGX_CONF_UNSET) {
! 1031: return "is duplicate";
! 1032: }
! 1033:
! 1034: value = cf->args->elts;
! 1035:
! 1036: if (ngx_strcasecmp(value[1].data, (u_char *) "on") == 0) {
! 1037: *fp = 1;
! 1038:
! 1039: } else if (ngx_strcasecmp(value[1].data, (u_char *) "off") == 0) {
! 1040: *fp = 0;
! 1041:
! 1042: } else {
! 1043: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 1044: "invalid value \"%s\" in \"%s\" directive, "
! 1045: "it must be \"on\" or \"off\"",
! 1046: value[1].data, cmd->name.data);
! 1047: return NGX_CONF_ERROR;
! 1048: }
! 1049:
! 1050: if (cmd->post) {
! 1051: post = cmd->post;
! 1052: return post->post_handler(cf, post, fp);
! 1053: }
! 1054:
! 1055: return NGX_CONF_OK;
! 1056: }
! 1057:
! 1058:
! 1059: char *
! 1060: ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1061: {
! 1062: char *p = conf;
! 1063:
! 1064: ngx_str_t *field, *value;
! 1065: ngx_conf_post_t *post;
! 1066:
! 1067: field = (ngx_str_t *) (p + cmd->offset);
! 1068:
! 1069: if (field->data) {
! 1070: return "is duplicate";
! 1071: }
! 1072:
! 1073: value = cf->args->elts;
! 1074:
! 1075: *field = value[1];
! 1076:
! 1077: if (cmd->post) {
! 1078: post = cmd->post;
! 1079: return post->post_handler(cf, post, field);
! 1080: }
! 1081:
! 1082: return NGX_CONF_OK;
! 1083: }
! 1084:
! 1085:
! 1086: char *
! 1087: ngx_conf_set_str_array_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1088: {
! 1089: char *p = conf;
! 1090:
! 1091: ngx_str_t *value, *s;
! 1092: ngx_array_t **a;
! 1093: ngx_conf_post_t *post;
! 1094:
! 1095: a = (ngx_array_t **) (p + cmd->offset);
! 1096:
! 1097: if (*a == NGX_CONF_UNSET_PTR) {
! 1098: *a = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
! 1099: if (*a == NULL) {
! 1100: return NGX_CONF_ERROR;
! 1101: }
! 1102: }
! 1103:
! 1104: s = ngx_array_push(*a);
! 1105: if (s == NULL) {
! 1106: return NGX_CONF_ERROR;
! 1107: }
! 1108:
! 1109: value = cf->args->elts;
! 1110:
! 1111: *s = value[1];
! 1112:
! 1113: if (cmd->post) {
! 1114: post = cmd->post;
! 1115: return post->post_handler(cf, post, s);
! 1116: }
! 1117:
! 1118: return NGX_CONF_OK;
! 1119: }
! 1120:
! 1121:
! 1122: char *
! 1123: ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1124: {
! 1125: char *p = conf;
! 1126:
! 1127: ngx_str_t *value;
! 1128: ngx_array_t **a;
! 1129: ngx_keyval_t *kv;
! 1130: ngx_conf_post_t *post;
! 1131:
! 1132: a = (ngx_array_t **) (p + cmd->offset);
! 1133:
! 1134: if (*a == NULL) {
! 1135: *a = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t));
! 1136: if (*a == NULL) {
! 1137: return NGX_CONF_ERROR;
! 1138: }
! 1139: }
! 1140:
! 1141: kv = ngx_array_push(*a);
! 1142: if (kv == NULL) {
! 1143: return NGX_CONF_ERROR;
! 1144: }
! 1145:
! 1146: value = cf->args->elts;
! 1147:
! 1148: kv->key = value[1];
! 1149: kv->value = value[2];
! 1150:
! 1151: if (cmd->post) {
! 1152: post = cmd->post;
! 1153: return post->post_handler(cf, post, kv);
! 1154: }
! 1155:
! 1156: return NGX_CONF_OK;
! 1157: }
! 1158:
! 1159:
! 1160: char *
! 1161: ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1162: {
! 1163: char *p = conf;
! 1164:
! 1165: ngx_int_t *np;
! 1166: ngx_str_t *value;
! 1167: ngx_conf_post_t *post;
! 1168:
! 1169:
! 1170: np = (ngx_int_t *) (p + cmd->offset);
! 1171:
! 1172: if (*np != NGX_CONF_UNSET) {
! 1173: return "is duplicate";
! 1174: }
! 1175:
! 1176: value = cf->args->elts;
! 1177: *np = ngx_atoi(value[1].data, value[1].len);
! 1178: if (*np == NGX_ERROR) {
! 1179: return "invalid number";
! 1180: }
! 1181:
! 1182: if (cmd->post) {
! 1183: post = cmd->post;
! 1184: return post->post_handler(cf, post, np);
! 1185: }
! 1186:
! 1187: return NGX_CONF_OK;
! 1188: }
! 1189:
! 1190:
! 1191: char *
! 1192: ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1193: {
! 1194: char *p = conf;
! 1195:
! 1196: size_t *sp;
! 1197: ngx_str_t *value;
! 1198: ngx_conf_post_t *post;
! 1199:
! 1200:
! 1201: sp = (size_t *) (p + cmd->offset);
! 1202: if (*sp != NGX_CONF_UNSET_SIZE) {
! 1203: return "is duplicate";
! 1204: }
! 1205:
! 1206: value = cf->args->elts;
! 1207:
! 1208: *sp = ngx_parse_size(&value[1]);
! 1209: if (*sp == (size_t) NGX_ERROR) {
! 1210: return "invalid value";
! 1211: }
! 1212:
! 1213: if (cmd->post) {
! 1214: post = cmd->post;
! 1215: return post->post_handler(cf, post, sp);
! 1216: }
! 1217:
! 1218: return NGX_CONF_OK;
! 1219: }
! 1220:
! 1221:
! 1222: char *
! 1223: ngx_conf_set_off_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1224: {
! 1225: char *p = conf;
! 1226:
! 1227: off_t *op;
! 1228: ngx_str_t *value;
! 1229: ngx_conf_post_t *post;
! 1230:
! 1231:
! 1232: op = (off_t *) (p + cmd->offset);
! 1233: if (*op != NGX_CONF_UNSET) {
! 1234: return "is duplicate";
! 1235: }
! 1236:
! 1237: value = cf->args->elts;
! 1238:
! 1239: *op = ngx_parse_offset(&value[1]);
! 1240: if (*op == (off_t) NGX_ERROR) {
! 1241: return "invalid value";
! 1242: }
! 1243:
! 1244: if (cmd->post) {
! 1245: post = cmd->post;
! 1246: return post->post_handler(cf, post, op);
! 1247: }
! 1248:
! 1249: return NGX_CONF_OK;
! 1250: }
! 1251:
! 1252:
! 1253: char *
! 1254: ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1255: {
! 1256: char *p = conf;
! 1257:
! 1258: ngx_msec_t *msp;
! 1259: ngx_str_t *value;
! 1260: ngx_conf_post_t *post;
! 1261:
! 1262:
! 1263: msp = (ngx_msec_t *) (p + cmd->offset);
! 1264: if (*msp != NGX_CONF_UNSET_MSEC) {
! 1265: return "is duplicate";
! 1266: }
! 1267:
! 1268: value = cf->args->elts;
! 1269:
! 1270: *msp = ngx_parse_time(&value[1], 0);
! 1271: if (*msp == (ngx_msec_t) NGX_ERROR) {
! 1272: return "invalid value";
! 1273: }
! 1274:
! 1275: if (cmd->post) {
! 1276: post = cmd->post;
! 1277: return post->post_handler(cf, post, msp);
! 1278: }
! 1279:
! 1280: return NGX_CONF_OK;
! 1281: }
! 1282:
! 1283:
! 1284: char *
! 1285: ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1286: {
! 1287: char *p = conf;
! 1288:
! 1289: time_t *sp;
! 1290: ngx_str_t *value;
! 1291: ngx_conf_post_t *post;
! 1292:
! 1293:
! 1294: sp = (time_t *) (p + cmd->offset);
! 1295: if (*sp != NGX_CONF_UNSET) {
! 1296: return "is duplicate";
! 1297: }
! 1298:
! 1299: value = cf->args->elts;
! 1300:
! 1301: *sp = ngx_parse_time(&value[1], 1);
! 1302: if (*sp == (time_t) NGX_ERROR) {
! 1303: return "invalid value";
! 1304: }
! 1305:
! 1306: if (cmd->post) {
! 1307: post = cmd->post;
! 1308: return post->post_handler(cf, post, sp);
! 1309: }
! 1310:
! 1311: return NGX_CONF_OK;
! 1312: }
! 1313:
! 1314:
! 1315: char *
! 1316: ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1317: {
! 1318: char *p = conf;
! 1319:
! 1320: ngx_str_t *value;
! 1321: ngx_bufs_t *bufs;
! 1322:
! 1323:
! 1324: bufs = (ngx_bufs_t *) (p + cmd->offset);
! 1325: if (bufs->num) {
! 1326: return "is duplicate";
! 1327: }
! 1328:
! 1329: value = cf->args->elts;
! 1330:
! 1331: bufs->num = ngx_atoi(value[1].data, value[1].len);
! 1332: if (bufs->num == NGX_ERROR || bufs->num == 0) {
! 1333: return "invalid value";
! 1334: }
! 1335:
! 1336: bufs->size = ngx_parse_size(&value[2]);
! 1337: if (bufs->size == (size_t) NGX_ERROR || bufs->size == 0) {
! 1338: return "invalid value";
! 1339: }
! 1340:
! 1341: return NGX_CONF_OK;
! 1342: }
! 1343:
! 1344:
! 1345: char *
! 1346: ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1347: {
! 1348: char *p = conf;
! 1349:
! 1350: ngx_uint_t *np, i;
! 1351: ngx_str_t *value;
! 1352: ngx_conf_enum_t *e;
! 1353:
! 1354: np = (ngx_uint_t *) (p + cmd->offset);
! 1355:
! 1356: if (*np != NGX_CONF_UNSET_UINT) {
! 1357: return "is duplicate";
! 1358: }
! 1359:
! 1360: value = cf->args->elts;
! 1361: e = cmd->post;
! 1362:
! 1363: for (i = 0; e[i].name.len != 0; i++) {
! 1364: if (e[i].name.len != value[1].len
! 1365: || ngx_strcasecmp(e[i].name.data, value[1].data) != 0)
! 1366: {
! 1367: continue;
! 1368: }
! 1369:
! 1370: *np = e[i].value;
! 1371:
! 1372: return NGX_CONF_OK;
! 1373: }
! 1374:
! 1375: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
! 1376: "invalid value \"%s\"", value[1].data);
! 1377:
! 1378: return NGX_CONF_ERROR;
! 1379: }
! 1380:
! 1381:
! 1382: char *
! 1383: ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1384: {
! 1385: char *p = conf;
! 1386:
! 1387: ngx_uint_t *np, i, m;
! 1388: ngx_str_t *value;
! 1389: ngx_conf_bitmask_t *mask;
! 1390:
! 1391:
! 1392: np = (ngx_uint_t *) (p + cmd->offset);
! 1393: value = cf->args->elts;
! 1394: mask = cmd->post;
! 1395:
! 1396: for (i = 1; i < cf->args->nelts; i++) {
! 1397: for (m = 0; mask[m].name.len != 0; m++) {
! 1398:
! 1399: if (mask[m].name.len != value[i].len
! 1400: || ngx_strcasecmp(mask[m].name.data, value[i].data) != 0)
! 1401: {
! 1402: continue;
! 1403: }
! 1404:
! 1405: if (*np & mask[m].mask) {
! 1406: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
! 1407: "duplicate value \"%s\"", value[i].data);
! 1408:
! 1409: } else {
! 1410: *np |= mask[m].mask;
! 1411: }
! 1412:
! 1413: break;
! 1414: }
! 1415:
! 1416: if (mask[m].name.len == 0) {
! 1417: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
! 1418: "invalid value \"%s\"", value[i].data);
! 1419:
! 1420: return NGX_CONF_ERROR;
! 1421: }
! 1422: }
! 1423:
! 1424: return NGX_CONF_OK;
! 1425: }
! 1426:
! 1427:
! 1428: #if 0
! 1429:
! 1430: char *
! 1431: ngx_conf_unsupported(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 1432: {
! 1433: return "unsupported on this platform";
! 1434: }
! 1435:
! 1436: #endif
! 1437:
! 1438:
! 1439: char *
! 1440: ngx_conf_deprecated(ngx_conf_t *cf, void *post, void *data)
! 1441: {
! 1442: ngx_conf_deprecated_t *d = post;
! 1443:
! 1444: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
! 1445: "the \"%s\" directive is deprecated, "
! 1446: "use the \"%s\" directive instead",
! 1447: d->old_name, d->new_name);
! 1448:
! 1449: return NGX_CONF_OK;
! 1450: }
! 1451:
! 1452:
! 1453: char *
! 1454: ngx_conf_check_num_bounds(ngx_conf_t *cf, void *post, void *data)
! 1455: {
! 1456: ngx_conf_num_bounds_t *bounds = post;
! 1457: ngx_int_t *np = data;
! 1458:
! 1459: if (bounds->high == -1) {
! 1460: if (*np >= bounds->low) {
! 1461: return NGX_CONF_OK;
! 1462: }
! 1463:
! 1464: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 1465: "value must be equal to or greater than %i",
! 1466: bounds->low);
! 1467:
! 1468: return NGX_CONF_ERROR;
! 1469: }
! 1470:
! 1471: if (*np >= bounds->low && *np <= bounds->high) {
! 1472: return NGX_CONF_OK;
! 1473: }
! 1474:
! 1475: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 1476: "value must be between %i and %i",
! 1477: bounds->low, bounds->high);
! 1478:
! 1479: return NGX_CONF_ERROR;
! 1480: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>