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