ratelimit: fix log levels of log suppression messages
[platform/upstream/pulseaudio.git] / src / pulsecore / conf-parser.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2.1 of the License,
9   or (at your option) any later version.
10
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <stdio.h>
28 #include <errno.h>
29
30 #include <pulse/xmalloc.h>
31
32 #include <pulsecore/core-error.h>
33 #include <pulsecore/log.h>
34 #include <pulsecore/core-util.h>
35 #include <pulsecore/macro.h>
36
37 #include "conf-parser.h"
38
39 #define WHITESPACE " \t\n"
40 #define COMMENTS "#;\n"
41
42 /* Run the user supplied parser for an assignment */
43 static int next_assignment(
44         const char *filename,
45         unsigned line,
46         const char *section,
47         const pa_config_item *t,
48         const char *lvalue,
49         const char *rvalue,
50         void *userdata) {
51
52     pa_assert(filename);
53     pa_assert(t);
54     pa_assert(lvalue);
55     pa_assert(rvalue);
56
57     for (; t->parse; t++) {
58
59         if (t->lvalue && !pa_streq(lvalue, t->lvalue))
60             continue;
61
62         if (t->section && !section)
63             continue;
64
65         if (t->section && !pa_streq(section, t->section))
66             continue;
67
68         return t->parse(filename, line, section, lvalue, rvalue, t->data, userdata);
69     }
70
71     pa_log("[%s:%u] Unknown lvalue '%s' in section '%s'.", filename, line, lvalue, pa_strna(section));
72
73     return -1;
74 }
75
76 /* Parse a variable assignment line */
77 static int parse_line(const char *filename, unsigned line, char **section, const pa_config_item *t, char *l, void *userdata) {
78     char *e, *c, *b;
79
80     b = l+strspn(l, WHITESPACE);
81
82     if ((c = strpbrk(b, COMMENTS)))
83         *c = 0;
84
85     if (!*b)
86         return 0;
87
88     if (pa_startswith(b, ".include ")) {
89         char *path = NULL, *fn;
90         int r;
91
92         fn = pa_strip(b+9);
93         if (!pa_is_path_absolute(fn)) {
94             const char *k;
95             if ((k = strrchr(filename, '/'))) {
96                 char *dir = pa_xstrndup(filename, k-filename);
97                 fn = path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", dir, fn);
98                 pa_xfree(dir);
99             }
100         }
101
102         r = pa_config_parse(fn, NULL, t, userdata);
103         pa_xfree(path);
104         return r;
105     }
106
107     if (*b == '[') {
108         size_t k;
109
110         k = strlen(b);
111         pa_assert(k > 0);
112
113         if (b[k-1] != ']') {
114             pa_log("[%s:%u] Invalid section header.", filename, line);
115             return -1;
116         }
117
118         pa_xfree(*section);
119         *section = pa_xstrndup(b+1, k-2);
120         return 0;
121     }
122
123     if (!(e = strchr(b, '='))) {
124         pa_log("[%s:%u] Missing '='.", filename, line);
125         return -1;
126     }
127
128     *e = 0;
129     e++;
130
131     return next_assignment(filename, line, *section, t, pa_strip(b), pa_strip(e), userdata);
132 }
133
134 /* Go through the file and parse each line */
135 int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata) {
136     int r = -1;
137     unsigned line = 0;
138     pa_bool_t do_close = !f;
139     char *section = NULL;
140
141     pa_assert(filename);
142     pa_assert(t);
143
144     if (!f && !(f = pa_fopen_cloexec(filename, "r"))) {
145         if (errno == ENOENT) {
146             pa_log_debug("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno));
147             r = 0;
148             goto finish;
149         }
150
151         pa_log_warn("Failed to open configuration file '%s': %s", filename, pa_cstrerror(errno));
152         goto finish;
153     }
154
155     while (!feof(f)) {
156         char l[4096];
157
158         if (!fgets(l, sizeof(l), f)) {
159             if (feof(f))
160                 break;
161
162             pa_log_warn("Failed to read configuration file '%s': %s", filename, pa_cstrerror(errno));
163             goto finish;
164         }
165
166         if (parse_line(filename, ++line, &section, t, l, userdata) < 0)
167             goto finish;
168     }
169
170     r = 0;
171
172 finish:
173     pa_xfree(section);
174
175     if (do_close && f)
176         fclose(f);
177
178     return r;
179 }
180
181 int pa_config_parse_int(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
182     int *i = data;
183     int32_t k;
184
185     pa_assert(filename);
186     pa_assert(lvalue);
187     pa_assert(rvalue);
188     pa_assert(data);
189
190     if (pa_atoi(rvalue, &k) < 0) {
191         pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
192         return -1;
193     }
194
195     *i = (int) k;
196     return 0;
197 }
198
199 int pa_config_parse_unsigned(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
200     unsigned *u = data;
201     uint32_t k;
202
203     pa_assert(filename);
204     pa_assert(lvalue);
205     pa_assert(rvalue);
206     pa_assert(data);
207
208     if (pa_atou(rvalue, &k) < 0) {
209         pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
210         return -1;
211     }
212
213     *u = (unsigned) k;
214     return 0;
215 }
216
217 int pa_config_parse_size(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
218     size_t *i = data;
219     uint32_t k;
220
221     pa_assert(filename);
222     pa_assert(lvalue);
223     pa_assert(rvalue);
224     pa_assert(data);
225
226     if (pa_atou(rvalue, &k) < 0) {
227         pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
228         return -1;
229     }
230
231     *i = (size_t) k;
232     return 0;
233 }
234
235 int pa_config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
236     int k;
237     pa_bool_t *b = data;
238
239     pa_assert(filename);
240     pa_assert(lvalue);
241     pa_assert(rvalue);
242     pa_assert(data);
243
244     if ((k = pa_parse_boolean(rvalue)) < 0) {
245         pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue);
246         return -1;
247     }
248
249     *b = !!k;
250
251     return 0;
252 }
253
254 int pa_config_parse_not_bool(
255         const char *filename, unsigned line,
256         const char *section,
257         const char *lvalue, const char *rvalue,
258         void *data, void *userdata) {
259
260     int k;
261     pa_bool_t *b = data;
262
263     pa_assert(filename);
264     pa_assert(lvalue);
265     pa_assert(rvalue);
266     pa_assert(data);
267
268     if ((k = pa_parse_boolean(rvalue)) < 0) {
269         pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue);
270         return -1;
271     }
272
273     *b = !k;
274
275     return 0;
276 }
277
278 int pa_config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) {
279     char **s = data;
280
281     pa_assert(filename);
282     pa_assert(lvalue);
283     pa_assert(rvalue);
284     pa_assert(data);
285
286     pa_xfree(*s);
287     *s = *rvalue ? pa_xstrdup(rvalue) : NULL;
288     return 0;
289 }