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