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