/src/avahi/avahi-daemon/ini-file-parser.c
Line | Count | Source (jump to first uncovered line) |
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/malloc.h> |
30 | | #include <avahi-core/log.h> |
31 | | |
32 | | #include "ini-file-parser.h" |
33 | | |
34 | 196 | AvahiIniFile* avahi_ini_file_load(const char *fname) { |
35 | 196 | AvahiIniFile *f; |
36 | 196 | FILE *fo; |
37 | 196 | AvahiIniFileGroup *group = NULL; |
38 | 196 | unsigned line; |
39 | | |
40 | 196 | assert(fname); |
41 | | |
42 | 196 | if (!(fo = fopen(fname, "r"))) { |
43 | 0 | avahi_log_error("Failed to open file '%s': %s", fname, strerror(errno)); |
44 | 0 | return NULL; |
45 | 0 | } |
46 | | |
47 | 196 | f = avahi_new(AvahiIniFile, 1); |
48 | 196 | AVAHI_LLIST_HEAD_INIT(AvahiIniFileGroup, f->groups); |
49 | 196 | f->n_groups = 0; |
50 | | |
51 | 196 | line = 0; |
52 | 2.90k | while (!feof(fo)) { |
53 | 2.75k | char ln[1024], *s, *e; |
54 | 2.75k | AvahiIniFilePair *pair; |
55 | | |
56 | 2.75k | if (!(fgets(ln, sizeof(ln), fo))) |
57 | 10 | break; |
58 | | |
59 | 2.74k | line++; |
60 | | |
61 | 2.74k | s = ln + strspn(ln, " \t"); |
62 | 2.74k | s[strcspn(s, "\r\n")] = 0; |
63 | | |
64 | | /* Skip comments and empty lines */ |
65 | 2.74k | if (*s == '#' || *s == '%' || *s == 0) |
66 | 711 | continue; |
67 | | |
68 | 2.02k | if (*s == '[') { |
69 | | /* new group */ |
70 | | |
71 | 706 | if (!(e = strchr(s, ']'))) { |
72 | 2 | avahi_log_error("Unclosed group header in %s:%u: <%s>", fname, line, s); |
73 | 2 | goto fail; |
74 | 2 | } |
75 | | |
76 | 704 | *e = 0; |
77 | | |
78 | 704 | group = avahi_new(AvahiIniFileGroup, 1); |
79 | 704 | group->name = avahi_strdup(s+1); |
80 | 704 | group->n_pairs = 0; |
81 | 704 | AVAHI_LLIST_HEAD_INIT(AvahiIniFilePair, group->pairs); |
82 | | |
83 | 704 | AVAHI_LLIST_PREPEND(AvahiIniFileGroup, groups, f->groups, group); |
84 | 704 | f->n_groups++; |
85 | 1.32k | } else { |
86 | | |
87 | | /* Normal assignment */ |
88 | 1.32k | if (!(e = strchr(s, '='))) { |
89 | 24 | avahi_log_error("Missing assignment in %s:%u: <%s>", fname, line, s); |
90 | 24 | goto fail; |
91 | 24 | } |
92 | | |
93 | 1.29k | if (!group) { |
94 | 1 | avahi_log_error("Assignment outside group in %s:%u <%s>", fname, line, s); |
95 | 1 | goto fail; |
96 | 1 | } |
97 | | |
98 | | /* Split the key and the value */ |
99 | 1.29k | *(e++) = 0; |
100 | | |
101 | 1.29k | pair = avahi_new(AvahiIniFilePair, 1); |
102 | 1.29k | pair->key = avahi_strdup(s); |
103 | 1.29k | pair->value = avahi_strdup(e); |
104 | | |
105 | 1.29k | AVAHI_LLIST_PREPEND(AvahiIniFilePair, pairs, group->pairs, pair); |
106 | 1.29k | group->n_pairs++; |
107 | 1.29k | } |
108 | 2.02k | } |
109 | | |
110 | 169 | fclose(fo); |
111 | | |
112 | 169 | return f; |
113 | | |
114 | 27 | fail: |
115 | | |
116 | 27 | if (fo) |
117 | 27 | fclose(fo); |
118 | | |
119 | 27 | if (f) |
120 | 27 | avahi_ini_file_free(f); |
121 | | |
122 | 27 | return NULL; |
123 | 196 | } |
124 | | |
125 | 196 | void avahi_ini_file_free(AvahiIniFile *f) { |
126 | 196 | AvahiIniFileGroup *g; |
127 | 196 | assert(f); |
128 | | |
129 | 900 | while ((g = f->groups)) { |
130 | 704 | AvahiIniFilePair *p; |
131 | | |
132 | 2.00k | while ((p = g->pairs)) { |
133 | 1.29k | avahi_free(p->key); |
134 | 1.29k | avahi_free(p->value); |
135 | | |
136 | 1.29k | AVAHI_LLIST_REMOVE(AvahiIniFilePair, pairs, g->pairs, p); |
137 | 1.29k | avahi_free(p); |
138 | 1.29k | } |
139 | | |
140 | 704 | avahi_free(g->name); |
141 | | |
142 | 704 | AVAHI_LLIST_REMOVE(AvahiIniFileGroup, groups, f->groups, g); |
143 | 704 | avahi_free(g); |
144 | 704 | } |
145 | | |
146 | 196 | avahi_free(f); |
147 | 196 | } |
148 | | |
149 | 1.29k | char** avahi_split_csv(const char *t) { |
150 | 1.29k | unsigned n_comma = 0; |
151 | 1.29k | const char *p; |
152 | 1.29k | char **r, **i; |
153 | | |
154 | 9.84k | for (p = t; *p; p++) |
155 | 8.54k | if (*p == ',') |
156 | 3.06k | n_comma++; |
157 | | |
158 | 1.29k | i = r = avahi_new(char*, n_comma+2); |
159 | | |
160 | 4.36k | for (;;) { |
161 | 4.36k | size_t n, l = strcspn(t, ","); |
162 | 4.36k | const char *c; |
163 | | |
164 | | /* Ignore leading blanks */ |
165 | 4.36k | for (c = t, n = l; isblank(*c); c++, n--); |
166 | | |
167 | | /* Ignore trailing blanks */ |
168 | 4.62k | for (; n > 0 && isblank(c[n-1]); n--); |
169 | | |
170 | 4.36k | *(i++) = avahi_strndup(c, n); |
171 | | |
172 | 4.36k | t += l; |
173 | | |
174 | 4.36k | if (*t == 0) |
175 | 1.29k | break; |
176 | | |
177 | 3.06k | assert(*t == ','); |
178 | 3.06k | t++; |
179 | 3.06k | } |
180 | | |
181 | 1.29k | *i = NULL; |
182 | | |
183 | 1.29k | return r; |
184 | 1.29k | } |
185 | | |
186 | 1.29k | void avahi_strfreev(char **p) { |
187 | 1.29k | char **i; |
188 | | |
189 | 1.29k | if (!p) |
190 | 0 | return; |
191 | | |
192 | 5.66k | for (i = p; *i; i++) |
193 | 4.36k | avahi_free(*i); |
194 | | |
195 | 1.29k | avahi_free(p); |
196 | 1.29k | } |