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