Return to ngx_conf_file.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / nginx / src / core |
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: }