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> 38efbcb4aeSJordan K. Hubbard #include <err.h> 3969761016SJordan K. Hubbard #include <sys/types.h> 40b704025fSJordan K. Hubbard #include <libutil.h> 41b704025fSJordan K. Hubbard 42b704025fSJordan K. Hubbard #define MAX_NAME 64 43b704025fSJordan K. Hubbard #define MAX_VALUE 512 44b704025fSJordan K. Hubbard 45b704025fSJordan K. Hubbard static properties 46b704025fSJordan K. Hubbard property_alloc(char *name, char *value) 47b704025fSJordan K. Hubbard { 48b704025fSJordan K. Hubbard properties n; 49b704025fSJordan K. Hubbard 50b704025fSJordan K. Hubbard n = (properties)malloc(sizeof(struct _property)); 51b704025fSJordan K. Hubbard n->next = NULL; 52b704025fSJordan K. Hubbard n->name = name ? strdup(name) : NULL; 53b704025fSJordan K. Hubbard n->value = value ? strdup(value) : NULL; 54b704025fSJordan K. Hubbard return n; 55b704025fSJordan K. Hubbard } 56b704025fSJordan K. Hubbard 57b704025fSJordan K. Hubbard properties 5850dfa596SJordan K. Hubbard properties_read(int fd) 59b704025fSJordan K. Hubbard { 60b704025fSJordan K. Hubbard properties head, ptr; 61b704025fSJordan K. Hubbard char hold_n[MAX_NAME + 1]; 62b704025fSJordan K. Hubbard char hold_v[MAX_VALUE + 1]; 63b704025fSJordan K. Hubbard char buf[BUFSIZ * 4]; 64b704025fSJordan K. Hubbard int bp, n, v, max; 65b704025fSJordan K. Hubbard enum { LOOK, COMMENT, NAME, VALUE, MVALUE, COMMIT, FILL, STOP } state; 66efbcb4aeSJordan K. Hubbard int ch = 0, blevel = 0; 67b704025fSJordan K. Hubbard 68b704025fSJordan K. Hubbard n = v = bp = max = 0; 69b704025fSJordan K. Hubbard head = ptr = NULL; 70b704025fSJordan K. Hubbard state = LOOK; 71b704025fSJordan K. Hubbard while (state != STOP) { 72b704025fSJordan K. Hubbard if (state != COMMIT) { 73b704025fSJordan K. Hubbard if (bp == max) 74b704025fSJordan K. Hubbard state = FILL; 75b704025fSJordan K. Hubbard else 76b704025fSJordan K. Hubbard ch = buf[bp++]; 77b704025fSJordan K. Hubbard } 78b704025fSJordan K. Hubbard switch(state) { 79b704025fSJordan K. Hubbard case FILL: 8050dfa596SJordan K. Hubbard if ((max = read(fd, buf, sizeof buf)) <= 0) { 81b704025fSJordan K. Hubbard state = STOP; 82b704025fSJordan K. Hubbard break; 83b704025fSJordan K. Hubbard } 84b704025fSJordan K. Hubbard else { 85b704025fSJordan K. Hubbard state = LOOK; 86b704025fSJordan K. Hubbard ch = buf[0]; 87b704025fSJordan K. Hubbard bp = 1; 88b704025fSJordan K. Hubbard } 89b704025fSJordan K. Hubbard /* Fall through deliberately since we already have a character and state == LOOK */ 90b704025fSJordan K. Hubbard 91b704025fSJordan K. Hubbard case LOOK: 92b704025fSJordan K. Hubbard if (isspace(ch)) 93b704025fSJordan K. Hubbard continue; 94b704025fSJordan K. Hubbard /* Allow shell or lisp style comments */ 95b704025fSJordan K. Hubbard else if (ch == '#' || ch == ';') { 96b704025fSJordan K. Hubbard state = COMMENT; 97b704025fSJordan K. Hubbard continue; 98b704025fSJordan K. Hubbard } 99b704025fSJordan K. Hubbard else if (isalnum(ch) || ch == '_') { 100b704025fSJordan K. Hubbard if (n >= MAX_NAME) { 101b704025fSJordan K. Hubbard n = 0; 102b704025fSJordan K. Hubbard state = COMMENT; 103b704025fSJordan K. Hubbard } 104b704025fSJordan K. Hubbard else { 105b704025fSJordan K. Hubbard hold_n[n++] = ch; 106b704025fSJordan K. Hubbard state = NAME; 107b704025fSJordan K. Hubbard } 108b704025fSJordan K. Hubbard } 109b704025fSJordan K. Hubbard else 110b704025fSJordan K. Hubbard state = COMMENT; /* Ignore the rest of the line */ 111b704025fSJordan K. Hubbard break; 112b704025fSJordan K. Hubbard 113b704025fSJordan K. Hubbard case COMMENT: 114b704025fSJordan K. Hubbard if (ch == '\n') 115b704025fSJordan K. Hubbard state = LOOK; 116b704025fSJordan K. Hubbard break; 117b704025fSJordan K. Hubbard 118b704025fSJordan K. Hubbard case NAME: 119b704025fSJordan K. Hubbard if (ch == '\n' || !ch) { 120b704025fSJordan K. Hubbard hold_n[n] = '\0'; 121b704025fSJordan K. Hubbard hold_v[0] = '\0'; 122b704025fSJordan K. Hubbard v = n = 0; 123b704025fSJordan K. Hubbard state = COMMIT; 124b704025fSJordan K. Hubbard } 125b704025fSJordan K. Hubbard else if (isspace(ch)) 126b704025fSJordan K. Hubbard continue; 127b704025fSJordan K. Hubbard else if (ch == '=') { 128b704025fSJordan K. Hubbard hold_n[n] = '\0'; 129b704025fSJordan K. Hubbard v = n = 0; 130b704025fSJordan K. Hubbard state = VALUE; 131b704025fSJordan K. Hubbard } 132b704025fSJordan K. Hubbard else 133b704025fSJordan K. Hubbard hold_n[n++] = ch; 134b704025fSJordan K. Hubbard break; 135b704025fSJordan K. Hubbard 136b704025fSJordan K. Hubbard case VALUE: 137b704025fSJordan K. Hubbard if (v == 0 && isspace(ch)) 138b704025fSJordan K. Hubbard continue; 139efbcb4aeSJordan K. Hubbard else if (ch == '{') { 140b704025fSJordan K. Hubbard state = MVALUE; 141efbcb4aeSJordan K. Hubbard ++blevel; 142efbcb4aeSJordan K. Hubbard } 143b704025fSJordan K. Hubbard else if (ch == '\n' || !ch) { 144b704025fSJordan K. Hubbard hold_v[v] = '\0'; 145b704025fSJordan K. Hubbard v = n = 0; 146b704025fSJordan K. Hubbard state = COMMIT; 147b704025fSJordan K. Hubbard } 148b704025fSJordan K. Hubbard else { 149b704025fSJordan K. Hubbard if (v >= MAX_VALUE) { 150b704025fSJordan K. Hubbard state = COMMENT; 151b704025fSJordan K. Hubbard v = n = 0; 152b704025fSJordan K. Hubbard break; 153b704025fSJordan K. Hubbard } 154b704025fSJordan K. Hubbard else 155b704025fSJordan K. Hubbard hold_v[v++] = ch; 156b704025fSJordan K. Hubbard } 157b704025fSJordan K. Hubbard break; 158b704025fSJordan K. Hubbard 159b704025fSJordan K. Hubbard case MVALUE: 160b704025fSJordan K. Hubbard /* multiline value */ 161b704025fSJordan K. Hubbard if (v >= MAX_VALUE) { 162efbcb4aeSJordan K. Hubbard warn("properties_read: value exceeds max length"); 163b704025fSJordan K. Hubbard state = COMMENT; 164b704025fSJordan K. Hubbard n = v = 0; 165b704025fSJordan K. Hubbard } 166efbcb4aeSJordan K. Hubbard else if (ch == '}' && !--blevel) { 167b704025fSJordan K. Hubbard hold_v[v] = '\0'; 168b704025fSJordan K. Hubbard v = n = 0; 169b704025fSJordan K. Hubbard state = COMMIT; 170b704025fSJordan K. Hubbard } 171efbcb4aeSJordan K. Hubbard else { 172b704025fSJordan K. Hubbard hold_v[v++] = ch; 173efbcb4aeSJordan K. Hubbard if (ch == '{') 174efbcb4aeSJordan K. Hubbard ++blevel; 175efbcb4aeSJordan K. Hubbard } 176b704025fSJordan K. Hubbard break; 177b704025fSJordan K. Hubbard 178b704025fSJordan K. Hubbard case COMMIT: 179b704025fSJordan K. Hubbard if (!head) 180b704025fSJordan K. Hubbard head = ptr = property_alloc(hold_n, hold_v); 181b704025fSJordan K. Hubbard else { 182b704025fSJordan K. Hubbard ptr->next = property_alloc(hold_n, hold_v); 183b704025fSJordan K. Hubbard ptr = ptr->next; 184b704025fSJordan K. Hubbard } 185b704025fSJordan K. Hubbard state = LOOK; 186b704025fSJordan K. Hubbard v = n = 0; 187b704025fSJordan K. Hubbard break; 188b704025fSJordan K. Hubbard 189b704025fSJordan K. Hubbard case STOP: 190b704025fSJordan K. Hubbard /* we don't handle this here, but this prevents warnings */ 191b704025fSJordan K. Hubbard break; 192b704025fSJordan K. Hubbard } 193b704025fSJordan K. Hubbard } 194b704025fSJordan K. Hubbard return head; 195b704025fSJordan K. Hubbard } 196b704025fSJordan K. Hubbard 197b704025fSJordan K. Hubbard char * 198b704025fSJordan K. Hubbard property_find(properties list, const char *name) 199b704025fSJordan K. Hubbard { 200b704025fSJordan K. Hubbard if (!list || !name || !name[0]) 201b704025fSJordan K. Hubbard return NULL; 202b704025fSJordan K. Hubbard while (list) { 203b704025fSJordan K. Hubbard if (!strcmp(list->name, name)) 204b704025fSJordan K. Hubbard return list->value; 205b704025fSJordan K. Hubbard list = list->next; 206b704025fSJordan K. Hubbard } 207b704025fSJordan K. Hubbard return NULL; 208b704025fSJordan K. Hubbard } 209b704025fSJordan K. Hubbard 210b704025fSJordan K. Hubbard void 211b704025fSJordan K. Hubbard properties_free(properties list) 212b704025fSJordan K. Hubbard { 213b704025fSJordan K. Hubbard properties tmp; 214b704025fSJordan K. Hubbard 215b704025fSJordan K. Hubbard while (list) { 216b704025fSJordan K. Hubbard tmp = list->next; 217b704025fSJordan K. Hubbard if (list->name) 218b704025fSJordan K. Hubbard free(list->name); 219b704025fSJordan K. Hubbard if (list->value) 220b704025fSJordan K. Hubbard free(list->value); 221b704025fSJordan K. Hubbard free(list); 222b704025fSJordan K. Hubbard list = tmp; 223b704025fSJordan K. Hubbard } 224b704025fSJordan K. Hubbard } 225