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(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 194 T_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 207 T_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 220 T_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 233 T_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 251 T_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 265 T_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 279 T_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 293 T_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 307 T_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 321 T_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 336 T_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 350 T_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 370 T_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 383 T_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 396 T_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 413 T_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 426 T_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 439 T_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 452 T_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 465 T_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 479 T_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 497 T_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 510 T_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 523 T_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 536 T_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 549 T_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 562 T_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 575 T_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 591 T_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 607 T_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 620 T_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 638 T_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 651 T_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 664 T_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 677 T_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 690 T_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 703 T_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 721 T_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 735 T_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 749 T_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 766 T_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 784 T_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 798 T_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 812 T_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 826 T_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 840 T_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 854 T_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 868 T_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 882 T_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 901 T_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 915 T_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 929 T_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 943 T_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 961 static int 962 t_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 1037 int 1038 main(int argc, char *argv[]) 1039 { 1040 1041 t_main(t_prepare, NULL, argc, argv); 1042 } 1043