openpam_readline.c revision 115619
1233648Seadler/*- 2230491Sjimharris * Copyright (c) 2003 Networks Associates Technology, Inc. 3230491Sjimharris * All rights reserved. 4233648Seadler * 5230491Sjimharris * This software was developed for the FreeBSD Project by ThinkSec AS and 6230491Sjimharris * Network Associates Laboratories, the Security Research Division of 7230491Sjimharris * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 8230491Sjimharris * ("CBOSS"), as part of the DARPA CHATS research program. 9230491Sjimharris * 10230491Sjimharris * Redistribution and use in source and binary forms, with or without 11230491Sjimharris * modification, are permitted provided that the following conditions 12230491Sjimharris * are met: 13230491Sjimharris * 1. Redistributions of source code must retain the above copyright 14230491Sjimharris * notice, this list of conditions and the following disclaimer. 15230491Sjimharris * 2. Redistributions in binary form must reproduce the above copyright 16233648Seadler * notice, this list of conditions and the following disclaimer in the 17230491Sjimharris * documentation and/or other materials provided with the distribution. 18230491Sjimharris * 3. The name of the author may not be used to endorse or promote 19230491Sjimharris * products derived from this software without specific prior written 20230491Sjimharris * permission. 21230491Sjimharris * 22230491Sjimharris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23230491Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24230491Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25230491Sjimharris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26230491Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27230491Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28230491Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29233648Seadler * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30230491Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31230491Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32230491Sjimharris * SUCH DAMAGE. 33230491Sjimharris * 34230491Sjimharris * $P4: //depot/projects/openpam/lib/openpam_readline.c#2 $ 35230491Sjimharris */ 36230491Sjimharris 37230491Sjimharris#include <ctype.h> 38230491Sjimharris#include <stdio.h> 39230491Sjimharris#include <stdlib.h> 40230491Sjimharris 41230491Sjimharris#include <security/pam_appl.h> 42230491Sjimharris#include "openpam_impl.h" 43230491Sjimharris 44230491Sjimharris#define MIN_LINE_LENGTH 128 45230491Sjimharris 46230491Sjimharris/* 47230491Sjimharris * OpenPAM extension 48230491Sjimharris * 49230491Sjimharris * Read a line from a file. 50230491Sjimharris */ 51230491Sjimharris 52230491Sjimharrischar * 53230491Sjimharrisopenpam_readline(FILE *f, int *lineno, size_t *lenp) 54230491Sjimharris{ 55232056Sbrueffer char *line; 56230491Sjimharris size_t len, size; 57230491Sjimharris int ch; 58230491Sjimharris 59230491Sjimharris if ((line = malloc(MIN_LINE_LENGTH)) == NULL) 60231615Sbrueffer return (NULL); 61230491Sjimharris size = MIN_LINE_LENGTH; 62230491Sjimharris len = 0; 63230491Sjimharris 64230491Sjimharris#define line_putch(ch) do { \ 65230491Sjimharris if (len >= size - 1) { \ 66230491Sjimharris char *tmp = realloc(line, size *= 2); \ 67230491Sjimharris if (tmp == NULL) \ 68230491Sjimharris goto fail; \ 69230491Sjimharris line = tmp; \ 70230491Sjimharris } \ 71230491Sjimharris line[len++] = ch; \ 72230491Sjimharris line[len] = '\0'; \ 73230491Sjimharris} while (0) 74230491Sjimharris 75230491Sjimharris for (;;) { 76230491Sjimharris ch = fgetc(f); 77230491Sjimharris /* strip comment */ 78230491Sjimharris if (ch == '#') { 79230491Sjimharris do { 80231615Sbrueffer ch = fgetc(f); 81231615Sbrueffer } while (ch != EOF && ch != '\n'); 82231615Sbrueffer } 83231615Sbrueffer /* eof */ 84231615Sbrueffer if (ch == EOF) { 85230491Sjimharris /* remove trailing whitespace */ 86230491Sjimharris while (len > 0 && isspace(line[len - 1])) 87230491Sjimharris --len; 88230491Sjimharris line[len] = '\0'; 89233648Seadler if (len == 0) 90230491Sjimharris goto fail; 91230491Sjimharris break; 92230491Sjimharris } 93230491Sjimharris /* eol */ 94230491Sjimharris if (ch == '\n') { 95230491Sjimharris if (lineno != NULL) 96231615Sbrueffer ++*lineno; 97230491Sjimharris 98230491Sjimharris /* remove trailing whitespace */ 99230491Sjimharris while (len > 0 && isspace(line[len - 1])) 100230491Sjimharris --len; 101235317Sgjb line[len] = '\0'; 102235317Sgjb /* skip blank lines */ 103230491Sjimharris if (len == 0) 104230491Sjimharris continue; 105230491Sjimharris /* continuation */ 106230491Sjimharris if (line[len - 1] == '\\') { 107230491Sjimharris line[--len] = '\0'; 108267938Sbapt /* fall through to whitespace case */ 109267938Sbapt } else { 110267938Sbapt break; 111267938Sbapt } 112267938Sbapt } 113230491Sjimharris /* whitespace */ 114230491Sjimharris if (isspace(ch)) { 115267938Sbapt /* 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