Home | History | Annotate | Line # | Download | only in t
t_openpam_readword.c revision 1.1.1.2
      1 /*	$NetBSD: t_openpam_readword.c,v 1.1.1.2 2013/12/27 19:16:12 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2012 Dag-Erling Smrgrav
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. The name of the author may not be used to endorse or promote
     16  *    products derived from this software without specific prior written
     17  *    permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  *
     31  * Id: t_openpam_readword.c 648 2013-03-05 17:54:27Z des
     32  */
     33 
     34 #ifdef HAVE_CONFIG_H
     35 # include "config.h"
     36 #endif
     37 
     38 #include <err.h>
     39 #include <stdio.h>
     40 #include <stdlib.h>
     41 #include <string.h>
     42 #include <unistd.h>
     43 
     44 #include <security/pam_appl.h>
     45 #include <security/openpam.h>
     46 
     47 #include "t.h"
     48 
     49 /*
     50  * Read a word from the temp file and verify that the result matches our
     51  * expectations: whether a word was read at all, how many lines were read
     52  * (in case of quoted or escaped newlines), whether we reached the end of
     53  * the file and whether we reached the end of the line.
     54  */
     55 static int
     56 orw_expect(struct t_file *tf, const char *expected, int lines, int eof, int eol)
     57 {
     58 	int ch, lineno = 0;
     59 	char *got;
     60 	size_t len;
     61 
     62 	got = openpam_readword(tf->file, &lineno, &len);
     63 	if (t_ferror(tf))
     64 		err(1, "%s(): %s", __func__, tf->name);
     65 	if (expected != NULL && got == NULL) {
     66 		t_verbose("expected <<%s>>, got nothing\n", expected);
     67 		return (0);
     68 	}
     69 	if (expected == NULL && got != NULL) {
     70 		t_verbose("expected nothing, got <<%s>>\n", got);
     71 		return (0);
     72 	}
     73 	if (expected != NULL && got != NULL && strcmp(expected, got) != 0) {
     74 		t_verbose("expected <<%s>>, got <<%s>>\n", expected, got);
     75 		return (0);
     76 	}
     77 	if (lineno != lines) {
     78 		t_verbose("expected to advance %d lines, advanced %d lines\n",
     79 		    lines, lineno);
     80 		return (0);
     81 	}
     82 	if (eof && !t_feof(tf)) {
     83 		t_verbose("expected EOF, but didn't get it\n");
     84 		return (0);
     85 	}
     86 	if (!eof && t_feof(tf)) {
     87 		t_verbose("didn't expect EOF, but got it anyway\n");
     88 		return (0);
     89 	}
     90 	ch = fgetc(tf->file);
     91 	if (t_ferror(tf))
     92 		err(1, "%s(): %s", __func__, tf->name);
     93 	if (eol && ch != '\n') {
     94 		t_verbose("expected EOL, but didn't get it\n");
     95 		return (0);
     96 	}
     97 	if (!eol && ch == '\n') {
     98 		t_verbose("didn't expect EOL, but got it anyway\n");
     99 		return (0);
    100 	}
    101 	if (ch != EOF)
    102 		ungetc(ch, tf->file);
    103 	return (1);
    104 }
    105 
    106 
    107 /***************************************************************************
    109  * Lines without words
    110  */
    111 
    112 T_FUNC(empty_input, "empty input")
    113 {
    114 	struct t_file *tf;
    115 	int ret;
    116 
    117 	tf = t_fopen(NULL);
    118 	ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
    119 	t_fclose(tf);
    120 	return (ret);
    121 }
    122 
    123 T_FUNC(empty_line, "empty line")
    124 {
    125 	struct t_file *tf;
    126 	int ret;
    127 
    128 	tf = t_fopen(NULL);
    129 	t_fprintf(tf, "\n");
    130 	t_frewind(tf);
    131 	ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    132 	t_fclose(tf);
    133 	return (ret);
    134 }
    135 
    136 T_FUNC(unterminated_line, "unterminated line")
    137 {
    138 	struct t_file *tf;
    139 	int ret;
    140 
    141 	tf = t_fopen(NULL);
    142 	t_fprintf(tf, " ");
    143 	t_frewind(tf);
    144 	ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
    145 	t_fclose(tf);
    146 	return (ret);
    147 }
    148 
    149 T_FUNC(single_whitespace, "single whitespace")
    150 {
    151 	struct t_file *tf;
    152 	int ret;
    153 
    154 	tf = t_fopen(NULL);
    155 	t_fprintf(tf, " \n");
    156 	t_frewind(tf);
    157 	ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    158 	t_fclose(tf);
    159 	return (ret);
    160 }
    161 
    162 T_FUNC(multiple_whitespace, "multiple whitespace")
    163 {
    164 	struct t_file *tf;
    165 	int ret;
    166 
    167 	tf = t_fopen(NULL);
    168 	t_fprintf(tf, " \t\r\n");
    169 	t_frewind(tf);
    170 	ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    171 	t_fclose(tf);
    172 	return (ret);
    173 }
    174 
    175 T_FUNC(comment, "comment")
    176 {
    177 	struct t_file *tf;
    178 	int ret;
    179 
    180 	tf = t_fopen(NULL);
    181 	t_fprintf(tf, "# comment\n");
    182 	t_frewind(tf);
    183 	ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    184 	t_fclose(tf);
    185 	return (ret);
    186 }
    187 
    188 T_FUNC(whitespace_before_comment, "whitespace before comment")
    189 {
    190 	struct t_file *tf;
    191 	int ret;
    192 
    193 	tf = t_fopen(NULL);
    194 	t_fprintf(tf, " # comment\n");
    195 	t_frewind(tf);
    196 	ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    197 	t_fclose(tf);
    198 	return (ret);
    199 }
    200 
    201 
    202 /***************************************************************************
    204  * Simple cases - no quotes or escapes
    205  */
    206 
    207 T_FUNC(single_word, "single word")
    208 {
    209 	const char *word = "hello";
    210 	struct t_file *tf;
    211 	int ret;
    212 
    213 	tf = t_fopen(NULL);
    214 	t_fprintf(tf, "%s\n", word);
    215 	t_frewind(tf);
    216 	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    217 	t_fclose(tf);
    218 	return (ret);
    219 }
    220 
    221 T_FUNC(single_whitespace_before_word, "single whitespace before word")
    222 {
    223 	const char *word = "hello";
    224 	struct t_file *tf;
    225 	int ret;
    226 
    227 	tf = t_fopen(NULL);
    228 	t_fprintf(tf, " %s\n", word);
    229 	t_frewind(tf);
    230 	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    231 	t_fclose(tf);
    232 	return (ret);
    233 }
    234 
    235 T_FUNC(double_whitespace_before_word, "double whitespace before word")
    236 {
    237 	const char *word = "hello";
    238 	struct t_file *tf;
    239 	int ret;
    240 
    241 	tf = t_fopen(NULL);
    242 	t_fprintf(tf, "  %s\n", word);
    243 	t_frewind(tf);
    244 	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    245 	t_fclose(tf);
    246 	return (ret);
    247 }
    248 
    249 T_FUNC(single_whitespace_after_word, "single whitespace after word")
    250 {
    251 	const char *word = "hello";
    252 	struct t_file *tf;
    253 	int ret;
    254 
    255 	tf = t_fopen(NULL);
    256 	t_fprintf(tf, "%s \n", word);
    257 	t_frewind(tf);
    258 	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/);
    259 	t_fclose(tf);
    260 	return (ret);
    261 }
    262 
    263 T_FUNC(double_whitespace_after_word, "double whitespace after word")
    264 {
    265 	const char *word = "hello";
    266 	struct t_file *tf;
    267 	int ret;
    268 
    269 	tf = t_fopen(NULL);
    270 	t_fprintf(tf, "%s  \n", word);
    271 	t_frewind(tf);
    272 	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/);
    273 	t_fclose(tf);
    274 	return (ret);
    275 }
    276 
    277 T_FUNC(comment_after_word, "comment after word")
    278 {
    279 	const char *word = "hello";
    280 	struct t_file *tf;
    281 	int ret;
    282 
    283 	tf = t_fopen(NULL);
    284 	t_fprintf(tf, "%s # comment\n", word);
    285 	t_frewind(tf);
    286 	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    287 	    orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    288 	t_fclose(tf);
    289 	return (ret);
    290 }
    291 
    292 T_FUNC(word_containing_hash, "word containing hash")
    293 {
    294 	const char *word = "hello#world";
    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(two_words, "two words")
    307 {
    308 	const char *word[] = { "hello", "world" };
    309 	struct t_file *tf;
    310 	int ret;
    311 
    312 	tf = t_fopen(NULL);
    313 	t_fprintf(tf, "%s %s\n", word[0], word[1]);
    314 	t_frewind(tf);
    315 	ret = orw_expect(tf, word[0], 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    316 	    orw_expect(tf, word[1], 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    317 	t_fclose(tf);
    318 	return (ret);
    319 }
    320 
    321 
    322 /***************************************************************************
    324  * Escapes
    325  */
    326 
    327 T_FUNC(naked_escape, "naked escape")
    328 {
    329 	struct t_file *tf;
    330 	int ret;
    331 
    332 	tf = t_fopen(NULL);
    333 	t_fprintf(tf, "\\");
    334 	t_frewind(tf);
    335 	ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
    336 	t_fclose(tf);
    337 	return (ret);
    338 }
    339 
    340 T_FUNC(escaped_escape, "escaped escape")
    341 {
    342 	struct t_file *tf;
    343 	int ret;
    344 
    345 	tf = t_fopen(NULL);
    346 	t_fprintf(tf, "\\\\\n");
    347 	t_frewind(tf);
    348 	ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    349 	t_fclose(tf);
    350 	return (ret);
    351 }
    352 
    353 T_FUNC(escaped_whitespace, "escaped whitespace")
    354 {
    355 	struct t_file *tf;
    356 	int ret;
    357 
    358 	tf = t_fopen(NULL);
    359 	t_fprintf(tf, "\\  \\\t \\\r \\\n\n");
    360 	t_frewind(tf);
    361 	ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    362 	    orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    363 	    orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    364 	    /* this last one is a line continuation */
    365 	    orw_expect(tf, NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    366 	t_fclose(tf);
    367 	return (ret);
    368 }
    369 
    370 T_FUNC(escaped_newline_before_word, "escaped newline before word")
    371 {
    372 	struct t_file *tf;
    373 	int ret;
    374 
    375 	tf = t_fopen(NULL);
    376 	t_fprintf(tf, "\\\nhello world\n");
    377 	t_frewind(tf);
    378 	ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/);
    379 	t_fclose(tf);
    380 	return (ret);
    381 }
    382 
    383 T_FUNC(escaped_newline_within_word, "escaped newline within word")
    384 {
    385 	struct t_file *tf;
    386 	int ret;
    387 
    388 	tf = t_fopen(NULL);
    389 	t_fprintf(tf, "hello\\\nworld\n");
    390 	t_frewind(tf);
    391 	ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    392 	t_fclose(tf);
    393 	return (ret);
    394 }
    395 
    396 T_FUNC(escaped_newline_after_word, "escaped newline after word")
    397 {
    398 	struct t_file *tf;
    399 	int ret;
    400 
    401 	tf = t_fopen(NULL);
    402 	t_fprintf(tf, "hello\\\n world\n");
    403 	t_frewind(tf);
    404 	ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/);
    405 	t_fclose(tf);
    406 	return (ret);
    407 }
    408 
    409 T_FUNC(escaped_letter, "escaped letter")
    410 {
    411 	struct t_file *tf;
    412 	int ret;
    413 
    414 	tf = t_fopen(NULL);
    415 	t_fprintf(tf, "\\z\n");
    416 	t_frewind(tf);
    417 	ret = orw_expect(tf, "z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    418 	t_fclose(tf);
    419 	return (ret);
    420 }
    421 
    422 
    423 /***************************************************************************
    425  * Quotes
    426  */
    427 
    428 T_FUNC(naked_single_quote, "naked single quote")
    429 {
    430 	struct t_file *tf;
    431 	int ret;
    432 
    433 	tf = t_fopen(NULL);
    434 	t_fprintf(tf, "'");
    435 	t_frewind(tf);
    436 	ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
    437 	t_fclose(tf);
    438 	return (ret);
    439 }
    440 
    441 T_FUNC(naked_double_quote, "naked double quote")
    442 {
    443 	struct t_file *tf;
    444 	int ret;
    445 
    446 	tf = t_fopen(NULL);
    447 	t_fprintf(tf, "\"");
    448 	t_frewind(tf);
    449 	ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
    450 	t_fclose(tf);
    451 	return (ret);
    452 }
    453 
    454 T_FUNC(empty_single_quotes, "empty single quotes")
    455 {
    456 	struct t_file *tf;
    457 	int ret;
    458 
    459 	tf = t_fopen(NULL);
    460 	t_fprintf(tf, "''\n");
    461 	t_frewind(tf);
    462 	ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    463 	t_fclose(tf);
    464 	return (ret);
    465 }
    466 
    467 T_FUNC(empty_double_quotes, "empty double quotes")
    468 {
    469 	struct t_file *tf;
    470 	int ret;
    471 
    472 	tf = t_fopen(NULL);
    473 	t_fprintf(tf, "\"\"\n");
    474 	t_frewind(tf);
    475 	ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    476 	t_fclose(tf);
    477 	return (ret);
    478 }
    479 
    480 T_FUNC(single_quotes_within_double_quotes, "single quotes within double quotes")
    481 {
    482 	struct t_file *tf;
    483 	int ret;
    484 
    485 	tf = t_fopen(NULL);
    486 	t_fprintf(tf, "\"' '\"\n");
    487 	t_frewind(tf);
    488 	ret = orw_expect(tf, "' '", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    489 	t_fclose(tf);
    490 	return (ret);
    491 }
    492 
    493 T_FUNC(double_quotes_within_single_quotes, "double quotes within single quotes")
    494 {
    495 	struct t_file *tf;
    496 	int ret;
    497 
    498 	tf = t_fopen(NULL);
    499 	t_fprintf(tf, "'\" \"'\n");
    500 	t_frewind(tf);
    501 	ret = orw_expect(tf, "\" \"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    502 	t_fclose(tf);
    503 	return (ret);
    504 }
    505 
    506 T_FUNC(single_quoted_whitespace, "single-quoted whitespace")
    507 {
    508 	struct t_file *tf;
    509 	int ret;
    510 
    511 	tf = t_fopen(NULL);
    512 	t_fprintf(tf, "' ' '\t' '\r' '\n'\n");
    513 	t_frewind(tf);
    514 	ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    515 	    orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    516 	    orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    517 	    orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    518 	t_fclose(tf);
    519 	return (ret);
    520 }
    521 
    522 T_FUNC(double_quoted_whitespace, "double-quoted whitespace")
    523 {
    524 	struct t_file *tf;
    525 	int ret;
    526 
    527 	tf = t_fopen(NULL);
    528 	t_fprintf(tf, "\" \" \"\t\" \"\r\" \"\n\"\n");
    529 	t_frewind(tf);
    530 	ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    531 	    orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    532 	    orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    533 	    orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    534 	t_fclose(tf);
    535 	return (ret);
    536 }
    537 
    538 T_FUNC(single_quoted_words, "single-quoted words")
    539 {
    540 	struct t_file *tf;
    541 	int ret;
    542 
    543 	tf = t_fopen(NULL);
    544 	t_fprintf(tf, "'hello world'\n");
    545 	t_frewind(tf);
    546 	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    547 	t_fclose(tf);
    548 	return (ret);
    549 }
    550 
    551 T_FUNC(double_quoted_words, "double-quoted words")
    552 {
    553 	struct t_file *tf;
    554 	int ret;
    555 
    556 	tf = t_fopen(NULL);
    557 	t_fprintf(tf, "\"hello world\"\n");
    558 	t_frewind(tf);
    559 	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    560 	t_fclose(tf);
    561 	return (ret);
    562 }
    563 
    564 
    565 /***************************************************************************
    567  * Combinations of quoted and unquoted text
    568  */
    569 
    570 T_FUNC(single_quote_before_word, "single quote before word")
    571 {
    572 	struct t_file *tf;
    573 	int ret;
    574 
    575 	tf = t_fopen(NULL);
    576 	t_fprintf(tf, "'hello 'world\n");
    577 	t_frewind(tf);
    578 	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    579 	t_fclose(tf);
    580 	return (ret);
    581 }
    582 
    583 T_FUNC(double_quote_before_word, "double quote before word")
    584 {
    585 	struct t_file *tf;
    586 	int ret;
    587 
    588 	tf = t_fopen(NULL);
    589 	t_fprintf(tf, "\"hello \"world\n");
    590 	t_frewind(tf);
    591 	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    592 	t_fclose(tf);
    593 	return (ret);
    594 }
    595 
    596 T_FUNC(single_quote_within_word, "single quote within word")
    597 {
    598 	struct t_file *tf;
    599 	int ret;
    600 
    601 	tf = t_fopen(NULL);
    602 	t_fprintf(tf, "hello' 'world\n");
    603 	t_frewind(tf);
    604 	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    605 	t_fclose(tf);
    606 	return (ret);
    607 }
    608 
    609 T_FUNC(double_quote_within_word, "double quote within word")
    610 {
    611 	struct t_file *tf;
    612 	int ret;
    613 
    614 	tf = t_fopen(NULL);
    615 	t_fprintf(tf, "hello\" \"world\n");
    616 	t_frewind(tf);
    617 	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    618 	t_fclose(tf);
    619 	return (ret);
    620 }
    621 
    622 T_FUNC(single_quote_after_word, "single quote after word")
    623 {
    624 	struct t_file *tf;
    625 	int ret;
    626 
    627 	tf = t_fopen(NULL);
    628 	t_fprintf(tf, "hello' world'\n");
    629 	t_frewind(tf);
    630 	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    631 	t_fclose(tf);
    632 	return (ret);
    633 }
    634 
    635 T_FUNC(double_quote_after_word, "double quote after word")
    636 {
    637 	struct t_file *tf;
    638 	int ret;
    639 
    640 	tf = t_fopen(NULL);
    641 	t_fprintf(tf, "hello\" world\"\n");
    642 	t_frewind(tf);
    643 	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    644 	t_fclose(tf);
    645 	return (ret);
    646 }
    647 
    648 
    649 /***************************************************************************
    651  * Combinations of escape and quotes
    652  */
    653 
    654 T_FUNC(escaped_single_quote,
    655     "escaped single quote")
    656 {
    657 	struct t_file *tf;
    658 	int ret;
    659 
    660 	tf = t_fopen(NULL);
    661 	t_fprintf(tf, "\\'\n");
    662 	t_frewind(tf);
    663 	ret = orw_expect(tf, "'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    664 	t_fclose(tf);
    665 	return (ret);
    666 }
    667 
    668 T_FUNC(escaped_double_quote,
    669     "escaped double quote")
    670 {
    671 	struct t_file *tf;
    672 	int ret;
    673 
    674 	tf = t_fopen(NULL);
    675 	t_fprintf(tf, "\\\"\n");
    676 	t_frewind(tf);
    677 	ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    678 	t_fclose(tf);
    679 	return (ret);
    680 }
    681 
    682 T_FUNC(escaped_whitespace_within_single_quotes,
    683     "escaped whitespace within single quotes")
    684 {
    685 	struct t_file *tf;
    686 	int ret;
    687 
    688 	tf = t_fopen(NULL);
    689 	t_fprintf(tf, "'\\ ' '\\\t' '\\\r' '\\\n'\n");
    690 	t_frewind(tf);
    691 	ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    692 	    orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    693 	    orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    694 	    orw_expect(tf, "\\\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    695 	t_fclose(tf);
    696 	return (ret);
    697 }
    698 
    699 T_FUNC(escaped_whitespace_within_double_quotes,
    700     "escaped whitespace within double quotes")
    701 {
    702 	struct t_file *tf;
    703 	int ret;
    704 
    705 	tf = t_fopen(NULL);
    706 	t_fprintf(tf, "\"\\ \" \"\\\t\" \"\\\r\" \"\\\n\"\n");
    707 	t_frewind(tf);
    708 	ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    709 	    orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    710 	    orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
    711 	    /* this last one is a line continuation */
    712 	    orw_expect(tf, "", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    713 	t_fclose(tf);
    714 	return (ret);
    715 }
    716 
    717 T_FUNC(escaped_letter_within_single_quotes,
    718     "escaped letter within single quotes")
    719 {
    720 	struct t_file *tf;
    721 	int ret;
    722 
    723 	tf = t_fopen(NULL);
    724 	t_fprintf(tf, "'\\z'\n");
    725 	t_frewind(tf);
    726 	ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    727 	t_fclose(tf);
    728 	return (ret);
    729 }
    730 
    731 T_FUNC(escaped_letter_within_double_quotes,
    732     "escaped letter within double quotes")
    733 {
    734 	struct t_file *tf;
    735 	int ret;
    736 
    737 	tf = t_fopen(NULL);
    738 	t_fprintf(tf, "\"\\z\"\n");
    739 	t_frewind(tf);
    740 	ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    741 	t_fclose(tf);
    742 	return (ret);
    743 }
    744 
    745 T_FUNC(escaped_escape_within_single_quotes,
    746     "escaped escape within single quotes")
    747 {
    748 	struct t_file *tf;
    749 	int ret;
    750 
    751 	tf = t_fopen(NULL);
    752 	t_fprintf(tf, "'\\\\'\n");
    753 	t_frewind(tf);
    754 	ret = orw_expect(tf, "\\\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    755 	t_fclose(tf);
    756 	return (ret);
    757 }
    758 
    759 T_FUNC(escaped_escape_within_double_quotes,
    760     "escaped escape within double quotes")
    761 {
    762 	struct t_file *tf;
    763 	int ret;
    764 
    765 	tf = t_fopen(NULL);
    766 	t_fprintf(tf, "\"\\\\\"\n");
    767 	t_frewind(tf);
    768 	ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    769 	t_fclose(tf);
    770 	return (ret);
    771 }
    772 
    773 T_FUNC(escaped_single_quote_within_single_quotes,
    774     "escaped single quote within single quotes")
    775 {
    776 	struct t_file *tf;
    777 	int ret;
    778 
    779 	tf = t_fopen(NULL);
    780 	t_fprintf(tf, "'\\''\n");
    781 	t_frewind(tf);
    782 	ret = orw_expect(tf, NULL, 1 /*lines*/, 1 /*eof*/, 0 /*eol*/);
    783 	t_fclose(tf);
    784 	return (ret);
    785 }
    786 
    787 T_FUNC(escaped_double_quote_within_single_quotes,
    788     "escaped double quote within single quotes")
    789 {
    790 	struct t_file *tf;
    791 	int ret;
    792 
    793 	tf = t_fopen(NULL);
    794 	t_fprintf(tf, "'\\\"'\n");
    795 	t_frewind(tf);
    796 	ret = orw_expect(tf, "\\\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    797 	t_fclose(tf);
    798 	return (ret);
    799 }
    800 
    801 T_FUNC(escaped_single_quote_within_double_quotes,
    802     "escaped single quote within double quotes")
    803 {
    804 	struct t_file *tf;
    805 	int ret;
    806 
    807 	tf = t_fopen(NULL);
    808 	t_fprintf(tf, "\"\\'\"\n");
    809 	t_frewind(tf);
    810 	ret = orw_expect(tf, "\\'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    811 	t_fclose(tf);
    812 	return (ret);
    813 }
    814 
    815 T_FUNC(escaped_double_quote_within_double_quotes,
    816     "escaped double quote within double quotes")
    817 {
    818 	struct t_file *tf;
    819 	int ret;
    820 
    821 	tf = t_fopen(NULL);
    822 	t_fprintf(tf, "\"\\\"\"\n");
    823 	t_frewind(tf);
    824 	ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
    825 	t_fclose(tf);
    826 	return (ret);
    827 }
    828 
    829 
    830 /***************************************************************************
    832  * Boilerplate
    833  */
    834 
    835 const struct t_test *t_plan[] = {
    836 	T(empty_input),
    837 	T(empty_line),
    838 	T(single_whitespace),
    839 	T(multiple_whitespace),
    840 	T(comment),
    841 	T(whitespace_before_comment),
    842 
    843 	T(single_word),
    844 	T(single_whitespace_before_word),
    845 	T(double_whitespace_before_word),
    846 	T(single_whitespace_after_word),
    847 	T(double_whitespace_after_word),
    848 	T(comment_after_word),
    849 	T(word_containing_hash),
    850 	T(two_words),
    851 
    852 	T(naked_escape),
    853 	T(escaped_escape),
    854 	T(escaped_whitespace),
    855 	T(escaped_newline_before_word),
    856 	T(escaped_newline_within_word),
    857 	T(escaped_newline_after_word),
    858 	T(escaped_letter),
    859 
    860 	T(naked_single_quote),
    861 	T(naked_double_quote),
    862 	T(empty_single_quotes),
    863 	T(empty_double_quotes),
    864 	T(single_quotes_within_double_quotes),
    865 	T(double_quotes_within_single_quotes),
    866 	T(single_quoted_whitespace),
    867 	T(double_quoted_whitespace),
    868 	T(single_quoted_words),
    869 	T(double_quoted_words),
    870 
    871 	T(single_quote_before_word),
    872 	T(double_quote_before_word),
    873 	T(single_quote_within_word),
    874 	T(double_quote_within_word),
    875 	T(single_quote_after_word),
    876 	T(double_quote_after_word),
    877 
    878 	T(escaped_single_quote),
    879 	T(escaped_double_quote),
    880 	T(escaped_whitespace_within_single_quotes),
    881 	T(escaped_whitespace_within_double_quotes),
    882 	T(escaped_letter_within_single_quotes),
    883 	T(escaped_letter_within_double_quotes),
    884 	T(escaped_escape_within_single_quotes),
    885 	T(escaped_escape_within_double_quotes),
    886 	T(escaped_single_quote_within_single_quotes),
    887 	T(escaped_double_quote_within_single_quotes),
    888 	T(escaped_single_quote_within_double_quotes),
    889 	T(escaped_double_quote_within_double_quotes),
    890 
    891 	NULL
    892 };
    893 
    894 const struct t_test **
    895 t_prepare(int argc, char *argv[])
    896 {
    897 
    898 	(void)argc;
    899 	(void)argv;
    900 	return (t_plan);
    901 }
    902 
    903 void
    904 t_cleanup(void)
    905 {
    906 }
    907