property.c revision 40117
1135446Strhodes/* 2224092Sdougb * 3135446Strhodes * Simple property list handling code. 4135446Strhodes * 5193149Sdougb * Copyright (c) 1998 6135446Strhodes * Jordan Hubbard. All rights reserved. 7135446Strhodes * 8135446Strhodes * Redistribution and use in source and binary forms, with or without 9135446Strhodes * modification, are permitted provided that the following conditions 10135446Strhodes * are met: 11135446Strhodes * 1. Redistributions of source code must retain the above copyright 12135446Strhodes * notice, this list of conditions and the following disclaimer, 13135446Strhodes * verbatim and that no modifications are made prior to this 14135446Strhodes * point in the file. 15135446Strhodes * 2. Redistributions in binary form must reproduce the above copyright 16135446Strhodes * notice, this list of conditions and the following disclaimer in the 17135446Strhodes * documentation and/or other materials provided with the distribution. 18234010Sdougb * 19135446Strhodes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20135446Strhodes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21135446Strhodes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22135446Strhodes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE 23193149Sdougb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24170222Sdougb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25135446Strhodes * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 26135446Strhodes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27135446Strhodes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28135446Strhodes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29135446Strhodes * SUCH DAMAGE. 30193149Sdougb * 31135446Strhodes */ 32135446Strhodes 33135446Strhodes#include <ctype.h> 34135446Strhodes#include <unistd.h> 35135446Strhodes#include <stdlib.h> 36135446Strhodes#include <stdio.h> 37135446Strhodes#include <string.h> 38135446Strhodes#include <sys/types.h> 39135446Strhodes#include <libutil.h> 40135446Strhodes 41135446Strhodes#define MAX_NAME 64 42135446Strhodes#define MAX_VALUE 512 43135446Strhodes 44193149Sdougbstatic properties 45135446Strhodesproperty_alloc(char *name, char *value) 46135446Strhodes{ 47224092Sdougb properties n; 48135446Strhodes 49135446Strhodes n = (properties)malloc(sizeof(struct _property)); 50135446Strhodes n->next = NULL; 51193149Sdougb n->name = name ? strdup(name) : NULL; 52193149Sdougb n->value = value ? strdup(value) : NULL; 53170222Sdougb return n; 54135446Strhodes} 55135446Strhodes 56135446Strhodesproperties 57170222Sdougbproperties_read(int fd) 58170222Sdougb{ 59170222Sdougb properties head, ptr; 60135446Strhodes char hold_n[MAX_NAME + 1]; 61135446Strhodes char hold_v[MAX_VALUE + 1]; 62170222Sdougb char buf[BUFSIZ * 4]; 63170222Sdougb int bp, n, v, max; 64170222Sdougb enum { LOOK, COMMENT, NAME, VALUE, MVALUE, COMMIT, FILL, STOP } state; 65135446Strhodes int ch = 0; 66135446Strhodes 67135446Strhodes n = v = bp = max = 0; 68135446Strhodes head = ptr = NULL; 69170222Sdougb state = LOOK; 70135446Strhodes while (state != STOP) { 71135446Strhodes if (state != COMMIT) { 72135446Strhodes if (bp == max) 73170222Sdougb state = FILL; 74170222Sdougb else 75135446Strhodes ch = buf[bp++]; 76135446Strhodes } 77135446Strhodes switch(state) { 78135446Strhodes case FILL: 79135446Strhodes if ((max = read(fd, buf, sizeof buf)) <= 0) { 80170222Sdougb state = STOP; 81135446Strhodes break; 82135446Strhodes } 83135446Strhodes else { 84135446Strhodes state = LOOK; 85170222Sdougb ch = buf[0]; 86170222Sdougb bp = 1; 87170222Sdougb } 88135446Strhodes /* Fall through deliberately since we already have a character and state == LOOK */ 89135446Strhodes 90170222Sdougb case LOOK: 91135446Strhodes if (isspace(ch)) 92135446Strhodes continue; 93135446Strhodes /* Allow shell or lisp style comments */ 94170222Sdougb else if (ch == '#' || ch == ';') { 95135446Strhodes state = COMMENT; 96135446Strhodes continue; 97135446Strhodes } 98135446Strhodes else if (isalnum(ch) || ch == '_') { 99135446Strhodes if (n >= MAX_NAME) { 100135446Strhodes n = 0; 101170222Sdougb state = COMMENT; 102135446Strhodes } 103135446Strhodes else { 104135446Strhodes hold_n[n++] = ch; 105135446Strhodes state = NAME; 106135446Strhodes } 107135446Strhodes } 108135446Strhodes else 109135446Strhodes state = COMMENT; /* Ignore the rest of the line */ 110135446Strhodes break; 111135446Strhodes 112135446Strhodes case COMMENT: 113170222Sdougb if (ch == '\n') 114170222Sdougb state = LOOK; 115170222Sdougb break; 116170222Sdougb 117135446Strhodes case NAME: 118135446Strhodes if (ch == '\n' || !ch) { 119170222Sdougb hold_n[n] = '\0'; 120135446Strhodes hold_v[0] = '\0'; 121170222Sdougb v = n = 0; 122135446Strhodes state = COMMIT; 123135446Strhodes } 124135446Strhodes else if (isspace(ch)) 125193149Sdougb continue; 126193149Sdougb else if (ch == '=') { 127224092Sdougb hold_n[n] = '\0'; 128224092Sdougb v = n = 0; 129170222Sdougb state = VALUE; 130193149Sdougb } 131193149Sdougb else 132193149Sdougb hold_n[n++] = ch; 133193149Sdougb break; 134193149Sdougb 135193149Sdougb case VALUE: 136193149Sdougb if (v == 0 && isspace(ch)) 137193149Sdougb continue; 138193149Sdougb else if (ch == '{') 139193149Sdougb state = MVALUE; 140193149Sdougb else if (ch == '\n' || !ch) { 141193149Sdougb hold_v[v] = '\0'; 142193149Sdougb v = n = 0; 143193149Sdougb state = COMMIT; 144193149Sdougb } 145193149Sdougb else { 146224092Sdougb if (v >= MAX_VALUE) { 147135446Strhodes state = COMMENT; 148135446Strhodes v = n = 0; 149193149Sdougb break; 150135446Strhodes } 151135446Strhodes else 152170222Sdougb hold_v[v++] = ch; 153135446Strhodes } 154135446Strhodes break; 155135446Strhodes 156135446Strhodes case MVALUE: 157170222Sdougb /* multiline value */ 158170222Sdougb if (v >= MAX_VALUE) { 159135446Strhodes state = COMMENT; 160135446Strhodes n = v = 0; 161170222Sdougb } 162135446Strhodes else if (ch == '}') { 163170222Sdougb hold_v[v] = '\0'; 164135446Strhodes v = n = 0; 165135446Strhodes state = COMMIT; 166135446Strhodes } 167135446Strhodes else 168193149Sdougb hold_v[v++] = ch; 169135446Strhodes break; 170170222Sdougb 171135446Strhodes case COMMIT: 172135446Strhodes if (!head) 173135446Strhodes head = ptr = property_alloc(hold_n, hold_v); 174135446Strhodes else { 175135446Strhodes ptr->next = property_alloc(hold_n, hold_v); 176135446Strhodes ptr = ptr->next; 177170222Sdougb } 178170222Sdougb state = LOOK; 179170222Sdougb v = n = 0; 180170222Sdougb break; 181170222Sdougb 182135446Strhodes case STOP: 183135446Strhodes /* we don't handle this here, but this prevents warnings */ 184170222Sdougb break; 185170222Sdougb } 186135446Strhodes } 187135446Strhodes return head; 188135446Strhodes} 189135446Strhodes 190135446Strhodeschar * 191193149Sdougbproperty_find(properties list, const char *name) 192193149Sdougb{ 193224092Sdougb if (!list || !name || !name[0]) 194170222Sdougb return NULL; 195135446Strhodes while (list) { 196135446Strhodes if (!strcmp(list->name, name)) 197135446Strhodes return list->value; 198135446Strhodes list = list->next; 199135446Strhodes } 200135446Strhodes return NULL; 201170222Sdougb} 202135446Strhodes 203135446Strhodesvoid 204135446Strhodesproperties_free(properties list) 205135446Strhodes{ 206135446Strhodes properties tmp; 207170222Sdougb 208170222Sdougb while (list) { 209170222Sdougb tmp = list->next; 210135446Strhodes if (list->name) 211135446Strhodes free(list->name); 212170222Sdougb if (list->value) 213170222Sdougb free(list->value); 214135446Strhodes free(list); 215135446Strhodes list = tmp; 216135446Strhodes } 217193149Sdougb} 218193149Sdougb