1 /* $NetBSD: t_openpam_readlinev.c,v 1.1.1.2 2013/12/27 19:16:12 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2012 Dag-Erling Smørgrav 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote 16 * products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * Id: t_openpam_readlinev.c 648 2013-03-05 17:54:27Z des 32 */ 33 34 #ifdef HAVE_CONFIG_H 35 # include "config.h" 36 #endif 37 38 #include <err.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 43 #include <security/pam_appl.h> 44 #include <security/openpam.h> 45 46 #include "openpam_impl.h" 47 #include "t.h" 48 49 /* 50 * Read a line from the temp file and verify that the result matches our 51 * expectations: whether a line was read at all, how many and which words 52 * it contained, how many lines were read (in case of quoted or escaped 53 * newlines) and whether we reached the end of the file. 54 */ 55 static int 56 orlv_expect(struct t_file *tf, const char **expectedv, int lines, int eof) 57 { 58 int expectedc, gotc, i, lineno = 0; 59 char **gotv; 60 61 expectedc = 0; 62 if (expectedv != NULL) 63 while (expectedv[expectedc] != NULL) 64 ++expectedc; 65 gotv = openpam_readlinev(tf->file, &lineno, &gotc); 66 if (t_ferror(tf)) 67 err(1, "%s(): %s", __func__, tf->name); 68 if (expectedv != NULL && gotv == NULL) { 69 t_verbose("expected %d words, got nothing\n", expectedc); 70 return (0); 71 } 72 if (expectedv == NULL && gotv != NULL) { 73 t_verbose("expected nothing, got %d words\n", gotc); 74 FREEV(gotc, gotv); 75 return (0); 76 } 77 if (expectedv != NULL && gotv != NULL) { 78 if (expectedc != gotc) { 79 t_verbose("expected %d words, got %d\n", 80 expectedc, gotc); 81 FREEV(gotc, gotv); 82 return (0); 83 } 84 for (i = 0; i < gotc; ++i) { 85 if (strcmp(expectedv[i], gotv[i]) != 0) { 86 t_verbose("word %d: expected <<%s>>, " 87 "got <<%s>>\n", i, expectedv[i], gotv[i]); 88 FREEV(gotc, gotv); 89 return (0); 90 } 91 } 92 FREEV(gotc, gotv); 93 } 94 if (lineno != lines) { 95 t_verbose("expected to advance %d lines, advanced %d lines\n", 96 lines, lineno); 97 return (0); 98 } 99 if (eof && !t_feof(tf)) { 100 t_verbose("expected EOF, but didn't get it\n"); 101 return (0); 102 } 103 if (!eof && t_feof(tf)) { 104 t_verbose("didn't expect EOF, but got it anyway\n"); 105 return (0); 106 } 107 return (1); 108 } 109 110 111 /*************************************************************************** 112 * Commonly-used lines 113 */ 114 115 static const char *empty[] = { 116 NULL 117 }; 118 119 static const char *hello[] = { 120 "hello", 121 NULL 122 }; 123 124 static const char *hello_world[] = { 125 "hello", 126 "world", 127 NULL 128 }; 129 130 131 /*************************************************************************** 132 * Lines without words 133 */ 134 135 T_FUNC(empty_input, "empty input") 136 { 137 struct t_file *tf; 138 int ret; 139 140 tf = t_fopen(NULL); 141 ret = orlv_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/); 142 t_fclose(tf); 143 return (ret); 144 } 145 146 T_FUNC(empty_line, "empty line") 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 = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 155 t_fclose(tf); 156 return (ret); 157 } 158 159 T_FUNC(unterminated_empty_line, "unterminated empty line") 160 { 161 struct t_file *tf; 162 int ret; 163 164 tf = t_fopen(NULL); 165 t_fprintf(tf, " "); 166 t_frewind(tf); 167 ret = orlv_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/); 168 t_fclose(tf); 169 return (ret); 170 } 171 172 T_FUNC(whitespace, "whitespace") 173 { 174 struct t_file *tf; 175 int ret; 176 177 tf = t_fopen(NULL); 178 t_fprintf(tf, " \n"); 179 t_frewind(tf); 180 ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 181 t_fclose(tf); 182 return (ret); 183 } 184 185 T_FUNC(comment, "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 = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 194 t_fclose(tf); 195 return (ret); 196 } 197 198 T_FUNC(whitespace_before_comment, "whitespace before comment") 199 { 200 struct t_file *tf; 201 int ret; 202 203 tf = t_fopen(NULL); 204 t_fprintf(tf, " # comment\n"); 205 t_frewind(tf); 206 ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 207 t_fclose(tf); 208 return (ret); 209 } 210 211 212 /*************************************************************************** 213 * Simple words 214 */ 215 216 T_FUNC(one_word, "one word") 217 { 218 struct t_file *tf; 219 int ret; 220 221 tf = t_fopen(NULL); 222 t_fprintf(tf, "hello\n"); 223 t_frewind(tf); 224 ret = orlv_expect(tf, hello, 1 /*lines*/, 0 /*eof*/); 225 t_fclose(tf); 226 return (ret); 227 } 228 229 T_FUNC(two_words, "two words") 230 { 231 struct t_file *tf; 232 int ret; 233 234 tf = t_fopen(NULL); 235 t_fprintf(tf, "hello world\n"); 236 t_frewind(tf); 237 ret = orlv_expect(tf, hello_world, 1 /*lines*/, 0 /*eof*/); 238 t_fclose(tf); 239 return (ret); 240 } 241 242 T_FUNC(unterminated_line, "unterminated line") 243 { 244 struct t_file *tf; 245 int ret; 246 247 tf = t_fopen(NULL); 248 t_fprintf(tf, "hello world"); 249 t_frewind(tf); 250 ret = orlv_expect(tf, hello_world, 0 /*lines*/, 1 /*eof*/); 251 t_fclose(tf); 252 return (ret); 253 } 254 255 256 /*************************************************************************** 257 * Boilerplate 258 */ 259 260 const struct t_test *t_plan[] = { 261 T(empty_input), 262 T(empty_line), 263 T(unterminated_empty_line), 264 T(whitespace), 265 T(comment), 266 T(whitespace_before_comment), 267 268 T(one_word), 269 T(two_words), 270 T(unterminated_line), 271 272 NULL 273 }; 274 275 const struct t_test ** 276 t_prepare(int argc, char *argv[]) 277 { 278 279 (void)argc; 280 (void)argv; 281 return (t_plan); 282 } 283 284 void 285 t_cleanup(void) 286 { 287 } 288