1236099Sdes/*- 2236099Sdes * Copyright (c) 2012 Dag-Erling Sm��rgrav 3236099Sdes * All rights reserved. 4236099Sdes * 5236099Sdes * Redistribution and use in source and binary forms, with or without 6236099Sdes * modification, are permitted provided that the following conditions 7236099Sdes * are met: 8236099Sdes * 1. Redistributions of source code must retain the above copyright 9263421Sdes * notice, this list of conditions and the following disclaimer. 10236099Sdes * 2. Redistributions in binary form must reproduce the above copyright 11236099Sdes * notice, this list of conditions and the following disclaimer in the 12236099Sdes * documentation and/or other materials provided with the distribution. 13236099Sdes * 3. The name of the author may not be used to endorse or promote 14236099Sdes * products derived from this software without specific prior written 15236099Sdes * permission. 16236099Sdes * 17236099Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18236099Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19236099Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20236099Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21236099Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22236099Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23236099Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24236099Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25236099Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26236099Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27236099Sdes * SUCH DAMAGE. 28236099Sdes * 29263421Sdes * $Id: t_openpam_readlinev.c 648 2013-03-05 17:54:27Z des $ 30236099Sdes */ 31236099Sdes 32236099Sdes#ifdef HAVE_CONFIG_H 33236099Sdes# include "config.h" 34236099Sdes#endif 35236099Sdes 36236099Sdes#include <err.h> 37236099Sdes#include <stdio.h> 38236099Sdes#include <stdlib.h> 39236099Sdes#include <string.h> 40236099Sdes 41236099Sdes#include <security/pam_appl.h> 42236099Sdes#include <security/openpam.h> 43236099Sdes 44236099Sdes#include "openpam_impl.h" 45236099Sdes#include "t.h" 46236099Sdes 47236099Sdes/* 48236099Sdes * Read a line from the temp file and verify that the result matches our 49236099Sdes * expectations: whether a line was read at all, how many and which words 50236099Sdes * it contained, how many lines were read (in case of quoted or escaped 51236099Sdes * newlines) and whether we reached the end of the file. 52236099Sdes */ 53236099Sdesstatic int 54263421Sdesorlv_expect(struct t_file *tf, const char **expectedv, int lines, int eof) 55236099Sdes{ 56236099Sdes int expectedc, gotc, i, lineno = 0; 57236099Sdes char **gotv; 58236099Sdes 59236099Sdes expectedc = 0; 60236099Sdes if (expectedv != NULL) 61236099Sdes while (expectedv[expectedc] != NULL) 62236099Sdes ++expectedc; 63263421Sdes gotv = openpam_readlinev(tf->file, &lineno, &gotc); 64263421Sdes if (t_ferror(tf)) 65263421Sdes err(1, "%s(): %s", __func__, tf->name); 66236099Sdes if (expectedv != NULL && gotv == NULL) { 67236099Sdes t_verbose("expected %d words, got nothing\n", expectedc); 68236099Sdes return (0); 69236099Sdes } 70236099Sdes if (expectedv == NULL && gotv != NULL) { 71236099Sdes t_verbose("expected nothing, got %d words\n", gotc); 72236099Sdes FREEV(gotc, gotv); 73236099Sdes return (0); 74236099Sdes } 75236099Sdes if (expectedv != NULL && gotv != NULL) { 76236099Sdes if (expectedc != gotc) { 77236099Sdes t_verbose("expected %d words, got %d\n", 78236099Sdes expectedc, gotc); 79236099Sdes FREEV(gotc, gotv); 80236099Sdes return (0); 81236099Sdes } 82236099Sdes for (i = 0; i < gotc; ++i) { 83236099Sdes if (strcmp(expectedv[i], gotv[i]) != 0) { 84236099Sdes t_verbose("word %d: expected <<%s>>, " 85236099Sdes "got <<%s>>\n", i, expectedv[i], gotv[i]); 86236099Sdes FREEV(gotc, gotv); 87236099Sdes return (0); 88236099Sdes } 89236099Sdes } 90236099Sdes FREEV(gotc, gotv); 91236099Sdes } 92236099Sdes if (lineno != lines) { 93236099Sdes t_verbose("expected to advance %d lines, advanced %d lines\n", 94236099Sdes lines, lineno); 95236099Sdes return (0); 96236099Sdes } 97263421Sdes if (eof && !t_feof(tf)) { 98236099Sdes t_verbose("expected EOF, but didn't get it\n"); 99236099Sdes return (0); 100236099Sdes } 101263421Sdes if (!eof && t_feof(tf)) { 102236099Sdes t_verbose("didn't expect EOF, but got it anyway\n"); 103236099Sdes return (0); 104236099Sdes } 105236099Sdes return (1); 106236099Sdes} 107236099Sdes 108236099Sdes 109236099Sdes/*************************************************************************** 110236099Sdes * Commonly-used lines 111236099Sdes */ 112236099Sdes 113236099Sdesstatic const char *empty[] = { 114236099Sdes NULL 115236099Sdes}; 116236099Sdes 117236099Sdesstatic const char *hello[] = { 118236099Sdes "hello", 119236099Sdes NULL 120236099Sdes}; 121236099Sdes 122236099Sdesstatic const char *hello_world[] = { 123236099Sdes "hello", 124236099Sdes "world", 125236099Sdes NULL 126236099Sdes}; 127236099Sdes 128236099Sdes 129236099Sdes/*************************************************************************** 130236099Sdes * Lines without words 131236099Sdes */ 132236099Sdes 133236099SdesT_FUNC(empty_input, "empty input") 134236099Sdes{ 135263421Sdes struct t_file *tf; 136236099Sdes int ret; 137236099Sdes 138263421Sdes tf = t_fopen(NULL); 139263421Sdes ret = orlv_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/); 140263421Sdes t_fclose(tf); 141236099Sdes return (ret); 142236099Sdes} 143236099Sdes 144236099SdesT_FUNC(empty_line, "empty line") 145236099Sdes{ 146263421Sdes struct t_file *tf; 147236099Sdes int ret; 148236099Sdes 149263421Sdes tf = t_fopen(NULL); 150263421Sdes t_fprintf(tf, "\n"); 151263421Sdes t_frewind(tf); 152263421Sdes ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 153263421Sdes t_fclose(tf); 154236099Sdes return (ret); 155236099Sdes} 156236099Sdes 157236099SdesT_FUNC(unterminated_empty_line, "unterminated empty line") 158236099Sdes{ 159263421Sdes struct t_file *tf; 160236099Sdes int ret; 161236099Sdes 162263421Sdes tf = t_fopen(NULL); 163263421Sdes t_fprintf(tf, " "); 164263421Sdes t_frewind(tf); 165263421Sdes ret = orlv_expect(tf, NULL, 0 /*lines*/, 1 /*eof*/); 166263421Sdes t_fclose(tf); 167236099Sdes return (ret); 168236099Sdes} 169236099Sdes 170236099SdesT_FUNC(whitespace, "whitespace") 171236099Sdes{ 172263421Sdes struct t_file *tf; 173236099Sdes int ret; 174236099Sdes 175263421Sdes tf = t_fopen(NULL); 176263421Sdes t_fprintf(tf, " \n"); 177263421Sdes t_frewind(tf); 178263421Sdes ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 179263421Sdes t_fclose(tf); 180236099Sdes return (ret); 181236099Sdes} 182236099Sdes 183236099SdesT_FUNC(comment, "comment") 184236099Sdes{ 185263421Sdes struct t_file *tf; 186236099Sdes int ret; 187236099Sdes 188263421Sdes tf = t_fopen(NULL); 189263421Sdes t_fprintf(tf, "# comment\n"); 190263421Sdes t_frewind(tf); 191263421Sdes ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 192263421Sdes t_fclose(tf); 193236099Sdes return (ret); 194236099Sdes} 195236099Sdes 196236099SdesT_FUNC(whitespace_before_comment, "whitespace before comment") 197236099Sdes{ 198263421Sdes struct t_file *tf; 199236099Sdes int ret; 200236099Sdes 201263421Sdes tf = t_fopen(NULL); 202263421Sdes t_fprintf(tf, " # comment\n"); 203263421Sdes t_frewind(tf); 204263421Sdes ret = orlv_expect(tf, empty, 1 /*lines*/, 0 /*eof*/); 205263421Sdes t_fclose(tf); 206236099Sdes return (ret); 207236099Sdes} 208236099Sdes 209236099Sdes 210236099Sdes/*************************************************************************** 211236099Sdes * Simple words 212236099Sdes */ 213236099Sdes 214236099SdesT_FUNC(one_word, "one word") 215236099Sdes{ 216263421Sdes struct t_file *tf; 217236099Sdes int ret; 218236099Sdes 219263421Sdes tf = t_fopen(NULL); 220263421Sdes t_fprintf(tf, "hello\n"); 221263421Sdes t_frewind(tf); 222263421Sdes ret = orlv_expect(tf, hello, 1 /*lines*/, 0 /*eof*/); 223263421Sdes t_fclose(tf); 224236099Sdes return (ret); 225236099Sdes} 226236099Sdes 227236099SdesT_FUNC(two_words, "two words") 228236099Sdes{ 229263421Sdes struct t_file *tf; 230236099Sdes int ret; 231236099Sdes 232263421Sdes tf = t_fopen(NULL); 233263421Sdes t_fprintf(tf, "hello world\n"); 234263421Sdes t_frewind(tf); 235263421Sdes ret = orlv_expect(tf, hello_world, 1 /*lines*/, 0 /*eof*/); 236263421Sdes t_fclose(tf); 237236099Sdes return (ret); 238236099Sdes} 239236099Sdes 240236099SdesT_FUNC(unterminated_line, "unterminated line") 241236099Sdes{ 242263421Sdes struct t_file *tf; 243236099Sdes int ret; 244236099Sdes 245263421Sdes tf = t_fopen(NULL); 246263421Sdes t_fprintf(tf, "hello world"); 247263421Sdes t_frewind(tf); 248263421Sdes ret = orlv_expect(tf, hello_world, 0 /*lines*/, 1 /*eof*/); 249263421Sdes t_fclose(tf); 250236099Sdes return (ret); 251236099Sdes} 252236099Sdes 253236099Sdes 254236099Sdes/*************************************************************************** 255236099Sdes * Boilerplate 256236099Sdes */ 257236099Sdes 258236099Sdesconst struct t_test *t_plan[] = { 259236099Sdes T(empty_input), 260236099Sdes T(empty_line), 261236099Sdes T(unterminated_empty_line), 262236099Sdes T(whitespace), 263236099Sdes T(comment), 264236099Sdes T(whitespace_before_comment), 265236099Sdes 266236099Sdes T(one_word), 267236099Sdes T(two_words), 268236099Sdes T(unterminated_line), 269236099Sdes 270236099Sdes NULL 271236099Sdes}; 272236099Sdes 273236099Sdesconst struct t_test ** 274236099Sdest_prepare(int argc, char *argv[]) 275236099Sdes{ 276236099Sdes 277236099Sdes (void)argc; 278236099Sdes (void)argv; 279236099Sdes return (t_plan); 280236099Sdes} 281236099Sdes 282236099Sdesvoid 283236099Sdest_cleanup(void) 284236099Sdes{ 285236099Sdes} 286