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