t_openpam_readword.c revision 255376
1236099Sdes/*-
2236099Sdes * Copyright (c) 2012 Dag-Erling Sm��rgrav
3236099Sdes * All rights reserved.
4236099Sdes *
5236099Sdes * Redistribution and use in source and binary forms, with or without
6236099Sdes * modification, are permitted provided that the following conditions
7236099Sdes * are met:
8236099Sdes * 1. Redistributions of source code must retain the above copyright
9255376Sdes *    notice, this list of conditions and the following disclaimer.
10236099Sdes * 2. Redistributions in binary form must reproduce the above copyright
11236099Sdes *    notice, this list of conditions and the following disclaimer in the
12236099Sdes *    documentation and/or other materials provided with the distribution.
13236099Sdes * 3. The name of the author may not be used to endorse or promote
14236099Sdes *    products derived from this software without specific prior written
15236099Sdes *    permission.
16236099Sdes *
17236099Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18236099Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19236099Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20236099Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21236099Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22236099Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23236099Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24236099Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25236099Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26236099Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27236099Sdes * SUCH DAMAGE.
28236099Sdes *
29255376Sdes * $Id: t_openpam_readword.c 648 2013-03-05 17:54:27Z des $
30236099Sdes */
31236099Sdes
32236099Sdes#ifdef HAVE_CONFIG_H
33236099Sdes# include "config.h"
34236099Sdes#endif
35236099Sdes
36236099Sdes#include <err.h>
37236099Sdes#include <stdio.h>
38236099Sdes#include <stdlib.h>
39236099Sdes#include <string.h>
40236099Sdes#include <unistd.h>
41236099Sdes
42236099Sdes#include <security/pam_appl.h>
43236099Sdes#include <security/openpam.h>
44236099Sdes
45236099Sdes#include "t.h"
46236099Sdes
47236099Sdes/*
48236099Sdes * Read a word from the temp file and verify that the result matches our
49236099Sdes * expectations: whether a word was read at all, how many lines were read
50236099Sdes * (in case of quoted or escaped newlines), whether we reached the end of
51236099Sdes * the file and whether we reached the end of the line.
52236099Sdes */
53236099Sdesstatic int
54255376Sdesorw_expect(struct t_file *tf, const char *expected, int lines, int eof, int eol)
55236099Sdes{
56236099Sdes	int ch, lineno = 0;
57236099Sdes	char *got;
58236099Sdes	size_t len;
59236099Sdes
60255376Sdes	got = openpam_readword(tf->file, &lineno, &len);
61255376Sdes	if (t_ferror(tf))
62255376Sdes		err(1, "%s(): %s", __func__, tf->name);
63236099Sdes	if (expected != NULL && got == NULL) {
64236099Sdes		t_verbose("expected <<%s>>, got nothing\n", expected);
65236099Sdes		return (0);
66236099Sdes	}
67236099Sdes	if (expected == NULL && got != NULL) {
68236099Sdes		t_verbose("expected nothing, got <<%s>>\n", got);
69236099Sdes		return (0);
70236099Sdes	}
71236099Sdes	if (expected != NULL && got != NULL && strcmp(expected, got) != 0) {
72236099Sdes		t_verbose("expected <<%s>>, got <<%s>>\n", expected, got);
73236099Sdes		return (0);
74236099Sdes	}
75236099Sdes	if (lineno != lines) {
76236099Sdes		t_verbose("expected to advance %d lines, advanced %d lines\n",
77236099Sdes		    lines, lineno);
78236099Sdes		return (0);
79236099Sdes	}
80255376Sdes	if (eof && !t_feof(tf)) {
81236099Sdes		t_verbose("expected EOF, but didn't get it\n");
82236099Sdes		return (0);
83236099Sdes	}
84255376Sdes	if (!eof && t_feof(tf)) {
85236099Sdes		t_verbose("didn't expect EOF, but got it anyway\n");
86236099Sdes		return (0);
87236099Sdes	}
88255376Sdes	ch = fgetc(tf->file);
89255376Sdes	if (t_ferror(tf))
90255376Sdes		err(1, "%s(): %s", __func__, tf->name);
91236099Sdes	if (eol && ch != '\n') {
92236099Sdes		t_verbose("expected EOL, but didn't get it\n");
93236099Sdes		return (0);
94236099Sdes	}
95236099Sdes	if (!eol && ch == '\n') {
96236099Sdes		t_verbose("didn't expect EOL, but got it anyway\n");
97236099Sdes		return (0);
98236099Sdes	}
99236099Sdes	if (ch != EOF)
100255376Sdes		ungetc(ch, tf->file);
101236099Sdes	return (1);
102236099Sdes}
103236099Sdes
104236099Sdes
105236099Sdes/***************************************************************************
106236099Sdes * Lines without words
107236099Sdes */
108236099Sdes
109236099SdesT_FUNC(empty_input, "empty input")
110236099Sdes{
111255376Sdes	struct t_file *tf;
112236099Sdes	int ret;
113236099Sdes
114255376Sdes	tf = t_fopen(NULL);
115255376Sdes	ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
116255376Sdes	t_fclose(tf);
117236099Sdes	return (ret);
118236099Sdes}
119236099Sdes
120236099SdesT_FUNC(empty_line, "empty line")
121236099Sdes{
122255376Sdes	struct t_file *tf;
123236099Sdes	int ret;
124236099Sdes
125255376Sdes	tf = t_fopen(NULL);
126255376Sdes	t_fprintf(tf, "\n");
127255376Sdes	t_frewind(tf);
128255376Sdes	ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
129255376Sdes	t_fclose(tf);
130236099Sdes	return (ret);
131236099Sdes}
132236099Sdes
133236099SdesT_FUNC(unterminated_line, "unterminated line")
134236099Sdes{
135255376Sdes	struct t_file *tf;
136236099Sdes	int ret;
137236099Sdes
138255376Sdes	tf = t_fopen(NULL);
139255376Sdes	t_fprintf(tf, " ");
140255376Sdes	t_frewind(tf);
141255376Sdes	ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
142255376Sdes	t_fclose(tf);
143236099Sdes	return (ret);
144236099Sdes}
145236099Sdes
146236099SdesT_FUNC(single_whitespace, "single whitespace")
147236099Sdes{
148255376Sdes	struct t_file *tf;
149236099Sdes	int ret;
150236099Sdes
151255376Sdes	tf = t_fopen(NULL);
152255376Sdes	t_fprintf(tf, " \n");
153255376Sdes	t_frewind(tf);
154255376Sdes	ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
155255376Sdes	t_fclose(tf);
156236099Sdes	return (ret);
157236099Sdes}
158236099Sdes
159236099SdesT_FUNC(multiple_whitespace, "multiple whitespace")
160236099Sdes{
161255376Sdes	struct t_file *tf;
162236099Sdes	int ret;
163236099Sdes
164255376Sdes	tf = t_fopen(NULL);
165255376Sdes	t_fprintf(tf, " \t\r\n");
166255376Sdes	t_frewind(tf);
167255376Sdes	ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
168255376Sdes	t_fclose(tf);
169236099Sdes	return (ret);
170236099Sdes}
171236099Sdes
172236099SdesT_FUNC(comment, "comment")
173236099Sdes{
174255376Sdes	struct t_file *tf;
175236099Sdes	int ret;
176236099Sdes
177255376Sdes	tf = t_fopen(NULL);
178255376Sdes	t_fprintf(tf, "# comment\n");
179255376Sdes	t_frewind(tf);
180255376Sdes	ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
181255376Sdes	t_fclose(tf);
182236099Sdes	return (ret);
183236099Sdes}
184236099Sdes
185236099SdesT_FUNC(whitespace_before_comment, "whitespace before comment")
186236099Sdes{
187255376Sdes	struct t_file *tf;
188236099Sdes	int ret;
189236099Sdes
190255376Sdes	tf = t_fopen(NULL);
191255376Sdes	t_fprintf(tf, " # comment\n");
192255376Sdes	t_frewind(tf);
193255376Sdes	ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
194255376Sdes	t_fclose(tf);
195236099Sdes	return (ret);
196236099Sdes}
197236099Sdes
198236099Sdes
199236099Sdes/***************************************************************************
200236099Sdes * Simple cases - no quotes or escapes
201236099Sdes */
202236099Sdes
203236099SdesT_FUNC(single_word, "single word")
204236099Sdes{
205236099Sdes	const char *word = "hello";
206255376Sdes	struct t_file *tf;
207236099Sdes	int ret;
208236099Sdes
209255376Sdes	tf = t_fopen(NULL);
210255376Sdes	t_fprintf(tf, "%s\n", word);
211255376Sdes	t_frewind(tf);
212255376Sdes	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
213255376Sdes	t_fclose(tf);
214236099Sdes	return (ret);
215236099Sdes}
216236099Sdes
217236099SdesT_FUNC(single_whitespace_before_word, "single whitespace before word")
218236099Sdes{
219236099Sdes	const char *word = "hello";
220255376Sdes	struct t_file *tf;
221236099Sdes	int ret;
222236099Sdes
223255376Sdes	tf = t_fopen(NULL);
224255376Sdes	t_fprintf(tf, " %s\n", word);
225255376Sdes	t_frewind(tf);
226255376Sdes	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
227255376Sdes	t_fclose(tf);
228236099Sdes	return (ret);
229236099Sdes}
230236099Sdes
231236099SdesT_FUNC(double_whitespace_before_word, "double whitespace before word")
232236099Sdes{
233236099Sdes	const char *word = "hello";
234255376Sdes	struct t_file *tf;
235236099Sdes	int ret;
236236099Sdes
237255376Sdes	tf = t_fopen(NULL);
238255376Sdes	t_fprintf(tf, "  %s\n", word);
239255376Sdes	t_frewind(tf);
240255376Sdes	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
241255376Sdes	t_fclose(tf);
242236099Sdes	return (ret);
243236099Sdes}
244236099Sdes
245236099SdesT_FUNC(single_whitespace_after_word, "single whitespace after word")
246236099Sdes{
247236099Sdes	const char *word = "hello";
248255376Sdes	struct t_file *tf;
249236099Sdes	int ret;
250236099Sdes
251255376Sdes	tf = t_fopen(NULL);
252255376Sdes	t_fprintf(tf, "%s \n", word);
253255376Sdes	t_frewind(tf);
254255376Sdes	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/);
255255376Sdes	t_fclose(tf);
256236099Sdes	return (ret);
257236099Sdes}
258236099Sdes
259236099SdesT_FUNC(double_whitespace_after_word, "double whitespace after word")
260236099Sdes{
261236099Sdes	const char *word = "hello";
262255376Sdes	struct t_file *tf;
263236099Sdes	int ret;
264236099Sdes
265255376Sdes	tf = t_fopen(NULL);
266255376Sdes	t_fprintf(tf, "%s  \n", word);
267255376Sdes	t_frewind(tf);
268255376Sdes	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/);
269255376Sdes	t_fclose(tf);
270236099Sdes	return (ret);
271236099Sdes}
272236099Sdes
273236099SdesT_FUNC(comment_after_word, "comment after word")
274236099Sdes{
275236099Sdes	const char *word = "hello";
276255376Sdes	struct t_file *tf;
277236099Sdes	int ret;
278236099Sdes
279255376Sdes	tf = t_fopen(NULL);
280255376Sdes	t_fprintf(tf, "%s # comment\n", word);
281255376Sdes	t_frewind(tf);
282255376Sdes	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
283255376Sdes	    orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
284255376Sdes	t_fclose(tf);
285236099Sdes	return (ret);
286236099Sdes}
287236099Sdes
288236099SdesT_FUNC(word_containing_hash, "word containing hash")
289236099Sdes{
290236099Sdes	const char *word = "hello#world";
291255376Sdes	struct t_file *tf;
292236099Sdes	int ret;
293236099Sdes
294255376Sdes	tf = t_fopen(NULL);
295255376Sdes	t_fprintf(tf, "%s\n", word);
296255376Sdes	t_frewind(tf);
297255376Sdes	ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
298255376Sdes	t_fclose(tf);
299236099Sdes	return (ret);
300236099Sdes}
301236099Sdes
302236099SdesT_FUNC(two_words, "two words")
303236099Sdes{
304236099Sdes	const char *word[] = { "hello", "world" };
305255376Sdes	struct t_file *tf;
306236099Sdes	int ret;
307236099Sdes
308255376Sdes	tf = t_fopen(NULL);
309255376Sdes	t_fprintf(tf, "%s %s\n", word[0], word[1]);
310255376Sdes	t_frewind(tf);
311255376Sdes	ret = orw_expect(tf, word[0], 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
312255376Sdes	    orw_expect(tf, word[1], 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
313255376Sdes	t_fclose(tf);
314236099Sdes	return (ret);
315236099Sdes}
316236099Sdes
317236099Sdes
318236099Sdes/***************************************************************************
319236099Sdes * Escapes
320236099Sdes */
321236099Sdes
322236099SdesT_FUNC(naked_escape, "naked escape")
323236099Sdes{
324255376Sdes	struct t_file *tf;
325236099Sdes	int ret;
326236099Sdes
327255376Sdes	tf = t_fopen(NULL);
328255376Sdes	t_fprintf(tf, "\\");
329255376Sdes	t_frewind(tf);
330255376Sdes	ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
331255376Sdes	t_fclose(tf);
332236099Sdes	return (ret);
333236099Sdes}
334236099Sdes
335236099SdesT_FUNC(escaped_escape, "escaped escape")
336236099Sdes{
337255376Sdes	struct t_file *tf;
338236099Sdes	int ret;
339236099Sdes
340255376Sdes	tf = t_fopen(NULL);
341255376Sdes	t_fprintf(tf, "\\\\\n");
342255376Sdes	t_frewind(tf);
343255376Sdes	ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
344255376Sdes	t_fclose(tf);
345236099Sdes	return (ret);
346236099Sdes}
347236099Sdes
348236099SdesT_FUNC(escaped_whitespace, "escaped whitespace")
349236099Sdes{
350255376Sdes	struct t_file *tf;
351236099Sdes	int ret;
352236099Sdes
353255376Sdes	tf = t_fopen(NULL);
354255376Sdes	t_fprintf(tf, "\\  \\\t \\\r \\\n\n");
355255376Sdes	t_frewind(tf);
356255376Sdes	ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
357255376Sdes	    orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
358255376Sdes	    orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
359236099Sdes	    /* this last one is a line continuation */
360255376Sdes	    orw_expect(tf, NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
361255376Sdes	t_fclose(tf);
362236099Sdes	return (ret);
363236099Sdes}
364236099Sdes
365236099SdesT_FUNC(escaped_newline_before_word, "escaped newline before word")
366236099Sdes{
367255376Sdes	struct t_file *tf;
368236099Sdes	int ret;
369236099Sdes
370255376Sdes	tf = t_fopen(NULL);
371255376Sdes	t_fprintf(tf, "\\\nhello world\n");
372255376Sdes	t_frewind(tf);
373255376Sdes	ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/);
374255376Sdes	t_fclose(tf);
375236099Sdes	return (ret);
376236099Sdes}
377236099Sdes
378236099SdesT_FUNC(escaped_newline_within_word, "escaped newline within word")
379236099Sdes{
380255376Sdes	struct t_file *tf;
381236099Sdes	int ret;
382236099Sdes
383255376Sdes	tf = t_fopen(NULL);
384255376Sdes	t_fprintf(tf, "hello\\\nworld\n");
385255376Sdes	t_frewind(tf);
386255376Sdes	ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
387255376Sdes	t_fclose(tf);
388236099Sdes	return (ret);
389236099Sdes}
390236099Sdes
391236099SdesT_FUNC(escaped_newline_after_word, "escaped newline after word")
392236099Sdes{
393255376Sdes	struct t_file *tf;
394236099Sdes	int ret;
395236099Sdes
396255376Sdes	tf = t_fopen(NULL);
397255376Sdes	t_fprintf(tf, "hello\\\n world\n");
398255376Sdes	t_frewind(tf);
399255376Sdes	ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/);
400255376Sdes	t_fclose(tf);
401236099Sdes	return (ret);
402236099Sdes}
403236099Sdes
404236099SdesT_FUNC(escaped_letter, "escaped letter")
405236099Sdes{
406255376Sdes	struct t_file *tf;
407236099Sdes	int ret;
408236099Sdes
409255376Sdes	tf = t_fopen(NULL);
410255376Sdes	t_fprintf(tf, "\\z\n");
411255376Sdes	t_frewind(tf);
412255376Sdes	ret = orw_expect(tf, "z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
413255376Sdes	t_fclose(tf);
414236099Sdes	return (ret);
415236099Sdes}
416236099Sdes
417236099Sdes
418236099Sdes/***************************************************************************
419236099Sdes * Quotes
420236099Sdes */
421236099Sdes
422236099SdesT_FUNC(naked_single_quote, "naked single quote")
423236099Sdes{
424255376Sdes	struct t_file *tf;
425236099Sdes	int ret;
426236099Sdes
427255376Sdes	tf = t_fopen(NULL);
428255376Sdes	t_fprintf(tf, "'");
429255376Sdes	t_frewind(tf);
430255376Sdes	ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
431255376Sdes	t_fclose(tf);
432236099Sdes	return (ret);
433236099Sdes}
434236099Sdes
435236099SdesT_FUNC(naked_double_quote, "naked double quote")
436236099Sdes{
437255376Sdes	struct t_file *tf;
438236099Sdes	int ret;
439236099Sdes
440255376Sdes	tf = t_fopen(NULL);
441255376Sdes	t_fprintf(tf, "\"");
442255376Sdes	t_frewind(tf);
443255376Sdes	ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
444255376Sdes	t_fclose(tf);
445236099Sdes	return (ret);
446236099Sdes}
447236099Sdes
448236099SdesT_FUNC(empty_single_quotes, "empty single quotes")
449236099Sdes{
450255376Sdes	struct t_file *tf;
451236099Sdes	int ret;
452236099Sdes
453255376Sdes	tf = t_fopen(NULL);
454255376Sdes	t_fprintf(tf, "''\n");
455255376Sdes	t_frewind(tf);
456255376Sdes	ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
457255376Sdes	t_fclose(tf);
458236099Sdes	return (ret);
459236099Sdes}
460236099Sdes
461236099SdesT_FUNC(empty_double_quotes, "empty double quotes")
462236099Sdes{
463255376Sdes	struct t_file *tf;
464236099Sdes	int ret;
465236099Sdes
466255376Sdes	tf = t_fopen(NULL);
467255376Sdes	t_fprintf(tf, "\"\"\n");
468255376Sdes	t_frewind(tf);
469255376Sdes	ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
470255376Sdes	t_fclose(tf);
471236099Sdes	return (ret);
472236099Sdes}
473236099Sdes
474236099SdesT_FUNC(single_quotes_within_double_quotes, "single quotes within double quotes")
475236099Sdes{
476255376Sdes	struct t_file *tf;
477236099Sdes	int ret;
478236099Sdes
479255376Sdes	tf = t_fopen(NULL);
480255376Sdes	t_fprintf(tf, "\"' '\"\n");
481255376Sdes	t_frewind(tf);
482255376Sdes	ret = orw_expect(tf, "' '", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
483255376Sdes	t_fclose(tf);
484236099Sdes	return (ret);
485236099Sdes}
486236099Sdes
487236099SdesT_FUNC(double_quotes_within_single_quotes, "double quotes within single quotes")
488236099Sdes{
489255376Sdes	struct t_file *tf;
490236099Sdes	int ret;
491236099Sdes
492255376Sdes	tf = t_fopen(NULL);
493255376Sdes	t_fprintf(tf, "'\" \"'\n");
494255376Sdes	t_frewind(tf);
495255376Sdes	ret = orw_expect(tf, "\" \"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
496255376Sdes	t_fclose(tf);
497236099Sdes	return (ret);
498236099Sdes}
499236099Sdes
500236099SdesT_FUNC(single_quoted_whitespace, "single-quoted whitespace")
501236099Sdes{
502255376Sdes	struct t_file *tf;
503236099Sdes	int ret;
504236099Sdes
505255376Sdes	tf = t_fopen(NULL);
506255376Sdes	t_fprintf(tf, "' ' '\t' '\r' '\n'\n");
507255376Sdes	t_frewind(tf);
508255376Sdes	ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
509255376Sdes	    orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
510255376Sdes	    orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
511255376Sdes	    orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
512255376Sdes	t_fclose(tf);
513236099Sdes	return (ret);
514236099Sdes}
515236099Sdes
516236099SdesT_FUNC(double_quoted_whitespace, "double-quoted whitespace")
517236099Sdes{
518255376Sdes	struct t_file *tf;
519236099Sdes	int ret;
520236099Sdes
521255376Sdes	tf = t_fopen(NULL);
522255376Sdes	t_fprintf(tf, "\" \" \"\t\" \"\r\" \"\n\"\n");
523255376Sdes	t_frewind(tf);
524255376Sdes	ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
525255376Sdes	    orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
526255376Sdes	    orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
527255376Sdes	    orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
528255376Sdes	t_fclose(tf);
529236099Sdes	return (ret);
530236099Sdes}
531236099Sdes
532236099SdesT_FUNC(single_quoted_words, "single-quoted words")
533236099Sdes{
534255376Sdes	struct t_file *tf;
535236099Sdes	int ret;
536236099Sdes
537255376Sdes	tf = t_fopen(NULL);
538255376Sdes	t_fprintf(tf, "'hello world'\n");
539255376Sdes	t_frewind(tf);
540255376Sdes	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
541255376Sdes	t_fclose(tf);
542236099Sdes	return (ret);
543236099Sdes}
544236099Sdes
545236099SdesT_FUNC(double_quoted_words, "double-quoted words")
546236099Sdes{
547255376Sdes	struct t_file *tf;
548236099Sdes	int ret;
549236099Sdes
550255376Sdes	tf = t_fopen(NULL);
551255376Sdes	t_fprintf(tf, "\"hello world\"\n");
552255376Sdes	t_frewind(tf);
553255376Sdes	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
554255376Sdes	t_fclose(tf);
555236099Sdes	return (ret);
556236099Sdes}
557236099Sdes
558236099Sdes
559236099Sdes/***************************************************************************
560255376Sdes * Combinations of quoted and unquoted text
561255376Sdes */
562255376Sdes
563255376SdesT_FUNC(single_quote_before_word, "single quote before word")
564255376Sdes{
565255376Sdes	struct t_file *tf;
566255376Sdes	int ret;
567255376Sdes
568255376Sdes	tf = t_fopen(NULL);
569255376Sdes	t_fprintf(tf, "'hello 'world\n");
570255376Sdes	t_frewind(tf);
571255376Sdes	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
572255376Sdes	t_fclose(tf);
573255376Sdes	return (ret);
574255376Sdes}
575255376Sdes
576255376SdesT_FUNC(double_quote_before_word, "double quote before word")
577255376Sdes{
578255376Sdes	struct t_file *tf;
579255376Sdes	int ret;
580255376Sdes
581255376Sdes	tf = t_fopen(NULL);
582255376Sdes	t_fprintf(tf, "\"hello \"world\n");
583255376Sdes	t_frewind(tf);
584255376Sdes	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
585255376Sdes	t_fclose(tf);
586255376Sdes	return (ret);
587255376Sdes}
588255376Sdes
589255376SdesT_FUNC(single_quote_within_word, "single quote within word")
590255376Sdes{
591255376Sdes	struct t_file *tf;
592255376Sdes	int ret;
593255376Sdes
594255376Sdes	tf = t_fopen(NULL);
595255376Sdes	t_fprintf(tf, "hello' 'world\n");
596255376Sdes	t_frewind(tf);
597255376Sdes	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
598255376Sdes	t_fclose(tf);
599255376Sdes	return (ret);
600255376Sdes}
601255376Sdes
602255376SdesT_FUNC(double_quote_within_word, "double quote within word")
603255376Sdes{
604255376Sdes	struct t_file *tf;
605255376Sdes	int ret;
606255376Sdes
607255376Sdes	tf = t_fopen(NULL);
608255376Sdes	t_fprintf(tf, "hello\" \"world\n");
609255376Sdes	t_frewind(tf);
610255376Sdes	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
611255376Sdes	t_fclose(tf);
612255376Sdes	return (ret);
613255376Sdes}
614255376Sdes
615255376SdesT_FUNC(single_quote_after_word, "single quote after word")
616255376Sdes{
617255376Sdes	struct t_file *tf;
618255376Sdes	int ret;
619255376Sdes
620255376Sdes	tf = t_fopen(NULL);
621255376Sdes	t_fprintf(tf, "hello' world'\n");
622255376Sdes	t_frewind(tf);
623255376Sdes	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
624255376Sdes	t_fclose(tf);
625255376Sdes	return (ret);
626255376Sdes}
627255376Sdes
628255376SdesT_FUNC(double_quote_after_word, "double quote after word")
629255376Sdes{
630255376Sdes	struct t_file *tf;
631255376Sdes	int ret;
632255376Sdes
633255376Sdes	tf = t_fopen(NULL);
634255376Sdes	t_fprintf(tf, "hello\" world\"\n");
635255376Sdes	t_frewind(tf);
636255376Sdes	ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
637255376Sdes	t_fclose(tf);
638255376Sdes	return (ret);
639255376Sdes}
640255376Sdes
641255376Sdes
642255376Sdes/***************************************************************************
643236099Sdes * Combinations of escape and quotes
644236099Sdes */
645236099Sdes
646236099SdesT_FUNC(escaped_single_quote,
647236099Sdes    "escaped single quote")
648236099Sdes{
649255376Sdes	struct t_file *tf;
650236099Sdes	int ret;
651236099Sdes
652255376Sdes	tf = t_fopen(NULL);
653255376Sdes	t_fprintf(tf, "\\'\n");
654255376Sdes	t_frewind(tf);
655255376Sdes	ret = orw_expect(tf, "'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
656255376Sdes	t_fclose(tf);
657236099Sdes	return (ret);
658236099Sdes}
659236099Sdes
660236099SdesT_FUNC(escaped_double_quote,
661236099Sdes    "escaped double quote")
662236099Sdes{
663255376Sdes	struct t_file *tf;
664236099Sdes	int ret;
665236099Sdes
666255376Sdes	tf = t_fopen(NULL);
667255376Sdes	t_fprintf(tf, "\\\"\n");
668255376Sdes	t_frewind(tf);
669255376Sdes	ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
670255376Sdes	t_fclose(tf);
671236099Sdes	return (ret);
672236099Sdes}
673236099Sdes
674236099SdesT_FUNC(escaped_whitespace_within_single_quotes,
675236099Sdes    "escaped whitespace within single quotes")
676236099Sdes{
677255376Sdes	struct t_file *tf;
678236099Sdes	int ret;
679236099Sdes
680255376Sdes	tf = t_fopen(NULL);
681255376Sdes	t_fprintf(tf, "'\\ ' '\\\t' '\\\r' '\\\n'\n");
682255376Sdes	t_frewind(tf);
683255376Sdes	ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
684255376Sdes	    orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
685255376Sdes	    orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
686255376Sdes	    orw_expect(tf, "\\\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
687255376Sdes	t_fclose(tf);
688236099Sdes	return (ret);
689236099Sdes}
690236099Sdes
691236099SdesT_FUNC(escaped_whitespace_within_double_quotes,
692236099Sdes    "escaped whitespace within double quotes")
693236099Sdes{
694255376Sdes	struct t_file *tf;
695236099Sdes	int ret;
696236099Sdes
697255376Sdes	tf = t_fopen(NULL);
698255376Sdes	t_fprintf(tf, "\"\\ \" \"\\\t\" \"\\\r\" \"\\\n\"\n");
699255376Sdes	t_frewind(tf);
700255376Sdes	ret = orw_expect(tf, "\\ ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
701255376Sdes	    orw_expect(tf, "\\\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
702255376Sdes	    orw_expect(tf, "\\\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
703236099Sdes	    /* this last one is a line continuation */
704255376Sdes	    orw_expect(tf, "", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
705255376Sdes	t_fclose(tf);
706236099Sdes	return (ret);
707236099Sdes}
708236099Sdes
709236099SdesT_FUNC(escaped_letter_within_single_quotes,
710236099Sdes    "escaped letter within single quotes")
711236099Sdes{
712255376Sdes	struct t_file *tf;
713236099Sdes	int ret;
714236099Sdes
715255376Sdes	tf = t_fopen(NULL);
716255376Sdes	t_fprintf(tf, "'\\z'\n");
717255376Sdes	t_frewind(tf);
718255376Sdes	ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
719255376Sdes	t_fclose(tf);
720236099Sdes	return (ret);
721236099Sdes}
722236099Sdes
723236099SdesT_FUNC(escaped_letter_within_double_quotes,
724236099Sdes    "escaped letter within double quotes")
725236099Sdes{
726255376Sdes	struct t_file *tf;
727236099Sdes	int ret;
728236099Sdes
729255376Sdes	tf = t_fopen(NULL);
730255376Sdes	t_fprintf(tf, "\"\\z\"\n");
731255376Sdes	t_frewind(tf);
732255376Sdes	ret = orw_expect(tf, "\\z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
733255376Sdes	t_fclose(tf);
734236099Sdes	return (ret);
735236099Sdes}
736236099Sdes
737236099SdesT_FUNC(escaped_escape_within_single_quotes,
738236099Sdes    "escaped escape within single quotes")
739236099Sdes{
740255376Sdes	struct t_file *tf;
741236099Sdes	int ret;
742236099Sdes
743255376Sdes	tf = t_fopen(NULL);
744255376Sdes	t_fprintf(tf, "'\\\\'\n");
745255376Sdes	t_frewind(tf);
746255376Sdes	ret = orw_expect(tf, "\\\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
747255376Sdes	t_fclose(tf);
748236099Sdes	return (ret);
749236099Sdes}
750236099Sdes
751236099SdesT_FUNC(escaped_escape_within_double_quotes,
752236099Sdes    "escaped escape within double quotes")
753236099Sdes{
754255376Sdes	struct t_file *tf;
755236099Sdes	int ret;
756236099Sdes
757255376Sdes	tf = t_fopen(NULL);
758255376Sdes	t_fprintf(tf, "\"\\\\\"\n");
759255376Sdes	t_frewind(tf);
760255376Sdes	ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
761255376Sdes	t_fclose(tf);
762236099Sdes	return (ret);
763236099Sdes}
764236099Sdes
765236099SdesT_FUNC(escaped_single_quote_within_single_quotes,
766236099Sdes    "escaped single quote within single quotes")
767236099Sdes{
768255376Sdes	struct t_file *tf;
769236099Sdes	int ret;
770236099Sdes
771255376Sdes	tf = t_fopen(NULL);
772255376Sdes	t_fprintf(tf, "'\\''\n");
773255376Sdes	t_frewind(tf);
774255376Sdes	ret = orw_expect(tf, NULL, 1 /*lines*/, 1 /*eof*/, 0 /*eol*/);
775255376Sdes	t_fclose(tf);
776236099Sdes	return (ret);
777236099Sdes}
778236099Sdes
779236099SdesT_FUNC(escaped_double_quote_within_single_quotes,
780236099Sdes    "escaped double quote within single quotes")
781236099Sdes{
782255376Sdes	struct t_file *tf;
783236099Sdes	int ret;
784236099Sdes
785255376Sdes	tf = t_fopen(NULL);
786255376Sdes	t_fprintf(tf, "'\\\"'\n");
787255376Sdes	t_frewind(tf);
788255376Sdes	ret = orw_expect(tf, "\\\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
789255376Sdes	t_fclose(tf);
790236099Sdes	return (ret);
791236099Sdes}
792236099Sdes
793236099SdesT_FUNC(escaped_single_quote_within_double_quotes,
794236099Sdes    "escaped single quote within double quotes")
795236099Sdes{
796255376Sdes	struct t_file *tf;
797236099Sdes	int ret;
798236099Sdes
799255376Sdes	tf = t_fopen(NULL);
800255376Sdes	t_fprintf(tf, "\"\\'\"\n");
801255376Sdes	t_frewind(tf);
802255376Sdes	ret = orw_expect(tf, "\\'", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
803255376Sdes	t_fclose(tf);
804236099Sdes	return (ret);
805236099Sdes}
806236099Sdes
807236099SdesT_FUNC(escaped_double_quote_within_double_quotes,
808236099Sdes    "escaped double quote within double quotes")
809236099Sdes{
810255376Sdes	struct t_file *tf;
811236099Sdes	int ret;
812236099Sdes
813255376Sdes	tf = t_fopen(NULL);
814255376Sdes	t_fprintf(tf, "\"\\\"\"\n");
815255376Sdes	t_frewind(tf);
816255376Sdes	ret = orw_expect(tf, "\"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
817255376Sdes	t_fclose(tf);
818236099Sdes	return (ret);
819236099Sdes}
820236099Sdes
821236099Sdes
822236099Sdes/***************************************************************************
823236099Sdes * Boilerplate
824236099Sdes */
825236099Sdes
826236099Sdesconst struct t_test *t_plan[] = {
827236099Sdes	T(empty_input),
828236099Sdes	T(empty_line),
829236099Sdes	T(single_whitespace),
830236099Sdes	T(multiple_whitespace),
831236099Sdes	T(comment),
832236099Sdes	T(whitespace_before_comment),
833236099Sdes
834236099Sdes	T(single_word),
835236099Sdes	T(single_whitespace_before_word),
836236099Sdes	T(double_whitespace_before_word),
837236099Sdes	T(single_whitespace_after_word),
838236099Sdes	T(double_whitespace_after_word),
839236099Sdes	T(comment_after_word),
840236099Sdes	T(word_containing_hash),
841236099Sdes	T(two_words),
842236099Sdes
843236099Sdes	T(naked_escape),
844236099Sdes	T(escaped_escape),
845236099Sdes	T(escaped_whitespace),
846236099Sdes	T(escaped_newline_before_word),
847236099Sdes	T(escaped_newline_within_word),
848236099Sdes	T(escaped_newline_after_word),
849236099Sdes	T(escaped_letter),
850236099Sdes
851236099Sdes	T(naked_single_quote),
852236099Sdes	T(naked_double_quote),
853236099Sdes	T(empty_single_quotes),
854236099Sdes	T(empty_double_quotes),
855236099Sdes	T(single_quotes_within_double_quotes),
856236099Sdes	T(double_quotes_within_single_quotes),
857236099Sdes	T(single_quoted_whitespace),
858236099Sdes	T(double_quoted_whitespace),
859236099Sdes	T(single_quoted_words),
860236099Sdes	T(double_quoted_words),
861236099Sdes
862255376Sdes	T(single_quote_before_word),
863255376Sdes	T(double_quote_before_word),
864255376Sdes	T(single_quote_within_word),
865255376Sdes	T(double_quote_within_word),
866255376Sdes	T(single_quote_after_word),
867255376Sdes	T(double_quote_after_word),
868255376Sdes
869236099Sdes	T(escaped_single_quote),
870236099Sdes	T(escaped_double_quote),
871236099Sdes	T(escaped_whitespace_within_single_quotes),
872236099Sdes	T(escaped_whitespace_within_double_quotes),
873236099Sdes	T(escaped_letter_within_single_quotes),
874236099Sdes	T(escaped_letter_within_double_quotes),
875236099Sdes	T(escaped_escape_within_single_quotes),
876236099Sdes	T(escaped_escape_within_double_quotes),
877236099Sdes	T(escaped_single_quote_within_single_quotes),
878236099Sdes	T(escaped_double_quote_within_single_quotes),
879236099Sdes	T(escaped_single_quote_within_double_quotes),
880236099Sdes	T(escaped_double_quote_within_double_quotes),
881236099Sdes
882236099Sdes	NULL
883236099Sdes};
884236099Sdes
885236099Sdesconst struct t_test **
886236099Sdest_prepare(int argc, char *argv[])
887236099Sdes{
888236099Sdes
889236099Sdes	(void)argc;
890236099Sdes	(void)argv;
891236099Sdes	return (t_plan);
892236099Sdes}
893236099Sdes
894236099Sdesvoid
895236099Sdest_cleanup(void)
896236099Sdes{
897236099Sdes}
898