source: openpam/trunk/t/t_openpam_readlinev.c @ 578

Last change on this file since 578 was 578, checked in by des, 3 years ago

As previously mentioned, move from 2-clause BSD to 3-clause BSD.

  • Property svn:keywords set to Id
File size: 6.1 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 * 3. The name of the author may not be used to endorse or promote
15 *    products derived from this software without specific prior written
16 *    permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33#ifdef HAVE_CONFIG_H
34# include "config.h"
35#endif
36
37#include <err.h>
38#include <errno.h>
39#include <fcntl.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44
45#include <security/pam_appl.h>
46#include <security/openpam.h>
47
48#include "openpam_impl.h"
49#include "t.h"
50
51static char filename[1024];
52static FILE *f;
53
54/*
55 * Open the temp file and immediately unlink it so it doesn't leak in case
56 * of premature exit.
57 */
58static void
59orlv_open(void)
60{
61        int fd;
62
63        if ((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0)
64                err(1, "%s(): %s", __func__, filename);
65        if ((f = fdopen(fd, "r+")) == NULL)
66                err(1, "%s(): %s", __func__, filename);
67        if (unlink(filename) < 0)
68                err(1, "%s(): %s", __func__, filename);
69}
70
71/*
72 * Write text to the temp file.
73 */
74static void
75orlv_output(const char *fmt, ...)
76{
77        va_list ap;
78
79        va_start(ap, fmt);
80        vfprintf(f, fmt, ap);
81        va_end(ap);
82        if (ferror(f))
83                err(1, "%s", filename);
84}
85
86/*
87 * Rewind the temp file.
88 */
89static void
90orlv_rewind(void)
91{
92
93        errno = 0;
94        rewind(f);
95        if (errno != 0)
96                err(1, "%s(): %s", __func__, filename);
97}
98
99/*
100 * Read a line from the temp file and verify that the result matches our
101 * expectations: whether a line was read at all, how many and which words
102 * it contained, how many lines were read (in case of quoted or escaped
103 * newlines) and whether we reached the end of the file.
104 */
105static int
106orlv_expect(const char **expectedv, int lines, int eof)
107{
108        int expectedc, gotc, i, lineno = 0;
109        char **gotv;
110
111        expectedc = 0;
112        if (expectedv != NULL)
113                while (expectedv[expectedc] != NULL)
114                        ++expectedc;
115        gotv = openpam_readlinev(f, &lineno, &gotc);
116        if (ferror(f))
117                err(1, "%s(): %s", __func__, filename);
118        if (expectedv != NULL && gotv == NULL) {
119                t_verbose("expected %d words, got nothing\n", expectedc);
120                return (0);
121        }
122        if (expectedv == NULL && gotv != NULL) {
123                t_verbose("expected nothing, got %d words\n", gotc);
124                FREEV(gotc, gotv);
125                return (0);
126        }
127        if (expectedv != NULL && gotv != NULL) {
128                if (expectedc != gotc) {
129                        t_verbose("expected %d words, got %d\n",
130                            expectedc, gotc);
131                        FREEV(gotc, gotv);
132                        return (0);
133                }
134                for (i = 0; i < gotc; ++i) {
135                        if (strcmp(expectedv[i], gotv[i]) != 0) {
136                                t_verbose("word %d: expected <<%s>>, "
137                                    "got <<%s>>\n", i, expectedv[i], gotv[i]);
138                                FREEV(gotc, gotv);
139                                return (0);
140                        }
141                }
142                FREEV(gotc, gotv);
143        }
144        if (lineno != lines) {
145                t_verbose("expected to advance %d lines, advanced %d lines\n",
146                    lines, lineno);
147                return (0);
148        }
149        if (eof && !feof(f)) {
150                t_verbose("expected EOF, but didn't get it\n");
151                return (0);
152        }
153        if (!eof && feof(f)) {
154                t_verbose("didn't expect EOF, but got it anyway\n");
155                return (0);
156        }
157        return (1);
158}
159
160/*
161 * Close the temp file.
162 */
163void
164orlv_close(void)
165{
166
167        if (fclose(f) != 0)
168                err(1, "%s(): %s", __func__, filename);
169        f = NULL;
170}
171
172
173/***************************************************************************
174 * Lines without words
175 */
176
177T_FUNC(empty_input, "empty input")
178{
179        int ret;
180
181        orlv_open();
182        ret = orlv_expect(NULL, 0 /*lines*/, 1 /*eof*/);
183        orlv_close();
184        return (ret);
185}
186
187T_FUNC(empty_line, "empty line")
188{
189        int ret;
190
191        orlv_open();
192        orlv_output("\n");
193        orlv_rewind();
194        ret = orlv_expect((const char *[]){ NULL },
195            1 /*lines*/, 0 /*eof*/);
196        orlv_close();
197        return (ret);
198}
199
200T_FUNC(unterminated_line, "unterminated line")
201{
202        int ret;
203
204        orlv_open();
205        orlv_output(" ");
206        orlv_rewind();
207        ret = orlv_expect((const char *[]){ NULL },
208            0 /*lines*/, 1 /*eof*/);
209        orlv_close();
210        return (ret);
211}
212
213T_FUNC(whitespace, "whitespace")
214{
215        int ret;
216
217        orlv_open();
218        orlv_output(" \n");
219        orlv_rewind();
220        ret = orlv_expect((const char *[]){ NULL },
221            1 /*lines*/, 0 /*eof*/);
222        orlv_close();
223        return (ret);
224}
225
226T_FUNC(comment, "comment")
227{
228        int ret;
229
230        orlv_open();
231        orlv_output("# comment\n");
232        orlv_rewind();
233        ret = orlv_expect((const char *[]){ NULL },
234            1 /*lines*/, 0 /*eof*/);
235        orlv_close();
236        return (ret);
237}
238
239T_FUNC(whitespace_before_comment, "whitespace before comment")
240{
241        int ret;
242
243        orlv_open();
244        orlv_output(" # comment\n");
245        orlv_rewind();
246        ret = orlv_expect((const char *[]){ NULL },
247            1 /*lines*/, 0 /*eof*/);
248        orlv_close();
249        return (ret);
250}
251
252
253/***************************************************************************
254 * Boilerplate
255 */
256
257const struct t_test *t_plan[] = {
258        T(empty_input),
259        T(empty_line),
260        T(unterminated_line),
261        T(whitespace),
262        T(comment),
263        T(whitespace_before_comment),
264
265        NULL
266};
267
268const struct t_test **
269t_prepare(int argc, char *argv[])
270{
271
272        (void)argc;
273        (void)argv;
274        snprintf(filename, sizeof filename, "%s.%d.tmp", t_progname, getpid());
275        if (filename == NULL)
276                err(1, "asprintf()");
277        return (t_plan);
278}
279
280void
281t_cleanup(void)
282{
283}
Note: See TracBrowser for help on using the repository browser.