2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * Simple property list handling code.
8 * Jordan Hubbard. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer,
15 * verbatim and that no modifications are made prior to this
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
37 #include <sys/types.h>
47 property_alloc(char *name, char *value)
51 if ((n = (properties)malloc(sizeof(struct _property))) == NULL)
55 if ((n->name = strdup(name)) == NULL) {
62 if ((n->value = strdup(value)) == NULL) {
73 properties_read(int fd)
76 char hold_n[PROPERTY_MAX_NAME + 1];
77 char hold_v[PROPERTY_MAX_VALUE + 1];
80 enum { LOOK, COMMENT, NAME, VALUE, MVALUE, COMMIT, FILL, STOP } state, last_state;
81 int ch = 0, blevel = 0;
85 state = last_state = LOOK;
86 while (state != STOP) {
87 if (state != COMMIT) {
96 if ((max = read(fd, buf, sizeof buf)) < 0) {
97 properties_free(head);
104 * Restore the state from before the fill (which will be
105 * initialised to LOOK for the first FILL). This ensures that
106 * if we were part-way through eg., a VALUE state, when the
107 * buffer ran out, that the previous operation will be allowed
117 if (isspace((unsigned char)ch))
119 /* Allow shell or lisp style comments */
120 else if (ch == '#' || ch == ';') {
124 else if (isalnum((unsigned char)ch) || ch == '_') {
125 if (n >= PROPERTY_MAX_NAME) {
135 state = COMMENT; /* Ignore the rest of the line */
144 if (ch == '\n' || !ch) {
150 else if (isspace((unsigned char)ch))
152 else if (ch == '=') {
162 if (v == 0 && ch == '\n') {
167 else if (v == 0 && isspace((unsigned char)ch))
169 else if (ch == '{') {
173 else if (ch == '\n' || !ch) {
179 if (v >= PROPERTY_MAX_VALUE) {
190 /* multiline value */
191 if (v >= PROPERTY_MAX_VALUE) {
192 warn("properties_read: value exceeds max length");
196 else if (ch == '}' && !--blevel) {
210 if ((head = ptr = property_alloc(hold_n, hold_v)) == NULL)
213 if ((ptr->next = property_alloc(hold_n, hold_v)) == NULL) {
214 properties_free(head);
224 /* we don't handle this here, but this prevents warnings */
228 if (head == NULL && (head = property_alloc(NULL, NULL)) == NULL)
235 property_find(properties list, const char *name)
237 if (list == NULL || name == NULL || !name[0])
239 while (list != NULL) {
240 if (list->name != NULL && strcmp(list->name, name) == 0)
241 return (list->value);
248 properties_free(properties list)