1 /*
2 * Copyright (c) 2007-2014, Anthony Minessale II
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of the original author; nor the names of any contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Contributors:
34 *
35 * Moises Silva <moy@sangoma.com>
36 */
37
38 #include "private/ftdm_core.h"
39
40 #ifndef FTDM_MOD_DIR
41 #define FTDM_MOD_DIR "."
42 #endif
43
44 #define FTDM_MAX_CONF_DIR 512
45
46 static char g_ftdm_config_dir[FTDM_MAX_CONF_DIR] = FTDM_CONFIG_DIR;
47 static char g_ftdm_mod_dir[FTDM_MAX_CONF_DIR] = FTDM_MOD_DIR;
48
ftdm_global_set_mod_directory(const char * path)49 FT_DECLARE(void) ftdm_global_set_mod_directory(const char *path)
50 {
51 snprintf(g_ftdm_mod_dir, sizeof(g_ftdm_mod_dir), "%s", path);
52 ftdm_log(FTDM_LOG_DEBUG, "New mod directory: %s\n", g_ftdm_mod_dir);
53 }
54
ftdm_global_set_config_directory(const char * path)55 FT_DECLARE(void) ftdm_global_set_config_directory(const char *path)
56 {
57 snprintf(g_ftdm_config_dir, sizeof(g_ftdm_config_dir), "%s", path);
58 ftdm_log(FTDM_LOG_DEBUG, "New config directory: %s\n", g_ftdm_config_dir);
59 }
60
ftdm_config_open_file(ftdm_config_t * cfg,const char * file_path)61 int ftdm_config_open_file(ftdm_config_t *cfg, const char *file_path)
62 {
63 FILE *f;
64 const char *path = NULL;
65 char path_buf[1024];
66
67 if (file_path[0] == '/') {
68 path = file_path;
69 } else {
70 snprintf(path_buf, sizeof(path_buf), "%s%s%s", g_ftdm_config_dir, FTDM_PATH_SEPARATOR, file_path);
71 path = path_buf;
72 }
73
74 if (!path) {
75 return 0;
76 }
77
78 memset(cfg, 0, sizeof(*cfg));
79 cfg->lockto = -1;
80 ftdm_log(FTDM_LOG_DEBUG, "Configuration file is %s\n", path);
81 f = fopen(path, "r");
82
83 if (!f) {
84 if (file_path[0] != '/') {
85 int last = -1;
86 char *var, *val;
87
88 snprintf(path_buf, sizeof(path_buf), "%s%sfreetdm.conf", g_ftdm_config_dir, FTDM_PATH_SEPARATOR);
89 path = path_buf;
90
91 if ((f = fopen(path, "r")) == 0) {
92 return 0;
93 }
94
95 cfg->file = f;
96 ftdm_set_string(cfg->path, path);
97
98 while (ftdm_config_next_pair(cfg, &var, &val)) {
99 if ((cfg->sectno != last) && !strcmp(cfg->section, file_path)) {
100 cfg->lockto = cfg->sectno;
101 return 1;
102 }
103 }
104
105 ftdm_config_close_file(cfg);
106 memset(cfg, 0, sizeof(*cfg));
107 return 0;
108 }
109
110 return 0;
111 } else {
112 cfg->file = f;
113 ftdm_set_string(cfg->path, path);
114 return 1;
115 }
116 }
117
ftdm_config_close_file(ftdm_config_t * cfg)118 void ftdm_config_close_file(ftdm_config_t *cfg)
119 {
120
121 if (cfg->file) {
122 fclose(cfg->file);
123 }
124
125 memset(cfg, 0, sizeof(*cfg));
126 }
127
128
129
ftdm_config_next_pair(ftdm_config_t * cfg,char ** var,char ** val)130 int ftdm_config_next_pair(ftdm_config_t *cfg, char **var, char **val)
131 {
132 int ret = 0;
133 char *p, *end;
134
135 *var = *val = NULL;
136
137 if (!cfg->path) {
138 return 0;
139 }
140
141 for (;;) {
142 cfg->lineno++;
143
144 if (!fgets(cfg->buf, sizeof(cfg->buf), cfg->file)) {
145 ret = 0;
146 break;
147 }
148 *var = cfg->buf;
149
150 if (**var == '[' && (end = strchr(*var, ']')) != 0) {
151 *end = '\0';
152 (*var)++;
153 if (**var == '+') {
154 (*var)++;
155 ftdm_copy_string(cfg->section, *var, sizeof(cfg->section));
156 cfg->sectno++;
157
158 if (cfg->lockto > -1 && cfg->sectno != cfg->lockto) {
159 break;
160 }
161 cfg->catno = 0;
162 cfg->lineno = 0;
163 *var = (char *) "";
164 *val = (char *) "";
165 return 1;
166 } else {
167 ftdm_copy_string(cfg->category, *var, sizeof(cfg->category));
168 cfg->catno++;
169 }
170 continue;
171 }
172
173
174
175 if (**var == '#' || **var == ';' || **var == '\n' || **var == '\r') {
176 continue;
177 }
178
179 if (!strncmp(*var, "__END__", 7)) {
180 break;
181 }
182
183
184 if ((end = strchr(*var, ';')) && *(end+1) == *end) {
185 *end = '\0';
186 end--;
187 } else if ((end = strchr(*var, '\n')) != 0) {
188 if (*(end - 1) == '\r') {
189 end--;
190 }
191 *end = '\0';
192 }
193
194 p = *var;
195 while ((*p == ' ' || *p == '\t') && p != end) {
196 *p = '\0';
197 p++;
198 }
199 *var = p;
200
201
202 if ((*val = strchr(*var, '=')) == 0) {
203 ret = -1;
204 /* log_printf(0, server.log, "Invalid syntax on %s: line %d\n", cfg->path, cfg->lineno); */
205 continue;
206 } else {
207 p = *val - 1;
208 *(*val) = '\0';
209 (*val)++;
210 if (*(*val) == '>') {
211 *(*val) = '\0';
212 (*val)++;
213 }
214
215 while ((*p == ' ' || *p == '\t') && p != *var) {
216 *p = '\0';
217 p--;
218 }
219
220 p = *val;
221 while ((*p == ' ' || *p == '\t') && p != end) {
222 *p = '\0';
223 p++;
224 }
225 *val = p;
226 ret = 1;
227 break;
228 }
229 }
230
231
232 return ret;
233
234 }
235
ftdm_config_get_cas_bits(char * strvalue,unsigned char * outbits)236 FT_DECLARE (int) ftdm_config_get_cas_bits(char *strvalue, unsigned char *outbits)
237 {
238 char cas_bits[5];
239 unsigned char bit = 0x8;
240 int x = 0;
241 char *double_colon = strchr(strvalue, ':');
242 if (!double_colon) {
243 ftdm_log(FTDM_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", strvalue);
244 return -1;
245 }
246 double_colon++;
247 *outbits = 0;
248 cas_bits[4] = 0;
249 if (sscanf(double_colon, "%c%c%c%c", &cas_bits[0], &cas_bits[1], &cas_bits[2], &cas_bits[3]) != 4) {
250 ftdm_log(FTDM_LOG_ERROR, "Invalid CAS bits specified: '%s', :xxxx definition expected, where x is 1 or 0\n", double_colon);
251 return -1;
252 }
253 ftdm_log(FTDM_LOG_DEBUG, "CAS bits specification found: %s\n", cas_bits);
254 for (; cas_bits[x]; x++) {
255 if ('1' == cas_bits[x]) {
256 *outbits |= bit;
257 } else if ('0' != cas_bits[x]) {
258 ftdm_log(FTDM_LOG_ERROR, "Invalid CAS pattern specified: %s, just 0 or 1 allowed for each bit\n",
259 strvalue);
260 return -1;
261 }
262 bit >>= 1;
263 }
264 return 0;
265 }
266
267 #define PARAMETERS_CHUNK_SIZE 20
ftdm_conf_node_create(const char * name,ftdm_conf_node_t ** node,ftdm_conf_node_t * parent)268 FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent)
269 {
270 ftdm_conf_node_t *newnode;
271 ftdm_conf_node_t *sibling = NULL;
272
273 ftdm_assert_return(name != NULL, FTDM_FAIL, "null node name");
274
275 newnode = ftdm_calloc(1, sizeof(**node));
276 if (!newnode) {
277 return FTDM_MEMERR;
278 }
279
280 strncpy(newnode->name, name, sizeof(newnode->name)-1);
281 newnode->name[sizeof(newnode->name)-1] = 0;
282
283 newnode->parameters = ftdm_calloc(PARAMETERS_CHUNK_SIZE, sizeof(*newnode->parameters));
284 if (!newnode->parameters) {
285 ftdm_safe_free(newnode);
286 return FTDM_MEMERR;
287 }
288 newnode->t_parameters = PARAMETERS_CHUNK_SIZE;
289
290 if (parent) {
291 /* store who my parent is */
292 newnode->parent = parent;
293
294 /* arrange them in FIFO order (newnode should be last) */
295 if (!parent->child) {
296 /* we're the first node being added */
297 parent->child = newnode;
298 } else {
299 if (!parent->last) {
300 /* we're the second node being added */
301 parent->last = newnode;
302 parent->child->next = newnode;
303 newnode->prev = parent->child;
304 } else {
305 /* we're the third or Nth node to be added */
306 sibling = parent->last;
307 sibling->next = newnode;
308 parent->last = newnode;
309 newnode->prev = sibling;
310 }
311 }
312 }
313
314 *node = newnode;
315
316 return FTDM_SUCCESS;
317 }
318
ftdm_conf_node_add_param(ftdm_conf_node_t * node,const char * param,const char * val)319 FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const char *param, const char *val)
320 {
321 void *newparameters;
322
323 ftdm_assert_return(param != NULL, FTDM_FAIL, "param is null");
324 ftdm_assert_return(val != NULL, FTDM_FAIL, "val is null");
325
326 if (node->n_parameters == node->t_parameters) {
327 newparameters = ftdm_realloc(node->parameters, (node->t_parameters + PARAMETERS_CHUNK_SIZE) * sizeof(*node->parameters));
328 if (!newparameters) {
329 return FTDM_MEMERR;
330 }
331 node->parameters = newparameters;
332 node->t_parameters = node->n_parameters + PARAMETERS_CHUNK_SIZE;
333 }
334 node->parameters[node->n_parameters].var = param;
335 node->parameters[node->n_parameters].val = val;
336 node->n_parameters++;
337 return FTDM_SUCCESS;
338 }
339
ftdm_conf_node_destroy(ftdm_conf_node_t * node)340 FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node)
341 {
342 ftdm_conf_node_t *curr = NULL;
343 ftdm_conf_node_t *child = node->child;
344 while (child) {
345 curr = child;
346 child = curr->next;
347 ftdm_conf_node_destroy(curr);
348 }
349 ftdm_free(node->parameters);
350 ftdm_free(node);
351 return FTDM_SUCCESS;
352 }
353
ftdm_build_dso_path(const char * name,char * path,ftdm_size_t len)354 FT_DECLARE(char *) ftdm_build_dso_path(const char *name, char *path, ftdm_size_t len)
355 {
356 #ifdef WIN32
357 const char *ext = ".dll";
358 //const char *EXT = ".DLL";
359 #elif defined (MACOSX) || defined (DARWIN)
360 const char *ext = ".dylib";
361 //const char *EXT = ".DYLIB";
362 #else
363 const char *ext = ".so";
364 //const char *EXT = ".SO";
365 #endif
366 if (*name == *FTDM_PATH_SEPARATOR) {
367 snprintf(path, len, "%s%s", name, ext);
368 } else {
369 snprintf(path, len, "%s%s%s%s", g_ftdm_mod_dir, FTDM_PATH_SEPARATOR, name, ext);
370 }
371 return path;
372 }
373
374 /* For Emacs:
375 * Local Variables:
376 * mode:c
377 * indent-tabs-mode:t
378 * tab-width:4
379 * c-basic-offset:4
380 * End:
381 * For VIM:
382 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
383 */
384