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 */ 62 static int 63 orw_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 118 T_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 129 T_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 142 T_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 155 T_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 168 T_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 181 T_FUNC(line_continuation_in_whitespace, "line continuation in whitespace") 182 { 183 struct t_file *tf; 184 int ret; 185 186 tf = t_fopen(NULL); 187 t_fprintf(tf, " \\\n \n"); 188 t_frewind(tf); 189 ret = orw_expect(tf, NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 190 t_fclose(tf); 191 return (ret); 192 } 193 194 T_FUNC(comment, "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 207 T_FUNC(whitespace_before_comment, "whitespace before 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, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 216 t_fclose(tf); 217 return (ret); 218 } 219 220 T_FUNC(single_quoted_comment, "single-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 233 T_FUNC(double_quoted_comment, "double-quoted comment") 234 { 235 struct t_file *tf; 236 int ret; 237 238 tf = t_fopen(NULL); 239 t_fprintf(tf, " \"# comment\"\n"); 240 t_frewind(tf); 241 ret = orw_expect(tf, "# comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 242 t_fclose(tf); 243 return (ret); 244 } 245 246 T_FUNC(comment_at_eof, "comment at end of file") 247 { 248 struct t_file *tf; 249 int ret; 250 251 tf = t_fopen(NULL); 252 t_fprintf(tf, "# comment"); 253 t_frewind(tf); 254 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 255 t_fclose(tf); 256 return (ret); 257 } 258 259 260 /*************************************************************************** 261 * Simple cases - no quotes or escapes 262 */ 263 264 T_FUNC(single_word, "single word") 265 { 266 const char *word = "hello"; 267 struct t_file *tf; 268 int ret; 269 270 tf = t_fopen(NULL); 271 t_fprintf(tf, "%s\n", word); 272 t_frewind(tf); 273 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 274 t_fclose(tf); 275 return (ret); 276 } 277 278 T_FUNC(single_whitespace_before_word, "single whitespace before word") 279 { 280 const char *word = "hello"; 281 struct t_file *tf; 282 int ret; 283 284 tf = t_fopen(NULL); 285 t_fprintf(tf, " %s\n", word); 286 t_frewind(tf); 287 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 288 t_fclose(tf); 289 return (ret); 290 } 291 292 T_FUNC(double_whitespace_before_word, "double whitespace before word") 293 { 294 const char *word = "hello"; 295 struct t_file *tf; 296 int ret; 297 298 tf = t_fopen(NULL); 299 t_fprintf(tf, " %s\n", word); 300 t_frewind(tf); 301 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 302 t_fclose(tf); 303 return (ret); 304 } 305 306 T_FUNC(single_whitespace_after_word, "single whitespace after word") 307 { 308 const char *word = "hello"; 309 struct t_file *tf; 310 int ret; 311 312 tf = t_fopen(NULL); 313 t_fprintf(tf, "%s \n", word); 314 t_frewind(tf); 315 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 316 t_fclose(tf); 317 return (ret); 318 } 319 320 T_FUNC(double_whitespace_after_word, "double whitespace after word") 321 { 322 const char *word = "hello"; 323 struct t_file *tf; 324 int ret; 325 326 tf = t_fopen(NULL); 327 t_fprintf(tf, "%s \n", word); 328 t_frewind(tf); 329 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 330 t_fclose(tf); 331 return (ret); 332 } 333 334 T_FUNC(comment_after_word, "comment after word") 335 { 336 const char *word = "hello"; 337 struct t_file *tf; 338 int ret; 339 340 tf = t_fopen(NULL); 341 t_fprintf(tf, "%s # comment\n", word); 342 t_frewind(tf); 343 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 344 orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 345 t_fclose(tf); 346 return (ret); 347 } 348 349 T_FUNC(word_containing_hash, "word containing hash") 350 { 351 const char *word = "hello#world"; 352 struct t_file *tf; 353 int ret; 354 355 tf = t_fopen(NULL); 356 t_fprintf(tf, "%s\n", word); 357 t_frewind(tf); 358 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 359 t_fclose(tf); 360 return (ret); 361 } 362 363 T_FUNC(two_words, "two words") 364 { 365 const char *word[] = { "hello", "world" }; 366 struct t_file *tf; 367 int ret; 368 369 tf = t_fopen(NULL); 370 t_fprintf(tf, "%s %s\n", word[0], word[1]); 371 t_frewind(tf); 372 ret = orw_expect(tf, word[0], 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 373 orw_expect(tf, word[1], 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 374 t_fclose(tf); 375 return (ret); 376 } 377 378 379 /*************************************************************************** 380 * Escapes 381 */ 382 383 T_FUNC(naked_escape, "naked escape") 384 { 385 struct t_file *tf; 386 int ret; 387 388 tf = t_fopen(NULL); 389 t_fprintf(tf, "\\"); 390 t_frewind(tf); 391 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 392 t_fclose(tf); 393 return (ret); 394 } 395 396 T_FUNC(escaped_escape, "escaped escape") 397 { 398 struct t_file *tf; 399 int ret; 400 401 tf = t_fopen(NULL); 402 t_fprintf(tf, "\\\\\n"); 403 t_frewind(tf); 404 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 405 t_fclose(tf); 406 return (ret); 407 } 408 409 T_FUNC(escaped_whitespace, "escaped whitespace") 410 { 411 struct t_file *tf; 412 int ret; 413 414 tf = t_fopen(NULL); 415 t_fprintf(tf, "\\ \\\t \\\r \\\n\n"); 416 t_frewind(tf); 417 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 418 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 419 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 420 /* this last one is a line continuation */ 421 orw_expect(tf, NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 422 t_fclose(tf); 423 return (ret); 424 } 425 426 T_FUNC(escaped_newline_before_word, "escaped newline before word") 427 { 428 struct t_file *tf; 429 int ret; 430 431 tf = t_fopen(NULL); 432 t_fprintf(tf, "\\\nhello world\n"); 433 t_frewind(tf); 434 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 435 t_fclose(tf); 436 return (ret); 437 } 438 439 T_FUNC(escaped_newline_within_word, "escaped newline within word") 440 { 441 struct t_file *tf; 442 int ret; 443 444 tf = t_fopen(NULL); 445 t_fprintf(tf, "hello\\\nworld\n"); 446 t_frewind(tf); 447 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 448 t_fclose(tf); 449 return (ret); 450 } 451 452 T_FUNC(escaped_newline_after_word, "escaped newline after word") 453 { 454 struct t_file *tf; 455 int ret; 456 457 tf = t_fopen(NULL); 458 t_fprintf(tf, "hello\\\n world\n"); 459 t_frewind(tf); 460 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 461 t_fclose(tf); 462 return (ret); 463 } 464 465 T_FUNC(escaped_letter, "escaped letter") 466 { 467 struct t_file *tf; 468 int ret; 469 470 tf = t_fopen(NULL); 471 t_fprintf(tf, "\\z\n"); 472 t_frewind(tf); 473 ret = orw_expect(tf, "z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 474 t_fclose(tf); 475 return (ret); 476 } 477 478 T_FUNC(escaped_comment, "escaped comment") 479 { 480 struct t_file *tf; 481 int ret; 482 483 tf = t_fopen(NULL); 484 t_fprintf(tf, " \\# comment\n"); 485 t_frewind(tf); 486 ret = orw_expect(tf, "#", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 487 orw_expect(tf, "comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 488 t_fclose(tf); 489 return (ret); 490 } 491 492 T_FUNC(escape_at_eof, "escape at end of file") 493 { 494 struct t_file *tf; 495 int ret; 496 497 tf = t_fopen(NULL); 498 t_fprintf(tf, "z\\"); 499 t_frewind(tf); 500 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 501 t_fclose(tf); 502 return (ret); 503 } 504 505 506 /*************************************************************************** 507 T_FUNC(escaped_comment, "escaped comment") 508 { 509 struct t_file *tf; 510 int ret; 511 512 tf = t_fopen(NULL); 513 t_fprintf(tf, " \\# comment\n"); 514 t_frewind(tf); 515 ret = orw_expect(tf, "#", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 516 orw_expect(tf, "comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 517 t_fclose(tf); 518 return (ret); 519 } 520 521 T_FUNC(escape_at_eof, "escape at end of file") 522 { 523 struct t_file *tf; 524 int ret; 525 526 tf = t_fopen(NULL); 527 t_fprintf(tf, "z\\"); 528 t_frewind(tf); 529 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 530 t_fclose(tf); 531 return (ret); 532 } 533 534 * Quotes 535 */ 536 537 T_FUNC(naked_single_quote, "naked single quote") 538 { 539 struct t_file *tf; 540 int ret; 541 542 tf = t_fopen(NULL); 543 t_fprintf(tf, "'"); 544 t_frewind(tf); 545 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 546 t_fclose(tf); 547 return (ret); 548 } 549 550 T_FUNC(naked_double_quote, "naked double quote") 551 { 552 struct t_file *tf; 553 int ret; 554 555 tf = t_fopen(NULL); 556 t_fprintf(tf, "\""); 557 t_frewind(tf); 558 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 559 t_fclose(tf); 560 return (ret); 561 } 562 563 T_FUNC(empty_single_quotes, "empty single quotes") 564 { 565 struct t_file *tf; 566 int ret; 567 568 tf = t_fopen(NULL); 569 t_fprintf(tf, "''\n"); 570 t_frewind(tf); 571 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 572 t_fclose(tf); 573 return (ret); 574 } 575 576 T_FUNC(empty_double_quotes, "empty double quotes") 577 { 578 struct t_file *tf; 579 int ret; 580 581 tf = t_fopen(NULL); 582 t_fprintf(tf, "\"\"\n"); 583 t_frewind(tf); 584 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 585 t_fclose(tf); 586 return (ret); 587 } 588 589 T_FUNC(single_quotes_within_double_quotes, "single quotes within double quotes") 590 { 591 struct t_file *tf; 592 int ret; 593 594 tf = t_fopen(NULL); 595 t_fprintf(tf, "\"' '\"\n"); 596 t_frewind(tf); 597 ret = orw_expect(tf, "' '", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 598 t_fclose(tf); 599 return (ret); 600 } 601 602 T_FUNC(double_quotes_within_single_quotes, "double quotes within single quotes") 603 { 604 struct t_file *tf; 605 int ret; 606 607 tf = t_fopen(NULL); 608 t_fprintf(tf, "'\" \"'\n"); 609 t_frewind(tf); 610 ret = orw_expect(tf, "\" \"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 611 t_fclose(tf); 612 return (ret); 613 } 614 615 T_FUNC(single_quoted_whitespace, "single-quoted whitespace") 616 { 617 struct t_file *tf; 618 int ret; 619 620 tf = t_fopen(NULL); 621 t_fprintf(tf, "' ' '\t' '\r' '\n'\n"); 622 t_frewind(tf); 623 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 624 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 625 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 626 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 627 t_fclose(tf); 628 return (ret); 629 } 630 631 T_FUNC(double_quoted_whitespace, "double-quoted whitespace") 632 { 633 struct t_file *tf; 634 int ret; 635 636 tf = t_fopen(NULL); 637 t_fprintf(tf, "\" \" \"\t\" \"\r\" \"\n\"\n"); 638 t_frewind(tf); 639 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 640 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 641 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 642 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 643 t_fclose(tf); 644 return (ret); 645 } 646 647 T_FUNC(single_quoted_words, "single-quoted words") 648 { 649 struct t_file *tf; 650 int ret; 651 652 tf = t_fopen(NULL); 653 t_fprintf(tf, "'hello world'\n"); 654 t_frewind(tf); 655 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 656 t_fclose(tf); 657 return (ret); 658 } 659 660 T_FUNC(double_quoted_words, "double-quoted words") 661 { 662 struct t_file *tf; 663 int ret; 664 665 tf = t_fopen(NULL); 666 t_fprintf(tf, "\"hello world\"\n"); 667 t_frewind(tf); 668 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 669 t_fclose(tf); 670 return (ret); 671 } 672 673 674 /*************************************************************************** 675 * Combinations of quoted and unquoted text 676 */ 677 678 T_FUNC(single_quote_before_word, "single quote before word") 679 { 680 struct t_file *tf; 681 int ret; 682 683 tf = t_fopen(NULL); 684 t_fprintf(tf, "'hello 'world\n"); 685 t_frewind(tf); 686 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 687 t_fclose(tf); 688 return (ret); 689 } 690 691 T_FUNC(double_quote_before_word, "double quote before word") 692 { 693 struct t_file *tf; 694 int ret; 695 696 tf = t_fopen(NULL); 697 t_fprintf(tf, "\"hello \"world\n"); 698 t_frewind(tf); 699 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 700 t_fclose(tf); 701 return (ret); 702 } 703 704 T_FUNC(single_quote_within_word, "single quote within word") 705 { 706 struct t_file *tf; 707 int ret; 708 709 tf = t_fopen(NULL); 710 t_fprintf(tf, "hello' 'world\n"); 711 t_frewind(tf); 712 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 713 t_fclose(tf); 714 return (ret); 715 } 716 717 T_FUNC(double_quote_within_word, "double quote within word") 718 { 719 struct t_file *tf; 720 int ret; 721 722 tf = t_fopen(NULL); 723 t_fprintf(tf, "hello\" \"world\n"); 724 t_frewind(tf); 725 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 726 t_fclose(tf); 727 return (ret); 728 } 729 730 T_FUNC(single_quote_after_word, "single quote after word") 731 { 732 struct t_file *tf; 733 int ret; 734 735 tf = t_fopen(NULL); 736 t_fprintf(tf, "hello' world'\n"); 737 t_frewind(tf); 738 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 739 t_fclose(tf); 740 return (ret); 741 } 742 743 T_FUNC(double_quote_after_word, "double quote after word") 744 { 745 struct t_file *tf; 746 int ret; 747 748 tf = t_fopen(NULL); 749 t_fprintf(tf, "hello\" world\"\n"); 750 t_frewind(tf); 751 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 752 t_fclose(tf); 753 return (ret); 754 } 755 756 757 /*************************************************************************** 758 * Combinations of escape and quotes 759 */ 760 761 T_FUNC(escaped_single_quote, 762 "escaped single quote") 763 { 764 struct t_file *tf; 765 int ret; 766 767 tf = t_fopen(NULL); 768 t_fprintf(tf, "\\'\n"); 769 t_frewind(tf); 770 ret = orw_expect(tf, "'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 771 t_fclose(tf); 772 return (ret); 773 } 774 775 T_FUNC(escaped_double_quote, 776 "escaped double quote") 777 { 778 struct t_file *tf; 779 int ret; 780 781 tf = t_fopen(NULL); 782 t_fprintf(tf, "\\\"\n"); 783 t_frewind(tf); 784 ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 785 t_fclose(tf); 786 return (ret); 787 } 788 789 T_FUNC(escaped_whitespace_within_single_quotes, 790 "escaped whitespace within single quotes") 791 { 792 struct t_file *tf; 793 int ret; 794 795 tf = t_fopen(NULL); 796 t_fprintf(tf, "'\\ ' '\\\t' '\\\r' '\\\n'\n"); 797 t_frewind(tf); 798 ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 799 orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 800 orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 801 orw_expect(tf, "\\\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 802 t_fclose(tf); 803 return (ret); 804 } 805 806 T_FUNC(escaped_whitespace_within_double_quotes, 807 "escaped whitespace within double quotes") 808 { 809 struct t_file *tf; 810 int ret; 811 812 tf = t_fopen(NULL); 813 t_fprintf(tf, "\"\\ \" \"\\\t\" \"\\\r\" \"\\\n\"\n"); 814 t_frewind(tf); 815 ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 816 orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 817 orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 818 /* this last one is a line continuation */ 819 orw_expect(tf, "", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 820 t_fclose(tf); 821 return (ret); 822 } 823 824 T_FUNC(escaped_letter_within_single_quotes, 825 "escaped letter within single quotes") 826 { 827 struct t_file *tf; 828 int ret; 829 830 tf = t_fopen(NULL); 831 t_fprintf(tf, "'\\z'\n"); 832 t_frewind(tf); 833 ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 834 t_fclose(tf); 835 return (ret); 836 } 837 838 T_FUNC(escaped_letter_within_double_quotes, 839 "escaped letter within double quotes") 840 { 841 struct t_file *tf; 842 int ret; 843 844 tf = t_fopen(NULL); 845 t_fprintf(tf, "\"\\z\"\n"); 846 t_frewind(tf); 847 ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 848 t_fclose(tf); 849 return (ret); 850 } 851 852 T_FUNC(escaped_escape_within_single_quotes, 853 "escaped escape within single quotes") 854 { 855 struct t_file *tf; 856 int ret; 857 858 tf = t_fopen(NULL); 859 t_fprintf(tf, "'\\\\'\n"); 860 t_frewind(tf); 861 ret = orw_expect(tf, "\\\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 862 t_fclose(tf); 863 return (ret); 864 } 865 866 T_FUNC(escaped_escape_within_double_quotes, 867 "escaped escape within double quotes") 868 { 869 struct t_file *tf; 870 int ret; 871 872 tf = t_fopen(NULL); 873 t_fprintf(tf, "\"\\\\\"\n"); 874 t_frewind(tf); 875 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 876 t_fclose(tf); 877 return (ret); 878 } 879 880 T_FUNC(escaped_single_quote_within_single_quotes, 881 "escaped single quote within single quotes") 882 { 883 struct t_file *tf; 884 int ret; 885 886 tf = t_fopen(NULL); 887 t_fprintf(tf, "'\\''\n"); 888 t_frewind(tf); 889 ret = orw_expect(tf, NULL, 1 /*lines*/, 1 /*eof*/, 0 /*eol*/); 890 t_fclose(tf); 891 return (ret); 892 } 893 894 T_FUNC(escaped_double_quote_within_single_quotes, 895 "escaped double quote within single quotes") 896 { 897 struct t_file *tf; 898 int ret; 899 900 tf = t_fopen(NULL); 901 t_fprintf(tf, "'\\\"'\n"); 902 t_frewind(tf); 903 ret = orw_expect(tf, "\\\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 904 t_fclose(tf); 905 return (ret); 906 } 907 908 T_FUNC(escaped_single_quote_within_double_quotes, 909 "escaped single quote within double quotes") 910 { 911 struct t_file *tf; 912 int ret; 913 914 tf = t_fopen(NULL); 915 t_fprintf(tf, "\"\\'\"\n"); 916 t_frewind(tf); 917 ret = orw_expect(tf, "\\'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 918 t_fclose(tf); 919 return (ret); 920 } 921 922 T_FUNC(escaped_double_quote_within_double_quotes, 923 "escaped double quote within double quotes") 924 { 925 struct t_file *tf; 926 int ret; 927 928 tf = t_fopen(NULL); 929 t_fprintf(tf, "\"\\\"\"\n"); 930 t_frewind(tf); 931 ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 932 t_fclose(tf); 933 return (ret); 934 } 935 936 937 /*************************************************************************** 938 * Line continuation 939 */ 940 941 T_FUNC(line_continuation_within_whitespace, "line continuation within whitespace") 942 { 943 struct t_file *tf; 944 int ret; 945 946 tf = t_fopen(NULL); 947 t_fprintf(tf, "hello \\\n world\n"); 948 t_frewind(tf); 949 ret = orw_expect(tf, "hello", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 950 orw_expect(tf, "world", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 951 t_fclose(tf); 952 return (ret); 953 } 954 955 T_FUNC(line_continuation_before_whitespace, "line continuation before whitespace") 956 { 957 struct t_file *tf; 958 int ret; 959 960 tf = t_fopen(NULL); 961 t_fprintf(tf, "hello\\\n world\n"); 962 t_frewind(tf); 963 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 964 orw_expect(tf, "world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 965 t_fclose(tf); 966 return (ret); 967 } 968 969 T_FUNC(line_continuation_after_whitespace, "line continuation after whitespace") 970 { 971 struct t_file *tf; 972 int ret; 973 974 tf = t_fopen(NULL); 975 t_fprintf(tf, "hello \\\nworld\n"); 976 t_frewind(tf); 977 ret = orw_expect(tf, "hello", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 978 orw_expect(tf, "world", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 979 t_fclose(tf); 980 return (ret); 981 } 982 983 T_FUNC(line_continuation_within_word, "line continuation within word") 984 { 985 struct t_file *tf; 986 int ret; 987 988 tf = t_fopen(NULL); 989 t_fprintf(tf, "hello\\\nworld\n"); 990 t_frewind(tf); 991 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 992 t_fclose(tf); 993 return (ret); 994 } 995 996 997 /*************************************************************************** 998 * Boilerplate 999 */ 1000 1001 static int 1002 t_prepare(int argc, char *argv[]) 1003 { 1004 1005 (void)argc; 1006 (void)argv; 1007 1008 T(empty_input); 1009 T(empty_line); 1010 T(unterminated_line); 1011 T(single_whitespace); 1012 T(multiple_whitespace); 1013 T(comment); 1014 T(whitespace_before_comment); 1015 T(single_quoted_comment); 1016 T(double_quoted_comment); 1017 T(comment_at_eof); 1018 1019 T(single_word); 1020 T(single_whitespace_before_word); 1021 T(double_whitespace_before_word); 1022 T(single_whitespace_after_word); 1023 T(double_whitespace_after_word); 1024 T(comment_after_word); 1025 T(word_containing_hash); 1026 T(two_words); 1027 1028 T(naked_escape); 1029 T(escaped_escape); 1030 T(escaped_whitespace); 1031 T(escaped_newline_before_word); 1032 T(escaped_newline_within_word); 1033 T(escaped_newline_after_word); 1034 T(escaped_letter); 1035 T(escaped_comment); 1036 T(escape_at_eof); 1037 1038 T(naked_single_quote); 1039 T(naked_double_quote); 1040 T(empty_single_quotes); 1041 T(empty_double_quotes); 1042 T(single_quotes_within_double_quotes); 1043 T(double_quotes_within_single_quotes); 1044 T(single_quoted_whitespace); 1045 T(double_quoted_whitespace); 1046 T(single_quoted_words); 1047 T(double_quoted_words); 1048 1049 T(single_quote_before_word); 1050 T(double_quote_before_word); 1051 T(single_quote_within_word); 1052 T(double_quote_within_word); 1053 T(single_quote_after_word); 1054 T(double_quote_after_word); 1055 1056 T(escaped_single_quote); 1057 T(escaped_double_quote); 1058 T(escaped_whitespace_within_single_quotes); 1059 T(escaped_whitespace_within_double_quotes); 1060 T(escaped_letter_within_single_quotes); 1061 T(escaped_letter_within_double_quotes); 1062 T(escaped_escape_within_single_quotes); 1063 T(escaped_escape_within_double_quotes); 1064 T(escaped_single_quote_within_single_quotes); 1065 T(escaped_double_quote_within_single_quotes); 1066 T(escaped_single_quote_within_double_quotes); 1067 T(escaped_double_quote_within_double_quotes); 1068 1069 T(line_continuation_within_whitespace); 1070 T(line_continuation_before_whitespace); 1071 T(line_continuation_after_whitespace); 1072 T(line_continuation_within_word); 1073 1074 return (0); 1075 } 1076 1077 int 1078 main(int argc, char *argv[]) 1079 { 1080 1081 t_main(t_prepare, NULL, argc, argv); 1082 } 1083