root/src/ftdm_config.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. FT_DECLARE
  2. FT_DECLARE
  3. ftdm_config_open_file
  4. ftdm_config_close_file
  5. ftdm_config_next_pair
  6. FT_DECLARE
  7. FT_DECLARE
  8. FT_DECLARE
  9. FT_DECLARE
  10. FT_DECLARE

   1 /*
   2  * Copyright (c) 2007, 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 
  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 
  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 
  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 
 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 
 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 
 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                         return -1;
 260                 }
 261                 bit >>= 1;
 262         }
 263         return 0;
 264 }
 265 
 266 #define PARAMETERS_CHUNK_SIZE 20
 267 FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent)
 268 {
 269         ftdm_conf_node_t *newnode;
 270         ftdm_conf_node_t *sibling = NULL;
 271 
 272         ftdm_assert_return(name != NULL, FTDM_FAIL, "null node name");
 273 
 274         newnode = ftdm_calloc(1, sizeof(**node));
 275         if (!newnode) {
 276                 return FTDM_MEMERR;
 277         }
 278 
 279         strncpy(newnode->name, name, sizeof(newnode->name)-1);  
 280         newnode->name[sizeof(newnode->name)-1] = 0;
 281 
 282         newnode->parameters = ftdm_calloc(PARAMETERS_CHUNK_SIZE, sizeof(*newnode->parameters));
 283         if (!newnode->parameters) {
 284                 ftdm_safe_free(newnode);
 285                 return FTDM_MEMERR;
 286         }
 287         newnode->t_parameters = PARAMETERS_CHUNK_SIZE;
 288 
 289         if (parent) {
 290                 /* store who my parent is */
 291                 newnode->parent = parent;
 292 
 293                 /* arrange them in FIFO order (newnode should be last) */
 294                 if (!parent->child) {
 295                         /* we're the first node being added */
 296                         parent->child = newnode;
 297                 } else {
 298                         if (!parent->last) {
 299                                 /* we're the second node being added */
 300                                 parent->last = newnode;
 301                                 parent->child->next = newnode;
 302                                 newnode->prev = parent->child;
 303                         } else {
 304                                 /* we're the third or Nth node to be added */
 305                                 sibling = parent->last;
 306                                 sibling->next = newnode;
 307                                 parent->last = newnode;
 308                                 newnode->prev = sibling;
 309                         }
 310                 }
 311         }
 312 
 313         *node = newnode;
 314 
 315         return FTDM_SUCCESS;
 316 }
 317 
 318 FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const char *param, const char *val)
 319 {
 320         void *newparameters;
 321 
 322         ftdm_assert_return(param != NULL, FTDM_FAIL, "param is null");
 323         ftdm_assert_return(val != NULL, FTDM_FAIL, "val is null");
 324 
 325         if (node->n_parameters == node->t_parameters) {
 326                 newparameters = ftdm_realloc(node->parameters, (node->t_parameters + PARAMETERS_CHUNK_SIZE) * sizeof(*node->parameters));
 327                 if (!newparameters) {
 328                         return FTDM_MEMERR;
 329                 }
 330                 node->parameters = newparameters;
 331                 node->t_parameters = node->n_parameters + PARAMETERS_CHUNK_SIZE;
 332         }
 333         node->parameters[node->n_parameters].var = param;
 334         node->parameters[node->n_parameters].val = val;
 335         node->n_parameters++;
 336         return FTDM_SUCCESS;
 337 }
 338 
 339 FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node)
 340 {
 341         ftdm_conf_node_t *curr = NULL;
 342         ftdm_conf_node_t *child = node->child;
 343         while (child) {
 344                 curr = child;
 345                 child = curr->next;
 346                 ftdm_conf_node_destroy(curr);
 347         }
 348         ftdm_free(node->parameters);
 349         ftdm_free(node);
 350         return FTDM_SUCCESS;
 351 }
 352 
 353 FT_DECLARE(char *) ftdm_build_dso_path(const char *name, char *path, ftdm_size_t len)
 354 {
 355 #ifdef WIN32
 356     const char *ext = ".dll";
 357     //const char *EXT = ".DLL";
 358 #elif defined (MACOSX) || defined (DARWIN)
 359     const char *ext = ".dylib";
 360     //const char *EXT = ".DYLIB";
 361 #else
 362     const char *ext = ".so";
 363     //const char *EXT = ".SO";
 364 #endif
 365         if (*name == *FTDM_PATH_SEPARATOR) {
 366                 snprintf(path, len, "%s%s", name, ext);
 367         } else {
 368                 snprintf(path, len, "%s%s%s%s", g_ftdm_mod_dir, FTDM_PATH_SEPARATOR, name, ext);
 369         }
 370         return path;    
 371 }
 372 
 373 /* For Emacs:
 374  * Local Variables:
 375  * mode:c
 376  * indent-tabs-mode:t
 377  * tab-width:4
 378  * c-basic-offset:4
 379  * End:
 380  * For VIM:
 381  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
 382  */

/* [<][>][^][v][top][bottom][index][help] */