1 /**
2  * @file conf.c  Configuration utils
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #define _DEFAULT_SOURCE 1
7 #define _BSD_SOURCE 1
8 #include <fcntl.h>
9 #ifdef HAVE_UNISTD_H
10 #include <unistd.h>
11 #endif
12 #include <stdio.h>
13 #include <sys/stat.h>
14 #ifdef HAVE_IO_H
15 #include <io.h>
16 #endif
17 #include <re.h>
18 #include <rem.h>
19 #include <baresip.h>
20 #include "core.h"
21 
22 
23 #define DEBUG_MODULE ""
24 #define DEBUG_LEVEL 0
25 #include <re_dbg.h>
26 
27 
28 #ifdef WIN32
29 #define open _open
30 #define read _read
31 #define close _close
32 #endif
33 
34 
35 #if defined (WIN32)
36 #define DIR_SEP "\\"
37 #else
38 #define DIR_SEP "/"
39 #endif
40 
41 
42 static const char *conf_path = NULL;
43 static struct conf *conf_obj;
44 
45 
46 /**
47  * Check if a file exists
48  *
49  * @param path Filename
50  *
51  * @return True if exist, False if not
52  */
conf_fileexist(const char * path)53 bool conf_fileexist(const char *path)
54 {
55 	struct stat st;
56 
57 	if (!path)
58 		 return false;
59 
60 	if (stat(path, &st) < 0)
61 		 return false;
62 
63 	if ((st.st_mode & S_IFMT) != S_IFREG)
64 		 return false;
65 
66 	return st.st_size > 0;
67 }
68 
69 
print_populated(const char * what,uint32_t n)70 static void print_populated(const char *what, uint32_t n)
71 {
72 	info("Populated %u %s%s\n", n, what, 1==n ? "" : "s");
73 }
74 
75 
76 /**
77  * Parse a config file, calling handler for each line
78  *
79  * @param filename Config file
80  * @param ch       Line handler
81  * @param arg      Handler argument
82  *
83  * @return 0 if success, otherwise errorcode
84  */
conf_parse(const char * filename,confline_h * ch,void * arg)85 int conf_parse(const char *filename, confline_h *ch, void *arg)
86 {
87 	struct pl pl, val;
88 	struct mbuf *mb;
89 	int err = 0, fd = open(filename, O_RDONLY);
90 	if (fd < 0)
91 		return errno;
92 
93 	mb = mbuf_alloc(1024);
94 	if (!mb) {
95 		err = ENOMEM;
96 		goto out;
97 	}
98 
99 	for (;;) {
100 		uint8_t buf[1024];
101 
102 		const ssize_t n = read(fd, (void *)buf, sizeof(buf));
103 		if (n < 0) {
104 			err = errno;
105 			break;
106 		}
107 		else if (n == 0)
108 			break;
109 
110 		err |= mbuf_write_mem(mb, buf, n);
111 	}
112 
113 	pl.p = (const char *)mb->buf;
114 	pl.l = mb->end;
115 
116 	while (pl.p < ((const char *)mb->buf + mb->end) && !err) {
117 		const char *lb = pl_strchr(&pl, '\n');
118 
119 		val.p = pl.p;
120 		val.l = lb ? (uint32_t)(lb - pl.p) : pl.l;
121 		pl_advance(&pl, val.l + 1);
122 
123 		if (!val.l || val.p[0] == '#')
124 			continue;
125 
126 		err = ch(&val, arg);
127 	}
128 
129  out:
130 	mem_deref(mb);
131 	(void)close(fd);
132 
133 	return err;
134 }
135 
136 
137 /**
138  * Set the path to configuration files
139  *
140  * @param path Configuration path
141  */
conf_path_set(const char * path)142 void conf_path_set(const char *path)
143 {
144 	conf_path = path;
145 }
146 
147 
148 /**
149  * Get the path to configuration files
150  *
151  * @param path Buffer to write path
152  * @param sz   Size of path buffer
153  *
154  * @return 0 if success, otherwise errorcode
155  */
conf_path_get(char * path,size_t sz)156 int conf_path_get(char *path, size_t sz)
157 {
158 	char buf[FS_PATH_MAX];
159 	int err;
160 
161 	/* Use explicit conf path */
162 	if (conf_path) {
163 		if (re_snprintf(path, sz, "%s", conf_path) < 0)
164 			return ENOMEM;
165 		return 0;
166 	}
167 
168 #ifdef CONFIG_PATH
169 	str_ncpy(buf, CONFIG_PATH, sizeof(buf));
170 	(void)err;
171 #else
172 	err = fs_gethome(buf, sizeof(buf));
173 	if (err)
174 		return err;
175 #endif
176 
177 	if (re_snprintf(path, sz, "%s" DIR_SEP ".baresip", buf) < 0)
178 		return ENOMEM;
179 
180 	return 0;
181 }
182 
183 
conf_get_range(const struct conf * conf,const char * name,struct range * rng)184 int conf_get_range(const struct conf *conf, const char *name,
185 		   struct range *rng)
186 {
187 	struct pl r, min, max;
188 	uint32_t v;
189 	int err;
190 
191 	err = conf_get(conf, name, &r);
192 	if (err)
193 		return err;
194 
195 	err = re_regex(r.p, r.l, "[0-9]+-[0-9]+", &min, &max);
196 	if (err) {
197 		/* fallback to non-range numeric value */
198 		err = conf_get_u32(conf, name, &v);
199 		if (err) {
200 			warning("conf: %s: could not parse range: (%r)\n",
201 				name, &r);
202 			return err;
203 		}
204 
205 		rng->min = rng->max = v;
206 
207 		return err;
208 	}
209 
210 	rng->min = pl_u32(&min);
211 	rng->max = pl_u32(&max);
212 
213 	if (rng->min > rng->max) {
214 		warning("conf: %s: invalid range (%u - %u)\n",
215 			name, rng->min, rng->max);
216 		return EINVAL;
217 	}
218 
219 	return 0;
220 }
221 
222 
conf_get_csv(const struct conf * conf,const char * name,char * str1,size_t sz1,char * str2,size_t sz2)223 int conf_get_csv(const struct conf *conf, const char *name,
224 		 char *str1, size_t sz1, char *str2, size_t sz2)
225 {
226 	struct pl r, pl1, pl2 = pl_null;
227 	int err;
228 
229 	err = conf_get(conf, name, &r);
230 	if (err)
231 		return err;
232 
233 	/* note: second value may be quoted */
234 	err = re_regex(r.p, r.l, "[^,]+,[~]*", &pl1, &pl2);
235 	if (err)
236 		return err;
237 
238 	(void)pl_strcpy(&pl1, str1, sz1);
239 	if (pl_isset(&pl2))
240 		(void)pl_strcpy(&pl2, str2, sz2);
241 
242 	return 0;
243 }
244 
245 
conf_get_vidsz(const struct conf * conf,const char * name,struct vidsz * sz)246 int conf_get_vidsz(const struct conf *conf, const char *name, struct vidsz *sz)
247 {
248 	struct pl r, w, h;
249 	int err;
250 
251 	err = conf_get(conf, name, &r);
252 	if (err)
253 		return err;
254 
255 	w.l = h.l = 0;
256 	err = re_regex(r.p, r.l, "[0-9]+x[0-9]+", &w, &h);
257 	if (err)
258 		return err;
259 
260 	if (pl_isset(&w) && pl_isset(&h)) {
261 		sz->w = pl_u32(&w);
262 		sz->h = pl_u32(&h);
263 	}
264 
265 	/* check resolution */
266 	if (sz->w & 0x1 || sz->h & 0x1) {
267 		warning("conf: %s: should be multiple of 2 (%u x %u)\n",
268 			name, sz->w, sz->h);
269 		return EINVAL;
270 	}
271 
272 	return 0;
273 }
274 
275 
conf_get_sa(const struct conf * conf,const char * name,struct sa * sa)276 int conf_get_sa(const struct conf *conf, const char *name, struct sa *sa)
277 {
278 	struct pl opt;
279 	int err;
280 
281 	if (!conf || !name || !sa)
282 		return EINVAL;
283 
284 	err = conf_get(conf, name, &opt);
285 	if (err)
286 		return err;
287 
288 	return sa_decode(sa, opt.p, opt.l);
289 }
290 
291 
292 /**
293  * Configure the system with default settings
294  *
295  * @return 0 if success, otherwise errorcode
296  */
conf_configure(void)297 int conf_configure(void)
298 {
299 	char path[FS_PATH_MAX], file[FS_PATH_MAX];
300 	int err;
301 
302 #if defined (WIN32)
303 	dbg_init(DBG_INFO, DBG_NONE);
304 #endif
305 
306 	err = conf_path_get(path, sizeof(path));
307 	if (err) {
308 		warning("conf: could not get config path: %m\n", err);
309 		return err;
310 	}
311 
312 	if (re_snprintf(file, sizeof(file), "%s/config", path) < 0)
313 		return ENOMEM;
314 
315 	if (!conf_fileexist(file)) {
316 
317 		(void)fs_mkdir(path, 0700);
318 
319 		err = config_write_template(file, conf_config());
320 		if (err)
321 			goto out;
322 	}
323 
324 	conf_obj = mem_deref(conf_obj);
325 	err = conf_alloc(&conf_obj, file);
326 	if (err)
327 		goto out;
328 
329 	err = config_parse_conf(conf_config(), conf_obj);
330 	if (err)
331 		goto out;
332 
333  out:
334 	return err;
335 }
336 
337 
338 /**
339  * Load all modules from config file
340  *
341  * @return 0 if success, otherwise errorcode
342  *
343  * @note conf_configure must be called first
344  */
conf_modules(void)345 int conf_modules(void)
346 {
347 	int err;
348 
349 	err = module_init(conf_obj);
350 	if (err) {
351 		warning("conf: configure module parse error (%m)\n", err);
352 		goto out;
353 	}
354 
355 	print_populated("audio codec",  list_count(baresip_aucodecl()));
356 	print_populated("audio filter", list_count(baresip_aufiltl()));
357 #ifdef USE_VIDEO
358 	print_populated("video codec",  list_count(baresip_vidcodecl()));
359 	print_populated("video filter", list_count(baresip_vidfiltl()));
360 #endif
361 
362  out:
363 	return err;
364 }
365 
366 
367 /**
368  * Get the current configuration object
369  *
370  * @return Config object
371  *
372  * @note It is only available after init and before conf_close()
373  */
conf_cur(void)374 struct conf *conf_cur(void)
375 {
376 	if (!conf_obj) {
377 		warning("conf: no config object\n");
378 	}
379 	return conf_obj;
380 }
381 
382 
conf_close(void)383 void conf_close(void)
384 {
385 	conf_obj = mem_deref(conf_obj);
386 }
387