source: openpam/trunk/t/t_openpam_readword.c @ 555

Last change on this file since 555 was 555, checked in by des, 2 years ago

Get rid of BSDisms

  • Property svn:keywords set to Id
File size: 8.6 KB
Line 
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 *    in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $Id$
28 */
29
30#include <err.h>
31#include <errno.h>
32#include <fcntl.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37
38#include <security/pam_appl.h>
39#include <security/openpam.h>
40
41#include "t.h"
42
43static char filename[1024];
44static FILE *f;
45
46/*
47 * Open the temp file and immediately unlink it so it doesn't leak in case
48 * of premature exit.
49 */
50static void
51orw_open(void)
52{
53        int fd;
54
55        if ((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0)
56                err(1, "%s(): %s", __func__, filename);
57        if ((f = fdopen(fd, "r+")) == NULL)
58                err(1, "%s(): %s", __func__, filename);
59        if (unlink(filename) < 0)
60                err(1, "%s(): %s", __func__, filename);
61}
62
63/*
64 * Write text to the temp file.
65 */
66static void
67orw_output(const char *fmt, ...)
68{
69        va_list ap;
70
71        va_start(ap, fmt);
72        vfprintf(f, fmt, ap);
73        va_end(ap);
74        if (ferror(f))
75                err(1, "%s", filename);
76}
77       
78/*
79 * Rewind the temp file.
80 */
81static void
82orw_rewind(void)
83{
84
85        errno = 0;
86        rewind(f);
87        if (errno != 0)
88                err(1, "%s(): %s", __func__, filename);
89}
90
91/*
92 * Read a word from the temp file and verify that the result matches our
93 * expectations: whether a word was read at all, how many lines were read
94 * (in case of quoted or escaped newlines), whether we reached the end of
95 * the file and whether we reached the end of the line.
96 */
97static int
98orw_expect(const char *expected, int lines, int eof, int eol)
99{
100        int ch, lineno = 0;
101        char *got;
102        size_t len;
103
104        got = openpam_readword(f, &lineno, &len);
105        if (ferror(f))
106                err(1, "%s(): %s", __func__, filename);
107        if (expected != NULL && got == NULL) {
108                t_verbose("expected <<%s>>, got nothing\n", expected);
109                return (0);
110        }
111        if (expected == NULL && got != NULL) {
112                t_verbose("expected nothing, got <<%s>>\n", got);
113                return (0);
114        }
115        if (expected != NULL && got != NULL && strcmp(expected, got) != 0) {
116                t_verbose("expected <<%s>>, got <<%s>>\n", expected, got);
117                return (0);
118        }
119        if (lineno != lines) {
120                t_verbose("expected to advance %d lines, advanced %d lines\n");
121                return (0);
122        }
123        if (eof && !feof(f)) {
124                t_verbose("expected EOF, but didn't get it\n");
125                return (0);
126        }
127        if (!eof && feof(f)) {
128                t_verbose("didn't expect EOF, but got it anyway\n");
129                return (0);
130        }
131        ch = fgetc(f);
132        if (ferror(f))
133                err(1, "%s(): %s", __func__, filename);
134        if (eol && ch != '\n') {
135                t_verbose("expected EOL, but didn't get it\n");
136                return (0);
137        }
138        if (!eol && ch == '\n') {
139                t_verbose("didn't expect EOL, but got it anyway\n");
140                return (0);
141        }
142        if (ch != EOF)
143                ungetc(ch, f);
144        return (1);
145}
146
147/*
148 * Close the temp file.
149 */
150void
151orw_close(void)
152{
153
154        if (fclose(f) != 0)
155                err(1, "%s(): %s", __func__, filename);
156}
157
158
159/***************************************************************************
160 * Lines without words
161 */
162
163T_FUNC(empty_input, "empty input")
164{
165        int ret;
166
167        orw_open();
168        ret = orw_expect(NULL, 0 /*lines*/, 1 /*eof*/, 0 /*eol*/);
169        orw_close();
170        return (ret);
171}
172
173T_FUNC(empty_line, "empty line")
174{
175        int ret;
176
177        orw_open();
178        orw_output("\n");
179        orw_rewind();
180        ret = orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
181        orw_close();
182        return (ret);
183}
184
185T_FUNC(single_whitespace, "single whitespace")
186{
187        int ret;
188
189        orw_open();
190        orw_output(" \n");
191        orw_rewind();
192        ret = orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
193        orw_close();
194        return (ret);
195}
196
197T_FUNC(multiple_whitespace, "multiple whitespace")
198{
199        int ret;
200
201        orw_open();
202        orw_output(" \t\r\n");
203        orw_rewind();
204        ret = orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
205        orw_close();
206        return (ret);
207}
208
209T_FUNC(comment, "comment")
210{
211        int ret;
212
213        orw_open();
214        orw_output("# comment\n");
215        orw_rewind();
216        ret = orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
217        orw_close();
218        return (ret);
219}
220
221T_FUNC(whitespace_before_comment, "whitespace before comment")
222{
223        int ret;
224
225        orw_open();
226        orw_output(" # comment\n");
227        orw_rewind();
228        ret = orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
229        orw_close();
230        return (ret);
231}
232
233
234/***************************************************************************
235 * Simple cases - no quotes or escapes
236 */
237
238T_FUNC(single_word, "single word")
239{
240        const char *word = "hello";
241        int ret;
242
243        orw_open();
244        orw_output("%s\n", word);
245        orw_rewind();
246        ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
247        orw_close();
248        return (ret);
249}
250
251T_FUNC(single_whitespace_before_word, "single whitespace before word")
252{
253        const char *word = "hello";
254        int ret;
255
256        orw_open();
257        orw_output(" %s\n", word);
258        orw_rewind();
259        ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
260        orw_close();
261        return (ret);
262}
263
264T_FUNC(double_whitespace_before_word, "double whitespace before word")
265{
266        const char *word = "hello";
267        int ret;
268
269        orw_open();
270        orw_output("  %s\n", word);
271        orw_rewind();
272        ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
273        orw_close();
274        return (ret);
275}
276
277T_FUNC(single_whitespace_after_word, "single whitespace after word")
278{
279        const char *word = "hello";
280        int ret;
281
282        orw_open();
283        orw_output("%s \n", word);
284        orw_rewind();
285        ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/);
286        orw_close();
287        return (ret);
288}
289
290T_FUNC(double_whitespace_after_word, "double whitespace after word")
291{
292        const char *word = "hello";
293        int ret;
294
295        orw_open();
296        orw_output("%s  \n", word);
297        orw_rewind();
298        ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/);
299        orw_close();
300        return (ret);
301}
302
303T_FUNC(comment_after_word, "comment after word")
304{
305        const char *word = "hello";
306        int ret;
307
308        orw_open();
309        orw_output("%s # comment\n", word);
310        orw_rewind();
311        ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
312            orw_expect(NULL, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
313        orw_close();
314        return (ret);
315}
316
317T_FUNC(word_containing_hash, "word containing hash")
318{
319        const char *word = "hello#world";
320        int ret;
321
322        orw_open();
323        orw_output("%s\n", word);
324        orw_rewind();
325        ret = orw_expect(word, 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
326        orw_close();
327        return (ret);
328}
329
330T_FUNC(two_words, "two words")
331{
332        const char *word[] = { "hello", "world" };
333        int ret;
334
335        orw_open();
336        orw_output("%s %s\n", word[0], word[1]);
337        orw_rewind();
338        ret = orw_expect(word[0], 0 /*lines*/, 0 /*eof*/, 0 /*eol*/) &&
339            orw_expect(word[1], 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
340        orw_close();
341        return (ret);
342}
343
344
345/***************************************************************************
346 * Complex cases
347 */
348
349T_FUNC(empty_single_quotes, "empty single quotes")
350{
351        int ret;
352
353        orw_open();
354        orw_output("''\n");
355        orw_rewind();
356        ret = orw_expect("", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
357        orw_close();
358        return (ret);
359}
360
361T_FUNC(empty_double_quotes, "empty double quotes")
362{
363        int ret;
364
365        orw_open();
366        orw_output("\"\"\n");
367        orw_rewind();
368        ret = orw_expect("", 0 /*lines*/, 0 /*eof*/, 1 /*eol*/);
369        orw_close();
370        return (ret);
371}
372
373
374
375const struct t_test *t_plan[] = {
376        T(empty_input),
377        T(empty_line),
378        T(single_whitespace),
379        T(multiple_whitespace),
380        T(comment),
381        T(whitespace_before_comment),
382        T(single_word),
383        T(single_whitespace_before_word),
384        T(double_whitespace_before_word),
385        T(single_whitespace_after_word),
386        T(double_whitespace_after_word),
387        T(comment_after_word),
388        T(word_containing_hash),
389        T(two_words),
390        T(empty_single_quotes),
391        T(empty_double_quotes),
392        NULL
393};
394
395const struct t_test **
396t_prepare(int argc, char *argv[])
397{
398
399        (void)argc;
400        (void)argv;
401        snprintf(filename, sizeof filename, "%s.%d.tmp", t_progname, getpid());
402        if (filename == NULL)
403                err(1, "asprintf()");
404        return (t_plan);
405}
406
407void
408t_cleanup(void)
409{
410}
Note: See TracBrowser for help on using the repository browser.