xref: /freebsd/lib/libutil/property.c (revision 8b1ef8d4645b65a6acfa34d3c1f460805e737a98)
1b704025fSJordan K. Hubbard /*
2b704025fSJordan K. Hubbard  *
3b704025fSJordan K. Hubbard  * Simple property list handling code.
4b704025fSJordan K. Hubbard  *
5b704025fSJordan K. Hubbard  * Copyright (c) 1998
6b704025fSJordan K. Hubbard  *	Jordan Hubbard.  All rights reserved.
7b704025fSJordan K. Hubbard  *
8b704025fSJordan K. Hubbard  * Redistribution and use in source and binary forms, with or without
9b704025fSJordan K. Hubbard  * modification, are permitted provided that the following conditions
10b704025fSJordan K. Hubbard  * are met:
11b704025fSJordan K. Hubbard  * 1. Redistributions of source code must retain the above copyright
12b704025fSJordan K. Hubbard  *    notice, this list of conditions and the following disclaimer,
13b704025fSJordan K. Hubbard  *    verbatim and that no modifications are made prior to this
14b704025fSJordan K. Hubbard  *    point in the file.
15b704025fSJordan K. Hubbard  * 2. Redistributions in binary form must reproduce the above copyright
16b704025fSJordan K. Hubbard  *    notice, this list of conditions and the following disclaimer in the
17b704025fSJordan K. Hubbard  *    documentation and/or other materials provided with the distribution.
18b704025fSJordan K. Hubbard  *
19b704025fSJordan K. Hubbard  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20b704025fSJordan K. Hubbard  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21b704025fSJordan K. Hubbard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22b704025fSJordan K. Hubbard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE
23b704025fSJordan K. Hubbard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24b704025fSJordan K. Hubbard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25b704025fSJordan K. Hubbard  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
26b704025fSJordan K. Hubbard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27b704025fSJordan K. Hubbard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28b704025fSJordan K. Hubbard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29b704025fSJordan K. Hubbard  * SUCH DAMAGE.
30b704025fSJordan K. Hubbard  *
31b704025fSJordan K. Hubbard  */
32b704025fSJordan K. Hubbard 
33b704025fSJordan K. Hubbard #include <ctype.h>
348b1ef8d4SJordan K. Hubbard #include <unistd.h>
35b704025fSJordan K. Hubbard #include <stdlib.h>
368b1ef8d4SJordan K. Hubbard #include <stdio.h>
37b704025fSJordan K. Hubbard #include <string.h>
3869761016SJordan K. Hubbard #include <sys/types.h>
39b704025fSJordan K. Hubbard #include <libutil.h>
40b704025fSJordan K. Hubbard 
41b704025fSJordan K. Hubbard #define MAX_NAME	64
42b704025fSJordan K. Hubbard #define MAX_VALUE	512
43b704025fSJordan K. Hubbard 
44b704025fSJordan K. Hubbard static properties
45b704025fSJordan K. Hubbard property_alloc(char *name, char *value)
46b704025fSJordan K. Hubbard {
47b704025fSJordan K. Hubbard     properties n;
48b704025fSJordan K. Hubbard 
49b704025fSJordan K. Hubbard     n = (properties)malloc(sizeof(struct _property));
50b704025fSJordan K. Hubbard     n->next = NULL;
51b704025fSJordan K. Hubbard     n->name = name ? strdup(name) : NULL;
52b704025fSJordan K. Hubbard     n->value = value ? strdup(value) : NULL;
53b704025fSJordan K. Hubbard     return n;
54b704025fSJordan K. Hubbard }
55b704025fSJordan K. Hubbard 
56b704025fSJordan K. Hubbard properties
5750dfa596SJordan K. Hubbard properties_read(int fd)
58b704025fSJordan K. Hubbard {
59b704025fSJordan K. Hubbard     properties head, ptr;
60b704025fSJordan K. Hubbard     char hold_n[MAX_NAME + 1];
61b704025fSJordan K. Hubbard     char hold_v[MAX_VALUE + 1];
62b704025fSJordan K. Hubbard     char buf[BUFSIZ * 4];
63b704025fSJordan K. Hubbard     int bp, n, v, max;
64b704025fSJordan K. Hubbard     enum { LOOK, COMMENT, NAME, VALUE, MVALUE, COMMIT, FILL, STOP } state;
65b704025fSJordan K. Hubbard     int ch = 0;
66b704025fSJordan K. Hubbard 
67b704025fSJordan K. Hubbard     n = v = bp = max = 0;
68b704025fSJordan K. Hubbard     head = ptr = NULL;
69b704025fSJordan K. Hubbard     state = LOOK;
70b704025fSJordan K. Hubbard     while (state != STOP) {
71b704025fSJordan K. Hubbard 	if (state != COMMIT) {
72b704025fSJordan K. Hubbard 	    if (bp == max)
73b704025fSJordan K. Hubbard 		state = FILL;
74b704025fSJordan K. Hubbard 	    else
75b704025fSJordan K. Hubbard 		ch = buf[bp++];
76b704025fSJordan K. Hubbard 	}
77b704025fSJordan K. Hubbard 	switch(state) {
78b704025fSJordan K. Hubbard 	case FILL:
7950dfa596SJordan K. Hubbard 	    if ((max = read(fd, buf, sizeof buf)) <= 0) {
80b704025fSJordan K. Hubbard 		state = STOP;
81b704025fSJordan K. Hubbard 		break;
82b704025fSJordan K. Hubbard 	    }
83b704025fSJordan K. Hubbard 	    else {
84b704025fSJordan K. Hubbard 		state = LOOK;
85b704025fSJordan K. Hubbard 		ch = buf[0];
86b704025fSJordan K. Hubbard 		bp = 1;
87b704025fSJordan K. Hubbard 	    }
88b704025fSJordan K. Hubbard 	    /* Fall through deliberately since we already have a character and state == LOOK */
89b704025fSJordan K. Hubbard 
90b704025fSJordan K. Hubbard 	case LOOK:
91b704025fSJordan K. Hubbard 	    if (isspace(ch))
92b704025fSJordan K. Hubbard 		continue;
93b704025fSJordan K. Hubbard 	    /* Allow shell or lisp style comments */
94b704025fSJordan K. Hubbard 	    else if (ch == '#' || ch == ';') {
95b704025fSJordan K. Hubbard 		state = COMMENT;
96b704025fSJordan K. Hubbard 		continue;
97b704025fSJordan K. Hubbard 	    }
98b704025fSJordan K. Hubbard 	    else if (isalnum(ch) || ch == '_') {
99b704025fSJordan K. Hubbard 		if (n >= MAX_NAME) {
100b704025fSJordan K. Hubbard 		    n = 0;
101b704025fSJordan K. Hubbard 		    state = COMMENT;
102b704025fSJordan K. Hubbard 		}
103b704025fSJordan K. Hubbard 		else {
104b704025fSJordan K. Hubbard 		    hold_n[n++] = ch;
105b704025fSJordan K. Hubbard 		    state = NAME;
106b704025fSJordan K. Hubbard 		}
107b704025fSJordan K. Hubbard 	    }
108b704025fSJordan K. Hubbard 	    else
109b704025fSJordan K. Hubbard 		state = COMMENT;	/* Ignore the rest of the line */
110b704025fSJordan K. Hubbard 	    break;
111b704025fSJordan K. Hubbard 
112b704025fSJordan K. Hubbard 	case COMMENT:
113b704025fSJordan K. Hubbard 	    if (ch == '\n')
114b704025fSJordan K. Hubbard 		state = LOOK;
115b704025fSJordan K. Hubbard 	    break;
116b704025fSJordan K. Hubbard 
117b704025fSJordan K. Hubbard 	case NAME:
118b704025fSJordan K. Hubbard 	    if (ch == '\n' || !ch) {
119b704025fSJordan K. Hubbard 		hold_n[n] = '\0';
120b704025fSJordan K. Hubbard 		hold_v[0] = '\0';
121b704025fSJordan K. Hubbard 		v = n = 0;
122b704025fSJordan K. Hubbard 		state = COMMIT;
123b704025fSJordan K. Hubbard 	    }
124b704025fSJordan K. Hubbard 	    else if (isspace(ch))
125b704025fSJordan K. Hubbard 		continue;
126b704025fSJordan K. Hubbard 	    else if (ch == '=') {
127b704025fSJordan K. Hubbard 		hold_n[n] = '\0';
128b704025fSJordan K. Hubbard 		v = n = 0;
129b704025fSJordan K. Hubbard 		state = VALUE;
130b704025fSJordan K. Hubbard 	    }
131b704025fSJordan K. Hubbard 	    else
132b704025fSJordan K. Hubbard 		hold_n[n++] = ch;
133b704025fSJordan K. Hubbard 	    break;
134b704025fSJordan K. Hubbard 
135b704025fSJordan K. Hubbard 	case VALUE:
136b704025fSJordan K. Hubbard 	    if (v == 0 && isspace(ch))
137b704025fSJordan K. Hubbard 		continue;
138b704025fSJordan K. Hubbard 	    else if (ch == '{')
139b704025fSJordan K. Hubbard 		state = MVALUE;
140b704025fSJordan K. Hubbard 	    else if (ch == '\n' || !ch) {
141b704025fSJordan K. Hubbard 		hold_v[v] = '\0';
142b704025fSJordan K. Hubbard 		v = n = 0;
143b704025fSJordan K. Hubbard 		state = COMMIT;
144b704025fSJordan K. Hubbard 	    }
145b704025fSJordan K. Hubbard 	    else {
146b704025fSJordan K. Hubbard 		if (v >= MAX_VALUE) {
147b704025fSJordan K. Hubbard 		    state = COMMENT;
148b704025fSJordan K. Hubbard 		    v = n = 0;
149b704025fSJordan K. Hubbard 		    break;
150b704025fSJordan K. Hubbard 		}
151b704025fSJordan K. Hubbard 		else
152b704025fSJordan K. Hubbard 		    hold_v[v++] = ch;
153b704025fSJordan K. Hubbard 	    }
154b704025fSJordan K. Hubbard 	    break;
155b704025fSJordan K. Hubbard 
156b704025fSJordan K. Hubbard 	case MVALUE:
157b704025fSJordan K. Hubbard 	    /* multiline value */
158b704025fSJordan K. Hubbard 	    if (v >= MAX_VALUE) {
159b704025fSJordan K. Hubbard 		state = COMMENT;
160b704025fSJordan K. Hubbard 		n = v = 0;
161b704025fSJordan K. Hubbard 	    }
162b704025fSJordan K. Hubbard 	    else if (ch == '}') {
163b704025fSJordan K. Hubbard 		hold_v[v] = '\0';
164b704025fSJordan K. Hubbard 		v = n = 0;
165b704025fSJordan K. Hubbard 		state = COMMIT;
166b704025fSJordan K. Hubbard 	    }
167b704025fSJordan K. Hubbard 	    else
168b704025fSJordan K. Hubbard 		hold_v[v++] = ch;
169b704025fSJordan K. Hubbard 	    break;
170b704025fSJordan K. Hubbard 
171b704025fSJordan K. Hubbard 	case COMMIT:
172b704025fSJordan K. Hubbard 	    if (!head)
173b704025fSJordan K. Hubbard 		head = ptr = property_alloc(hold_n, hold_v);
174b704025fSJordan K. Hubbard 	    else {
175b704025fSJordan K. Hubbard 		ptr->next = property_alloc(hold_n, hold_v);
176b704025fSJordan K. Hubbard 		ptr = ptr->next;
177b704025fSJordan K. Hubbard 	    }
178b704025fSJordan K. Hubbard 	    state = LOOK;
179b704025fSJordan K. Hubbard 	    v = n = 0;
180b704025fSJordan K. Hubbard 	    break;
181b704025fSJordan K. Hubbard 
182b704025fSJordan K. Hubbard 	case STOP:
183b704025fSJordan K. Hubbard 	    /* we don't handle this here, but this prevents warnings */
184b704025fSJordan K. Hubbard 	    break;
185b704025fSJordan K. Hubbard 	}
186b704025fSJordan K. Hubbard     }
187b704025fSJordan K. Hubbard     return head;
188b704025fSJordan K. Hubbard }
189b704025fSJordan K. Hubbard 
190b704025fSJordan K. Hubbard char *
191b704025fSJordan K. Hubbard property_find(properties list, const char *name)
192b704025fSJordan K. Hubbard {
193b704025fSJordan K. Hubbard     if (!list || !name || !name[0])
194b704025fSJordan K. Hubbard 	return NULL;
195b704025fSJordan K. Hubbard     while (list) {
196b704025fSJordan K. Hubbard 	if (!strcmp(list->name, name))
197b704025fSJordan K. Hubbard 	    return list->value;
198b704025fSJordan K. Hubbard 	list = list->next;
199b704025fSJordan K. Hubbard     }
200b704025fSJordan K. Hubbard     return NULL;
201b704025fSJordan K. Hubbard }
202b704025fSJordan K. Hubbard 
203b704025fSJordan K. Hubbard void
204b704025fSJordan K. Hubbard properties_free(properties list)
205b704025fSJordan K. Hubbard {
206b704025fSJordan K. Hubbard     properties tmp;
207b704025fSJordan K. Hubbard 
208b704025fSJordan K. Hubbard     while (list) {
209b704025fSJordan K. Hubbard 	tmp = list->next;
210b704025fSJordan K. Hubbard 	if (list->name)
211b704025fSJordan K. Hubbard 	    free(list->name);
212b704025fSJordan K. Hubbard 	if (list->value)
213b704025fSJordan K. Hubbard 	    free(list->value);
214b704025fSJordan K. Hubbard 	free(list);
215b704025fSJordan K. Hubbard 	list = tmp;
216b704025fSJordan K. Hubbard     }
217b704025fSJordan K. Hubbard }
218