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(comment, "comment") 173 { 174 struct t_file *tf; 175 int ret; 176 177 tf = t_fopen(NULL); 178 t_fprintf(tf, "# comment\n"); 179 t_frewind(tf); 180 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 181 t_fclose(tf); 182 return (ret); 183 } 184 185 T_FUNC(whitespace_before_comment, "whitespace before 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 199 /*************************************************************************** 200 * Simple cases - no quotes or escapes 201 */ 202 203 T_FUNC(single_word, "single word") 204 { 205 const char *word = "hello"; 206 struct t_file *tf; 207 int ret; 208 209 tf = t_fopen(NULL); 210 t_fprintf(tf, "%s\n", word); 211 t_frewind(tf); 212 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 213 t_fclose(tf); 214 return (ret); 215 } 216 217 T_FUNC(single_whitespace_before_word, "single whitespace before word") 218 { 219 const char *word = "hello"; 220 struct t_file *tf; 221 int ret; 222 223 tf = t_fopen(NULL); 224 t_fprintf(tf, " %s\n", word); 225 t_frewind(tf); 226 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 227 t_fclose(tf); 228 return (ret); 229 } 230 231 T_FUNC(double_whitespace_before_word, "double whitespace before word") 232 { 233 const char *word = "hello"; 234 struct t_file *tf; 235 int ret; 236 237 tf = t_fopen(NULL); 238 t_fprintf(tf, " %s\n", word); 239 t_frewind(tf); 240 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 241 t_fclose(tf); 242 return (ret); 243 } 244 245 T_FUNC(single_whitespace_after_word, "single whitespace after word") 246 { 247 const char *word = "hello"; 248 struct t_file *tf; 249 int ret; 250 251 tf = t_fopen(NULL); 252 t_fprintf(tf, "%s \n", word); 253 t_frewind(tf); 254 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 255 t_fclose(tf); 256 return (ret); 257 } 258 259 T_FUNC(double_whitespace_after_word, "double whitespace after word") 260 { 261 const char *word = "hello"; 262 struct t_file *tf; 263 int ret; 264 265 tf = t_fopen(NULL); 266 t_fprintf(tf, "%s \n", word); 267 t_frewind(tf); 268 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/); 269 t_fclose(tf); 270 return (ret); 271 } 272 273 T_FUNC(comment_after_word, "comment after word") 274 { 275 const char *word = "hello"; 276 struct t_file *tf; 277 int ret; 278 279 tf = t_fopen(NULL); 280 t_fprintf(tf, "%s # comment\n", word); 281 t_frewind(tf); 282 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 283 orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 284 t_fclose(tf); 285 return (ret); 286 } 287 288 T_FUNC(word_containing_hash, "word containing hash") 289 { 290 const char *word = "hello#world"; 291 struct t_file *tf; 292 int ret; 293 294 tf = t_fopen(NULL); 295 t_fprintf(tf, "%s\n", word); 296 t_frewind(tf); 297 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 298 t_fclose(tf); 299 return (ret); 300 } 301 302 T_FUNC(two_words, "two words") 303 { 304 const char *word[] = { "hello", "world" }; 305 struct t_file *tf; 306 int ret; 307 308 tf = t_fopen(NULL); 309 t_fprintf(tf, "%s %s\n", word[0], word[1]); 310 t_frewind(tf); 311 ret = orw_expect(tf, word[0], 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 312 orw_expect(tf, word[1], 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 313 t_fclose(tf); 314 return (ret); 315 } 316 317 318 /*************************************************************************** 319 * Escapes 320 */ 321 322 T_FUNC(naked_escape, "naked escape") 323 { 324 struct t_file *tf; 325 int ret; 326 327 tf = t_fopen(NULL); 328 t_fprintf(tf, "\\"); 329 t_frewind(tf); 330 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 331 t_fclose(tf); 332 return (ret); 333 } 334 335 T_FUNC(escaped_escape, "escaped escape") 336 { 337 struct t_file *tf; 338 int ret; 339 340 tf = t_fopen(NULL); 341 t_fprintf(tf, "\\\\\n"); 342 t_frewind(tf); 343 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 344 t_fclose(tf); 345 return (ret); 346 } 347 348 T_FUNC(escaped_whitespace, "escaped whitespace") 349 { 350 struct t_file *tf; 351 int ret; 352 353 tf = t_fopen(NULL); 354 t_fprintf(tf, "\\ \\\t \\\r \\\n\n"); 355 t_frewind(tf); 356 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 357 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 358 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 359 /* this last one is a line continuation */ 360 orw_expect(tf, NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 361 t_fclose(tf); 362 return (ret); 363 } 364 365 T_FUNC(escaped_newline_before_word, "escaped newline before word") 366 { 367 struct t_file *tf; 368 int ret; 369 370 tf = t_fopen(NULL); 371 t_fprintf(tf, "\\\nhello world\n"); 372 t_frewind(tf); 373 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 374 t_fclose(tf); 375 return (ret); 376 } 377 378 T_FUNC(escaped_newline_within_word, "escaped newline within word") 379 { 380 struct t_file *tf; 381 int ret; 382 383 tf = t_fopen(NULL); 384 t_fprintf(tf, "hello\\\nworld\n"); 385 t_frewind(tf); 386 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 387 t_fclose(tf); 388 return (ret); 389 } 390 391 T_FUNC(escaped_newline_after_word, "escaped newline after word") 392 { 393 struct t_file *tf; 394 int ret; 395 396 tf = t_fopen(NULL); 397 t_fprintf(tf, "hello\\\n world\n"); 398 t_frewind(tf); 399 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/); 400 t_fclose(tf); 401 return (ret); 402 } 403 404 T_FUNC(escaped_letter, "escaped letter") 405 { 406 struct t_file *tf; 407 int ret; 408 409 tf = t_fopen(NULL); 410 t_fprintf(tf, "\\z\n"); 411 t_frewind(tf); 412 ret = orw_expect(tf, "z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 413 t_fclose(tf); 414 return (ret); 415 } 416 417 418 /*************************************************************************** 419 * Quotes 420 */ 421 422 T_FUNC(naked_single_quote, "naked single quote") 423 { 424 struct t_file *tf; 425 int ret; 426 427 tf = t_fopen(NULL); 428 t_fprintf(tf, "'"); 429 t_frewind(tf); 430 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 431 t_fclose(tf); 432 return (ret); 433 } 434 435 T_FUNC(naked_double_quote, "naked double quote") 436 { 437 struct t_file *tf; 438 int ret; 439 440 tf = t_fopen(NULL); 441 t_fprintf(tf, "\""); 442 t_frewind(tf); 443 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/); 444 t_fclose(tf); 445 return (ret); 446 } 447 448 T_FUNC(empty_single_quotes, "empty single quotes") 449 { 450 struct t_file *tf; 451 int ret; 452 453 tf = t_fopen(NULL); 454 t_fprintf(tf, "''\n"); 455 t_frewind(tf); 456 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 457 t_fclose(tf); 458 return (ret); 459 } 460 461 T_FUNC(empty_double_quotes, "empty double quotes") 462 { 463 struct t_file *tf; 464 int ret; 465 466 tf = t_fopen(NULL); 467 t_fprintf(tf, "\"\"\n"); 468 t_frewind(tf); 469 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 470 t_fclose(tf); 471 return (ret); 472 } 473 474 T_FUNC(single_quotes_within_double_quotes, "single quotes within double quotes") 475 { 476 struct t_file *tf; 477 int ret; 478 479 tf = t_fopen(NULL); 480 t_fprintf(tf, "\"' '\"\n"); 481 t_frewind(tf); 482 ret = orw_expect(tf, "' '", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 483 t_fclose(tf); 484 return (ret); 485 } 486 487 T_FUNC(double_quotes_within_single_quotes, "double quotes within single quotes") 488 { 489 struct t_file *tf; 490 int ret; 491 492 tf = t_fopen(NULL); 493 t_fprintf(tf, "'\" \"'\n"); 494 t_frewind(tf); 495 ret = orw_expect(tf, "\" \"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 496 t_fclose(tf); 497 return (ret); 498 } 499 500 T_FUNC(single_quoted_whitespace, "single-quoted whitespace") 501 { 502 struct t_file *tf; 503 int ret; 504 505 tf = t_fopen(NULL); 506 t_fprintf(tf, "' ' '\t' '\r' '\n'\n"); 507 t_frewind(tf); 508 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 509 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 510 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 511 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 512 t_fclose(tf); 513 return (ret); 514 } 515 516 T_FUNC(double_quoted_whitespace, "double-quoted whitespace") 517 { 518 struct t_file *tf; 519 int ret; 520 521 tf = t_fopen(NULL); 522 t_fprintf(tf, "\" \" \"\t\" \"\r\" \"\n\"\n"); 523 t_frewind(tf); 524 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 525 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 526 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 527 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 528 t_fclose(tf); 529 return (ret); 530 } 531 532 T_FUNC(single_quoted_words, "single-quoted words") 533 { 534 struct t_file *tf; 535 int ret; 536 537 tf = t_fopen(NULL); 538 t_fprintf(tf, "'hello world'\n"); 539 t_frewind(tf); 540 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 541 t_fclose(tf); 542 return (ret); 543 } 544 545 T_FUNC(double_quoted_words, "double-quoted words") 546 { 547 struct t_file *tf; 548 int ret; 549 550 tf = t_fopen(NULL); 551 t_fprintf(tf, "\"hello world\"\n"); 552 t_frewind(tf); 553 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 554 t_fclose(tf); 555 return (ret); 556 } 557 558 559 /*************************************************************************** 560 * Combinations of quoted and unquoted text 561 */ 562 563 T_FUNC(single_quote_before_word, "single quote before word") 564 { 565 struct t_file *tf; 566 int ret; 567 568 tf = t_fopen(NULL); 569 t_fprintf(tf, "'hello 'world\n"); 570 t_frewind(tf); 571 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 572 t_fclose(tf); 573 return (ret); 574 } 575 576 T_FUNC(double_quote_before_word, "double quote before word") 577 { 578 struct t_file *tf; 579 int ret; 580 581 tf = t_fopen(NULL); 582 t_fprintf(tf, "\"hello \"world\n"); 583 t_frewind(tf); 584 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 585 t_fclose(tf); 586 return (ret); 587 } 588 589 T_FUNC(single_quote_within_word, "single quote within word") 590 { 591 struct t_file *tf; 592 int ret; 593 594 tf = t_fopen(NULL); 595 t_fprintf(tf, "hello' 'world\n"); 596 t_frewind(tf); 597 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 598 t_fclose(tf); 599 return (ret); 600 } 601 602 T_FUNC(double_quote_within_word, "double quote within word") 603 { 604 struct t_file *tf; 605 int ret; 606 607 tf = t_fopen(NULL); 608 t_fprintf(tf, "hello\" \"world\n"); 609 t_frewind(tf); 610 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 611 t_fclose(tf); 612 return (ret); 613 } 614 615 T_FUNC(single_quote_after_word, "single quote after word") 616 { 617 struct t_file *tf; 618 int ret; 619 620 tf = t_fopen(NULL); 621 t_fprintf(tf, "hello' world'\n"); 622 t_frewind(tf); 623 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 624 t_fclose(tf); 625 return (ret); 626 } 627 628 T_FUNC(double_quote_after_word, "double quote after word") 629 { 630 struct t_file *tf; 631 int ret; 632 633 tf = t_fopen(NULL); 634 t_fprintf(tf, "hello\" world\"\n"); 635 t_frewind(tf); 636 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 637 t_fclose(tf); 638 return (ret); 639 } 640 641 642 /*************************************************************************** 643 * Combinations of escape and quotes 644 */ 645 646 T_FUNC(escaped_single_quote, 647 "escaped single quote") 648 { 649 struct t_file *tf; 650 int ret; 651 652 tf = t_fopen(NULL); 653 t_fprintf(tf, "\\'\n"); 654 t_frewind(tf); 655 ret = orw_expect(tf, "'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 656 t_fclose(tf); 657 return (ret); 658 } 659 660 T_FUNC(escaped_double_quote, 661 "escaped double quote") 662 { 663 struct t_file *tf; 664 int ret; 665 666 tf = t_fopen(NULL); 667 t_fprintf(tf, "\\\"\n"); 668 t_frewind(tf); 669 ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 670 t_fclose(tf); 671 return (ret); 672 } 673 674 T_FUNC(escaped_whitespace_within_single_quotes, 675 "escaped whitespace within single quotes") 676 { 677 struct t_file *tf; 678 int ret; 679 680 tf = t_fopen(NULL); 681 t_fprintf(tf, "'\\ ' '\\\t' '\\\r' '\\\n'\n"); 682 t_frewind(tf); 683 ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 684 orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 685 orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 686 orw_expect(tf, "\\\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 687 t_fclose(tf); 688 return (ret); 689 } 690 691 T_FUNC(escaped_whitespace_within_double_quotes, 692 "escaped whitespace within double quotes") 693 { 694 struct t_file *tf; 695 int ret; 696 697 tf = t_fopen(NULL); 698 t_fprintf(tf, "\"\\ \" \"\\\t\" \"\\\r\" \"\\\n\"\n"); 699 t_frewind(tf); 700 ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 701 orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 702 orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) && 703 /* this last one is a line continuation */ 704 orw_expect(tf, "", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/); 705 t_fclose(tf); 706 return (ret); 707 } 708 709 T_FUNC(escaped_letter_within_single_quotes, 710 "escaped letter within single quotes") 711 { 712 struct t_file *tf; 713 int ret; 714 715 tf = t_fopen(NULL); 716 t_fprintf(tf, "'\\z'\n"); 717 t_frewind(tf); 718 ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 719 t_fclose(tf); 720 return (ret); 721 } 722 723 T_FUNC(escaped_letter_within_double_quotes, 724 "escaped letter within double quotes") 725 { 726 struct t_file *tf; 727 int ret; 728 729 tf = t_fopen(NULL); 730 t_fprintf(tf, "\"\\z\"\n"); 731 t_frewind(tf); 732 ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 733 t_fclose(tf); 734 return (ret); 735 } 736 737 T_FUNC(escaped_escape_within_single_quotes, 738 "escaped escape within single quotes") 739 { 740 struct t_file *tf; 741 int ret; 742 743 tf = t_fopen(NULL); 744 t_fprintf(tf, "'\\\\'\n"); 745 t_frewind(tf); 746 ret = orw_expect(tf, "\\\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 747 t_fclose(tf); 748 return (ret); 749 } 750 751 T_FUNC(escaped_escape_within_double_quotes, 752 "escaped escape within double quotes") 753 { 754 struct t_file *tf; 755 int ret; 756 757 tf = t_fopen(NULL); 758 t_fprintf(tf, "\"\\\\\"\n"); 759 t_frewind(tf); 760 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 761 t_fclose(tf); 762 return (ret); 763 } 764 765 T_FUNC(escaped_single_quote_within_single_quotes, 766 "escaped single quote within single quotes") 767 { 768 struct t_file *tf; 769 int ret; 770 771 tf = t_fopen(NULL); 772 t_fprintf(tf, "'\\''\n"); 773 t_frewind(tf); 774 ret = orw_expect(tf, NULL, 1 /*lines*/, 1 /*eof*/, 0 /*eol*/); 775 t_fclose(tf); 776 return (ret); 777 } 778 779 T_FUNC(escaped_double_quote_within_single_quotes, 780 "escaped double quote within single quotes") 781 { 782 struct t_file *tf; 783 int ret; 784 785 tf = t_fopen(NULL); 786 t_fprintf(tf, "'\\\"'\n"); 787 t_frewind(tf); 788 ret = orw_expect(tf, "\\\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 789 t_fclose(tf); 790 return (ret); 791 } 792 793 T_FUNC(escaped_single_quote_within_double_quotes, 794 "escaped single quote within double quotes") 795 { 796 struct t_file *tf; 797 int ret; 798 799 tf = t_fopen(NULL); 800 t_fprintf(tf, "\"\\'\"\n"); 801 t_frewind(tf); 802 ret = orw_expect(tf, "\\'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 803 t_fclose(tf); 804 return (ret); 805 } 806 807 T_FUNC(escaped_double_quote_within_double_quotes, 808 "escaped double quote within double quotes") 809 { 810 struct t_file *tf; 811 int ret; 812 813 tf = t_fopen(NULL); 814 t_fprintf(tf, "\"\\\"\"\n"); 815 t_frewind(tf); 816 ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/); 817 t_fclose(tf); 818 return (ret); 819 } 820 821 822 /*************************************************************************** 823 * Boilerplate 824 */ 825 826 static const struct t_test *t_plan[] = { 827 T(empty_input), 828 T(empty_line), 829 T(single_whitespace), 830 T(multiple_whitespace), 831 T(comment), 832 T(whitespace_before_comment), 833 834 T(single_word), 835 T(single_whitespace_before_word), 836 T(double_whitespace_before_word), 837 T(single_whitespace_after_word), 838 T(double_whitespace_after_word), 839 T(comment_after_word), 840 T(word_containing_hash), 841 T(two_words), 842 843 T(naked_escape), 844 T(escaped_escape), 845 T(escaped_whitespace), 846 T(escaped_newline_before_word), 847 T(escaped_newline_within_word), 848 T(escaped_newline_after_word), 849 T(escaped_letter), 850 851 T(naked_single_quote), 852 T(naked_double_quote), 853 T(empty_single_quotes), 854 T(empty_double_quotes), 855 T(single_quotes_within_double_quotes), 856 T(double_quotes_within_single_quotes), 857 T(single_quoted_whitespace), 858 T(double_quoted_whitespace), 859 T(single_quoted_words), 860 T(double_quoted_words), 861 862 T(single_quote_before_word), 863 T(double_quote_before_word), 864 T(single_quote_within_word), 865 T(double_quote_within_word), 866 T(single_quote_after_word), 867 T(double_quote_after_word), 868 869 T(escaped_single_quote), 870 T(escaped_double_quote), 871 T(escaped_whitespace_within_single_quotes), 872 T(escaped_whitespace_within_double_quotes), 873 T(escaped_letter_within_single_quotes), 874 T(escaped_letter_within_double_quotes), 875 T(escaped_escape_within_single_quotes), 876 T(escaped_escape_within_double_quotes), 877 T(escaped_single_quote_within_single_quotes), 878 T(escaped_double_quote_within_single_quotes), 879 T(escaped_single_quote_within_double_quotes), 880 T(escaped_double_quote_within_double_quotes), 881 882 NULL 883 }; 884 885 const struct t_test ** 886 t_prepare(int argc, char *argv[]) 887 { 888 889 (void)argc; 890 (void)argv; 891 return (t_plan); 892 } 893 894 void 895 t_cleanup(void) 896 { 897 } 898