Wed Jan 8 2020 09:49:50

Asterisk developer's documentation


res_config_sqlite.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2006, Proformatique
5  *
6  * Written by Richard Braun <rbraun@proformatique.com>
7  *
8  * Based on res_sqlite3 by Anthony Minessale II,
9  * and res_config_mysql by Matthew Boehm
10  *
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2. See the LICENSE file
19  * at the top of the source tree.
20  */
21 
22 /*!
23  * \page res_config_sqlite
24  *
25  * \section intro_sec Presentation
26  *
27  * res_config_sqlite is a module for the Asterisk Open Source PBX to
28  * support SQLite 2 databases. It can be used to fetch configuration
29  * from a database (static configuration files and/or using the Asterisk
30  * RealTime Architecture - ARA). It can also be used to log CDR entries.
31  * Note that Asterisk already comes with a module named cdr_sqlite.
32  * There are two reasons for including it in res_config_sqlite:
33  * the first is that rewriting it was a training to learn how to write a
34  * simple module for Asterisk, the other is to have the same database open for
35  * all kinds of operations, which improves reliability and performance.
36  *
37  * \section conf_sec Configuration
38  *
39  * The main configuration file is res_config_sqlite.conf. It must be readable or
40  * res_config_sqlite will fail to start. It is suggested to use the sample file
41  * in this package as a starting point. The file has only one section
42  * named <code>general</code>. Here are the supported parameters :
43  *
44  * <dl>
45  * <dt><code>dbfile</code></dt>
46  * <dd>The absolute path to the SQLite database (the file can be non existent,
47  * res_config_sqlite will create it if it has the appropriate rights)</dd>
48  * <dt><code>config_table</code></dt>
49  * <dd>The table used for static configuration</dd>
50  * <dt><code>cdr_table</code></dt>
51  * <dd>The table used to store CDR entries (if ommitted, CDR support is
52  * disabled)</dd>
53  * </dl>
54  *
55  * To use res_config_sqlite for static and/or RealTime configuration, refer to the
56  * Asterisk documentation. The file tables.sql can be used to create the
57  * needed tables.
58  *
59  * \section status_sec Driver status
60  *
61  * The CLI command <code>show sqlite status</code> returns status information
62  * about the running driver.
63  *
64  * \section credits_sec Credits
65  *
66  * res_config_sqlite was developed by Richard Braun at the Proformatique company.
67  */
68 
69 /*!
70  * \file
71  * \brief res_config_sqlite module.
72  */
73 
74 /*** MODULEINFO
75  <depend>sqlite</depend>
76  <support_level>extended</support_level>
77  ***/
78 
79 #include "asterisk.h"
80 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 371590 $")
81 
82 #include <sqlite.h>
83 
84 #include "asterisk/logger.h"
85 #include "asterisk/app.h"
86 #include "asterisk/pbx.h"
87 #include "asterisk/cdr.h"
88 #include "asterisk/cli.h"
89 #include "asterisk/lock.h"
90 #include "asterisk/config.h"
91 #include "asterisk/module.h"
92 #include "asterisk/linkedlists.h"
93 
94 #define MACRO_BEGIN do {
95 #define MACRO_END } while (0)
96 
97 #define RES_CONFIG_SQLITE_NAME "res_config_sqlite"
98 #define RES_CONFIG_SQLITE_DRIVER "sqlite"
99 #define RES_CONFIG_SQLITE_DESCRIPTION "Resource Module for SQLite 2"
100 #define RES_CONFIG_SQLITE_CONF_FILE "res_config_sqlite.conf"
101 
102 enum {
112 };
113 
114 #define SET_VAR(config, to, from) \
115 MACRO_BEGIN \
116  int __error; \
117  \
118  __error = set_var(&to, #to, from->value); \
119  \
120  if (__error) { \
121  ast_config_destroy(config); \
122  unload_config(); \
123  return 1; \
124  } \
125 MACRO_END
126 
129 
130 /*!
131  * Maximum number of loops before giving up executing a query. Calls to
132  * sqlite_xxx() functions which can return SQLITE_BUSY
133  * are enclosed by RES_CONFIG_SQLITE_BEGIN and RES_CONFIG_SQLITE_END, e.g.
134  * <pre>
135  * char *errormsg;
136  * int error;
137  *
138  * RES_CONFIG_SQLITE_BEGIN
139  * error = sqlite_exec(db, query, NULL, NULL, &errormsg);
140  * RES_CONFIG_SQLITE_END(error)
141  *
142  * if (error)
143  * ...;
144  * </pre>
145  */
146 #define RES_CONFIG_SQLITE_MAX_LOOPS 10
147 
148 /*!
149  * Macro used before executing a query.
150  *
151  * \see RES_CONFIG_SQLITE_MAX_LOOPS.
152  */
153 #define RES_CONFIG_SQLITE_BEGIN \
154 MACRO_BEGIN \
155  int __i; \
156  \
157  for (__i = 0; __i < RES_CONFIG_SQLITE_MAX_LOOPS; __i++) {
158 
159 /*!
160  * Macro used after executing a query.
161  *
162  * \see RES_CONFIG_SQLITE_MAX_LOOPS.
163  */
164 #define RES_CONFIG_SQLITE_END(error) \
165  if (error != SQLITE_BUSY) \
166  break; \
167  usleep(1000); \
168  } \
169 MACRO_END;
170 
171 /*!
172  * Structure sent to the SQLite callback function for static configuration.
173  *
174  * \see add_cfg_entry()
175  */
177  struct ast_config *cfg;
178  struct ast_category *cat;
179  char *cat_name;
180  struct ast_flags flags;
181  const char *who_asked;
182 };
183 
184 /*!
185  * Structure sent to the SQLite callback function for RealTime configuration.
186  *
187  * \see add_rt_cfg_entry()
188  */
190  struct ast_variable *var;
192 };
193 
194 /*!
195  * Structure sent to the SQLite callback function for RealTime configuration
196  * (realtime_multi_handler()).
197  *
198  * \see add_rt_multi_cfg_entry()
199  */
201  struct ast_config *cfg;
202  char *initfield;
203 };
204 
205 /*!
206  * \brief Allocate a variable.
207  * \param var the address of the variable to set (it will be allocated)
208  * \param name the name of the variable (for error handling)
209  * \param value the value to store in var
210  * \retval 0 on success
211  * \retval 1 if an allocation error occurred
212  */
213 static int set_var(char **var, const char *name, const char *value);
214 
215 /*!
216  * \brief Load the configuration file.
217  * \see unload_config()
218  *
219  * This function sets dbfile, config_table, and cdr_table. It calls
220  * check_vars() before returning, and unload_config() if an error occurred.
221  *
222  * \retval 0 on success
223  * \retval 1 if an error occurred
224  */
225 static int load_config(void);
226 
227 /*!
228  * \brief Free resources related to configuration.
229  * \see load_config()
230  */
231 static void unload_config(void);
232 
233 /*!
234  * \brief Asterisk callback function for CDR support.
235  * \param cdr the CDR entry Asterisk sends us.
236  *
237  * Asterisk will call this function each time a CDR entry must be logged if
238  * CDR support is enabled.
239  *
240  * \retval 0 on success
241  * \retval 1 if an error occurred
242  */
243 static int cdr_handler(struct ast_cdr *cdr);
244 
245 /*!
246  * \brief SQLite callback function for static configuration.
247  *
248  * This function is passed to the SQLite engine as a callback function to
249  * parse a row and store it in a struct ast_config object. It relies on
250  * resulting rows being sorted by category.
251  *
252  * \param arg a pointer to a struct cfg_entry_args object
253  * \param argc number of columns
254  * \param argv values in the row
255  * \param columnNames names and types of the columns
256  * \retval 0 on success
257  * \retval 1 if an error occurred
258  * \see cfg_entry_args
259  * \see sql_get_config_table
260  * \see config_handler()
261  */
262 static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames);
263 
264 /*!
265  * \brief Asterisk callback function for static configuration.
266  *
267  * Asterisk will call this function when it loads its static configuration,
268  * which usually happens at startup and reload.
269  *
270  * \param database the database to use (ignored)
271  * \param table the table to use
272  * \param file the file to load from the database
273  * \param cfg the struct ast_config object to use when storing variables
274  * \param flags Optional flags. Not used.
275  * \param suggested_incl suggest include.
276  * \param who_asked
277  * \retval cfg object
278  * \retval NULL if an error occurred
279  * \see add_cfg_entry()
280  */
281 static struct ast_config * config_handler(const char *database, const char *table, const char *file,
282  struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked);
283 
284 /*!
285  * \brief Helper function to parse a va_list object into 2 dynamic arrays of
286  * strings, parameters and values.
287  *
288  * ap must have the following format : param1 val1 param2 val2 param3 val3 ...
289  * arguments will be extracted to create 2 arrays:
290  *
291  * <ul>
292  * <li>params : param1 param2 param3 ...</li>
293  * <li>vals : val1 val2 val3 ...</li>
294  * </ul>
295  *
296  * The address of these arrays are stored in params_ptr and vals_ptr. It
297  * is the responsibility of the caller to release the memory of these arrays.
298  * It is considered an error that va_list has a null or odd number of strings.
299  *
300  * \param ap the va_list object to parse
301  * \param params_ptr where the address of the params array is stored
302  * \param vals_ptr where the address of the vals array is stored
303  * \param warn
304  * \retval the number of elements in the arrays (which have the same size).
305  * \retval 0 if an error occurred.
306  */
307 static size_t get_params(va_list ap, const char ***params_ptr,
308  const char ***vals_ptr, int warn);
309 
310 /*!
311  * \brief SQLite callback function for RealTime configuration.
312  *
313  * This function is passed to the SQLite engine as a callback function to
314  * parse a row and store it in a linked list of struct ast_variable objects.
315  *
316  * \param arg a pointer to a struct rt_cfg_entry_args object
317  * \param argc number of columns
318  * \param argv values in the row
319  * \param columnNames names and types of the columns
320  * \retval 0 on success.
321  * \retval 1 if an error occurred.
322  * \see rt_cfg_entry_args
323  * \see realtime_handler()
324  */
325 static int add_rt_cfg_entry(void *arg, int argc, char **argv,
326  char **columnNames);
327 
328 /*!
329  * \brief Asterisk callback function for RealTime configuration.
330  *
331  * Asterisk will call this function each time it requires a variable
332  * through the RealTime architecture. ap is a list of parameters and
333  * values used to find a specific row, e.g one parameter "name" and
334  * one value "123" so that the SQL query becomes <code>SELECT * FROM
335  * table WHERE name = '123';</code>.
336  *
337  * \param database the database to use (ignored)
338  * \param table the table to use
339  * \param ap list of parameters and values to match
340  *
341  * \retval a linked list of struct ast_variable objects
342  * \retval NULL if an error occurred
343  * \see add_rt_cfg_entry()
344  */
345 static struct ast_variable * realtime_handler(const char *database,
346  const char *table, va_list ap);
347 
348 /*!
349  * \brief SQLite callback function for RealTime configuration.
350  *
351  * This function performs the same actions as add_rt_cfg_entry() except
352  * that the rt_multi_cfg_entry_args structure is designed to store
353  * categories in addition to variables.
354  *
355  * \param arg a pointer to a struct rt_multi_cfg_entry_args object
356  * \param argc number of columns
357  * \param argv values in the row
358  * \param columnNames names and types of the columns
359  * \retval 0 on success.
360  * \retval 1 if an error occurred.
361  * \see rt_multi_cfg_entry_args
362  * \see realtime_multi_handler()
363  */
364 static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv,
365  char **columnNames);
366 
367 /*!
368  * \brief Asterisk callback function for RealTime configuration.
369  *
370  * This function performs the same actions as realtime_handler() except
371  * that it can store variables per category, and can return several
372  * categories.
373  *
374  * \param database the database to use (ignored)
375  * \param table the table to use
376  * \param ap list of parameters and values to match
377  * \retval a struct ast_config object storing categories and variables.
378  * \retval NULL if an error occurred.
379  *
380  * \see add_rt_multi_cfg_entry()
381  */
382 static struct ast_config * realtime_multi_handler(const char *database,
383  const char *table, va_list ap);
384 
385 /*!
386  * \brief Asterisk callback function for RealTime configuration (variable
387  * update).
388  *
389  * Asterisk will call this function each time a variable has been modified
390  * internally and must be updated in the backend engine. keyfield and entity
391  * are used to find the row to update, e.g. <code>UPDATE table SET ... WHERE
392  * keyfield = 'entity';</code>. ap is a list of parameters and values with the
393  * same format as the other realtime functions.
394  *
395  * \param database the database to use (ignored)
396  * \param table the table to use
397  * \param keyfield the column of the matching cell
398  * \param entity the value of the matching cell
399  * \param ap list of parameters and new values to update in the database
400  * \retval the number of affected rows.
401  * \retval -1 if an error occurred.
402  */
403 static int realtime_update_handler(const char *database, const char *table,
404  const char *keyfield, const char *entity, va_list ap);
405 static int realtime_update2_handler(const char *database, const char *table,
406  va_list ap);
407 
408 /*!
409  * \brief Asterisk callback function for RealTime configuration (variable
410  * create/store).
411  *
412  * Asterisk will call this function each time a variable has been created
413  * internally and must be stored in the backend engine.
414  * are used to find the row to update, e.g. ap is a list of parameters and
415  * values with the same format as the other realtime functions.
416  *
417  * \param database the database to use (ignored)
418  * \param table the table to use
419  * \param ap list of parameters and new values to insert into the database
420  * \retval the rowid of inserted row.
421  * \retval -1 if an error occurred.
422  */
423 static int realtime_store_handler(const char *database, const char *table,
424  va_list ap);
425 
426 /*!
427  * \brief Asterisk callback function for RealTime configuration (destroys
428  * variable).
429  *
430  * Asterisk will call this function each time a variable has been destroyed
431  * internally and must be removed from the backend engine. keyfield and entity
432  * are used to find the row to delete, e.g. <code>DELETE FROM table WHERE
433  * keyfield = 'entity';</code>. ap is a list of parameters and values with the
434  * same format as the other realtime functions.
435  *
436  * \param database the database to use (ignored)
437  * \param table the table to use
438  * \param keyfield the column of the matching cell
439  * \param entity the value of the matching cell
440  * \param ap list of additional parameters for cell matching
441  * \retval the number of affected rows.
442  * \retval -1 if an error occurred.
443  */
444 static int realtime_destroy_handler(const char *database, const char *table,
445  const char *keyfield, const char *entity, va_list ap);
446 
447 /*!
448  * \brief Asterisk callback function for the CLI status command.
449  *
450  * \param e CLI command
451  * \param cmd
452  * \param a CLI argument list
453  * \return RESULT_SUCCESS
454  */
455 static char *handle_cli_show_sqlite_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
456 static char *handle_cli_sqlite_show_tables(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
457 
458 static int realtime_require_handler(const char *database, const char *table, va_list ap);
459 static int realtime_unload_handler(const char *unused, const char *tablename);
460 
461 /*! The SQLite database object. */
462 static sqlite *db;
463 
464 /*! Set to 1 if CDR support is enabled. */
465 static int use_cdr;
466 
467 /*! Set to 1 if the CDR callback function was registered. */
468 static int cdr_registered;
469 
470 /*! Set to 1 if the CLI status command callback function was registered. */
472 
473 /*! The path of the database file. */
474 static char *dbfile;
475 
476 /*! The name of the static configuration table. */
477 static char *config_table;
478 
479 /*! The name of the table used to store CDR entries. */
480 static char *cdr_table;
481 
482 /*!
483  * The structure specifying all callback functions used by Asterisk for static
484  * and RealTime configuration.
485  */
487 {
489  .load_func = config_handler,
490  .realtime_func = realtime_handler,
491  .realtime_multi_func = realtime_multi_handler,
492  .store_func = realtime_store_handler,
493  .destroy_func = realtime_destroy_handler,
494  .update_func = realtime_update_handler,
495  .update2_func = realtime_update2_handler,
496  .require_func = realtime_require_handler,
497  .unload_func = realtime_unload_handler,
498 };
499 
500 /*!
501  * The mutex used to prevent simultaneous access to the SQLite database.
502  */
504 
505 /*!
506  * Structure containing details and callback functions for the CLI status
507  * command.
508  */
509 static struct ast_cli_entry cli_status[] = {
510  AST_CLI_DEFINE(handle_cli_show_sqlite_status, "Show status information about the SQLite 2 driver"),
511  AST_CLI_DEFINE(handle_cli_sqlite_show_tables, "Cached table information about the SQLite 2 driver"),
512 };
513 
515  char *name;
516  char *type;
517  unsigned char isint; /*!< By definition, only INTEGER PRIMARY KEY is an integer; everything else is a string. */
519 };
520 
522  char *name;
524  AST_RWLIST_ENTRY(sqlite_cache_tables) list;
525 };
526 
527 static AST_RWLIST_HEAD_STATIC(sqlite_tables, sqlite_cache_tables);
528 
529 /*
530  * Taken from Asterisk 1.2 cdr_sqlite.so.
531  */
532 
533 /*! SQL query format to create the CDR table if non existent. */
534 static char *sql_create_cdr_table =
535 "CREATE TABLE '%q' (\n"
536 " id INTEGER,\n"
537 " clid VARCHAR(80) NOT NULL DEFAULT '',\n"
538 " src VARCHAR(80) NOT NULL DEFAULT '',\n"
539 " dst VARCHAR(80) NOT NULL DEFAULT '',\n"
540 " dcontext VARCHAR(80) NOT NULL DEFAULT '',\n"
541 " channel VARCHAR(80) NOT NULL DEFAULT '',\n"
542 " dstchannel VARCHAR(80) NOT NULL DEFAULT '',\n"
543 " lastapp VARCHAR(80) NOT NULL DEFAULT '',\n"
544 " lastdata VARCHAR(80) NOT NULL DEFAULT '',\n"
545 " start DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\n"
546 " answer DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\n"
547 " end DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\n"
548 " duration INT(11) NOT NULL DEFAULT 0,\n"
549 " billsec INT(11) NOT NULL DEFAULT 0,\n"
550 " disposition VARCHAR(45) NOT NULL DEFAULT '',\n"
551 " amaflags INT(11) NOT NULL DEFAULT 0,\n"
552 " accountcode VARCHAR(20) NOT NULL DEFAULT '',\n"
553 " uniqueid VARCHAR(32) NOT NULL DEFAULT '',\n"
554 " userfield VARCHAR(255) NOT NULL DEFAULT '',\n"
555 " PRIMARY KEY (id)\n"
556 ");";
557 
558 /*!
559  * SQL query format to describe the table structure
560  */
561 #define sql_table_structure "SELECT sql FROM sqlite_master WHERE type='table' AND tbl_name='%s'"
562 
563 /*!
564  * SQL query format to fetch the static configuration of a file.
565  * Rows must be sorted by category.
566  *
567  * \see add_cfg_entry()
568  */
569 #define sql_get_config_table \
570  "SELECT *" \
571  " FROM '%q'" \
572  " WHERE filename = '%q' AND commented = 0" \
573  " ORDER BY cat_metric ASC, var_metric ASC;"
574 
575 static void free_table(struct sqlite_cache_tables *tblptr)
576 {
577  struct sqlite_cache_columns *col;
578 
579  /* Obtain a write lock to ensure there are no read locks outstanding */
580  AST_RWLIST_WRLOCK(&(tblptr->columns));
581  while ((col = AST_RWLIST_REMOVE_HEAD(&(tblptr->columns), list))) {
582  ast_free(col);
583  }
584  AST_RWLIST_UNLOCK(&(tblptr->columns));
585  AST_RWLIST_HEAD_DESTROY(&(tblptr->columns));
586  ast_free(tblptr);
587 }
588 
589 static int find_table_cb(void *vtblptr, int argc, char **argv, char **columnNames)
590 {
591  struct sqlite_cache_tables *tblptr = vtblptr;
592  char *sql = ast_strdupa(argv[0]), *start, *end, *type, *remainder;
593  int i;
595  AST_APP_ARG(ld)[100]; /* This means we support up to 100 columns per table */
596  );
597  struct sqlite_cache_columns *col;
598 
599  /* This is really fun. We get to parse an SQL statement to figure out
600  * what columns are in the table.
601  */
602  if ((start = strchr(sql, '(')) && (end = strrchr(sql, ')'))) {
603  start++;
604  *end = '\0';
605  } else {
606  /* Abort */
607  return -1;
608  }
609 
610  AST_STANDARD_APP_ARGS(fie, start);
611  for (i = 0; i < fie.argc; i++) {
612  fie.ld[i] = ast_skip_blanks(fie.ld[i]);
613  ast_debug(5, "Found field: %s\n", fie.ld[i]);
614  if (strncasecmp(fie.ld[i], "PRIMARY KEY", 11) == 0 && (start = strchr(fie.ld[i], '(')) && (end = strchr(fie.ld[i], ')'))) {
615  *end = '\0';
616  AST_RWLIST_TRAVERSE(&(tblptr->columns), col, list) {
617  if (strcasecmp(start + 1, col->name) == 0 && strcasestr(col->type, "INTEGER")) {
618  col->isint = 1;
619  }
620  }
621  continue;
622  }
623  /* type delimiter could be any space character */
624  for (type = fie.ld[i]; *type > 32; type++);
625  *type++ = '\0';
626  type = ast_skip_blanks(type);
627  for (remainder = type; *remainder > 32; remainder++);
628  *remainder = '\0';
629  if (!(col = ast_calloc(1, sizeof(*col) + strlen(fie.ld[i]) + strlen(type) + 2))) {
630  return -1;
631  }
632  col->name = (char *)col + sizeof(*col);
633  col->type = (char *)col + sizeof(*col) + strlen(fie.ld[i]) + 1;
634  strcpy(col->name, fie.ld[i]); /* SAFE */
635  strcpy(col->type, type); /* SAFE */
636  if (strcasestr(col->type, "INTEGER") && strcasestr(col->type, "PRIMARY KEY")) {
637  col->isint = 1;
638  }
639  AST_LIST_INSERT_TAIL(&(tblptr->columns), col, list);
640  }
641  return 0;
642 }
643 
644 static struct sqlite_cache_tables *find_table(const char *tablename)
645 {
646  struct sqlite_cache_tables *tblptr;
647  int i, err;
648  char *sql, *errstr = NULL;
649 
650  AST_RWLIST_RDLOCK(&sqlite_tables);
651 
652  for (i = 0; i < 2; i++) {
653  AST_RWLIST_TRAVERSE(&sqlite_tables, tblptr, list) {
654  if (strcmp(tblptr->name, tablename) == 0) {
655  break;
656  }
657  }
658  if (tblptr) {
659  AST_RWLIST_RDLOCK(&(tblptr->columns));
660  AST_RWLIST_UNLOCK(&sqlite_tables);
661  return tblptr;
662  }
663 
664  if (i == 0) {
665  AST_RWLIST_UNLOCK(&sqlite_tables);
666  AST_RWLIST_WRLOCK(&sqlite_tables);
667  }
668  }
669 
670  /* Table structure not cached; build the structure now */
671  if (ast_asprintf(&sql, sql_table_structure, tablename) < 0) {
672  sql = NULL;
673  }
674  if (!(tblptr = ast_calloc(1, sizeof(*tblptr) + strlen(tablename) + 1))) {
675  AST_RWLIST_UNLOCK(&sqlite_tables);
676  ast_log(LOG_ERROR, "Memory error. Cannot cache table '%s'\n", tablename);
677  ast_free(sql);
678  return NULL;
679  }
680  tblptr->name = (char *)tblptr + sizeof(*tblptr);
681  strcpy(tblptr->name, tablename); /* SAFE */
682  AST_RWLIST_HEAD_INIT(&(tblptr->columns));
683 
684  ast_debug(1, "About to query table structure: %s\n", sql);
685 
687  if ((err = sqlite_exec(db, sql, find_table_cb, tblptr, &errstr))) {
689  ast_log(LOG_WARNING, "SQLite error %d: %s\n", err, errstr);
690  ast_free(errstr);
691  free_table(tblptr);
692  AST_RWLIST_UNLOCK(&sqlite_tables);
693  ast_free(sql);
694  return NULL;
695  }
697  ast_free(sql);
698 
699  if (AST_LIST_EMPTY(&(tblptr->columns))) {
700  free_table(tblptr);
701  AST_RWLIST_UNLOCK(&sqlite_tables);
702  return NULL;
703  }
704 
705  AST_RWLIST_INSERT_TAIL(&sqlite_tables, tblptr, list);
706  AST_RWLIST_RDLOCK(&(tblptr->columns));
707  AST_RWLIST_UNLOCK(&sqlite_tables);
708  return tblptr;
709 }
710 
711 #define release_table(a) AST_RWLIST_UNLOCK(&((a)->columns))
712 
713 static int set_var(char **var, const char *name, const char *value)
714 {
715  if (*var)
716  ast_free(*var);
717 
718  *var = ast_strdup(value);
719 
720  if (!*var) {
721  ast_log(LOG_WARNING, "Unable to allocate variable %s\n", name);
722  return 1;
723  }
724 
725  return 0;
726 }
727 
728 static int check_vars(void)
729 {
730  if (!dbfile) {
731  ast_log(LOG_ERROR, "Required parameter undefined: dbfile\n");
732  return 1;
733  }
734 
735  use_cdr = (cdr_table != NULL);
736 
737  return 0;
738 }
739 
740 static int load_config(void)
741 {
742  struct ast_config *config;
743  struct ast_variable *var;
744  int error;
745  struct ast_flags config_flags = { 0 };
746 
747  config = ast_config_load(RES_CONFIG_SQLITE_CONF_FILE, config_flags);
748 
749  if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
750  ast_log(LOG_ERROR, "Unable to load " RES_CONFIG_SQLITE_CONF_FILE "\n");
751  return 1;
752  }
753 
754  for (var = ast_variable_browse(config, "general"); var; var = var->next) {
755  if (!strcasecmp(var->name, "dbfile"))
756  SET_VAR(config, dbfile, var);
757  else if (!strcasecmp(var->name, "config_table"))
758  SET_VAR(config, config_table, var);
759  else if (!strcasecmp(var->name, "cdr_table")) {
760  SET_VAR(config, cdr_table, var);
761  } else
762  ast_log(LOG_WARNING, "Unknown parameter : %s\n", var->name);
763  }
764 
765  ast_config_destroy(config);
766  error = check_vars();
767 
768  if (error) {
769  unload_config();
770  return 1;
771  }
772 
773  return 0;
774 }
775 
776 static void unload_config(void)
777 {
778  struct sqlite_cache_tables *tbl;
779  ast_free(dbfile);
780  dbfile = NULL;
781  ast_free(config_table);
782  config_table = NULL;
783  ast_free(cdr_table);
784  cdr_table = NULL;
785  AST_RWLIST_WRLOCK(&sqlite_tables);
786  while ((tbl = AST_RWLIST_REMOVE_HEAD(&sqlite_tables, list))) {
787  free_table(tbl);
788  }
789  AST_RWLIST_UNLOCK(&sqlite_tables);
790 }
791 
792 static int cdr_handler(struct ast_cdr *cdr)
793 {
794  char *errormsg = NULL, *tmp, workspace[500];
795  int error, scannum;
796  struct sqlite_cache_tables *tbl = find_table(cdr_table);
797  struct sqlite_cache_columns *col;
798  struct ast_str *sql1 = ast_str_create(160), *sql2 = ast_str_create(16);
799  int first = 1;
800 
801  if (!tbl) {
802  ast_log(LOG_WARNING, "No such table: %s\n", cdr_table);
803  return -1;
804  }
805 
806  ast_str_set(&sql1, 0, "INSERT INTO %s (", cdr_table);
807  ast_str_set(&sql2, 0, ") VALUES (");
808 
809  AST_RWLIST_TRAVERSE(&(tbl->columns), col, list) {
810  if (col->isint) {
811  ast_cdr_getvar(cdr, col->name, &tmp, workspace, sizeof(workspace), 0, 1);
812  if (!tmp) {
813  continue;
814  }
815  if (sscanf(tmp, "%30d", &scannum) == 1) {
816  ast_str_append(&sql1, 0, "%s%s", first ? "" : ",", col->name);
817  ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", scannum);
818  }
819  } else {
820  ast_cdr_getvar(cdr, col->name, &tmp, workspace, sizeof(workspace), 0, 0);
821  if (!tmp) {
822  continue;
823  }
824  ast_str_append(&sql1, 0, "%s%s", first ? "" : ",", col->name);
825  tmp = sqlite_mprintf("%Q", tmp);
826  ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", tmp);
827  sqlite_freemem(tmp);
828  }
829  first = 0;
830  }
831  release_table(tbl);
832 
833  ast_str_append(&sql1, 0, "%s)", ast_str_buffer(sql2));
834  ast_free(sql2);
835 
836  ast_debug(1, "SQL query: %s\n", ast_str_buffer(sql1));
837 
839 
841  error = sqlite_exec(db, ast_str_buffer(sql1), NULL, NULL, &errormsg);
842  RES_CONFIG_SQLITE_END(error)
843 
845 
846  ast_free(sql1);
847 
848  if (error) {
849  ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
850  sqlite_freemem(errormsg);
851  return 1;
852  }
853  sqlite_freemem(errormsg);
854 
855  return 0;
856 }
857 
858 static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
859 {
860  struct cfg_entry_args *args;
861  struct ast_variable *var;
862 
863  if (argc != RES_CONFIG_SQLITE_CONFIG_COLUMNS) {
864  ast_log(LOG_WARNING, "Corrupt table\n");
865  return 1;
866  }
867 
868  args = arg;
869 
870  if (!strcmp(argv[RES_CONFIG_SQLITE_CONFIG_VAR_NAME], "#include")) {
871  struct ast_config *cfg;
872  char *val;
873 
875  cfg = ast_config_internal_load(val, args->cfg, args->flags, "", args->who_asked);
876 
877  if (!cfg) {
878  ast_log(LOG_WARNING, "Unable to include %s\n", val);
879  return 1;
880  } else {
881  args->cfg = cfg;
882  return 0;
883  }
884  }
885 
886  if (!args->cat_name || strcmp(args->cat_name, argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY])) {
887  args->cat = ast_category_new(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY], "", 99999);
888 
889  if (!args->cat) {
890  ast_log(LOG_WARNING, "Unable to allocate category\n");
891  return 1;
892  }
893 
894  ast_free(args->cat_name);
895  args->cat_name = ast_strdup(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY]);
896 
897  if (!args->cat_name) {
898  ast_category_destroy(args->cat);
899  return 1;
900  }
901 
902  ast_category_append(args->cfg, args->cat);
903  }
904 
905  var = ast_variable_new(argv[RES_CONFIG_SQLITE_CONFIG_VAR_NAME], argv[RES_CONFIG_SQLITE_CONFIG_VAR_VAL], "");
906 
907  if (!var) {
908  ast_log(LOG_WARNING, "Unable to allocate variable\n");
909  return 1;
910  }
911 
912  ast_variable_append(args->cat, var);
913 
914  return 0;
915 }
916 
917 static struct ast_config *config_handler(const char *database, const char *table, const char *file,
918  struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked)
919 {
920  struct cfg_entry_args args;
921  char *query, *errormsg = NULL;
922  int error;
923 
924  if (!config_table) {
925  if (!table) {
926  ast_log(LOG_ERROR, "Table name unspecified\n");
927  return NULL;
928  }
929  } else
930  table = config_table;
931 
932  query = sqlite_mprintf(sql_get_config_table, table, file);
933 
934  if (!query) {
935  ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
936  return NULL;
937  }
938 
939  ast_debug(1, "SQL query: %s\n", query);
940  args.cfg = cfg;
941  args.cat = NULL;
942  args.cat_name = NULL;
943  args.flags = flags;
944  args.who_asked = who_asked;
945 
947 
949  error = sqlite_exec(db, query, add_cfg_entry, &args, &errormsg);
950  RES_CONFIG_SQLITE_END(error)
951 
953 
954  ast_free(args.cat_name);
955  sqlite_freemem(query);
956 
957  if (error) {
958  ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
959  sqlite_freemem(errormsg);
960  return NULL;
961  }
962  sqlite_freemem(errormsg);
963 
964  return cfg;
965 }
966 
967 static size_t get_params(va_list ap, const char ***params_ptr, const char ***vals_ptr, int warn)
968 {
969  const char **tmp, *param, *val, **params, **vals;
970  size_t params_count;
971 
972  params = NULL;
973  vals = NULL;
974  params_count = 0;
975 
976  while ((param = va_arg(ap, const char *)) && (val = va_arg(ap, const char *))) {
977  if (!(tmp = ast_realloc(params, (params_count + 1) * sizeof(char *)))) {
978  ast_free(params);
979  ast_free(vals);
980  return 0;
981  }
982  params = tmp;
983 
984  if (!(tmp = ast_realloc(vals, (params_count + 1) * sizeof(char *)))) {
985  ast_free(params);
986  ast_free(vals);
987  return 0;
988  }
989  vals = tmp;
990 
991  params[params_count] = param;
992  vals[params_count] = val;
993  params_count++;
994  }
995 
996  if (params_count > 0) {
997  *params_ptr = params;
998  *vals_ptr = vals;
999  } else if (warn) {
1000  ast_log(LOG_WARNING, "1 parameter and 1 value at least required\n");
1001  }
1002 
1003  return params_count;
1004 }
1005 
1006 static int add_rt_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
1007 {
1008  struct rt_cfg_entry_args *args;
1009  struct ast_variable *var;
1010  int i;
1011 
1012  args = arg;
1013 
1014  for (i = 0; i < argc; i++) {
1015  if (!argv[i])
1016  continue;
1017 
1018  if (!(var = ast_variable_new(columnNames[i], argv[i], "")))
1019  return 1;
1020 
1021  if (!args->var)
1022  args->var = var;
1023 
1024  if (!args->last)
1025  args->last = var;
1026  else {
1027  args->last->next = var;
1028  args->last = var;
1029  }
1030  }
1031 
1032  return 0;
1033 }
1034 
1035 static struct ast_variable * realtime_handler(const char *database, const char *table, va_list ap)
1036 {
1037  char *query, *errormsg = NULL, *op, *tmp_str;
1038  struct rt_cfg_entry_args args;
1039  const char **params, **vals;
1040  size_t params_count;
1041  int error;
1042 
1043  if (!table) {
1044  ast_log(LOG_WARNING, "Table name unspecified\n");
1045  return NULL;
1046  }
1047 
1048  params_count = get_params(ap, &params, &vals, 1);
1049 
1050  if (params_count == 0)
1051  return NULL;
1052 
1053  op = (strchr(params[0], ' ') == NULL) ? " =" : "";
1054 
1055 /* \cond DOXYGEN_CAN_PARSE_THIS */
1056 #undef QUERY
1057 #define QUERY "SELECT * FROM '%q' WHERE%s %q%s '%q'"
1058 /* \endcond */
1059 
1060  query = sqlite_mprintf(QUERY, table, (config_table && !strcmp(config_table, table)) ? " commented = 0 AND" : "", params[0], op, vals[0]);
1061 
1062  if (!query) {
1063  ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
1064  ast_free(params);
1065  ast_free(vals);
1066  return NULL;
1067  }
1068 
1069  if (params_count > 1) {
1070  size_t i;
1071 
1072  for (i = 1; i < params_count; i++) {
1073  op = (strchr(params[i], ' ') == NULL) ? " =" : "";
1074  tmp_str = sqlite_mprintf("%s AND %q%s '%q'", query, params[i], op, vals[i]);
1075  sqlite_freemem(query);
1076 
1077  if (!tmp_str) {
1078  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1079  ast_free(params);
1080  ast_free(vals);
1081  return NULL;
1082  }
1083 
1084  query = tmp_str;
1085  }
1086  }
1087 
1088  ast_free(params);
1089  ast_free(vals);
1090 
1091  tmp_str = sqlite_mprintf("%s LIMIT 1;", query);
1092  sqlite_freemem(query);
1093 
1094  if (!tmp_str) {
1095  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1096  return NULL;
1097  }
1098 
1099  query = tmp_str;
1100  ast_debug(1, "SQL query: %s\n", query);
1101  args.var = NULL;
1102  args.last = NULL;
1103 
1105 
1107  error = sqlite_exec(db, query, add_rt_cfg_entry, &args, &errormsg);
1108  RES_CONFIG_SQLITE_END(error)
1109 
1111 
1112  sqlite_freemem(query);
1113 
1114  if (error) {
1115  ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
1116  sqlite_freemem(errormsg);
1117  ast_variables_destroy(args.var);
1118  return NULL;
1119  }
1120  sqlite_freemem(errormsg);
1121 
1122  return args.var;
1123 }
1124 
1125 static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
1126 {
1127  struct rt_multi_cfg_entry_args *args;
1128  struct ast_category *cat;
1129  struct ast_variable *var;
1130  char *cat_name;
1131  size_t i;
1132 
1133  args = arg;
1134  cat_name = NULL;
1135 
1136  /*
1137  * cat_name should always be set here, since initfield is forged from
1138  * params[0] in realtime_multi_handler(), which is a search parameter
1139  * of the SQL query.
1140  */
1141  for (i = 0; i < argc; i++) {
1142  if (!strcmp(args->initfield, columnNames[i]))
1143  cat_name = argv[i];
1144  }
1145 
1146  if (!cat_name) {
1147  ast_log(LOG_ERROR, "Bogus SQL results, cat_name is NULL !\n");
1148  return 1;
1149  }
1150 
1151  if (!(cat = ast_category_new(cat_name, "", 99999))) {
1152  ast_log(LOG_WARNING, "Unable to allocate category\n");
1153  return 1;
1154  }
1155 
1156  ast_category_append(args->cfg, cat);
1157 
1158  for (i = 0; i < argc; i++) {
1159  if (!argv[i]) {
1160  continue;
1161  }
1162 
1163  if (!(var = ast_variable_new(columnNames[i], argv[i], ""))) {
1164  ast_log(LOG_WARNING, "Unable to allocate variable\n");
1165  return 1;
1166  }
1167 
1168  ast_variable_append(cat, var);
1169  }
1170 
1171  return 0;
1172 }
1173 
1174 static struct ast_config *realtime_multi_handler(const char *database,
1175  const char *table, va_list ap)
1176 {
1177  char *query, *errormsg = NULL, *op, *tmp_str, *initfield;
1178  struct rt_multi_cfg_entry_args args;
1179  const char **params, **vals;
1180  struct ast_config *cfg;
1181  size_t params_count;
1182  int error;
1183 
1184  if (!table) {
1185  ast_log(LOG_WARNING, "Table name unspecified\n");
1186  return NULL;
1187  }
1188 
1189  if (!(cfg = ast_config_new())) {
1190  ast_log(LOG_WARNING, "Unable to allocate configuration structure\n");
1191  return NULL;
1192  }
1193 
1194  if (!(params_count = get_params(ap, &params, &vals, 1))) {
1195  ast_config_destroy(cfg);
1196  return NULL;
1197  }
1198 
1199  if (!(initfield = ast_strdup(params[0]))) {
1200  ast_config_destroy(cfg);
1201  ast_free(params);
1202  ast_free(vals);
1203  return NULL;
1204  }
1205 
1206  tmp_str = strchr(initfield, ' ');
1207 
1208  if (tmp_str)
1209  *tmp_str = '\0';
1210 
1211  op = (!strchr(params[0], ' ')) ? " =" : "";
1212 
1213  /*
1214  * Asterisk sends us an already escaped string when searching for
1215  * "exten LIKE" (uh!). Handle it separately.
1216  */
1217  tmp_str = (!strcmp(vals[0], "\\_%")) ? "_%" : (char *)vals[0];
1218 
1219 /* \cond DOXYGEN_CAN_PARSE_THIS */
1220 #undef QUERY
1221 #define QUERY "SELECT * FROM '%q' WHERE%s %q%s '%q'"
1222 /* \endcond */
1223 
1224  if (!(query = sqlite_mprintf(QUERY, table, (config_table && !strcmp(config_table, table)) ? " commented = 0 AND" : "", params[0], op, tmp_str))) {
1225  ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
1226  ast_config_destroy(cfg);
1227  ast_free(params);
1228  ast_free(vals);
1229  ast_free(initfield);
1230  return NULL;
1231  }
1232 
1233  if (params_count > 1) {
1234  size_t i;
1235 
1236  for (i = 1; i < params_count; i++) {
1237  op = (!strchr(params[i], ' ')) ? " =" : "";
1238  tmp_str = sqlite_mprintf("%s AND %q%s '%q'", query, params[i], op, vals[i]);
1239  sqlite_freemem(query);
1240 
1241  if (!tmp_str) {
1242  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1243  ast_config_destroy(cfg);
1244  ast_free(params);
1245  ast_free(vals);
1246  ast_free(initfield);
1247  return NULL;
1248  }
1249 
1250  query = tmp_str;
1251  }
1252  }
1253 
1254  ast_free(params);
1255  ast_free(vals);
1256 
1257  if (!(tmp_str = sqlite_mprintf("%s ORDER BY %q;", query, initfield))) {
1258  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1259  sqlite_freemem(query);
1260  ast_config_destroy(cfg);
1261  ast_free(initfield);
1262  return NULL;
1263  }
1264 
1265  sqlite_freemem(query);
1266  query = tmp_str;
1267  ast_debug(1, "SQL query: %s\n", query);
1268  args.cfg = cfg;
1269  args.initfield = initfield;
1270 
1272 
1274  error = sqlite_exec(db, query, add_rt_multi_cfg_entry, &args, &errormsg);
1275  RES_CONFIG_SQLITE_END(error)
1276 
1278 
1279  sqlite_freemem(query);
1280  ast_free(initfield);
1281 
1282  if (error) {
1283  ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
1284  sqlite_freemem(errormsg);
1285  ast_config_destroy(cfg);
1286  return NULL;
1287  }
1288  sqlite_freemem(errormsg);
1289 
1290  return cfg;
1291 }
1292 
1293 static int realtime_update_handler(const char *database, const char *table,
1294  const char *keyfield, const char *entity, va_list ap)
1295 {
1296  char *query, *errormsg = NULL, *tmp_str;
1297  const char **params, **vals;
1298  size_t params_count;
1299  int error, rows_num;
1300 
1301  if (!table) {
1302  ast_log(LOG_WARNING, "Table name unspecified\n");
1303  return -1;
1304  }
1305 
1306  if (!(params_count = get_params(ap, &params, &vals, 1)))
1307  return -1;
1308 
1309 /* \cond DOXYGEN_CAN_PARSE_THIS */
1310 #undef QUERY
1311 #define QUERY "UPDATE '%q' SET %q = '%q'"
1312 /* \endcond */
1313 
1314  if (!(query = sqlite_mprintf(QUERY, table, params[0], vals[0]))) {
1315  ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
1316  ast_free(params);
1317  ast_free(vals);
1318  return -1;
1319  }
1320 
1321  if (params_count > 1) {
1322  size_t i;
1323 
1324  for (i = 1; i < params_count; i++) {
1325  tmp_str = sqlite_mprintf("%s, %q = '%q'", query, params[i], vals[i]);
1326  sqlite_freemem(query);
1327 
1328  if (!tmp_str) {
1329  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1330  ast_free(params);
1331  ast_free(vals);
1332  return -1;
1333  }
1334 
1335  query = tmp_str;
1336  }
1337  }
1338 
1339  ast_free(params);
1340  ast_free(vals);
1341 
1342  if (!(tmp_str = sqlite_mprintf("%s WHERE %q = '%q';", query, keyfield, entity))) {
1343  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1344  sqlite_freemem(query);
1345  return -1;
1346  }
1347 
1348  sqlite_freemem(query);
1349  query = tmp_str;
1350  ast_debug(1, "SQL query: %s\n", query);
1351 
1353 
1355  error = sqlite_exec(db, query, NULL, NULL, &errormsg);
1356  RES_CONFIG_SQLITE_END(error)
1357 
1358  if (!error)
1359  rows_num = sqlite_changes(db);
1360  else
1361  rows_num = -1;
1362 
1364 
1365  sqlite_freemem(query);
1366 
1367  if (error) {
1368  ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
1369  }
1370  sqlite_freemem(errormsg);
1371 
1372  return rows_num;
1373 }
1374 
1375 static int realtime_update2_handler(const char *database, const char *table,
1376  va_list ap)
1377 {
1378  char *errormsg = NULL, *tmp1, *tmp2;
1379  int error, rows_num, first = 1;
1380  struct ast_str *sql = ast_str_thread_get(&sql_buf, 100);
1381  struct ast_str *where = ast_str_thread_get(&where_buf, 100);
1382  const char *param, *value;
1383 
1384  if (!table) {
1385  ast_log(LOG_WARNING, "Table name unspecified\n");
1386  return -1;
1387  }
1388 
1389  if (!sql) {
1390  return -1;
1391  }
1392 
1393  ast_str_set(&sql, 0, "UPDATE %s SET", table);
1394  ast_str_set(&where, 0, " WHERE");
1395 
1396  while ((param = va_arg(ap, const char *))) {
1397  value = va_arg(ap, const char *);
1398  ast_str_append(&where, 0, "%s %s = %s",
1399  first ? "" : " AND",
1400  tmp1 = sqlite_mprintf("%q", param),
1401  tmp2 = sqlite_mprintf("%Q", value));
1402  sqlite_freemem(tmp1);
1403  sqlite_freemem(tmp2);
1404  first = 0;
1405  }
1406 
1407  if (first) {
1408  ast_log(LOG_ERROR, "No criteria specified on update to '%s@%s'!\n", table, database);
1409  return -1;
1410  }
1411 
1412  first = 1;
1413  while ((param = va_arg(ap, const char *))) {
1414  value = va_arg(ap, const char *);
1415  ast_str_append(&sql, 0, "%s %s = %s",
1416  first ? "" : ",",
1417  tmp1 = sqlite_mprintf("%q", param),
1418  tmp2 = sqlite_mprintf("%Q", value));
1419  sqlite_freemem(tmp1);
1420  sqlite_freemem(tmp2);
1421  first = 0;
1422  }
1423 
1424  ast_str_append(&sql, 0, " %s", ast_str_buffer(where));
1425  ast_debug(1, "SQL query: %s\n", ast_str_buffer(sql));
1426 
1428 
1430  error = sqlite_exec(db, ast_str_buffer(sql), NULL, NULL, &errormsg);
1431  RES_CONFIG_SQLITE_END(error)
1432 
1433  if (!error) {
1434  rows_num = sqlite_changes(db);
1435  } else {
1436  rows_num = -1;
1437  }
1438 
1440 
1441  if (error) {
1442  ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
1443  }
1444  sqlite_freemem(errormsg);
1445 
1446  return rows_num;
1447 }
1448 
1449 static int realtime_store_handler(const char *database, const char *table, va_list ap)
1450 {
1451  char *errormsg = NULL, *tmp_str, *tmp_keys = NULL, *tmp_keys2 = NULL, *tmp_vals = NULL, *tmp_vals2 = NULL;
1452  const char **params, **vals;
1453  size_t params_count;
1454  int error, rows_id;
1455  size_t i;
1456 
1457  if (!table) {
1458  ast_log(LOG_WARNING, "Table name unspecified\n");
1459  return -1;
1460  }
1461 
1462  if (!(params_count = get_params(ap, &params, &vals, 1)))
1463  return -1;
1464 
1465 /* \cond DOXYGEN_CAN_PARSE_THIS */
1466 #undef QUERY
1467 #define QUERY "INSERT into '%q' (%s) VALUES (%s);"
1468 /* \endcond */
1469 
1470  for (i = 0; i < params_count; i++) {
1471  if ( tmp_keys2 ) {
1472  tmp_keys = sqlite_mprintf("%s, %q", tmp_keys2, params[i]);
1473  sqlite_freemem(tmp_keys2);
1474  } else {
1475  tmp_keys = sqlite_mprintf("%q", params[i]);
1476  }
1477  if (!tmp_keys) {
1478  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1479  sqlite_freemem(tmp_vals);
1480  ast_free(params);
1481  ast_free(vals);
1482  return -1;
1483  }
1484 
1485  if ( tmp_vals2 ) {
1486  tmp_vals = sqlite_mprintf("%s, '%q'", tmp_vals2, vals[i]);
1487  sqlite_freemem(tmp_vals2);
1488  } else {
1489  tmp_vals = sqlite_mprintf("'%q'", vals[i]);
1490  }
1491  if (!tmp_vals) {
1492  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1493  sqlite_freemem(tmp_keys);
1494  ast_free(params);
1495  ast_free(vals);
1496  return -1;
1497  }
1498 
1499 
1500  tmp_keys2 = tmp_keys;
1501  tmp_vals2 = tmp_vals;
1502  }
1503 
1504  ast_free(params);
1505  ast_free(vals);
1506 
1507  if (!(tmp_str = sqlite_mprintf(QUERY, table, tmp_keys, tmp_vals))) {
1508  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1509  sqlite_freemem(tmp_keys);
1510  sqlite_freemem(tmp_vals);
1511  return -1;
1512  }
1513 
1514  sqlite_freemem(tmp_keys);
1515  sqlite_freemem(tmp_vals);
1516 
1517  ast_debug(1, "SQL query: %s\n", tmp_str);
1518 
1520 
1522  error = sqlite_exec(db, tmp_str, NULL, NULL, &errormsg);
1523  RES_CONFIG_SQLITE_END(error)
1524 
1525  if (!error) {
1526  rows_id = sqlite_last_insert_rowid(db);
1527  } else {
1528  rows_id = -1;
1529  }
1530 
1532 
1533  sqlite_freemem(tmp_str);
1534 
1535  if (error) {
1536  ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
1537  }
1538  sqlite_freemem(errormsg);
1539 
1540  return rows_id;
1541 }
1542 
1543 static int realtime_destroy_handler(const char *database, const char *table,
1544  const char *keyfield, const char *entity, va_list ap)
1545 {
1546  char *query, *errormsg = NULL, *tmp_str;
1547  const char **params = NULL, **vals = NULL;
1548  size_t params_count;
1549  int error, rows_num;
1550  size_t i;
1551 
1552  if (!table) {
1553  ast_log(LOG_WARNING, "Table name unspecified\n");
1554  return -1;
1555  }
1556 
1557  params_count = get_params(ap, &params, &vals, 0);
1558 
1559 /* \cond DOXYGEN_CAN_PARSE_THIS */
1560 #undef QUERY
1561 #define QUERY "DELETE FROM '%q' WHERE"
1562 /* \endcond */
1563 
1564  if (!(query = sqlite_mprintf(QUERY, table))) {
1565  ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
1566  ast_free(params);
1567  ast_free(vals);
1568  return -1;
1569  }
1570 
1571  for (i = 0; i < params_count; i++) {
1572  tmp_str = sqlite_mprintf("%s %q = '%q' AND", query, params[i], vals[i]);
1573  sqlite_freemem(query);
1574 
1575  if (!tmp_str) {
1576  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1577  ast_free(params);
1578  ast_free(vals);
1579  return -1;
1580  }
1581 
1582  query = tmp_str;
1583  }
1584 
1585  ast_free(params);
1586  ast_free(vals);
1587  if (!(tmp_str = sqlite_mprintf("%s %q = '%q';", query, keyfield, entity))) {
1588  ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
1589  sqlite_freemem(query);
1590  return -1;
1591  }
1592  sqlite_freemem(query);
1593  query = tmp_str;
1594  ast_debug(1, "SQL query: %s\n", query);
1595 
1597 
1599  error = sqlite_exec(db, query, NULL, NULL, &errormsg);
1600  RES_CONFIG_SQLITE_END(error)
1601 
1602  if (!error) {
1603  rows_num = sqlite_changes(db);
1604  } else {
1605  rows_num = -1;
1606  }
1607 
1609 
1610  sqlite_freemem(query);
1611 
1612  if (error) {
1613  ast_log(LOG_WARNING, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
1614  }
1615  sqlite_freemem(errormsg);
1616 
1617  return rows_num;
1618 }
1619 
1620 static int realtime_require_handler(const char *unused, const char *tablename, va_list ap)
1621 {
1622  struct sqlite_cache_tables *tbl = find_table(tablename);
1623  struct sqlite_cache_columns *col;
1624  char *elm;
1625  int type, res = 0;
1626 
1627  if (!tbl) {
1628  return -1;
1629  }
1630 
1631  while ((elm = va_arg(ap, char *))) {
1632  type = va_arg(ap, require_type);
1633  va_arg(ap, int);
1634  /* Check if the field matches the criteria */
1635  AST_RWLIST_TRAVERSE(&tbl->columns, col, list) {
1636  if (strcmp(col->name, elm) == 0) {
1637  /* SQLite only has two types - the 32-bit integer field that
1638  * is the key column, and everything else (everything else
1639  * being a string).
1640  */
1641  if (col->isint && !ast_rq_is_int(type)) {
1642  ast_log(LOG_WARNING, "Realtime table %s: column '%s' is an integer field, but Asterisk requires that it not be!\n", tablename, col->name);
1643  res = -1;
1644  }
1645  break;
1646  }
1647  }
1648  if (!col) {
1649  ast_log(LOG_WARNING, "Realtime table %s requires column '%s', but that column does not exist!\n", tablename, elm);
1650  }
1651  }
1652  AST_RWLIST_UNLOCK(&(tbl->columns));
1653  return res;
1654 }
1655 
1656 static int realtime_unload_handler(const char *unused, const char *tablename)
1657 {
1658  struct sqlite_cache_tables *tbl;
1659  AST_RWLIST_WRLOCK(&sqlite_tables);
1660  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&sqlite_tables, tbl, list) {
1661  if (!strcasecmp(tbl->name, tablename)) {
1663  free_table(tbl);
1664  }
1665  }
1667  AST_RWLIST_UNLOCK(&sqlite_tables);
1668  return 0;
1669 }
1670 
1671 static char *handle_cli_show_sqlite_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1672 {
1673  switch (cmd) {
1674  case CLI_INIT:
1675  e->command = "sqlite show status";
1676  e->usage =
1677  "Usage: sqlite show status\n"
1678  " Show status information about the SQLite 2 driver\n";
1679  return NULL;
1680  case CLI_GENERATE:
1681  return NULL;
1682  }
1683 
1684  if (a->argc != 3)
1685  return CLI_SHOWUSAGE;
1686 
1687  ast_cli(a->fd, "SQLite database path: %s\n", dbfile);
1688  ast_cli(a->fd, "config_table: ");
1689 
1690  if (!config_table)
1691  ast_cli(a->fd, "unspecified, must be present in extconfig.conf\n");
1692  else
1693  ast_cli(a->fd, "%s\n", config_table);
1694 
1695  ast_cli(a->fd, "cdr_table: ");
1696 
1697  if (!cdr_table)
1698  ast_cli(a->fd, "unspecified, CDR support disabled\n");
1699  else
1700  ast_cli(a->fd, "%s\n", cdr_table);
1701 
1702  return CLI_SUCCESS;
1703 }
1704 
1705 static char *handle_cli_sqlite_show_tables(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1706 {
1707  struct sqlite_cache_tables *tbl;
1708  struct sqlite_cache_columns *col;
1709  int found = 0;
1710 
1711  switch (cmd) {
1712  case CLI_INIT:
1713  e->command = "sqlite show tables";
1714  e->usage =
1715  "Usage: sqlite show tables\n"
1716  " Show table information about the SQLite 2 driver\n";
1717  return NULL;
1718  case CLI_GENERATE:
1719  return NULL;
1720  }
1721 
1722  if (a->argc != 3)
1723  return CLI_SHOWUSAGE;
1724 
1725  AST_RWLIST_RDLOCK(&sqlite_tables);
1726  AST_RWLIST_TRAVERSE(&sqlite_tables, tbl, list) {
1727  found++;
1728  ast_cli(a->fd, "Table %s:\n", tbl->name);
1729  AST_RWLIST_TRAVERSE(&(tbl->columns), col, list) {
1730  fprintf(stderr, "%s\n", col->name);
1731  ast_cli(a->fd, " %20.20s %-30.30s\n", col->name, col->type);
1732  }
1733  }
1734  AST_RWLIST_UNLOCK(&sqlite_tables);
1735 
1736  if (!found) {
1737  ast_cli(a->fd, "No tables currently in cache\n");
1738  }
1739 
1740  return CLI_SUCCESS;
1741 }
1742 
1743 static int unload_module(void)
1744 {
1745  if (cli_status_registered)
1746  ast_cli_unregister_multiple(cli_status, ARRAY_LEN(cli_status));
1747 
1748  if (cdr_registered)
1750 
1751  ast_config_engine_deregister(&sqlite_engine);
1752 
1753  if (db)
1754  sqlite_close(db);
1755 
1756  unload_config();
1757 
1758  return 0;
1759 }
1760 
1761 static int load_module(void)
1762 {
1763  char *errormsg = NULL;
1764  int error;
1765 
1766  db = NULL;
1767  cdr_registered = 0;
1768  cli_status_registered = 0;
1769  dbfile = NULL;
1770  config_table = NULL;
1771  cdr_table = NULL;
1772  error = load_config();
1773 
1774  if (error)
1775  return AST_MODULE_LOAD_DECLINE;
1776 
1777  if (!(db = sqlite_open(dbfile, 0660, &errormsg))) {
1778  ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
1779  sqlite_freemem(errormsg);
1780  unload_module();
1781  return 1;
1782  }
1783 
1784  sqlite_freemem(errormsg);
1785  errormsg = NULL;
1786  ast_config_engine_register(&sqlite_engine);
1787 
1788  if (use_cdr) {
1789  char *query;
1790 
1791 /* \cond DOXYGEN_CAN_PARSE_THIS */
1792 #undef QUERY
1793 #define QUERY "SELECT COUNT(id) FROM %Q;"
1794 /* \endcond */
1795 
1796  query = sqlite_mprintf(QUERY, cdr_table);
1797 
1798  if (!query) {
1799  ast_log(LOG_ERROR, "Unable to allocate SQL query\n");
1800  unload_module();
1801  return 1;
1802  }
1803 
1804  ast_debug(1, "SQL query: %s\n", query);
1805 
1807  error = sqlite_exec(db, query, NULL, NULL, &errormsg);
1808  RES_CONFIG_SQLITE_END(error)
1809 
1810  sqlite_freemem(query);
1811 
1812  if (error) {
1813  /*
1814  * Unexpected error.
1815  */
1816  if (error != SQLITE_ERROR) {
1817  ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
1818  sqlite_freemem(errormsg);
1819  unload_module();
1820  return 1;
1821  }
1822 
1823  sqlite_freemem(errormsg);
1824  errormsg = NULL;
1825  query = sqlite_mprintf(sql_create_cdr_table, cdr_table);
1826 
1827  if (!query) {
1828  ast_log(LOG_ERROR, "Unable to allocate SQL query\n");
1829  unload_module();
1830  return 1;
1831  }
1832 
1833  ast_debug(1, "SQL query: %s\n", query);
1834 
1836  error = sqlite_exec(db, query, NULL, NULL, &errormsg);
1837  RES_CONFIG_SQLITE_END(error)
1838 
1839  sqlite_freemem(query);
1840 
1841  if (error) {
1842  ast_log(LOG_ERROR, "%s\n", S_OR(errormsg, sqlite_error_string(error)));
1843  sqlite_freemem(errormsg);
1844  unload_module();
1845  return 1;
1846  }
1847  }
1848  sqlite_freemem(errormsg);
1849  errormsg = NULL;
1850 
1852 
1853  if (error) {
1854  unload_module();
1855  return 1;
1856  }
1857 
1858  cdr_registered = 1;
1859  }
1860 
1861  error = ast_cli_register_multiple(cli_status, ARRAY_LEN(cli_status));
1862 
1863  if (error) {
1864  unload_module();
1865  return 1;
1866  }
1867 
1868  cli_status_registered = 1;
1869 
1870  return 0;
1871 }
1872 
1873 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Realtime SQLite configuration",
1874  .load = load_module,
1875  .unload = unload_module,
1876  .load_pri = AST_MODPRI_REALTIME_DRIVER,
1877 );
#define RES_CONFIG_SQLITE_CONF_FILE
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:81
static int find_table_cb(void *vtblptr, int argc, char **argv, char **columnNames)
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:383
char * initfield
static int realtime_destroy_handler(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap)
Asterisk callback function for RealTime configuration (destroys variable).
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
#define AST_RWLIST_HEAD_DESTROY(head)
Destroys an rwlist head structure.
Definition: linkedlists.h:652
static struct ast_threadstorage where_buf
static int set_var(char **var, const char *name, const char *value)
Allocate a variable.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_variable * realtime_handler(const char *database, const char *table, va_list ap)
Asterisk callback function for RealTime configuration.
#define RES_CONFIG_SQLITE_NAME
static const char config[]
Definition: cdr_csv.c:57
struct ast_category * cat
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int unload_module(void)
#define RES_CONFIG_SQLITE_DRIVER
static int amaflags
Definition: chan_iax2.c:386
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
static struct sqlite_cache_tables * find_table(const char *tablename)
struct ast_config * cfg
#define ast_strdup(a)
Definition: astmm.h:109
Definition: ast_expr2.c:325
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
#define RES_CONFIG_SQLITE_BEGIN
static int realtime_store_handler(const char *database, const char *table, va_list ap)
Asterisk callback function for RealTime configuration (variable create/store).
struct ast_flags flags
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
static int load_module(void)
#define release_table(a)
#define sql_get_config_table
static int entity
Definition: isdn_lib.c:259
static char * handle_cli_show_sqlite_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Asterisk callback function for the CLI status command.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static void unload_config(void)
Free resources related to configuration.
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
static void free_table(struct sqlite_cache_tables *tblptr)
Definition: cli.h:146
static int add_rt_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
SQLite callback function for RealTime configuration.
Configuration File Parser.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
static struct ast_threadstorage sql_buf
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
static int use_cdr
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_variable * var
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: config.c:586
static int realtime_update2_handler(const char *database, const char *table, va_list ap)
#define AST_RWLIST_HEAD_INIT(head)
Initializes an rwlist head structure.
Definition: linkedlists.h:624
int value
Definition: syslog.c:39
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static struct ast_config_engine sqlite_engine
Configuration engine structure, used to define realtime drivers.
Definition: config.h:121
static char * dbfile
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category structure.
Definition: config.c:673
#define CONFIG_STATUS_FILEMISSING
Definition: config.h:50
static char * table
Definition: cdr_odbc.c:50
void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw)
Definition: cdr.c:264
Call Detail Record API.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_asprintf(a, b, c...)
Definition: astmm.h:121
struct ast_config * cfg
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
void ast_category_destroy(struct ast_category *cat)
Definition: config.c:762
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:130
static int cli_status_registered
const int fd
Definition: cli.h:153
static char * config_table
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
static struct ast_cli_entry cli_status[]
static int cdr_registered
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:565
A set of macros to manage forward-linked lists.
const char * name
Definition: config.h:77
#define sql_table_structure
static int check_vars(void)
Core PBX routines and definitions.
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
struct sqlite_cache_tables::_columns columns
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
Responsible for call detail data.
Definition: cdr.h:82
static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
SQLite callback function for static configuration.
struct ast_variable * last
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
char * cat_name
static struct @350 args
#define CLI_SHOWUSAGE
Definition: cli.h:44
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: config.c:483
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:97
struct sla_ringing_trunk * first
Definition: app_meetme.c:965
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_config_engine_register(struct ast_config_engine *newconfig)
Register config engine.
Definition: config.c:2378
static const char name[]
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
static char * handle_cli_sqlite_show_tables(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: config.c:888
static char * cdr_table
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:829
static struct ast_config * config_handler(const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked)
Asterisk callback function for static configuration.
Structure used to handle boolean flags.
Definition: utils.h:200
static size_t get_params(va_list ap, const char ***params_ptr, const char ***vals_ptr, int warn)
Helper function to parse a va_list object into 2 dynamic arrays of strings, parameters and values...
Support for logging to various files, console and syslog Configuration in file logger.conf.
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:414
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:726
static int realtime_unload_handler(const char *unused, const char *tablename)
static int realtime_update_handler(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap)
Asterisk callback function for RealTime configuration (variable update).
static char * sql_create_cdr_table
Standard Command Line Interface.
#define ast_calloc(a, b)
Definition: astmm.h:82
int ast_rq_is_int(require_type type)
Check if require type is an integer type.
Definition: config.h:768
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
#define RES_CONFIG_SQLITE_DESCRIPTION
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
#define ast_realloc(a, b)
Definition: astmm.h:103
#define SET_VAR(config, to, from)
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static int load_config(void)
Load the configuration file.
static int realtime_require_handler(const char *database, const char *table, va_list ap)
static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
SQLite callback function for RealTime configuration.
static struct ast_config * realtime_multi_handler(const char *database, const char *table, va_list ap)
Asterisk callback function for RealTime configuration.
#define RES_CONFIG_SQLITE_END(error)
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
struct ast_variable * next
Definition: config.h:82
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:669
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Definition: config.c:719
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
struct ast_config * ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file, const char *who_asked)
Definition: config.c:2459
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
const char * who_asked
Asterisk module definitions.
char * strcasestr(const char *, const char *)
require_type
Types used in ast_realtime_require_field.
Definition: config.h:57
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
void ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:165
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
Definition: config.c:278
#define AST_RWLIST_HEAD(name, type)
Defines a structure to be used to hold a read/write list of specified type.
Definition: linkedlists.h:198
static int cdr_handler(struct ast_cdr *cdr)
Asterisk callback function for CDR support.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
static ast_mutex_t mutex
static sqlite * db
int ast_config_engine_deregister(struct ast_config_engine *del)
Deregister config engine.
Definition: config.c:2397
#define ast_mutex_unlock(a)
Definition: lock.h:156