openpam_readline.c revision 228690
1115619Sdes/*- 2115619Sdes * Copyright (c) 2003 Networks Associates Technology, Inc. 3228690Sdes * Copyright (c) 2004-2011 Dag-Erling Sm��rgrav 4115619Sdes * All rights reserved. 5115619Sdes * 6115619Sdes * This software was developed for the FreeBSD Project by ThinkSec AS and 7115619Sdes * Network Associates Laboratories, the Security Research Division of 8115619Sdes * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 9115619Sdes * ("CBOSS"), as part of the DARPA CHATS research program. 10115619Sdes * 11115619Sdes * Redistribution and use in source and binary forms, with or without 12115619Sdes * modification, are permitted provided that the following conditions 13115619Sdes * are met: 14115619Sdes * 1. Redistributions of source code must retain the above copyright 15115619Sdes * notice, this list of conditions and the following disclaimer. 16115619Sdes * 2. Redistributions in binary form must reproduce the above copyright 17115619Sdes * notice, this list of conditions and the following disclaimer in the 18115619Sdes * documentation and/or other materials provided with the distribution. 19115619Sdes * 3. The name of the author may not be used to endorse or promote 20115619Sdes * products derived from this software without specific prior written 21115619Sdes * permission. 22115619Sdes * 23115619Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24115619Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25115619Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26115619Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27115619Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28115619Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29115619Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30115619Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31115619Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32115619Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33115619Sdes * SUCH DAMAGE. 34115619Sdes * 35228690Sdes * $Id: openpam_readline.c 473 2011-11-03 10:48:25Z des $ 36115619Sdes */ 37115619Sdes 38228690Sdes#ifdef HAVE_CONFIG_H 39228690Sdes# include "config.h" 40228690Sdes#endif 41228690Sdes 42115619Sdes#include <ctype.h> 43115619Sdes#include <stdio.h> 44115619Sdes#include <stdlib.h> 45115619Sdes 46115619Sdes#include <security/pam_appl.h> 47115619Sdes#include "openpam_impl.h" 48115619Sdes 49115619Sdes#define MIN_LINE_LENGTH 128 50115619Sdes 51115619Sdes/* 52115619Sdes * OpenPAM extension 53115619Sdes * 54115619Sdes * Read a line from a file. 55115619Sdes */ 56115619Sdes 57115619Sdeschar * 58115619Sdesopenpam_readline(FILE *f, int *lineno, size_t *lenp) 59115619Sdes{ 60168463Sdes char *line; 61115619Sdes size_t len, size; 62115619Sdes int ch; 63115619Sdes 64115619Sdes if ((line = malloc(MIN_LINE_LENGTH)) == NULL) 65115619Sdes return (NULL); 66115619Sdes size = MIN_LINE_LENGTH; 67115619Sdes len = 0; 68115619Sdes 69115619Sdes#define line_putch(ch) do { \ 70115619Sdes if (len >= size - 1) { \ 71168463Sdes char *tmp = realloc(line, size *= 2); \ 72115619Sdes if (tmp == NULL) \ 73115619Sdes goto fail; \ 74115619Sdes line = tmp; \ 75115619Sdes } \ 76115619Sdes line[len++] = ch; \ 77115619Sdes line[len] = '\0'; \ 78115619Sdes} while (0) 79115619Sdes 80115619Sdes for (;;) { 81115619Sdes ch = fgetc(f); 82115619Sdes /* strip comment */ 83115619Sdes if (ch == '#') { 84115619Sdes do { 85115619Sdes ch = fgetc(f); 86115619Sdes } while (ch != EOF && ch != '\n'); 87115619Sdes } 88115619Sdes /* eof */ 89115619Sdes if (ch == EOF) { 90228690Sdes /* done */ 91115619Sdes break; 92115619Sdes } 93115619Sdes /* eol */ 94115619Sdes if (ch == '\n') { 95115619Sdes if (lineno != NULL) 96115619Sdes ++*lineno; 97115619Sdes /* skip blank lines */ 98115619Sdes if (len == 0) 99115619Sdes continue; 100115619Sdes /* continuation */ 101115619Sdes if (line[len - 1] == '\\') { 102115619Sdes line[--len] = '\0'; 103228690Sdes continue; 104115619Sdes } 105228690Sdes /* done */ 106228690Sdes break; 107115619Sdes } 108115619Sdes /* whitespace */ 109115619Sdes if (isspace(ch)) { 110115619Sdes /* ignore leading whitespace */ 111115619Sdes /* collapse linear whitespace */ 112115619Sdes if (len > 0 && line[len - 1] != ' ') 113115619Sdes line_putch(' '); 114115619Sdes continue; 115115619Sdes } 116115619Sdes /* anything else */ 117115619Sdes line_putch(ch); 118115619Sdes } 119115619Sdes 120228690Sdes /* remove trailing whitespace */ 121228690Sdes while (len > 0 && isspace((unsigned char)line[len - 1])) 122228690Sdes --len; 123228690Sdes line[len] = '\0'; 124228690Sdes if (len == 0) 125228690Sdes goto fail; 126115619Sdes if (lenp != NULL) 127115619Sdes *lenp = len; 128115619Sdes return (line); 129228690Sdesfail: 130115619Sdes FREE(line); 131115619Sdes return (NULL); 132115619Sdes} 133115619Sdes 134115619Sdes/** 135115619Sdes * The =openpam_readline function reads a line from a file, and returns it 136115619Sdes * in a NUL-terminated buffer allocated with =malloc. 137115619Sdes * 138115619Sdes * The =openpam_readline function performs a certain amount of processing 139228690Sdes * on the data it reads: 140115619Sdes * 141228690Sdes * - Comments (introduced by a hash sign) are stripped, as is leading and 142228690Sdes * trailing whitespace. 143228690Sdes * - Any amount of linear whitespace is collapsed to a single space. 144228690Sdes * - Blank lines are ignored. 145228690Sdes * - If a line ends in a backslash, the backslash is stripped and the 146228690Sdes * next line is appended. 147228690Sdes * 148115619Sdes * If =lineno is not =NULL, the integer variable it points to is 149115619Sdes * incremented every time a newline character is read. 150115619Sdes * 151115619Sdes * If =lenp is not =NULL, the length of the line (not including the 152115619Sdes * terminating NUL character) is stored in the variable it points to. 153115619Sdes * 154115619Sdes * The caller is responsible for releasing the returned buffer by passing 155115619Sdes * it to =free. 156115619Sdes */ 157