t_openpam_readword.c revision 1.1.1.7 1 /*-
2 * Copyright (c) 2012-2017 Dag-Erling Smrgrav
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
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <err.h>
35 #include <stdint.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include <cryb/test.h>
42
43 #include <security/pam_appl.h>
44 #include <security/openpam.h>
45
46 #define T_FUNC(n, d) \
47 static const char *t_ ## n ## _desc = d; \
48 static int t_ ## n ## _func(OPENPAM_UNUSED(char **desc), \
49 OPENPAM_UNUSED(void *arg))
50
51 #define T(n) \
52 t_add_test(&t_ ## n ## _func, NULL, "%s", t_ ## n ## _desc)
53
54 /*
55 * Read a word from the temp file and verify that the result matches our
56 * expectations: whether a word was read at all, how many lines were read
57 * (in case of quoted or escaped newlines), whether we reached the end of
58 * the file and whether we reached the end of the line.
59 */
60 static int
61 orw_expect(struct t_file *tf, const char *expected, int lines, int eof, int eol)
62 {
63 int ch, lineno = 0;
64 char *got;
65 size_t len;
66 int ret;
67
68 got = openpam_readword(tf->file, &lineno, &len);
69 ret = 1;
70 if (t_ferror(tf))
71 err(1, "%s(): %s", __func__, tf->name);
72 if (expected != NULL && got == NULL) {
73 t_printv("expected <<%s>>, got nothing\n", expected);
74 ret = 0;
75 } else if (expected == NULL && got != NULL) {
76 t_printv("expected nothing, got <<%s>>\n", got);
77 ret = 0;
78 } else if (expected != NULL && got != NULL && strcmp(expected, got) != 0) {
79 t_printv("expected <<%s>>, got <<%s>>\n", expected, got);
80 ret = 0;
81 }
82 free(got);
83 if (lineno != lines) {
84 t_printv("expected to advance %d lines, advanced %d lines\n",
85 lines, lineno);
86 ret = 0;
87 }
88 if (eof && !t_feof(tf)) {
89 t_printv("expected EOF, but didn't get it\n");
90 ret = 0;
91 }
92 if (!eof && t_feof(tf)) {
93 t_printv("didn't expect EOF, but got it anyway\n");
94 ret = 0;
95 }
96 ch = fgetc(tf->file);
97 if (t_ferror(tf))
98 err(1, "%s(): %s", __func__, tf->name);
99 if (eol && ch != '\n') {
100 t_printv("expected EOL, but didn't get it\n");
101 ret = 0;
102 } else if (!eol && ch == '\n') {
103 t_printv("didn't expect EOL, but got it anyway\n");
104 ret = 0;
105 }
106 if (ch != EOF)
107 ungetc(ch, tf->file);
108 return (ret);
109 }
110
111
112 /***************************************************************************
114 * Lines without words
115 */
116
117 T_FUNC(empty_input, "empty input")
118 {
119 struct t_file *tf;
120 int ret;
121
122 tf = t_fopen(NULL);
123 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
124 t_fclose(tf);
125 return (ret);
126 }
127
128 T_FUNC(empty_line, "empty line")
129 {
130 struct t_file *tf;
131 int ret;
132
133 tf = t_fopen(NULL);
134 t_fprintf(tf, "\n");
135 t_frewind(tf);
136 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
137 t_fclose(tf);
138 return (ret);
139 }
140
141 T_FUNC(unterminated_line, "unterminated line")
142 {
143 struct t_file *tf;
144 int ret;
145
146 tf = t_fopen(NULL);
147 t_fprintf(tf, " ");
148 t_frewind(tf);
149 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
150 t_fclose(tf);
151 return (ret);
152 }
153
154 T_FUNC(single_whitespace, "single whitespace")
155 {
156 struct t_file *tf;
157 int ret;
158
159 tf = t_fopen(NULL);
160 t_fprintf(tf, " \n");
161 t_frewind(tf);
162 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
163 t_fclose(tf);
164 return (ret);
165 }
166
167 T_FUNC(multiple_whitespace, "multiple whitespace")
168 {
169 struct t_file *tf;
170 int ret;
171
172 tf = t_fopen(NULL);
173 t_fprintf(tf, " \t\r\n");
174 t_frewind(tf);
175 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
176 t_fclose(tf);
177 return (ret);
178 }
179
180 T_FUNC(comment, "comment")
181 {
182 struct t_file *tf;
183 int ret;
184
185 tf = t_fopen(NULL);
186 t_fprintf(tf, "# comment\n");
187 t_frewind(tf);
188 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
189 t_fclose(tf);
190 return (ret);
191 }
192
193 T_FUNC(whitespace_before_comment, "whitespace before comment")
194 {
195 struct t_file *tf;
196 int ret;
197
198 tf = t_fopen(NULL);
199 t_fprintf(tf, " # comment\n");
200 t_frewind(tf);
201 ret = orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
202 t_fclose(tf);
203 return (ret);
204 }
205
206 T_FUNC(single_quoted_comment, "single-quoted comment")
207 {
208 struct t_file *tf;
209 int ret;
210
211 tf = t_fopen(NULL);
212 t_fprintf(tf, " '# comment'\n");
213 t_frewind(tf);
214 ret = orw_expect(tf, "# comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
215 t_fclose(tf);
216 return (ret);
217 }
218
219 T_FUNC(double_quoted_comment, "double-quoted comment")
220 {
221 struct t_file *tf;
222 int ret;
223
224 tf = t_fopen(NULL);
225 t_fprintf(tf, " \"# comment\"\n");
226 t_frewind(tf);
227 ret = orw_expect(tf, "# comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
228 t_fclose(tf);
229 return (ret);
230 }
231
232 T_FUNC(comment_at_eof, "comment at end of file")
233 {
234 struct t_file *tf;
235 int ret;
236
237 tf = t_fopen(NULL);
238 t_fprintf(tf, "# comment");
239 t_frewind(tf);
240 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
241 t_fclose(tf);
242 return (ret);
243 }
244
245
246 /***************************************************************************
248 * Simple cases - no quotes or escapes
249 */
250
251 T_FUNC(single_word, "single word")
252 {
253 const char *word = "hello";
254 struct t_file *tf;
255 int ret;
256
257 tf = t_fopen(NULL);
258 t_fprintf(tf, "%s\n", word);
259 t_frewind(tf);
260 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
261 t_fclose(tf);
262 return (ret);
263 }
264
265 T_FUNC(single_whitespace_before_word, "single whitespace before word")
266 {
267 const char *word = "hello";
268 struct t_file *tf;
269 int ret;
270
271 tf = t_fopen(NULL);
272 t_fprintf(tf, " %s\n", word);
273 t_frewind(tf);
274 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
275 t_fclose(tf);
276 return (ret);
277 }
278
279 T_FUNC(double_whitespace_before_word, "double whitespace before word")
280 {
281 const char *word = "hello";
282 struct t_file *tf;
283 int ret;
284
285 tf = t_fopen(NULL);
286 t_fprintf(tf, " %s\n", word);
287 t_frewind(tf);
288 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
289 t_fclose(tf);
290 return (ret);
291 }
292
293 T_FUNC(single_whitespace_after_word, "single whitespace after word")
294 {
295 const char *word = "hello";
296 struct t_file *tf;
297 int ret;
298
299 tf = t_fopen(NULL);
300 t_fprintf(tf, "%s \n", word);
301 t_frewind(tf);
302 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/);
303 t_fclose(tf);
304 return (ret);
305 }
306
307 T_FUNC(double_whitespace_after_word, "double whitespace after word")
308 {
309 const char *word = "hello";
310 struct t_file *tf;
311 int ret;
312
313 tf = t_fopen(NULL);
314 t_fprintf(tf, "%s \n", word);
315 t_frewind(tf);
316 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/);
317 t_fclose(tf);
318 return (ret);
319 }
320
321 T_FUNC(comment_after_word, "comment after word")
322 {
323 const char *word = "hello";
324 struct t_file *tf;
325 int ret;
326
327 tf = t_fopen(NULL);
328 t_fprintf(tf, "%s # comment\n", word);
329 t_frewind(tf);
330 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
331 orw_expect(tf, NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
332 t_fclose(tf);
333 return (ret);
334 }
335
336 T_FUNC(word_containing_hash, "word containing hash")
337 {
338 const char *word = "hello#world";
339 struct t_file *tf;
340 int ret;
341
342 tf = t_fopen(NULL);
343 t_fprintf(tf, "%s\n", word);
344 t_frewind(tf);
345 ret = orw_expect(tf, word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
346 t_fclose(tf);
347 return (ret);
348 }
349
350 T_FUNC(two_words, "two words")
351 {
352 const char *word[] = { "hello", "world" };
353 struct t_file *tf;
354 int ret;
355
356 tf = t_fopen(NULL);
357 t_fprintf(tf, "%s %s\n", word[0], word[1]);
358 t_frewind(tf);
359 ret = orw_expect(tf, word[0], 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
360 orw_expect(tf, word[1], 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
361 t_fclose(tf);
362 return (ret);
363 }
364
365
366 /***************************************************************************
368 * Escapes
369 */
370
371 T_FUNC(naked_escape, "naked escape")
372 {
373 struct t_file *tf;
374 int ret;
375
376 tf = t_fopen(NULL);
377 t_fprintf(tf, "\\");
378 t_frewind(tf);
379 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
380 t_fclose(tf);
381 return (ret);
382 }
383
384 T_FUNC(escaped_escape, "escaped escape")
385 {
386 struct t_file *tf;
387 int ret;
388
389 tf = t_fopen(NULL);
390 t_fprintf(tf, "\\\\\n");
391 t_frewind(tf);
392 ret = orw_expect(tf, "\\", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
393 t_fclose(tf);
394 return (ret);
395 }
396
397 T_FUNC(escaped_whitespace, "escaped whitespace")
398 {
399 struct t_file *tf;
400 int ret;
401
402 tf = t_fopen(NULL);
403 t_fprintf(tf, "\\ \\\t \\\r \\\n\n");
404 t_frewind(tf);
405 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
406 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
407 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
408 /* this last one is a line continuation */
409 orw_expect(tf, NULL, 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
410 t_fclose(tf);
411 return (ret);
412 }
413
414 T_FUNC(escaped_newline_before_word, "escaped newline before word")
415 {
416 struct t_file *tf;
417 int ret;
418
419 tf = t_fopen(NULL);
420 t_fprintf(tf, "\\\nhello world\n");
421 t_frewind(tf);
422 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/);
423 t_fclose(tf);
424 return (ret);
425 }
426
427 T_FUNC(escaped_newline_within_word, "escaped newline within word")
428 {
429 struct t_file *tf;
430 int ret;
431
432 tf = t_fopen(NULL);
433 t_fprintf(tf, "hello\\\nworld\n");
434 t_frewind(tf);
435 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
436 t_fclose(tf);
437 return (ret);
438 }
439
440 T_FUNC(escaped_newline_after_word, "escaped newline after word")
441 {
442 struct t_file *tf;
443 int ret;
444
445 tf = t_fopen(NULL);
446 t_fprintf(tf, "hello\\\n world\n");
447 t_frewind(tf);
448 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/);
449 t_fclose(tf);
450 return (ret);
451 }
452
453 T_FUNC(escaped_letter, "escaped letter")
454 {
455 struct t_file *tf;
456 int ret;
457
458 tf = t_fopen(NULL);
459 t_fprintf(tf, "\\z\n");
460 t_frewind(tf);
461 ret = orw_expect(tf, "z", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
462 t_fclose(tf);
463 return (ret);
464 }
465
466 T_FUNC(escaped_comment, "escaped comment")
467 {
468 struct t_file *tf;
469 int ret;
470
471 tf = t_fopen(NULL);
472 t_fprintf(tf, " \\# comment\n");
473 t_frewind(tf);
474 ret = orw_expect(tf, "#", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
475 orw_expect(tf, "comment", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
476 t_fclose(tf);
477 return (ret);
478 }
479
480 T_FUNC(escape_at_eof, "escape at end of file")
481 {
482 struct t_file *tf;
483 int ret;
484
485 tf = t_fopen(NULL);
486 t_fprintf(tf, "z\\");
487 t_frewind(tf);
488 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
489 t_fclose(tf);
490 return (ret);
491 }
492
493
494 /***************************************************************************
496 * Quotes
497 */
498
499 T_FUNC(naked_single_quote, "naked single quote")
500 {
501 struct t_file *tf;
502 int ret;
503
504 tf = t_fopen(NULL);
505 t_fprintf(tf, "'");
506 t_frewind(tf);
507 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
508 t_fclose(tf);
509 return (ret);
510 }
511
512 T_FUNC(naked_double_quote, "naked double quote")
513 {
514 struct t_file *tf;
515 int ret;
516
517 tf = t_fopen(NULL);
518 t_fprintf(tf, "\"");
519 t_frewind(tf);
520 ret = orw_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
521 t_fclose(tf);
522 return (ret);
523 }
524
525 T_FUNC(empty_single_quotes, "empty single quotes")
526 {
527 struct t_file *tf;
528 int ret;
529
530 tf = t_fopen(NULL);
531 t_fprintf(tf, "''\n");
532 t_frewind(tf);
533 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
534 t_fclose(tf);
535 return (ret);
536 }
537
538 T_FUNC(empty_double_quotes, "empty double quotes")
539 {
540 struct t_file *tf;
541 int ret;
542
543 tf = t_fopen(NULL);
544 t_fprintf(tf, "\"\"\n");
545 t_frewind(tf);
546 ret = orw_expect(tf, "", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
547 t_fclose(tf);
548 return (ret);
549 }
550
551 T_FUNC(single_quotes_within_double_quotes, "single quotes within double quotes")
552 {
553 struct t_file *tf;
554 int ret;
555
556 tf = t_fopen(NULL);
557 t_fprintf(tf, "\"' '\"\n");
558 t_frewind(tf);
559 ret = orw_expect(tf, "' '", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
560 t_fclose(tf);
561 return (ret);
562 }
563
564 T_FUNC(double_quotes_within_single_quotes, "double quotes within single quotes")
565 {
566 struct t_file *tf;
567 int ret;
568
569 tf = t_fopen(NULL);
570 t_fprintf(tf, "'\" \"'\n");
571 t_frewind(tf);
572 ret = orw_expect(tf, "\" \"", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
573 t_fclose(tf);
574 return (ret);
575 }
576
577 T_FUNC(single_quoted_whitespace, "single-quoted whitespace")
578 {
579 struct t_file *tf;
580 int ret;
581
582 tf = t_fopen(NULL);
583 t_fprintf(tf, "' ' '\t' '\r' '\n'\n");
584 t_frewind(tf);
585 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
586 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
587 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
588 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
589 t_fclose(tf);
590 return (ret);
591 }
592
593 T_FUNC(double_quoted_whitespace, "double-quoted whitespace")
594 {
595 struct t_file *tf;
596 int ret;
597
598 tf = t_fopen(NULL);
599 t_fprintf(tf, "\" \" \"\t\" \"\r\" \"\n\"\n");
600 t_frewind(tf);
601 ret = orw_expect(tf, " ", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
602 orw_expect(tf, "\t", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
603 orw_expect(tf, "\r", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
604 orw_expect(tf, "\n", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
605 t_fclose(tf);
606 return (ret);
607 }
608
609 T_FUNC(single_quoted_words, "single-quoted words")
610 {
611 struct t_file *tf;
612 int ret;
613
614 tf = t_fopen(NULL);
615 t_fprintf(tf, "'hello world'\n");
616 t_frewind(tf);
617 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
618 t_fclose(tf);
619 return (ret);
620 }
621
622 T_FUNC(double_quoted_words, "double-quoted words")
623 {
624 struct t_file *tf;
625 int ret;
626
627 tf = t_fopen(NULL);
628 t_fprintf(tf, "\"hello world\"\n");
629 t_frewind(tf);
630 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
631 t_fclose(tf);
632 return (ret);
633 }
634
635
636 /***************************************************************************
638 * Combinations of quoted and unquoted text
639 */
640
641 T_FUNC(single_quote_before_word, "single quote before word")
642 {
643 struct t_file *tf;
644 int ret;
645
646 tf = t_fopen(NULL);
647 t_fprintf(tf, "'hello 'world\n");
648 t_frewind(tf);
649 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
650 t_fclose(tf);
651 return (ret);
652 }
653
654 T_FUNC(double_quote_before_word, "double quote before word")
655 {
656 struct t_file *tf;
657 int ret;
658
659 tf = t_fopen(NULL);
660 t_fprintf(tf, "\"hello \"world\n");
661 t_frewind(tf);
662 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
663 t_fclose(tf);
664 return (ret);
665 }
666
667 T_FUNC(single_quote_within_word, "single quote within word")
668 {
669 struct t_file *tf;
670 int ret;
671
672 tf = t_fopen(NULL);
673 t_fprintf(tf, "hello' 'world\n");
674 t_frewind(tf);
675 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
676 t_fclose(tf);
677 return (ret);
678 }
679
680 T_FUNC(double_quote_within_word, "double quote within word")
681 {
682 struct t_file *tf;
683 int ret;
684
685 tf = t_fopen(NULL);
686 t_fprintf(tf, "hello\" \"world\n");
687 t_frewind(tf);
688 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
689 t_fclose(tf);
690 return (ret);
691 }
692
693 T_FUNC(single_quote_after_word, "single quote after word")
694 {
695 struct t_file *tf;
696 int ret;
697
698 tf = t_fopen(NULL);
699 t_fprintf(tf, "hello' world'\n");
700 t_frewind(tf);
701 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
702 t_fclose(tf);
703 return (ret);
704 }
705
706 T_FUNC(double_quote_after_word, "double quote after word")
707 {
708 struct t_file *tf;
709 int ret;
710
711 tf = t_fopen(NULL);
712 t_fprintf(tf, "hello\" world\"\n");
713 t_frewind(tf);
714 ret = orw_expect(tf, "hello world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
715 t_fclose(tf);
716 return (ret);
717 }
718
719
720 /***************************************************************************
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 /***************************************************************************
903 * Line continuation
904 */
905
906 T_FUNC(line_continuation_within_whitespace, "line continuation within whitespace")
907 {
908 struct t_file *tf;
909 int ret;
910
911 tf = t_fopen(NULL);
912 t_fprintf(tf, "hello \\\n world\n");
913 t_frewind(tf);
914 ret = orw_expect(tf, "hello", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
915 orw_expect(tf, "world", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
916 t_fclose(tf);
917 return (ret);
918 }
919
920 T_FUNC(line_continuation_before_whitespace, "line continuation before whitespace")
921 {
922 struct t_file *tf;
923 int ret;
924
925 tf = t_fopen(NULL);
926 t_fprintf(tf, "hello\\\n world\n");
927 t_frewind(tf);
928 ret = orw_expect(tf, "hello", 1 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
929 orw_expect(tf, "world", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
930 t_fclose(tf);
931 return (ret);
932 }
933
934 T_FUNC(line_continuation_after_whitespace, "line continuation after whitespace")
935 {
936 struct t_file *tf;
937 int ret;
938
939 tf = t_fopen(NULL);
940 t_fprintf(tf, "hello \\\nworld\n");
941 t_frewind(tf);
942 ret = orw_expect(tf, "hello", 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
943 orw_expect(tf, "world", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
944 t_fclose(tf);
945 return (ret);
946 }
947
948 T_FUNC(line_continuation_within_word, "line continuation within word")
949 {
950 struct t_file *tf;
951 int ret;
952
953 tf = t_fopen(NULL);
954 t_fprintf(tf, "hello\\\nworld\n");
955 t_frewind(tf);
956 ret = orw_expect(tf, "helloworld", 1 /*lines*/, 0 /*eof*/, 1 /*eol*/);
957 t_fclose(tf);
958 return (ret);
959 }
960
961
962 /***************************************************************************
964 * Boilerplate
965 */
966
967 static int
968 t_prepare(int argc, char *argv[])
969 {
970
971 (void)argc;
972 (void)argv;
973
974 T(empty_input);
975 T(empty_line);
976 T(unterminated_line);
977 T(single_whitespace);
978 T(multiple_whitespace);
979 T(comment);
980 T(whitespace_before_comment);
981 T(single_quoted_comment);
982 T(double_quoted_comment);
983 T(comment_at_eof);
984
985 T(single_word);
986 T(single_whitespace_before_word);
987 T(double_whitespace_before_word);
988 T(single_whitespace_after_word);
989 T(double_whitespace_after_word);
990 T(comment_after_word);
991 T(word_containing_hash);
992 T(two_words);
993
994 T(naked_escape);
995 T(escaped_escape);
996 T(escaped_whitespace);
997 T(escaped_newline_before_word);
998 T(escaped_newline_within_word);
999 T(escaped_newline_after_word);
1000 T(escaped_letter);
1001 T(escaped_comment);
1002 T(escape_at_eof);
1003
1004 T(naked_single_quote);
1005 T(naked_double_quote);
1006 T(empty_single_quotes);
1007 T(empty_double_quotes);
1008 T(single_quotes_within_double_quotes);
1009 T(double_quotes_within_single_quotes);
1010 T(single_quoted_whitespace);
1011 T(double_quoted_whitespace);
1012 T(single_quoted_words);
1013 T(double_quoted_words);
1014
1015 T(single_quote_before_word);
1016 T(double_quote_before_word);
1017 T(single_quote_within_word);
1018 T(double_quote_within_word);
1019 T(single_quote_after_word);
1020 T(double_quote_after_word);
1021
1022 T(escaped_single_quote);
1023 T(escaped_double_quote);
1024 T(escaped_whitespace_within_single_quotes);
1025 T(escaped_whitespace_within_double_quotes);
1026 T(escaped_letter_within_single_quotes);
1027 T(escaped_letter_within_double_quotes);
1028 T(escaped_escape_within_single_quotes);
1029 T(escaped_escape_within_double_quotes);
1030 T(escaped_single_quote_within_single_quotes);
1031 T(escaped_double_quote_within_single_quotes);
1032 T(escaped_single_quote_within_double_quotes);
1033 T(escaped_double_quote_within_double_quotes);
1034
1035 T(line_continuation_within_whitespace);
1036 T(line_continuation_before_whitespace);
1037 T(line_continuation_after_whitespace);
1038 T(line_continuation_within_word);
1039
1040 return (0);
1041 }
1042
1043 int
1044 main(int argc, char *argv[])
1045 {
1046
1047 t_main(t_prepare, NULL, argc, argv);
1048 }
1049