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