openpam_readline.c revision 168463
1/*- 2 * Copyright (c) 2003 Networks Associates Technology, Inc. 3 * All rights reserved. 4 * 5 * This software was developed for the FreeBSD Project by ThinkSec AS and 6 * Network Associates Laboratories, the Security Research Division of 7 * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 8 * ("CBOSS"), as part of the DARPA CHATS research program. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote 19 * products derived from this software without specific prior written 20 * permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $Id: openpam_readline.c 380 2006-03-14 14:42:09Z des $ 35 */ 36 37#include <ctype.h> 38#include <stdio.h> 39#include <stdlib.h> 40 41#include <security/pam_appl.h> 42#include "openpam_impl.h" 43 44#define MIN_LINE_LENGTH 128 45 46/* 47 * OpenPAM extension 48 * 49 * Read a line from a file. 50 */ 51 52char * 53openpam_readline(FILE *f, int *lineno, size_t *lenp) 54{ 55 char *line; 56 size_t len, size; 57 int ch; 58 59 if ((line = malloc(MIN_LINE_LENGTH)) == NULL) 60 return (NULL); 61 size = MIN_LINE_LENGTH; 62 len = 0; 63 64#define line_putch(ch) do { \ 65 if (len >= size - 1) { \ 66 char *tmp = realloc(line, size *= 2); \ 67 if (tmp == NULL) \ 68 goto fail; \ 69 line = tmp; \ 70 } \ 71 line[len++] = ch; \ 72 line[len] = '\0'; \ 73} while (0) 74 75 for (;;) { 76 ch = fgetc(f); 77 /* strip comment */ 78 if (ch == '#') { 79 do { 80 ch = fgetc(f); 81 } while (ch != EOF && ch != '\n'); 82 } 83 /* eof */ 84 if (ch == EOF) { 85 /* remove trailing whitespace */ 86 while (len > 0 && isspace((int)line[len - 1])) 87 --len; 88 line[len] = '\0'; 89 if (len == 0) 90 goto fail; 91 break; 92 } 93 /* eol */ 94 if (ch == '\n') { 95 if (lineno != NULL) 96 ++*lineno; 97 98 /* remove trailing whitespace */ 99 while (len > 0 && isspace((int)line[len - 1])) 100 --len; 101 line[len] = '\0'; 102 /* skip blank lines */ 103 if (len == 0) 104 continue; 105 /* continuation */ 106 if (line[len - 1] == '\\') { 107 line[--len] = '\0'; 108 /* fall through to whitespace case */ 109 } else { 110 break; 111 } 112 } 113 /* whitespace */ 114 if (isspace(ch)) { 115 /* ignore leading whitespace */ 116 /* collapse linear whitespace */ 117 if (len > 0 && line[len - 1] != ' ') 118 line_putch(' '); 119 continue; 120 } 121 /* anything else */ 122 line_putch(ch); 123 } 124 125 if (lenp != NULL) 126 *lenp = len; 127 return (line); 128 fail: 129 FREE(line); 130 return (NULL); 131} 132 133/** 134 * The =openpam_readline function reads a line from a file, and returns it 135 * in a NUL-terminated buffer allocated with =malloc. 136 * 137 * The =openpam_readline function performs a certain amount of processing 138 * on the data it reads. 139 * Comments (introduced by a hash sign) are stripped, as is leading and 140 * trailing whitespace. 141 * Any amount of linear whitespace is collapsed to a single space. 142 * Blank lines are ignored. 143 * If a line ends in a backslash, the backslash is stripped and the next 144 * line is appended. 145 * 146 * If =lineno is not =NULL, the integer variable it points to is 147 * incremented every time a newline character is read. 148 * 149 * If =lenp is not =NULL, the length of the line (not including the 150 * terminating NUL character) is stored in the variable it points to. 151 * 152 * The caller is responsible for releasing the returned buffer by passing 153 * it to =free. 154 */ 155