1 /* $NetBSD: ntp_scanner.c,v 1.13 2018/04/07 00:19:53 christos Exp $ */ 2 3 4 /* ntp_scanner.c 5 * 6 * The source code for a simple lexical analyzer. 7 * 8 * Written By: Sachin Kamboj 9 * University of Delaware 10 * Newark, DE 19711 11 * Copyright (c) 2006 12 */ 13 14 #ifdef HAVE_CONFIG_H 15 # include <config.h> 16 #endif 17 18 #include <stdio.h> 19 #include <ctype.h> 20 #include <stdlib.h> 21 #include <errno.h> 22 #include <string.h> 23 24 #include "ntpd.h" 25 #include "ntp_config.h" 26 #include "ntpsim.h" 27 #include "ntp_scanner.h" 28 #include "ntp_parser.h" 29 30 /* ntp_keyword.h declares finite state machine and token text */ 31 #include "ntp_keyword.h" 32 33 34 35 /* SCANNER GLOBAL VARIABLES 36 * ------------------------ 37 */ 38 39 #define MAX_LEXEME (1024 + 1) /* The maximum size of a lexeme */ 40 char yytext[MAX_LEXEME]; /* Buffer for storing the input text/lexeme */ 41 u_int32 conf_file_sum; /* Simple sum of characters read */ 42 43 static struct FILE_INFO * lex_stack = NULL; 44 45 46 47 /* CONSTANTS 48 * --------- 49 */ 50 51 52 /* SCANNER GLOBAL VARIABLES 53 * ------------------------ 54 */ 55 const char special_chars[] = "{}(),;|="; 56 57 58 /* FUNCTIONS 59 * --------- 60 */ 61 62 static int is_keyword(char *lexeme, follby *pfollowedby); 63 64 65 /* 66 * keyword() - Return the keyword associated with token T_ identifier. 67 * See also token_name() for the string-ized T_ identifier. 68 * Example: keyword(T_Server) returns "server" 69 * token_name(T_Server) returns "T_Server" 70 */ 71 const char * 72 keyword( 73 int token 74 ) 75 { 76 size_t i; 77 const char *text; 78 79 i = token - LOWEST_KEYWORD_ID; 80 81 if (i < COUNTOF(keyword_text)) 82 text = keyword_text[i]; 83 else 84 text = NULL; 85 86 return (text != NULL) 87 ? text 88 : "(keyword not found)"; 89 } 90 91 92 /* FILE & STRING BUFFER INTERFACE 93 * ------------------------------ 94 * 95 * This set out as a couple of wrapper functions around the standard C 96 * fgetc and ungetc functions in order to include positional 97 * bookkeeping. Alas, this is no longer a good solution with nested 98 * input files and the possibility to send configuration commands via 99 * 'ntpdc' and 'ntpq'. 100 * 101 * Now there are a few functions to maintain a stack of nested input 102 * sources (though nesting is only allowd for disk files) and from the 103 * scanner / parser point of view there's no difference between both 104 * types of sources. 105 * 106 * The 'fgetc()' / 'ungetc()' replacements now operate on a FILE_INFO 107 * structure. Instead of trying different 'ungetc()' strategies for file 108 * and buffer based parsing, we keep the backup char in our own 109 * FILE_INFO structure. This is sufficient, as the parser does *not* 110 * jump around via 'seek' or the like, and there's no need to 111 * check/clear the backup store in other places than 'lex_getch()'. 112 */ 113 114 /* 115 * Allocate an info structure and attach it to a file. 116 * 117 * Note: When 'mode' is NULL, then the INFO block will be set up to 118 * contain a NULL file pointer, as suited for remote config command 119 * parsing. Otherwise having a NULL file pointer is considered an error, 120 * and a NULL info block pointer is returned to indicate failure! 121 * 122 * Note: We use a variable-sized structure to hold a copy of the file 123 * name (or, more proper, the input source description). This is more 124 * secure than keeping a reference to some other storage that might go 125 * out of scope. 126 */ 127 static struct FILE_INFO * 128 lex_open( 129 const char *path, 130 const char *mode 131 ) 132 { 133 struct FILE_INFO *stream; 134 size_t nnambuf; 135 136 nnambuf = strlen(path); 137 stream = emalloc_zero(sizeof(*stream) + nnambuf); 138 stream->curpos.nline = 1; 139 stream->backch = EOF; 140 /* copy name with memcpy -- trailing NUL already there! */ 141 memcpy(stream->fname, path, nnambuf); 142 143 if (NULL != mode) { 144 stream->fpi = fopen(path, mode); 145 if (NULL == stream->fpi) { 146 free(stream); 147 stream = NULL; 148 } 149 } 150 return stream; 151 } 152 153 /* get next character from buffer or file. This will return any putback 154 * character first; it will also make sure the last line is at least 155 * virtually terminated with a '\n'. 156 */ 157 static int 158 lex_getch( 159 struct FILE_INFO *stream 160 ) 161 { 162 int ch; 163 164 if (NULL == stream || stream->force_eof) 165 return EOF; 166 167 if (EOF != stream->backch) { 168 ch = stream->backch; 169 stream->backch = EOF; 170 if (stream->fpi) 171 conf_file_sum += ch; 172 stream->curpos.ncol++; 173 } else if (stream->fpi) { 174 /* fetch next 7-bit ASCII char (or EOF) from file */ 175 while ((ch = fgetc(stream->fpi)) != EOF && ch > SCHAR_MAX) 176 stream->curpos.ncol++; 177 if (EOF != ch) { 178 conf_file_sum += ch; 179 stream->curpos.ncol++; 180 } 181 } else { 182 /* fetch next 7-bit ASCII char from buffer */ 183 const char * scan; 184 scan = &remote_config.buffer[remote_config.pos]; 185 while ((ch = (u_char)*scan) > SCHAR_MAX) { 186 scan++; 187 stream->curpos.ncol++; 188 } 189 if ('\0' != ch) { 190 scan++; 191 stream->curpos.ncol++; 192 } else { 193 ch = EOF; 194 } 195 remote_config.pos = (int)(scan - remote_config.buffer); 196 } 197 198 /* If the last line ends without '\n', generate one. This 199 * happens most likely on Windows, where editors often have a 200 * sloppy concept of a line. 201 */ 202 if (EOF == ch && stream->curpos.ncol != 0) 203 ch = '\n'; 204 205 /* update scan position tallies */ 206 if (ch == '\n') { 207 stream->bakpos = stream->curpos; 208 stream->curpos.nline++; 209 stream->curpos.ncol = 0; 210 } 211 212 return ch; 213 } 214 215 /* Note: lex_ungetch will fail to track more than one line of push 216 * back. But since it guarantees only one char of back storage anyway, 217 * this should not be a problem. 218 */ 219 static int 220 lex_ungetch( 221 int ch, 222 struct FILE_INFO *stream 223 ) 224 { 225 /* check preconditions */ 226 if (NULL == stream || stream->force_eof) 227 return EOF; 228 if (EOF != stream->backch || EOF == ch) 229 return EOF; 230 231 /* keep for later reference and update checksum */ 232 stream->backch = (u_char)ch; 233 if (stream->fpi) 234 conf_file_sum -= stream->backch; 235 236 /* update position */ 237 if (stream->backch == '\n') { 238 stream->curpos = stream->bakpos; 239 stream->bakpos.ncol = -1; 240 } 241 stream->curpos.ncol--; 242 return stream->backch; 243 } 244 245 /* dispose of an input structure. If the file pointer is not NULL, close 246 * the file. This function does not check the result of 'fclose()'. 247 */ 248 static void 249 lex_close( 250 struct FILE_INFO *stream 251 ) 252 { 253 if (NULL != stream) { 254 if (NULL != stream->fpi) 255 fclose(stream->fpi); 256 free(stream); 257 } 258 } 259 260 /* INPUT STACK 261 * ----------- 262 * 263 * Nested input sources are a bit tricky at first glance. We deal with 264 * this problem using a stack of input sources, that is, a forward 265 * linked list of FILE_INFO structs. 266 * 267 * This stack is never empty during parsing; while an encounter with EOF 268 * can and will remove nested input sources, removing the last element 269 * in the stack will not work during parsing, and the EOF condition of 270 * the outermost input file remains until the parser folds up. 271 */ 272 273 static struct FILE_INFO * 274 _drop_stack_do( 275 struct FILE_INFO * head 276 ) 277 { 278 struct FILE_INFO * tail; 279 while (NULL != head) { 280 tail = head->st_next; 281 lex_close(head); 282 head = tail; 283 } 284 return head; 285 } 286 287 288 289 /* Create a singleton input source on an empty lexer stack. This will 290 * fail if there is already an input source, or if the underlying disk 291 * file cannot be opened. 292 * 293 * Returns TRUE if a new input object was successfully created. 294 */ 295 int/*BOOL*/ 296 lex_init_stack( 297 const char * path, 298 const char * mode 299 ) 300 { 301 if (NULL != lex_stack || NULL == path) 302 return FALSE; 303 304 lex_stack = lex_open(path, mode); 305 return (NULL != lex_stack); 306 } 307 308 /* This removes *all* input sources from the stack, leaving the head 309 * pointer as NULL. Any attempt to parse in that state is likely to bomb 310 * with segmentation faults or the like. 311 * 312 * In other words: Use this to clean up after parsing, and do not parse 313 * anything until the next 'lex_init_stack()' succeeded. 314 */ 315 void 316 lex_drop_stack() 317 { 318 lex_stack = _drop_stack_do(lex_stack); 319 } 320 321 /* Flush the lexer input stack: This will nip all input objects on the 322 * stack (but keeps the current top-of-stack) and marks the top-of-stack 323 * as inactive. Any further calls to lex_getch yield only EOF, and it's 324 * no longer possible to push something back. 325 * 326 * Returns TRUE if there is a head element (top-of-stack) that was not 327 * in the force-eof mode before this call. 328 */ 329 int/*BOOL*/ 330 lex_flush_stack() 331 { 332 int retv = FALSE; 333 334 if (NULL != lex_stack) { 335 retv = !lex_stack->force_eof; 336 lex_stack->force_eof = TRUE; 337 lex_stack->st_next = _drop_stack_do( 338 lex_stack->st_next); 339 } 340 return retv; 341 } 342 343 /* Push another file on the parsing stack. If the mode is NULL, create a 344 * FILE_INFO suitable for in-memory parsing; otherwise, create a 345 * FILE_INFO that is bound to a local/disc file. Note that 'path' must 346 * not be NULL, or the function will fail. 347 * 348 * Returns TRUE if a new info record was pushed onto the stack. 349 */ 350 int/*BOOL*/ lex_push_file( 351 const char * path, 352 const char * mode 353 ) 354 { 355 struct FILE_INFO * next = NULL; 356 357 if (NULL != path) { 358 next = lex_open(path, mode); 359 if (NULL != next) { 360 next->st_next = lex_stack; 361 lex_stack = next; 362 } 363 } 364 return (NULL != next); 365 } 366 367 /* Pop, close & free the top of the include stack, unless the stack 368 * contains only a singleton input object. In that case the function 369 * fails, because the parser does not expect the input stack to be 370 * empty. 371 * 372 * Returns TRUE if an object was successfuly popped from the stack. 373 */ 374 int/*BOOL*/ 375 lex_pop_file(void) 376 { 377 struct FILE_INFO * head = lex_stack; 378 struct FILE_INFO * tail = NULL; 379 380 if (NULL != head) { 381 tail = head->st_next; 382 if (NULL != tail) { 383 lex_stack = tail; 384 lex_close(head); 385 } 386 } 387 return (NULL != tail); 388 } 389 390 /* Get include nesting level. This currently loops over the stack and 391 * counts elements; but since this is of concern only with an include 392 * statement and the nesting depth has a small limit, there's no 393 * bottleneck expected here. 394 * 395 * Returns the nesting level of includes, that is, the current depth of 396 * the lexer input stack. 397 * 398 * Note: 399 */ 400 size_t 401 lex_level(void) 402 { 403 size_t cnt = 0; 404 struct FILE_INFO *ipf = lex_stack; 405 406 while (NULL != ipf) { 407 cnt++; 408 ipf = ipf->st_next; 409 } 410 return cnt; 411 } 412 413 /* check if the current input is from a file */ 414 int/*BOOL*/ 415 lex_from_file(void) 416 { 417 return (NULL != lex_stack) && (NULL != lex_stack->fpi); 418 } 419 420 struct FILE_INFO * 421 lex_current() 422 { 423 /* this became so simple, it could be a macro. But then, 424 * lex_stack needed to be global... 425 */ 426 return lex_stack; 427 } 428 429 430 /* STATE MACHINES 431 * -------------- 432 */ 433 434 /* Keywords */ 435 static int 436 is_keyword( 437 char *lexeme, 438 follby *pfollowedby 439 ) 440 { 441 follby fb; 442 int curr_s; /* current state index */ 443 int token; 444 int i; 445 446 curr_s = SCANNER_INIT_S; 447 token = 0; 448 449 for (i = 0; lexeme[i]; i++) { 450 while (curr_s && (lexeme[i] != SS_CH(sst[curr_s]))) 451 curr_s = SS_OTHER_N(sst[curr_s]); 452 453 if (curr_s && (lexeme[i] == SS_CH(sst[curr_s]))) { 454 if ('\0' == lexeme[i + 1] 455 && FOLLBY_NON_ACCEPTING 456 != SS_FB(sst[curr_s])) { 457 fb = SS_FB(sst[curr_s]); 458 *pfollowedby = fb; 459 token = curr_s; 460 break; 461 } 462 curr_s = SS_MATCH_N(sst[curr_s]); 463 } else 464 break; 465 } 466 467 return token; 468 } 469 470 471 /* Integer */ 472 static int 473 is_integer( 474 char *lexeme 475 ) 476 { 477 int i; 478 int is_neg; 479 u_int u_val; 480 481 i = 0; 482 483 /* Allow a leading minus sign */ 484 if (lexeme[i] == '-') { 485 i++; 486 is_neg = TRUE; 487 } else { 488 is_neg = FALSE; 489 } 490 491 /* Check that all the remaining characters are digits */ 492 for (; lexeme[i] != '\0'; i++) { 493 if (!isdigit((u_char)lexeme[i])) 494 return FALSE; 495 } 496 497 if (is_neg) 498 return TRUE; 499 500 /* Reject numbers that fit in unsigned but not in signed int */ 501 if (1 == sscanf(lexeme, "%u", &u_val)) 502 return (u_val <= INT_MAX); 503 else 504 return FALSE; 505 } 506 507 508 /* U_int -- assumes is_integer() has returned FALSE */ 509 static int 510 is_u_int( 511 char *lexeme 512 ) 513 { 514 int i; 515 int is_hex; 516 517 i = 0; 518 if ('0' == lexeme[i] && 'x' == tolower((u_char)lexeme[i + 1])) { 519 i += 2; 520 is_hex = TRUE; 521 } else { 522 is_hex = FALSE; 523 } 524 525 /* Check that all the remaining characters are digits */ 526 for (; lexeme[i] != '\0'; i++) { 527 if (is_hex && !isxdigit((u_char)lexeme[i])) 528 return FALSE; 529 if (!is_hex && !isdigit((u_char)lexeme[i])) 530 return FALSE; 531 } 532 533 return TRUE; 534 } 535 536 537 /* Double */ 538 static int 539 is_double( 540 char *lexeme 541 ) 542 { 543 u_int num_digits = 0; /* Number of digits read */ 544 u_int i; 545 546 i = 0; 547 548 /* Check for an optional '+' or '-' */ 549 if ('+' == lexeme[i] || '-' == lexeme[i]) 550 i++; 551 552 /* Read the integer part */ 553 for (; lexeme[i] && isdigit((u_char)lexeme[i]); i++) 554 num_digits++; 555 556 /* Check for the optional decimal point */ 557 if ('.' == lexeme[i]) { 558 i++; 559 /* Check for any digits after the decimal point */ 560 for (; lexeme[i] && isdigit((u_char)lexeme[i]); i++) 561 num_digits++; 562 } 563 564 /* 565 * The number of digits in both the decimal part and the 566 * fraction part must not be zero at this point 567 */ 568 if (!num_digits) 569 return 0; 570 571 /* Check if we are done */ 572 if (!lexeme[i]) 573 return 1; 574 575 /* There is still more input, read the exponent */ 576 if ('e' == tolower((u_char)lexeme[i])) 577 i++; 578 else 579 return 0; 580 581 /* Read an optional Sign */ 582 if ('+' == lexeme[i] || '-' == lexeme[i]) 583 i++; 584 585 /* Now read the exponent part */ 586 while (lexeme[i] && isdigit((u_char)lexeme[i])) 587 i++; 588 589 /* Check if we are done */ 590 if (!lexeme[i]) 591 return 1; 592 else 593 return 0; 594 } 595 596 597 /* is_special() - Test whether a character is a token */ 598 static inline int 599 is_special( 600 int ch 601 ) 602 { 603 return strchr(special_chars, ch) != NULL; 604 } 605 606 607 static int 608 is_EOC( 609 int ch 610 ) 611 { 612 if ((old_config_style && (ch == '\n')) || 613 (!old_config_style && (ch == ';'))) 614 return 1; 615 return 0; 616 } 617 618 619 char * 620 quote_if_needed(char *str) 621 { 622 char *ret; 623 size_t len; 624 size_t octets; 625 626 len = strlen(str); 627 octets = len + 2 + 1; 628 ret = emalloc(octets); 629 if ('"' != str[0] 630 && (strcspn(str, special_chars) < len 631 || strchr(str, ' ') != NULL)) { 632 snprintf(ret, octets, "\"%s\"", str); 633 } else 634 strlcpy(ret, str, octets); 635 636 return ret; 637 } 638 639 640 static int 641 create_string_token( 642 char *lexeme 643 ) 644 { 645 char *pch; 646 647 /* 648 * ignore end of line whitespace 649 */ 650 pch = lexeme; 651 while (*pch && isspace((u_char)*pch)) 652 pch++; 653 654 if (!*pch) { 655 yylval.Integer = T_EOC; 656 return yylval.Integer; 657 } 658 659 yylval.String = estrdup(lexeme); 660 return T_String; 661 } 662 663 664 /* 665 * yylex() - function that does the actual scanning. 666 * Bison expects this function to be called yylex and for it to take no 667 * input and return an int. 668 * Conceptually yylex "returns" yylval as well as the actual return 669 * value representing the token or type. 670 */ 671 int 672 yylex(void) 673 { 674 static follby followedby = FOLLBY_TOKEN; 675 size_t i; 676 int instring; 677 int yylval_was_set; 678 int converted; 679 int token; /* The return value */ 680 int ch; 681 682 instring = FALSE; 683 yylval_was_set = FALSE; 684 685 do { 686 /* Ignore whitespace at the beginning */ 687 while (EOF != (ch = lex_getch(lex_stack)) && 688 isspace(ch) && 689 !is_EOC(ch)) 690 691 ; /* Null Statement */ 692 693 if (EOF == ch) { 694 695 if ( ! lex_pop_file()) 696 return 0; 697 token = T_EOC; 698 goto normal_return; 699 700 } else if (is_EOC(ch)) { 701 702 /* end FOLLBY_STRINGS_TO_EOC effect */ 703 followedby = FOLLBY_TOKEN; 704 token = T_EOC; 705 goto normal_return; 706 707 } else if (is_special(ch) && FOLLBY_TOKEN == followedby) { 708 /* special chars are their own token values */ 709 token = ch; 710 /* 711 * '=' outside simulator configuration implies 712 * a single string following as in: 713 * setvar Owner = "The Boss" default 714 */ 715 if ('=' == ch && old_config_style) 716 followedby = FOLLBY_STRING; 717 yytext[0] = (char)ch; 718 yytext[1] = '\0'; 719 goto normal_return; 720 } else 721 lex_ungetch(ch, lex_stack); 722 723 /* save the position of start of the token */ 724 lex_stack->tokpos = lex_stack->curpos; 725 726 /* Read in the lexeme */ 727 i = 0; 728 while (EOF != (ch = lex_getch(lex_stack))) { 729 730 yytext[i] = (char)ch; 731 732 /* Break on whitespace or a special character */ 733 if (isspace(ch) || is_EOC(ch) 734 || '"' == ch 735 || (FOLLBY_TOKEN == followedby 736 && is_special(ch))) 737 break; 738 739 /* Read the rest of the line on reading a start 740 of comment character */ 741 if ('#' == ch) { 742 while (EOF != (ch = lex_getch(lex_stack)) 743 && '\n' != ch) 744 ; /* Null Statement */ 745 break; 746 } 747 748 i++; 749 if (i >= COUNTOF(yytext)) 750 goto lex_too_long; 751 } 752 /* Pick up all of the string inside between " marks, to 753 * end of line. If we make it to EOL without a 754 * terminating " assume it for them. 755 * 756 * XXX - HMS: I'm not sure we want to assume the closing " 757 */ 758 if ('"' == ch) { 759 instring = TRUE; 760 while (EOF != (ch = lex_getch(lex_stack)) && 761 ch != '"' && ch != '\n') { 762 yytext[i++] = (char)ch; 763 if (i >= COUNTOF(yytext)) 764 goto lex_too_long; 765 } 766 /* 767 * yytext[i] will be pushed back as not part of 768 * this lexeme, but any closing quote should 769 * not be pushed back, so we read another char. 770 */ 771 if ('"' == ch) 772 ch = lex_getch(lex_stack); 773 } 774 /* Pushback the last character read that is not a part 775 * of this lexeme. This fails silently if ch is EOF, 776 * but then the EOF condition persists and is handled on 777 * the next turn by the include stack mechanism. 778 */ 779 lex_ungetch(ch, lex_stack); 780 781 yytext[i] = '\0'; 782 } while (i == 0); 783 784 /* Now return the desired token */ 785 786 /* First make sure that the parser is *not* expecting a string 787 * as the next token (based on the previous token that was 788 * returned) and that we haven't read a string. 789 */ 790 791 if (followedby == FOLLBY_TOKEN && !instring) { 792 token = is_keyword(yytext, &followedby); 793 if (token) { 794 /* 795 * T_Server is exceptional as it forces the 796 * following token to be a string in the 797 * non-simulator parts of the configuration, 798 * but in the simulator configuration section, 799 * "server" is followed by "=" which must be 800 * recognized as a token not a string. 801 */ 802 if (T_Server == token && !old_config_style) 803 followedby = FOLLBY_TOKEN; 804 goto normal_return; 805 } else if (is_integer(yytext)) { 806 yylval_was_set = TRUE; 807 errno = 0; 808 if ((yylval.Integer = strtol(yytext, NULL, 10)) == 0 809 && ((errno == EINVAL) || (errno == ERANGE))) { 810 msyslog(LOG_ERR, 811 "Integer cannot be represented: %s", 812 yytext); 813 if (lex_from_file()) { 814 exit(1); 815 } else { 816 /* force end of parsing */ 817 yylval.Integer = 0; 818 return 0; 819 } 820 } 821 token = T_Integer; 822 goto normal_return; 823 } else if (is_u_int(yytext)) { 824 yylval_was_set = TRUE; 825 if ('0' == yytext[0] && 826 'x' == tolower((unsigned long)yytext[1])) 827 converted = sscanf(&yytext[2], "%x", 828 &yylval.U_int); 829 else 830 converted = sscanf(yytext, "%u", 831 &yylval.U_int); 832 if (1 != converted) { 833 msyslog(LOG_ERR, 834 "U_int cannot be represented: %s", 835 yytext); 836 if (lex_from_file()) { 837 exit(1); 838 } else { 839 /* force end of parsing */ 840 yylval.Integer = 0; 841 return 0; 842 } 843 } 844 token = T_U_int; 845 goto normal_return; 846 } else if (is_double(yytext)) { 847 yylval_was_set = TRUE; 848 errno = 0; 849 if ((yylval.Double = atof(yytext)) == 0 && errno == ERANGE) { 850 msyslog(LOG_ERR, 851 "Double too large to represent: %s", 852 yytext); 853 exit(1); 854 } else { 855 token = T_Double; 856 goto normal_return; 857 } 858 } else { 859 /* Default: Everything is a string */ 860 yylval_was_set = TRUE; 861 token = create_string_token(yytext); 862 goto normal_return; 863 } 864 } 865 866 /* 867 * Either followedby is not FOLLBY_TOKEN or this lexeme is part 868 * of a string. Hence, we need to return T_String. 869 * 870 * _Except_ we might have a -4 or -6 flag on a an association 871 * configuration line (server, peer, pool, etc.). 872 * 873 * This is a terrible hack, but the grammar is ambiguous so we 874 * don't have a choice. [SK] 875 * 876 * The ambiguity is in the keyword scanner, not ntp_parser.y. 877 * We do not require server addresses be quoted in ntp.conf, 878 * complicating the scanner's job. To avoid trying (and 879 * failing) to match an IP address or DNS name to a keyword, 880 * the association keywords use FOLLBY_STRING in the keyword 881 * table, which tells the scanner to force the next token to be 882 * a T_String, so it does not try to match a keyword but rather 883 * expects a string when -4/-6 modifiers to server, peer, etc. 884 * are encountered. 885 * restrict -4 and restrict -6 parsing works correctly without 886 * this hack, as restrict uses FOLLBY_TOKEN. [DH] 887 */ 888 if ('-' == yytext[0]) { 889 if ('4' == yytext[1]) { 890 token = T_Ipv4_flag; 891 goto normal_return; 892 } else if ('6' == yytext[1]) { 893 token = T_Ipv6_flag; 894 goto normal_return; 895 } 896 } 897 898 if (FOLLBY_STRING == followedby) 899 followedby = FOLLBY_TOKEN; 900 901 yylval_was_set = TRUE; 902 token = create_string_token(yytext); 903 904 normal_return: 905 if (T_EOC == token) 906 DPRINTF(4,("\t<end of command>\n")); 907 else 908 DPRINTF(4, ("yylex: lexeme '%s' -> %s\n", yytext, 909 token_name(token))); 910 911 if (!yylval_was_set) 912 yylval.Integer = token; 913 914 return token; 915 916 lex_too_long: 917 yytext[min(sizeof(yytext) - 1, 50)] = 0; 918 msyslog(LOG_ERR, 919 "configuration item on line %d longer than limit of %lu, began with '%s'", 920 lex_stack->curpos.nline, (u_long)min(sizeof(yytext) - 1, 50), 921 yytext); 922 923 /* 924 * If we hit the length limit reading the startup configuration 925 * file, abort. 926 */ 927 if (lex_from_file()) 928 exit(sizeof(yytext) - 1); 929 930 /* 931 * If it's runtime configuration via ntpq :config treat it as 932 * if the configuration text ended before the too-long lexeme, 933 * hostname, or string. 934 */ 935 yylval.Integer = 0; 936 return 0; 937 } 938