1/*- 2 * Copyright (c) 2012-2017 Dag-Erling Sm��rgrav 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $OpenPAM: t_openpam_readword.c 938 2017-04-30 21:34:42Z des $ 30 */ 31 32#ifdef HAVE_CONFIG_H 33# include "config.h" 34#endif 35 36#include <err.h> 37#include <stdint.h> 38#include <stdio.h> 39#include <stdlib.h> 40#include <string.h> 41#include <unistd.h> 42 43#include <cryb/test.h> 44 45#include <security/pam_appl.h> 46#include <security/openpam.h> 47 48#define T_FUNC(n, d) \ 49 static const char *t_ ## n ## _desc = d; \ 50 static int t_ ## n ## _func(OPENPAM_UNUSED(char **desc), \ 51 OPENPAM_UNUSED(void *arg)) 52 53#define T(n) \ 54 t_add_test(&t_ ## n ## _func, NULL, "%s", t_ ## n ## _desc) 55 56/* 57 * Read a word from the temp file and verify that the result matches our 58 * expectations: whether a word was read at all, how many lines were read 59 * (in case of quoted or escaped newlines), whether we reached the end of 60 * the file and whether we reached the end of the line. 61 */ 62static int 63orw_expect(struct t_file *tf, const char *expected, int lines, int eof, int eol) 64{ 65 int ch, lineno = 0; 66 char *got; 67 size_t len; 68 int ret; 69 70 got = openpam_readword(tf->file, &lineno, &len); 71 ret = 1; 72 if (t_ferror(tf)) 73 err(1, "%s(): %s", __func__, tf->name); 74 if (expected != NULL && got == NULL) { 75 t_printv("expected <<%s>>, got nothing\n", expected); 76 ret = 0; 77 } else if (expected == NULL && got != NULL) { 78 t_printv("expected nothing, got <<%s>>\n", got); 79 ret = 0; 80 } else if (expected != NULL && got != NULL && strcmp(expected, got) != 0) { 81 t_printv("expected <<%s>>, got <<%s>>\n", expected, got); 82 ret = 0; 83 } 84 free(got); 85 if (lineno != lines) { 86 t_printv("expected to advance %d lines, advanced %d lines\n", 87 lines, lineno); 88 ret = 0; 89 } 90 if (eof && !t_feof(tf)) { 91 t_printv("expected EOF, but didn't get it\n"); 92 ret = 0; 93 } 94 if (!eof && t_feof(tf)) { 95 t_printv("didn't expect EOF, but got it anyway\n"); 96 ret = 0; 97 } 98 ch = fgetc(tf->file); 99 if (t_ferror(tf)) 100 err(1, "%s(): %s", __func__, tf->name); 101 if (eol && ch != '\n') { 102 t_printv("expected EOL, but didn't get it\n"); 103 ret = 0; 104 } else if (!eol && ch == '\n') { 105 t_printv("didn't expect EOL, but got it anyway\n"); 106 ret = 0; 107 } 108 if (ch != EOF) 109 ungetc(ch, tf->file); 110 return (ret); 111} 112 113 114/*************************************************************************** 115 * Lines without words 116 */ 117 118T_FUNC(empty_input, "empty input") 119{ 120 struct t_file *tf; 121 int ret; 122 123 tf = t_fopen(NULL); 124 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 125 t_fclose(tf); 126 return (ret); 127} 128 129T_FUNC(empty_line, "empty line") 130{ 131 struct t_file *tf; 132 int ret; 133 134 tf = t_fopen(NULL); 135 t_fprintf(tf, "\n"); 136 t_frewind(tf); 137 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 138 t_fclose(tf); 139 return (ret); 140} 141 142T_FUNC(unterminated_line, "unterminated line") 143{ 144 struct t_file *tf; 145 int ret; 146 147 tf = t_fopen(NULL); 148 t_fprintf(tf, " "); 149 t_frewind(tf); 150 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 151 t_fclose(tf); 152 return (ret); 153} 154 155T_FUNC(single_whitespace, "single whitespace") 156{ 157 struct t_file *tf; 158 int ret; 159 160 tf = t_fopen(NULL); 161 t_fprintf(tf, " \n"); 162 t_frewind(tf); 163 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 164 t_fclose(tf); 165 return (ret); 166} 167 168T_FUNC(multiple_whitespace, "multiple whitespace") 169{ 170 struct t_file *tf; 171 int ret; 172 173 tf = t_fopen(NULL); 174 t_fprintf(tf, " \t\r\n"); 175 t_frewind(tf); 176 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 177 t_fclose(tf); 178 return (ret); 179} 180 181T_FUNC(comment, "comment") 182{ 183 struct t_file *tf; 184 int ret; 185 186 tf = t_fopen(NULL); 187 t_fprintf(tf, "# comment\n"); 188 t_frewind(tf); 189 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 190 t_fclose(tf); 191 return (ret); 192} 193 194T_FUNC(whitespace_before_comment, "whitespace before comment") 195{ 196 struct t_file *tf; 197 int ret; 198 199 tf = t_fopen(NULL); 200 t_fprintf(tf, " # comment\n"); 201 t_frewind(tf); 202 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 203 t_fclose(tf); 204 return (ret); 205} 206 207T_FUNC(single_quoted_comment, "single-quoted comment") 208{ 209 struct t_file *tf; 210 int ret; 211 212 tf = t_fopen(NULL); 213 t_fprintf(tf, " '# comment'\n"); 214 t_frewind(tf); 215 ret = orw_expect(tf, "# comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 216 t_fclose(tf); 217 return (ret); 218} 219 220T_FUNC(double_quoted_comment, "double-quoted comment") 221{ 222 struct t_file *tf; 223 int ret; 224 225 tf = t_fopen(NULL); 226 t_fprintf(tf, " \"# comment\"\n"); 227 t_frewind(tf); 228 ret = orw_expect(tf, "# comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 229 t_fclose(tf); 230 return (ret); 231} 232 233T_FUNC(comment_at_eof, "comment at end of file") 234{ 235 struct t_file *tf; 236 int ret; 237 238 tf = t_fopen(NULL); 239 t_fprintf(tf, "# comment"); 240 t_frewind(tf); 241 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 242 t_fclose(tf); 243 return (ret); 244} 245 246 247/*************************************************************************** 248 * Simple cases - no quotes or escapes 249 */ 250 251T_FUNC(single_word, "single word") 252{ 253 const char *word = "hello"; 254 struct t_file *tf; 255 int ret; 256 257 tf = t_fopen(NULL); 258 t_fprintf(tf, "%s\n", word); 259 t_frewind(tf); 260 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 261 t_fclose(tf); 262 return (ret); 263} 264 265T_FUNC(single_whitespace_before_word, "single whitespace before word") 266{ 267 const char *word = "hello"; 268 struct t_file *tf; 269 int ret; 270 271 tf = t_fopen(NULL); 272 t_fprintf(tf, " %s\n", word); 273 t_frewind(tf); 274 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 275 t_fclose(tf); 276 return (ret); 277} 278 279T_FUNC(double_whitespace_before_word, "double whitespace before word") 280{ 281 const char *word = "hello"; 282 struct t_file *tf; 283 int ret; 284 285 tf = t_fopen(NULL); 286 t_fprintf(tf, " %s\n", word); 287 t_frewind(tf); 288 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 289 t_fclose(tf); 290 return (ret); 291} 292 293T_FUNC(single_whitespace_after_word, "single whitespace after word") 294{ 295 const char *word = "hello"; 296 struct t_file *tf; 297 int ret; 298 299 tf = t_fopen(NULL); 300 t_fprintf(tf, "%s \n", word); 301 t_frewind(tf); 302 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 303 t_fclose(tf); 304 return (ret); 305} 306 307T_FUNC(double_whitespace_after_word, "double whitespace after word") 308{ 309 const char *word = "hello"; 310 struct t_file *tf; 311 int ret; 312 313 tf = t_fopen(NULL); 314 t_fprintf(tf, "%s \n", word); 315 t_frewind(tf); 316 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 317 t_fclose(tf); 318 return (ret); 319} 320 321T_FUNC(comment_after_word, "comment after word") 322{ 323 const char *word = "hello"; 324 struct t_file *tf; 325 int ret; 326 327 tf = t_fopen(NULL); 328 t_fprintf(tf, "%s # comment\n", word); 329 t_frewind(tf); 330 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 331 orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 332 t_fclose(tf); 333 return (ret); 334} 335 336T_FUNC(word_containing_hash, "word containing hash") 337{ 338 const char *word = "hello#world"; 339 struct t_file *tf; 340 int ret; 341 342 tf = t_fopen(NULL); 343 t_fprintf(tf, "%s\n", word); 344 t_frewind(tf); 345 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 346 t_fclose(tf); 347 return (ret); 348} 349 350T_FUNC(two_words, "two words") 351{ 352 const char *word[] = { "hello", "world" }; 353 struct t_file *tf; 354 int ret; 355 356 tf = t_fopen(NULL); 357 t_fprintf(tf, "%s %s\n", word[0], word[1]); 358 t_frewind(tf); 359 ret = orw_expect(tf, word[0], 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 360 orw_expect(tf, word[1], 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 361 t_fclose(tf); 362 return (ret); 363} 364 365 366/*************************************************************************** 367 * Escapes 368 */ 369 370T_FUNC(naked_escape, "naked escape") 371{ 372 struct t_file *tf; 373 int ret; 374 375 tf = t_fopen(NULL); 376 t_fprintf(tf, "\\"); 377 t_frewind(tf); 378 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 379 t_fclose(tf); 380 return (ret); 381} 382 383T_FUNC(escaped_escape, "escaped escape") 384{ 385 struct t_file *tf; 386 int ret; 387 388 tf = t_fopen(NULL); 389 t_fprintf(tf, "\\\\\n"); 390 t_frewind(tf); 391 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 392 t_fclose(tf); 393 return (ret); 394} 395 396T_FUNC(escaped_whitespace, "escaped whitespace") 397{ 398 struct t_file *tf; 399 int ret; 400 401 tf = t_fopen(NULL); 402 t_fprintf(tf, "\\ \\\t \\\r \\\n\n"); 403 t_frewind(tf); 404 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 405 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 406 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 407 /* this last one is a line continuation */ 408 orw_expect(tf, NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 409 t_fclose(tf); 410 return (ret); 411} 412 413T_FUNC(escaped_newline_before_word, "escaped newline before word") 414{ 415 struct t_file *tf; 416 int ret; 417 418 tf = t_fopen(NULL); 419 t_fprintf(tf, "\\\nhello world\n"); 420 t_frewind(tf); 421 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 422 t_fclose(tf); 423 return (ret); 424} 425 426T_FUNC(escaped_newline_within_word, "escaped newline within word") 427{ 428 struct t_file *tf; 429 int ret; 430 431 tf = t_fopen(NULL); 432 t_fprintf(tf, "hello\\\nworld\n"); 433 t_frewind(tf); 434 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 435 t_fclose(tf); 436 return (ret); 437} 438 439T_FUNC(escaped_newline_after_word, "escaped newline after word") 440{ 441 struct t_file *tf; 442 int ret; 443 444 tf = t_fopen(NULL); 445 t_fprintf(tf, "hello\\\n world\n"); 446 t_frewind(tf); 447 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 448 t_fclose(tf); 449 return (ret); 450} 451 452T_FUNC(escaped_letter, "escaped letter") 453{ 454 struct t_file *tf; 455 int ret; 456 457 tf = t_fopen(NULL); 458 t_fprintf(tf, "\\z\n"); 459 t_frewind(tf); 460 ret = orw_expect(tf, "z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 461 t_fclose(tf); 462 return (ret); 463} 464 465T_FUNC(escaped_comment, "escaped comment") 466{ 467 struct t_file *tf; 468 int ret; 469 470 tf = t_fopen(NULL); 471 t_fprintf(tf, " \\# comment\n"); 472 t_frewind(tf); 473 ret = orw_expect(tf, "#", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 474 orw_expect(tf, "comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 475 t_fclose(tf); 476 return (ret); 477} 478 479T_FUNC(escape_at_eof, "escape at end of file") 480{ 481 struct t_file *tf; 482 int ret; 483 484 tf = t_fopen(NULL); 485 t_fprintf(tf, "z\\"); 486 t_frewind(tf); 487 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 488 t_fclose(tf); 489 return (ret); 490} 491 492 493/*************************************************************************** 494 * Quotes 495 */ 496 497T_FUNC(naked_single_quote, "naked single quote") 498{ 499 struct t_file *tf; 500 int ret; 501 502 tf = t_fopen(NULL); 503 t_fprintf(tf, "'"); 504 t_frewind(tf); 505 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 506 t_fclose(tf); 507 return (ret); 508} 509 510T_FUNC(naked_double_quote, "naked double quote") 511{ 512 struct t_file *tf; 513 int ret; 514 515 tf = t_fopen(NULL); 516 t_fprintf(tf, "\""); 517 t_frewind(tf); 518 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 519 t_fclose(tf); 520 return (ret); 521} 522 523T_FUNC(empty_single_quotes, "empty single quotes") 524{ 525 struct t_file *tf; 526 int ret; 527 528 tf = t_fopen(NULL); 529 t_fprintf(tf, "''\n"); 530 t_frewind(tf); 531 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 532 t_fclose(tf); 533 return (ret); 534} 535 536T_FUNC(empty_double_quotes, "empty double quotes") 537{ 538 struct t_file *tf; 539 int ret; 540 541 tf = t_fopen(NULL); 542 t_fprintf(tf, "\"\"\n"); 543 t_frewind(tf); 544 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 545 t_fclose(tf); 546 return (ret); 547} 548 549T_FUNC(single_quotes_within_double_quotes, "single quotes within double quotes") 550{ 551 struct t_file *tf; 552 int ret; 553 554 tf = t_fopen(NULL); 555 t_fprintf(tf, "\"' '\"\n"); 556 t_frewind(tf); 557 ret = orw_expect(tf, "' '", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 558 t_fclose(tf); 559 return (ret); 560} 561 562T_FUNC(double_quotes_within_single_quotes, "double quotes within single quotes") 563{ 564 struct t_file *tf; 565 int ret; 566 567 tf = t_fopen(NULL); 568 t_fprintf(tf, "'\" \"'\n"); 569 t_frewind(tf); 570 ret = orw_expect(tf, "\" \"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 571 t_fclose(tf); 572 return (ret); 573} 574 575T_FUNC(single_quoted_whitespace, "single-quoted whitespace") 576{ 577 struct t_file *tf; 578 int ret; 579 580 tf = t_fopen(NULL); 581 t_fprintf(tf, "' ' '\t' '\r' '\n'\n"); 582 t_frewind(tf); 583 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 584 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 585 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 586 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 587 t_fclose(tf); 588 return (ret); 589} 590 591T_FUNC(double_quoted_whitespace, "double-quoted whitespace") 592{ 593 struct t_file *tf; 594 int ret; 595 596 tf = t_fopen(NULL); 597 t_fprintf(tf, "\" \" \"\t\" \"\r\" \"\n\"\n"); 598 t_frewind(tf); 599 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 600 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 601 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 602 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 603 t_fclose(tf); 604 return (ret); 605} 606 607T_FUNC(single_quoted_words, "single-quoted words") 608{ 609 struct t_file *tf; 610 int ret; 611 612 tf = t_fopen(NULL); 613 t_fprintf(tf, "'hello world'\n"); 614 t_frewind(tf); 615 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 616 t_fclose(tf); 617 return (ret); 618} 619 620T_FUNC(double_quoted_words, "double-quoted words") 621{ 622 struct t_file *tf; 623 int ret; 624 625 tf = t_fopen(NULL); 626 t_fprintf(tf, "\"hello world\"\n"); 627 t_frewind(tf); 628 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 629 t_fclose(tf); 630 return (ret); 631} 632 633 634/*************************************************************************** 635 * Combinations of quoted and unquoted text 636 */ 637 638T_FUNC(single_quote_before_word, "single quote before word") 639{ 640 struct t_file *tf; 641 int ret; 642 643 tf = t_fopen(NULL); 644 t_fprintf(tf, "'hello 'world\n"); 645 t_frewind(tf); 646 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 647 t_fclose(tf); 648 return (ret); 649} 650 651T_FUNC(double_quote_before_word, "double quote before word") 652{ 653 struct t_file *tf; 654 int ret; 655 656 tf = t_fopen(NULL); 657 t_fprintf(tf, "\"hello \"world\n"); 658 t_frewind(tf); 659 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 660 t_fclose(tf); 661 return (ret); 662} 663 664T_FUNC(single_quote_within_word, "single quote within word") 665{ 666 struct t_file *tf; 667 int ret; 668 669 tf = t_fopen(NULL); 670 t_fprintf(tf, "hello' 'world\n"); 671 t_frewind(tf); 672 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 673 t_fclose(tf); 674 return (ret); 675} 676 677T_FUNC(double_quote_within_word, "double quote within word") 678{ 679 struct t_file *tf; 680 int ret; 681 682 tf = t_fopen(NULL); 683 t_fprintf(tf, "hello\" \"world\n"); 684 t_frewind(tf); 685 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 686 t_fclose(tf); 687 return (ret); 688} 689 690T_FUNC(single_quote_after_word, "single quote after word") 691{ 692 struct t_file *tf; 693 int ret; 694 695 tf = t_fopen(NULL); 696 t_fprintf(tf, "hello' world'\n"); 697 t_frewind(tf); 698 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 699 t_fclose(tf); 700 return (ret); 701} 702 703T_FUNC(double_quote_after_word, "double quote after word") 704{ 705 struct t_file *tf; 706 int ret; 707 708 tf = t_fopen(NULL); 709 t_fprintf(tf, "hello\" world\"\n"); 710 t_frewind(tf); 711 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 712 t_fclose(tf); 713 return (ret); 714} 715 716 717/*************************************************************************** 718 * Combinations of escape and quotes 719 */ 720 721T_FUNC(escaped_single_quote, 722 "escaped single quote") 723{ 724 struct t_file *tf; 725 int ret; 726 727 tf = t_fopen(NULL); 728 t_fprintf(tf, "\\'\n"); 729 t_frewind(tf); 730 ret = orw_expect(tf, "'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 731 t_fclose(tf); 732 return (ret); 733} 734 735T_FUNC(escaped_double_quote, 736 "escaped double quote") 737{ 738 struct t_file *tf; 739 int ret; 740 741 tf = t_fopen(NULL); 742 t_fprintf(tf, "\\\"\n"); 743 t_frewind(tf); 744 ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 745 t_fclose(tf); 746 return (ret); 747} 748 749T_FUNC(escaped_whitespace_within_single_quotes, 750 "escaped whitespace within single quotes") 751{ 752 struct t_file *tf; 753 int ret; 754 755 tf = t_fopen(NULL); 756 t_fprintf(tf, "'\\ ' '\\\t' '\\\r' '\\\n'\n"); 757 t_frewind(tf); 758 ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 759 orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 760 orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 761 orw_expect(tf, "\\\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 762 t_fclose(tf); 763 return (ret); 764} 765 766T_FUNC(escaped_whitespace_within_double_quotes, 767 "escaped whitespace within double quotes") 768{ 769 struct t_file *tf; 770 int ret; 771 772 tf = t_fopen(NULL); 773 t_fprintf(tf, "\"\\ \" \"\\\t\" \"\\\r\" \"\\\n\"\n"); 774 t_frewind(tf); 775 ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 776 orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 777 orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 778 /* this last one is a line continuation */ 779 orw_expect(tf, "", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 780 t_fclose(tf); 781 return (ret); 782} 783 784T_FUNC(escaped_letter_within_single_quotes, 785 "escaped letter within single quotes") 786{ 787 struct t_file *tf; 788 int ret; 789 790 tf = t_fopen(NULL); 791 t_fprintf(tf, "'\\z'\n"); 792 t_frewind(tf); 793 ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 794 t_fclose(tf); 795 return (ret); 796} 797 798T_FUNC(escaped_letter_within_double_quotes, 799 "escaped letter within double quotes") 800{ 801 struct t_file *tf; 802 int ret; 803 804 tf = t_fopen(NULL); 805 t_fprintf(tf, "\"\\z\"\n"); 806 t_frewind(tf); 807 ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 808 t_fclose(tf); 809 return (ret); 810} 811 812T_FUNC(escaped_escape_within_single_quotes, 813 "escaped escape within single quotes") 814{ 815 struct t_file *tf; 816 int ret; 817 818 tf = t_fopen(NULL); 819 t_fprintf(tf, "'\\\\'\n"); 820 t_frewind(tf); 821 ret = orw_expect(tf, "\\\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 822 t_fclose(tf); 823 return (ret); 824} 825 826T_FUNC(escaped_escape_within_double_quotes, 827 "escaped escape within double quotes") 828{ 829 struct t_file *tf; 830 int ret; 831 832 tf = t_fopen(NULL); 833 t_fprintf(tf, "\"\\\\\"\n"); 834 t_frewind(tf); 835 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 836 t_fclose(tf); 837 return (ret); 838} 839 840T_FUNC(escaped_single_quote_within_single_quotes, 841 "escaped single quote within single quotes") 842{ 843 struct t_file *tf; 844 int ret; 845 846 tf = t_fopen(NULL); 847 t_fprintf(tf, "'\\''\n"); 848 t_frewind(tf); 849 ret = orw_expect(tf, NULL, 1 /*lines*/, 1 /*eof*/, 0 /*eol*/); 850 t_fclose(tf); 851 return (ret); 852} 853 854T_FUNC(escaped_double_quote_within_single_quotes, 855 "escaped double quote within single quotes") 856{ 857 struct t_file *tf; 858 int ret; 859 860 tf = t_fopen(NULL); 861 t_fprintf(tf, "'\\\"'\n"); 862 t_frewind(tf); 863 ret = orw_expect(tf, "\\\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 864 t_fclose(tf); 865 return (ret); 866} 867 868T_FUNC(escaped_single_quote_within_double_quotes, 869 "escaped single quote within double quotes") 870{ 871 struct t_file *tf; 872 int ret; 873 874 tf = t_fopen(NULL); 875 t_fprintf(tf, "\"\\'\"\n"); 876 t_frewind(tf); 877 ret = orw_expect(tf, "\\'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 878 t_fclose(tf); 879 return (ret); 880} 881 882T_FUNC(escaped_double_quote_within_double_quotes, 883 "escaped double quote within double quotes") 884{ 885 struct t_file *tf; 886 int ret; 887 888 tf = t_fopen(NULL); 889 t_fprintf(tf, "\"\\\"\"\n"); 890 t_frewind(tf); 891 ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 892 t_fclose(tf); 893 return (ret); 894} 895 896 897/*************************************************************************** 898 * Line continuation 899 */ 900 901T_FUNC(line_continuation_within_whitespace, "line continuation within whitespace") 902{ 903 struct t_file *tf; 904 int ret; 905 906 tf = t_fopen(NULL); 907 t_fprintf(tf, "hello \\\n world\n"); 908 t_frewind(tf); 909 ret = orw_expect(tf, "hello", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 910 orw_expect(tf, "world", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 911 t_fclose(tf); 912 return (ret); 913} 914 915T_FUNC(line_continuation_before_whitespace, "line continuation before whitespace") 916{ 917 struct t_file *tf; 918 int ret; 919 920 tf = t_fopen(NULL); 921 t_fprintf(tf, "hello\\\n world\n"); 922 t_frewind(tf); 923 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 924 orw_expect(tf, "world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 925 t_fclose(tf); 926 return (ret); 927} 928 929T_FUNC(line_continuation_after_whitespace, "line continuation after whitespace") 930{ 931 struct t_file *tf; 932 int ret; 933 934 tf = t_fopen(NULL); 935 t_fprintf(tf, "hello \\\nworld\n"); 936 t_frewind(tf); 937 ret = orw_expect(tf, "hello", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 938 orw_expect(tf, "world", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 939 t_fclose(tf); 940 return (ret); 941} 942 943T_FUNC(line_continuation_within_word, "line continuation within word") 944{ 945 struct t_file *tf; 946 int ret; 947 948 tf = t_fopen(NULL); 949 t_fprintf(tf, "hello\\\nworld\n"); 950 t_frewind(tf); 951 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 952 t_fclose(tf); 953 return (ret); 954} 955 956 957/*************************************************************************** 958 * Boilerplate 959 */ 960 961static int 962t_prepare(int argc, char *argv[]) 963{ 964 965 (void)argc; 966 (void)argv; 967 968 T(empty_input); 969 T(empty_line); 970 T(unterminated_line); 971 T(single_whitespace); 972 T(multiple_whitespace); 973 T(comment); 974 T(whitespace_before_comment); 975 T(single_quoted_comment); 976 T(double_quoted_comment); 977 T(comment_at_eof); 978 979 T(single_word); 980 T(single_whitespace_before_word); 981 T(double_whitespace_before_word); 982 T(single_whitespace_after_word); 983 T(double_whitespace_after_word); 984 T(comment_after_word); 985 T(word_containing_hash); 986 T(two_words); 987 988 T(naked_escape); 989 T(escaped_escape); 990 T(escaped_whitespace); 991 T(escaped_newline_before_word); 992 T(escaped_newline_within_word); 993 T(escaped_newline_after_word); 994 T(escaped_letter); 995 T(escaped_comment); 996 T(escape_at_eof); 997 998 T(naked_single_quote); 999 T(naked_double_quote); 1000 T(empty_single_quotes); 1001 T(empty_double_quotes); 1002 T(single_quotes_within_double_quotes); 1003 T(double_quotes_within_single_quotes); 1004 T(single_quoted_whitespace); 1005 T(double_quoted_whitespace); 1006 T(single_quoted_words); 1007 T(double_quoted_words); 1008 1009 T(single_quote_before_word); 1010 T(double_quote_before_word); 1011 T(single_quote_within_word); 1012 T(double_quote_within_word); 1013 T(single_quote_after_word); 1014 T(double_quote_after_word); 1015 1016 T(escaped_single_quote); 1017 T(escaped_double_quote); 1018 T(escaped_whitespace_within_single_quotes); 1019 T(escaped_whitespace_within_double_quotes); 1020 T(escaped_letter_within_single_quotes); 1021 T(escaped_letter_within_double_quotes); 1022 T(escaped_escape_within_single_quotes); 1023 T(escaped_escape_within_double_quotes); 1024 T(escaped_single_quote_within_single_quotes); 1025 T(escaped_double_quote_within_single_quotes); 1026 T(escaped_single_quote_within_double_quotes); 1027 T(escaped_double_quote_within_double_quotes); 1028 1029 T(line_continuation_within_whitespace); 1030 T(line_continuation_before_whitespace); 1031 T(line_continuation_after_whitespace); 1032 T(line_continuation_within_word); 1033 1034 return (0); 1035} 1036 1037int 1038main(int argc, char *argv[]) 1039{ 1040 1041 t_main(t_prepare, NULL, argc, argv); 1042} 1043