1deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering/*** 2deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering This file is part of avahi. 3a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 4deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi is free software; you can redistribute it and/or modify it 5deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering under the terms of the GNU Lesser General Public License as 6deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering published by the Free Software Foundation; either version 2.1 of the 7deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering License, or (at your option) any later version. 8a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 9deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi is distributed in the hope that it will be useful, but WITHOUT 10deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General 12deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering Public License for more details. 13a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 14deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering You should have received a copy of the GNU Lesser General Public 15deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering License along with avahi; if not, write to the Free Software 16deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 17deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering USA. 18deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering***/ 19deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 2015f5bd4aa32e7c462ebccc8c1ef8da70bdcc68f4Lennart Poettering#ifdef HAVE_CONFIG_H 2115f5bd4aa32e7c462ebccc8c1ef8da70bdcc68f4Lennart Poettering#include <config.h> 2215f5bd4aa32e7c462ebccc8c1ef8da70bdcc68f4Lennart Poettering#endif 2315f5bd4aa32e7c462ebccc8c1ef8da70bdcc68f4Lennart Poettering 24deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering#include <stdio.h> 25deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering#include <string.h> 26deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering#include <errno.h> 27e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering#include <ctype.h> 28deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 298e46e738cae449bf44232c66e973c8e9e15fbcb5Robert Ginda#include "avahi-common/avahi-malloc.h" 30deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering#include <avahi-core/log.h> 31deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 32deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering#include "ini-file-parser.h" 33deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 34deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart PoetteringAvahiIniFile* avahi_ini_file_load(const char *fname) { 35deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AvahiIniFile *f; 36deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering FILE *fo; 37deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AvahiIniFileGroup *group = NULL; 38deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering unsigned line; 39a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 40deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering assert(fname); 41deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 42deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (!(fo = fopen(fname, "r"))) { 43deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_log_error("Failed to open file '%s': %s", fname, strerror(errno)); 44deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering return NULL; 45deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering } 46a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 47deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering f = avahi_new(AvahiIniFile, 1); 48deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AVAHI_LLIST_HEAD_INIT(AvahiIniFileGroup, f->groups); 49deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering f->n_groups = 0; 50deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 51deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering line = 0; 52deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering while (!feof(fo)) { 53deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering char ln[256], *s, *e; 54deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AvahiIniFilePair *pair; 55a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 56deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (!(fgets(ln, sizeof(ln), fo))) 57deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering break; 58deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 59deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering line++; 60a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 61deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering s = ln + strspn(ln, " \t"); 62deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering s[strcspn(s, "\r\n")] = 0; 63deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 64deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering /* Skip comments and empty lines */ 65deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (*s == '#' || *s == '%' || *s == 0) 66deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering continue; 67deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 68deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (*s == '[') { 69deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering /* new group */ 70a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 71deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (!(e = strchr(s, ']'))) { 72deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_log_error("Unclosed group header in %s:%u: <%s>", fname, line, s); 73deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering goto fail; 74deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering } 75deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 76deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering *e = 0; 77a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 78deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering group = avahi_new(AvahiIniFileGroup, 1); 79deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering group->name = avahi_strdup(s+1); 80deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering group->n_pairs = 0; 81deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AVAHI_LLIST_HEAD_INIT(AvahiIniFilePair, group->pairs); 82a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 83deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AVAHI_LLIST_PREPEND(AvahiIniFileGroup, groups, f->groups, group); 84deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering f->n_groups++; 85deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering } else { 86deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 87deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering /* Normal assignment */ 88deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (!(e = strchr(s, '='))) { 89deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_log_error("Missing assignment in %s:%u: <%s>", fname, line, s); 90deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering goto fail; 91deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering } 92a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 93deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (!group) { 94deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_log_error("Assignment outside group in %s:%u <%s>", fname, line, s); 95deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering goto fail; 96deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering } 97a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 98deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering /* Split the key and the value */ 99deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering *(e++) = 0; 100a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 101deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering pair = avahi_new(AvahiIniFilePair, 1); 102deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering pair->key = avahi_strdup(s); 103deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering pair->value = avahi_strdup(e); 104a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 105deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AVAHI_LLIST_PREPEND(AvahiIniFilePair, pairs, group->pairs, pair); 106deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering group->n_pairs++; 107deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering } 108deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering } 109a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 110deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering fclose(fo); 111a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 112deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering return f; 113deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 114deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poetteringfail: 115deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 116deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (fo) 117deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering fclose(fo); 118deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 119deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (f) 120deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_ini_file_free(f); 121deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 122deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering return NULL; 123deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering} 124deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 125deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poetteringvoid avahi_ini_file_free(AvahiIniFile *f) { 126deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AvahiIniFileGroup *g; 127deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering assert(f); 128deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 129deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering while ((g = f->groups)) { 130deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AvahiIniFilePair *p; 131a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 132deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering while ((p = g->pairs)) { 133deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_free(p->key); 134deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_free(p->value); 135deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 136deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AVAHI_LLIST_REMOVE(AvahiIniFilePair, pairs, g->pairs, p); 137deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_free(p); 138deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering } 139deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 140deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_free(g->name); 141deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 142deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering AVAHI_LLIST_REMOVE(AvahiIniFileGroup, groups, f->groups, g); 143deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_free(g); 144deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering } 145deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 146deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_free(f); 147deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering} 148deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 149deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poetteringchar** avahi_split_csv(const char *t) { 150deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering unsigned n_comma = 0; 151deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering const char *p; 152deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering char **r, **i; 153deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 154deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering for (p = t; *p; p++) 155deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (*p == ',') 156deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering n_comma++; 157deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 158deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering i = r = avahi_new(char*, n_comma+2); 159deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 160deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering for (;;) { 161e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering size_t n, l = strcspn(t, ","); 162e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering const char *c; 163deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 164e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering /* Ignore leading blanks */ 165e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering for (c = t, n = l; isblank(*c); c++, n--); 166e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering 167e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering /* Ignore trailing blanks */ 168e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering for (; n > 0 && isblank(c[n-1]); n--); 169e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering 170e2f7e83d25a5f0966938163c18b1fd8c399393b1Lennart Poettering *(i++) = avahi_strndup(c, n); 171deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 172deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering t += l; 173deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 174deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (*t == 0) 175deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering break; 176deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 177deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering assert(*t == ','); 178deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering t++; 179deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering } 180deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 181deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering *i = NULL; 182deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 183deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering return r; 184deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering} 185deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 186deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poetteringvoid avahi_strfreev(char **p) { 187deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering char **i; 188deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 189deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering if (!p) 190deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering return; 191a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering 192deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering for (i = p; *i; i++) 193deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_free(*i); 194deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering 195deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering avahi_free(p); 196deb6bcac8d1e1ecec4aafaee2d27dbe467e4f461Lennart Poettering} 197