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