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