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