]> code.delx.au - pulseaudio/blob - polyp/conf.c
make module-combine autoloadable
[pulseaudio] / polyp / conf.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 polypaudio 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 General Public License
17 along with polypaudio; 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 <errno.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <sys/stat.h>
31
32 #include "conf.h"
33 #include "util.h"
34 #include "xmalloc.h"
35 #include "strbuf.h"
36
37 static const struct pa_conf default_conf = {
38 .cmd = PA_CMD_DAEMON,
39 .daemonize = 0,
40 .fail = 1,
41 .verbose = 0,
42 .high_priority = 0,
43 .disallow_module_loading = 0,
44 .exit_idle_time = -1,
45 .module_idle_time = 20,
46 .scache_idle_time = 20,
47 .auto_log_target = 1,
48 .script_commands = NULL,
49 .dl_search_path = NULL,
50 .default_script_file = NULL,
51 .log_target = PA_LOG_SYSLOG,
52 };
53
54 #define ENV_SCRIPT_FILE "POLYP_SCRIPT"
55 #define ENV_CONFIG_FILE "POLYP_CONFIG"
56
57 #ifndef DEFAULT_SCRIPT_FILE
58 #define DEFAULT_SCRIPT_FILE "/etc/polypaudio/default.pa"
59 #endif
60
61 #ifndef DEFAULT_CONFIG_FILE
62 #define DEFAULT_CONFIG_FILE "/etc/polypaudio/config"
63 #endif
64
65 #define DEFAULT_SCRIPT_FILE_LOCAL ".polypaudio.pa"
66 #define DEFAULT_CONFIG_FILE_LOCAL ".polypaudio.conf"
67
68 char* default_file(const char *envvar, const char *global, const char *local) {
69 char *p, *h;
70
71 assert(envvar && global && local);
72
73 if ((p = getenv(envvar)))
74 return pa_xstrdup(p);
75
76 if ((h = getenv("HOME"))) {
77 struct stat st;
78 p = pa_sprintf_malloc("%s/%s", h, local);
79 if (stat(p, &st) >= 0)
80 return p;
81
82 pa_xfree(p);
83 }
84
85 return pa_xstrdup(global);
86 }
87
88
89 struct pa_conf* pa_conf_new(void) {
90 struct pa_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
91 c->default_script_file = default_file(ENV_SCRIPT_FILE, DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_LOCAL);
92 return c;
93 }
94
95 void pa_conf_free(struct pa_conf *c) {
96 assert(c);
97 pa_xfree(c->script_commands);
98 pa_xfree(c->dl_search_path);
99 pa_xfree(c->default_script_file);
100 pa_xfree(c);
101 }
102
103 #define WHITESPACE " \t\n"
104 #define COMMENTS "#;\n"
105
106 #define PARSE_BOOLEAN(t, v) \
107 do { \
108 if (!strcmp(lvalue, t)) { \
109 int b; \
110 if ((b = pa_parse_boolean(rvalue)) < 0) \
111 goto fail; \
112 c->v = b; \
113 return 0; \
114 } \
115 } while (0)
116
117 #define PARSE_STRING(t, v) \
118 do { \
119 if (!strcmp(lvalue, t)) { \
120 pa_xfree(c->v); \
121 c->v = *rvalue ? pa_xstrdup(rvalue) : NULL; \
122 return 0; \
123 } \
124 } while (0)
125
126 #define PARSE_INTEGER(t, v) \
127 do { \
128 if (!strcmp(lvalue, t)) { \
129 char *x = NULL; \
130 int i = strtol(rvalue, &x, 0); \
131 if (!x || *x) \
132 goto fail; \
133 c->v = i; \
134 return 0; \
135 } \
136 } while(0)
137
138 static int next_assignment(struct pa_conf *c, char *lvalue, char *rvalue, unsigned n) {
139 PARSE_BOOLEAN("daemonize", daemonize);
140 PARSE_BOOLEAN("fail", fail);
141 PARSE_BOOLEAN("verbose", verbose);
142 PARSE_BOOLEAN("high-priority", high_priority);
143 PARSE_BOOLEAN("disallow-module-loading", disallow_module_loading);
144
145 PARSE_INTEGER("exit-idle-time", exit_idle_time);
146 PARSE_INTEGER("module-idle-time", module_idle_time);
147 PARSE_INTEGER("scache-idle-time", scache_idle_time);
148
149 PARSE_STRING("dl-search-path", dl_search_path);
150 PARSE_STRING("default-script-file", default_script_file);
151
152 if (!strcmp(lvalue, "log-target")) {
153 if (!strcmp(rvalue, "auto"))
154 c->auto_log_target = 1;
155 else if (!strcmp(rvalue, "syslog")) {
156 c->auto_log_target = 0;
157 c->log_target = PA_LOG_SYSLOG;
158 } else if (!strcmp(rvalue, "stderr")) {
159 c->auto_log_target = 0;
160 c->log_target = PA_LOG_STDERR;
161 } else
162 goto fail;
163
164 return 0;
165 }
166
167 fail:
168 pa_log(__FILE__": line %u: parse error.\n", n);
169 return -1;
170 }
171
172 #undef PARSE_STRING
173 #undef PARSE_BOOLEAN
174
175 static int in_string(char c, const char *s) {
176 for (; *s; s++)
177 if (*s == c)
178 return 1;
179
180 return 0;
181 }
182
183 static char *strip(char *s) {
184 char *b = s+strspn(s, WHITESPACE);
185 char *e, *l = NULL;
186
187 for (e = b; *e; e++)
188 if (!in_string(*e, WHITESPACE))
189 l = e;
190
191 if (l)
192 *(l+1) = 0;
193
194 return b;
195 }
196
197 static int parse_line(struct pa_conf *conf, char *l, unsigned n) {
198 char *e, *c, *b = l+strspn(l, WHITESPACE);
199
200 if ((c = strpbrk(b, COMMENTS)))
201 *c = 0;
202
203 if (!*b)
204 return 0;
205
206 if (!(e = strchr(b, '='))) {
207 pa_log(__FILE__": line %u: missing '='.\n", n);
208 return -1;
209 }
210
211 *e = 0;
212 e++;
213
214 return next_assignment(conf, strip(b), strip(e), n);
215 }
216
217
218 int pa_conf_load(struct pa_conf *c, const char *filename) {
219 FILE *f;
220 int r = 0;
221 unsigned n = 0;
222 char *def = NULL;
223 assert(c);
224
225 if (!filename)
226 filename = def = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL);
227
228 if (!(f = fopen(filename, "r"))) {
229 if (errno != ENOENT)
230 pa_log(__FILE__": WARNING: failed to open configuration file '%s': %s\n", filename, strerror(errno));
231
232 goto finish;
233 }
234
235 while (!feof(f)) {
236 char l[256];
237 if (!fgets(l, sizeof(l), f)) {
238 if (!feof(f))
239 pa_log(__FILE__": WARNING: failed to read configuration file '%s': %s\n", filename, strerror(errno));
240
241 break;
242 }
243
244 if (parse_line(c, l, ++n) < 0)
245 r = -1;
246 }
247
248 finish:
249
250 if (f)
251 fclose(f);
252
253 pa_xfree(def);
254
255 return r;
256 }
257
258 char *pa_conf_dump(struct pa_conf *c) {
259 struct pa_strbuf *s = pa_strbuf_new();
260 char *d;
261
262 d = default_file(ENV_CONFIG_FILE, DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCAL);
263 pa_strbuf_printf(s, "### Default configuration file: %s ###\n", d);
264
265 pa_strbuf_printf(s, "verbose = %i\n", !!c->verbose);
266 pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize);
267 pa_strbuf_printf(s, "fail = %i\n", !!c->fail);
268 pa_strbuf_printf(s, "high-priority = %i\n", !!c->high_priority);
269 pa_strbuf_printf(s, "disallow-module-loading = %i\n", !!c->disallow_module_loading);
270 pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
271 pa_strbuf_printf(s, "module-idle-time = %i\n", c->module_idle_time);
272 pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time);
273 pa_strbuf_printf(s, "dl-search-path = %s\n", c->dl_search_path ? c->dl_search_path : "");
274 pa_strbuf_printf(s, "default-script-file = %s\n", c->default_script_file);
275 pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr"));
276
277 pa_xfree(d);
278
279 return pa_strbuf_tostring_free(s);
280 }