Thu Jul 9 13:40:39 2009

Asterisk developer's documentation


res_config_sqlite.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2006, Proformatique
00005  *
00006  * Written by Richard Braun <rbraun@proformatique.com>
00007  *
00008  * Based on res_sqlite3 by Anthony Minessale II,
00009  * and res_config_mysql by Matthew Boehm
00010  *
00011  * See http://www.asterisk.org for more information about
00012  * the Asterisk project. Please do not directly contact
00013  * any of the maintainers of this project for assistance;
00014  * the project provides a web site, mailing lists and IRC
00015  * channels for your use.
00016  *
00017  * This program is free software, distributed under the terms of
00018  * the GNU General Public License Version 2. See the LICENSE file
00019  * at the top of the source tree.
00020  */
00021 
00022 /*!
00023  * \page res_config_sqlite
00024  *
00025  * \section intro_sec Presentation
00026  *
00027  * res_config_sqlite is a module for the Asterisk Open Source PBX to
00028  * support SQLite 2 databases. It can be used to fetch configuration
00029  * from a database (static configuration files and/or using the Asterisk
00030  * RealTime Architecture - ARA).  It can also be used to log CDR entries. 
00031  * Note that Asterisk already comes with a module named cdr_sqlite.
00032  * There are two reasons for including it in res_config_sqlite:
00033  * the first is that rewriting it was a training to learn how to write a
00034  * simple module for Asterisk, the other is to have the same database open for
00035  * all kinds of operations, which improves reliability and performance.
00036  *
00037  * \section conf_sec Configuration
00038  *
00039  * The main configuration file is res_config_sqlite.conf. It must be readable or
00040  * res_config_sqlite will fail to start. It is suggested to use the sample file
00041  * in this package as a starting point. The file has only one section
00042  * named <code>general</code>. Here are the supported parameters :
00043  *
00044  * <dl>
00045  * <dt><code>dbfile</code></dt>
00046  * <dd>The absolute path to the SQLite database (the file can be non existent,
00047  *       res_config_sqlite will create it if it has the appropriate rights)</dd>
00048  * <dt><code>config_table</code></dt>
00049  * <dd>The table used for static configuration</dd>
00050  * <dt><code>cdr_table</code></dt>
00051  * <dd>The table used to store CDR entries (if ommitted, CDR support is
00052  *       disabled)</dd>
00053  * </dl>
00054  *
00055  * To use res_config_sqlite for static and/or RealTime configuration, refer to the
00056  * Asterisk documentation. The file tables.sql can be used to create the
00057  * needed tables.
00058  *
00059  * \section status_sec Driver status
00060  *
00061  * The CLI command <code>show sqlite status</code> returns status information
00062  * about the running driver.
00063  *
00064  * \section credits_sec Credits
00065  *
00066  * res_config_sqlite was developed by Richard Braun at the Proformatique company.
00067  */
00068 
00069 /*!
00070  * \file
00071  * \brief res_config_sqlite module.
00072  */
00073 
00074 /*** MODULEINFO
00075    <depend>sqlite</depend>
00076  ***/
00077 
00078 #include "asterisk.h"
00079 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 159855 $")
00080 #include <sqlite.h>
00081 
00082 #include "asterisk/logger.h"
00083 #include "asterisk/pbx.h"
00084 #include "asterisk/cdr.h"
00085 #include "asterisk/cli.h"
00086 #include "asterisk/lock.h"
00087 #include "asterisk/config.h"
00088 #include "asterisk/module.h"
00089 #include "asterisk/linkedlists.h"
00090 
00091 #define MACRO_BEGIN  do {
00092 #define MACRO_END } while (0)
00093 
00094 #define RES_CONFIG_SQLITE_NAME "res_config_sqlite"
00095 #define RES_CONFIG_SQLITE_DRIVER "sqlite"
00096 #define RES_CONFIG_SQLITE_DESCRIPTION "Resource Module for SQLite 2"
00097 #define RES_CONFIG_SQLITE_CONF_FILE "res_config_sqlite.conf"
00098 
00099 enum {
00100    RES_CONFIG_SQLITE_CONFIG_ID,
00101    RES_CONFIG_SQLITE_CONFIG_CAT_METRIC,
00102    RES_CONFIG_SQLITE_CONFIG_VAR_METRIC,
00103    RES_CONFIG_SQLITE_CONFIG_COMMENTED,
00104    RES_CONFIG_SQLITE_CONFIG_FILENAME,
00105    RES_CONFIG_SQLITE_CONFIG_CATEGORY,
00106    RES_CONFIG_SQLITE_CONFIG_VAR_NAME,
00107    RES_CONFIG_SQLITE_CONFIG_VAR_VAL,
00108    RES_CONFIG_SQLITE_CONFIG_COLUMNS,
00109 };
00110 
00111 #define SET_VAR(config, to, from)         \
00112 MACRO_BEGIN                \
00113    int __error;               \
00114                      \
00115    __error = set_var(&to, #to, from->value); \
00116                      \
00117    if (__error) {             \
00118       ast_config_destroy(config);      \
00119       unload_config();        \
00120       return 1;            \
00121    }                 \
00122 MACRO_END
00123 
00124 /*!
00125  * Maximum number of loops before giving up executing a query. Calls to
00126  * sqlite_xxx() functions which can return SQLITE_BUSY or SQLITE_LOCKED
00127  * are enclosed by RES_CONFIG_SQLITE_BEGIN and RES_CONFIG_SQLITE_END, e.g.
00128  * <pre>
00129  * char *errormsg;
00130  * int error;
00131  *
00132  * RES_CONFIG_SQLITE_BEGIN
00133  *  error = sqlite_exec(db, query, NULL, NULL, &errormsg);
00134  * RES_CONFIG_SQLITE_END(error)
00135  *
00136  * if (error)
00137  *  ...;
00138  * </pre>
00139  */
00140 #define RES_CONFIG_SQLITE_MAX_LOOPS 10
00141 
00142 /*!
00143  * Macro used before executing a query.
00144  *
00145  * \see RES_CONFIG_SQLITE_MAX_LOOPS.
00146  */
00147 #define RES_CONFIG_SQLITE_BEGIN                 \
00148 MACRO_BEGIN                      \
00149    int __i;                   \
00150                            \
00151    for (__i = 0; __i < RES_CONFIG_SQLITE_MAX_LOOPS; __i++)  {
00152 
00153 /*!
00154  * Macro used after executing a query.
00155  *
00156  * \see RES_CONFIG_SQLITE_MAX_LOOPS.
00157  */
00158 #define RES_CONFIG_SQLITE_END(error)               \
00159       if (error != SQLITE_BUSY && error != SQLITE_LOCKED)   \
00160          break;                  \
00161       usleep(1000);                 \
00162    }                       \
00163 MACRO_END;
00164 
00165 /*!
00166  * Structure sent to the SQLite callback function for static configuration.
00167  *
00168  * \see add_cfg_entry()
00169  */
00170 struct cfg_entry_args {
00171    struct ast_config *cfg;
00172    struct ast_category *cat;
00173    char *cat_name;
00174    struct ast_flags flags;
00175    const char *who_asked;
00176 };
00177 
00178 /*!
00179  * Structure sent to the SQLite callback function for RealTime configuration.
00180  *
00181  * \see add_rt_cfg_entry()
00182  */
00183 struct rt_cfg_entry_args {
00184    struct ast_variable *var;
00185    struct ast_variable *last;
00186 };
00187 
00188 /*!
00189  * Structure sent to the SQLite callback function for RealTime configuration
00190  * (realtime_multi_handler()).
00191  *
00192  * \see add_rt_multi_cfg_entry()
00193  */
00194 struct rt_multi_cfg_entry_args {
00195    struct ast_config *cfg;
00196    char *initfield;
00197 };
00198 
00199 /*!
00200  * \brief Allocate a variable.
00201  * \param var the address of the variable to set (it will be allocated)
00202  * \param name the name of the variable (for error handling)
00203  * \param value the value to store in var
00204  * \retval 0 on success
00205  * \retval 1 if an allocation error occurred
00206  */
00207 static int set_var(char **var, const char *name, const char *value);
00208 
00209 /*!
00210  * \brief Load the configuration file.
00211  * \see unload_config()
00212  *
00213  * This function sets dbfile, config_table, and cdr_table. It calls
00214  * check_vars() before returning, and unload_config() if an error occurred.
00215  *
00216  * \retval 0 on success
00217  * \retval 1 if an error occurred
00218  */
00219 static int load_config(void);
00220 
00221 /*!
00222  * \brief Free resources related to configuration.
00223  * \see load_config()
00224  */
00225 static void unload_config(void);
00226 
00227 /*!
00228  * \brief Asterisk callback function for CDR support.
00229  * \param cdr the CDR entry Asterisk sends us.
00230  *
00231  * Asterisk will call this function each time a CDR entry must be logged if
00232  * CDR support is enabled.
00233  *
00234  * \retval 0 on success
00235  * \retval 1 if an error occurred
00236  */
00237 static int cdr_handler(struct ast_cdr *cdr);
00238 
00239 /*!
00240  * \brief SQLite callback function for static configuration.
00241  *
00242  * This function is passed to the SQLite engine as a callback function to
00243  * parse a row and store it in a struct ast_config object. It relies on
00244  * resulting rows being sorted by category.
00245  *
00246  * \param arg a pointer to a struct cfg_entry_args object
00247  * \param argc number of columns
00248  * \param argv values in the row
00249  * \param columnNames names and types of the columns
00250  * \retval 0 on success
00251  * \retval 1 if an error occurred
00252  * \see cfg_entry_args
00253  * \see sql_get_config_table
00254  * \see config_handler()
00255  */
00256 static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames);
00257 
00258 /*!
00259  * \brief Asterisk callback function for static configuration.
00260  *
00261  * Asterisk will call this function when it loads its static configuration,
00262  * which usually happens at startup and reload.
00263  *
00264  * \param database the database to use (ignored)
00265  * \param table the table to use
00266  * \param file the file to load from the database
00267  * \param cfg the struct ast_config object to use when storing variables
00268  * \param flags Optional flags.  Not used.
00269  * \param suggested_incl suggest include.
00270  * \retval cfg object
00271  * \retval NULL if an error occurred
00272  * \see add_cfg_entry()
00273  */
00274 static struct ast_config * config_handler(const char *database, const char *table, const char *file,
00275    struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked);
00276 
00277 /*!
00278  * \brief Helper function to parse a va_list object into 2 dynamic arrays of
00279  * strings, parameters and values.
00280  *
00281  * ap must have the following format : param1 val1 param2 val2 param3 val3 ...
00282  * arguments will be extracted to create 2 arrays:
00283  *
00284  * <ul>
00285  * <li>params : param1 param2 param3 ...</li>
00286  * <li>vals : val1 val2 val3 ...</li>
00287  * </ul>
00288  *
00289  * The address of these arrays are stored in params_ptr and vals_ptr. It
00290  * is the responsibility of the caller to release the memory of these arrays.
00291  * It is considered an error that va_list has a null or odd number of strings.
00292  *
00293  * \param ap the va_list object to parse
00294  * \param params_ptr where the address of the params array is stored
00295  * \param vals_ptr where the address of the vals array is stored
00296  * \retval the number of elements in the arrays (which have the same size).
00297  * \retval 0 if an error occurred.
00298  */
00299 static size_t get_params(va_list ap, const char ***params_ptr,
00300    const char ***vals_ptr);
00301 
00302 /*!
00303  * \brief SQLite callback function for RealTime configuration.
00304  *
00305  * This function is passed to the SQLite engine as a callback function to
00306  * parse a row and store it in a linked list of struct ast_variable objects.
00307  *
00308  * \param arg a pointer to a struct rt_cfg_entry_args object
00309  * \param argc number of columns
00310  * \param argv values in the row
00311  * \param columnNames names and types of the columns
00312  * \retval 0 on success.
00313  * \retval 1 if an error occurred.
00314  * \see rt_cfg_entry_args
00315  * \see realtime_handler()
00316  */
00317 static int add_rt_cfg_entry(void *arg, int argc, char **argv,
00318    char **columnNames);
00319 
00320 /*!
00321  * \brief Asterisk callback function for RealTime configuration.
00322  *
00323  * Asterisk will call this function each time it requires a variable
00324  * through the RealTime architecture. ap is a list of parameters and
00325  * values used to find a specific row, e.g one parameter "name" and
00326  * one value "123" so that the SQL query becomes <code>SELECT * FROM
00327  * table WHERE name = '123';</code>.
00328  *
00329  * \param database the database to use (ignored)
00330  * \param table the table to use
00331  * \param ap list of parameters and values to match
00332  *
00333  * \retval a linked list of struct ast_variable objects
00334  * \retval NULL if an error occurred
00335  * \see add_rt_cfg_entry()
00336  */
00337 static struct ast_variable * realtime_handler(const char *database,
00338    const char *table, va_list ap);
00339 
00340 /*!
00341  * \brief SQLite callback function for RealTime configuration.
00342  *
00343  * This function performs the same actions as add_rt_cfg_entry() except
00344  * that the rt_multi_cfg_entry_args structure is designed to store
00345  * categories in addition to variables.
00346  *
00347  * \param arg a pointer to a struct rt_multi_cfg_entry_args object
00348  * \param argc number of columns
00349  * \param argv values in the row
00350  * \param columnNames names and types of the columns
00351  * \retval 0 on success.
00352  * \retval 1 if an error occurred.
00353  * \see rt_multi_cfg_entry_args
00354  * \see realtime_multi_handler()
00355  */
00356 static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv,
00357    char **columnNames);
00358 
00359 /*!
00360  * \brief Asterisk callback function for RealTime configuration.
00361  *
00362  * This function performs the same actions as realtime_handler() except
00363  * that it can store variables per category, and can return several
00364  * categories.
00365  *
00366  * \param database the database to use (ignored)
00367  * \param table the table to use
00368  * \param ap list of parameters and values to match
00369  * \retval a struct ast_config object storing categories and variables.
00370  * \retval NULL if an error occurred.
00371  *
00372  * \see add_rt_multi_cfg_entry()
00373  */
00374 static struct ast_config * realtime_multi_handler(const char *database,
00375    const char *table, va_list ap);
00376 
00377 /*!
00378  * \brief Asterisk callback function for RealTime configuration (variable
00379  * update).
00380  *
00381  * Asterisk will call this function each time a variable has been modified
00382  * internally and must be updated in the backend engine. keyfield and entity
00383  * are used to find the row to update, e.g. <code>UPDATE table SET ... WHERE
00384  * keyfield = 'entity';</code>. ap is a list of parameters and values with the
00385  * same format as the other realtime functions.
00386  *
00387  * \param database the database to use (ignored)
00388  * \param table the table to use
00389  * \param keyfield the column of the matching cell
00390  * \param entity the value of the matching cell
00391  * \param ap list of parameters and new values to update in the database
00392  * \retval the number of affected rows.
00393  * \retval -1 if an error occurred.
00394  */
00395 static int realtime_update_handler(const char *database, const char *table,
00396    const char *keyfield, const char *entity, va_list ap);
00397 
00398 /*!
00399  * \brief Asterisk callback function for RealTime configuration (variable
00400  * create/store).
00401  *
00402  * Asterisk will call this function each time a variable has been created
00403  * internally and must be stored in the backend engine.
00404  * are used to find the row to update, e.g. ap is a list of parameters and
00405  * values with the same format as the other realtime functions.
00406  *
00407  * \param database the database to use (ignored)
00408  * \param table the table to use
00409  * \param ap list of parameters and new values to insert into the database
00410  * \retval the rowid of inserted row.
00411  * \retval -1 if an error occurred.
00412  */
00413 static int realtime_store_handler(const char *database, const char *table,
00414    va_list ap);
00415 
00416 /*!
00417  * \brief Asterisk callback function for RealTime configuration (destroys
00418  * variable).
00419  *
00420  * Asterisk will call this function each time a variable has been destroyed
00421  * internally and must be removed from the backend engine. keyfield and entity
00422  * are used to find the row to delete, e.g. <code>DELETE FROM table WHERE
00423  * keyfield = 'entity';</code>. ap is a list of parameters and values with the
00424  * same format as the other realtime functions.
00425  *
00426  * \param database the database to use (ignored)
00427  * \param table the table to use
00428  * \param keyfield the column of the matching cell
00429  * \param entity the value of the matching cell
00430  * \param ap list of additional parameters for cell matching
00431  * \retval the number of affected rows.
00432  * \retval -1 if an error occurred.
00433  */
00434 static int realtime_destroy_handler(const char *database, const char *table,
00435    const char *keyfield, const char *entity, va_list ap);
00436 
00437 /*!
00438  * \brief Asterisk callback function for the CLI status command.
00439  *
00440  * \param e CLI command
00441  * \param cmd 
00442  * \param a CLI argument list
00443  * \return RESULT_SUCCESS
00444  */
00445 static char *handle_cli_show_sqlite_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
00446 
00447 /*! The SQLite database object. */
00448 static sqlite *db;
00449 
00450 /*! Set to 1 if CDR support is enabled. */
00451 static int use_cdr;
00452 
00453 /*! Set to 1 if the CDR callback function was registered. */
00454 static int cdr_registered;
00455 
00456 /*! Set to 1 if the CLI status command callback function was registered. */
00457 static int cli_status_registered;
00458 
00459 /*! The path of the database file. */
00460 static char *dbfile;
00461 
00462 /*! The name of the static configuration table. */
00463 static char *config_table;
00464 
00465 /*! The name of the table used to store CDR entries. */
00466 static char *cdr_table;
00467 
00468 /*!
00469  * The structure specifying all callback functions used by Asterisk for static
00470  * and RealTime configuration.
00471  */
00472 static struct ast_config_engine sqlite_engine =
00473 {
00474    .name = RES_CONFIG_SQLITE_DRIVER,
00475    .load_func = config_handler,
00476    .realtime_func = realtime_handler,
00477    .realtime_multi_func = realtime_multi_handler,
00478    .store_func = realtime_store_handler,
00479    .destroy_func = realtime_destroy_handler,
00480    .update_func = realtime_update_handler
00481 };
00482 
00483 /*!
00484  * The mutex used to prevent simultaneous access to the SQLite database.
00485  */
00486 AST_MUTEX_DEFINE_STATIC(mutex);
00487 
00488 /*!
00489  * Structure containing details and callback functions for the CLI status
00490  * command.
00491  */
00492 static struct ast_cli_entry cli_status[] = {
00493    AST_CLI_DEFINE(handle_cli_show_sqlite_status, "Show status information about the SQLite 2 driver"),
00494 };
00495 
00496 /*
00497  * Taken from Asterisk 1.2 cdr_sqlite.so.
00498  */
00499 
00500 /*! SQL query format to create the CDR table if non existent. */
00501 static char *sql_create_cdr_table =
00502 "CREATE TABLE '%q' (\n"
00503 "  id    INTEGER,\n"
00504 "  clid     VARCHAR(80) NOT NULL DEFAULT '',\n"
00505 "  src      VARCHAR(80) NOT NULL DEFAULT '',\n"
00506 "  dst      VARCHAR(80) NOT NULL DEFAULT '',\n"
00507 "  dcontext VARCHAR(80) NOT NULL DEFAULT '',\n"
00508 "  channel     VARCHAR(80) NOT NULL DEFAULT '',\n"
00509 "  dstchannel  VARCHAR(80) NOT NULL DEFAULT '',\n"
00510 "  lastapp     VARCHAR(80) NOT NULL DEFAULT '',\n"
00511 "  lastdata VARCHAR(80) NOT NULL DEFAULT '',\n"
00512 "  start    DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\n"
00513 "  answer      DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\n"
00514 "  end      DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',\n"
00515 "  duration INT(11)     NOT NULL DEFAULT 0,\n"
00516 "  billsec     INT(11)     NOT NULL DEFAULT 0,\n"
00517 "  disposition VARCHAR(45) NOT NULL DEFAULT '',\n"
00518 "  amaflags INT(11)     NOT NULL DEFAULT 0,\n"
00519 "  accountcode VARCHAR(20) NOT NULL DEFAULT '',\n"
00520 "  uniqueid VARCHAR(32) NOT NULL DEFAULT '',\n"
00521 "  userfield   VARCHAR(255)   NOT NULL DEFAULT '',\n"
00522 "  PRIMARY KEY (id)\n"
00523 ");";
00524 
00525 /*! SQL query format to insert a CDR entry. */
00526 #define sql_add_cdr_entry \
00527    "INSERT INTO '%q' (" \
00528    "  clid," \
00529    "  src," \
00530    "  dst," \
00531    "  dcontext," \
00532    "  channel," \
00533    "  dstchannel," \
00534    "  lastapp," \
00535    "  lastdata," \
00536    "  start," \
00537    "  answer," \
00538    "  end," \
00539    "  duration," \
00540    "  billsec," \
00541    "  disposition," \
00542    "  amaflags," \
00543    "  accountcode," \
00544    "  uniqueid," \
00545    "  userfield" \
00546    ") VALUES (" \
00547    "  '%q'," \
00548    "  '%q'," \
00549    "  '%q'," \
00550    "  '%q'," \
00551    "  '%q'," \
00552    "  '%q'," \
00553    "  '%q'," \
00554    "  '%q'," \
00555    "  datetime(%d,'unixepoch','localtime')," \
00556    "  datetime(%d,'unixepoch','localtime')," \
00557    "  datetime(%d,'unixepoch','localtime')," \
00558    "  '%ld'," \
00559    "  '%ld'," \
00560    "  '%ld'," \
00561    "  '%ld'," \
00562    "  '%q'," \
00563    "  '%q'," \
00564    "  '%q'" \
00565    ");"
00566 
00567 /*!
00568  * SQL query format to fetch the static configuration of a file.
00569  * Rows must be sorted by category.
00570  *
00571  * \see add_cfg_entry()
00572  */
00573 #define sql_get_config_table \
00574    "SELECT *" \
00575    "  FROM '%q'" \
00576    "  WHERE filename = '%q' AND commented = 0" \
00577    "  ORDER BY cat_metric ASC, var_metric ASC;"
00578 
00579 static int set_var(char **var, const char *name, const char *value)
00580 {
00581    if (*var)
00582       ast_free(*var);
00583 
00584    *var = ast_strdup(value);
00585 
00586    if (!*var) {
00587       ast_log(LOG_WARNING, "Unable to allocate variable %s\n", name);
00588       return 1;
00589    }
00590 
00591    return 0;
00592 }
00593 
00594 static int check_vars(void)
00595 {
00596    if (!dbfile) {
00597       ast_log(LOG_ERROR, "Required parameter undefined: dbfile\n");
00598       return 1;
00599    }
00600 
00601    use_cdr = (cdr_table != NULL);
00602 
00603    return 0;
00604 }
00605 
00606 static int load_config(void)
00607 {
00608    struct ast_config *config;
00609    struct ast_variable *var;
00610    int error;
00611    struct ast_flags config_flags = { 0 };
00612 
00613    config = ast_config_load(RES_CONFIG_SQLITE_CONF_FILE, config_flags);
00614 
00615    if (!config) {
00616       ast_log(LOG_ERROR, "Unable to load " RES_CONFIG_SQLITE_CONF_FILE "\n");
00617       return 1;
00618    }
00619 
00620    for (var = ast_variable_browse(config, "general"); var; var = var->next) {
00621       if (!strcasecmp(var->name, "dbfile"))
00622          SET_VAR(config, dbfile, var);
00623       else if (!strcasecmp(var->name, "config_table"))
00624          SET_VAR(config, config_table, var);
00625       else if (!strcasecmp(var->name, "cdr_table"))
00626          SET_VAR(config, cdr_table, var);
00627       else
00628          ast_log(LOG_WARNING, "Unknown parameter : %s\n", var->name);
00629    }
00630 
00631    ast_config_destroy(config);
00632    error = check_vars();
00633 
00634    if (error) {
00635       unload_config();
00636       return 1;
00637    }
00638 
00639    return 0;
00640 }
00641 
00642 static void unload_config(void)
00643 {
00644    ast_free(dbfile);
00645    dbfile = NULL;
00646    ast_free(config_table);
00647    config_table = NULL;
00648    ast_free(cdr_table);
00649    cdr_table = NULL;
00650 }
00651 
00652 static int cdr_handler(struct ast_cdr *cdr)
00653 {
00654    char *query, *errormsg;
00655    int error;
00656 
00657    query = sqlite_mprintf(sql_add_cdr_entry, cdr_table, cdr->clid,
00658          cdr->src, cdr->dst, cdr->dcontext, cdr->channel,
00659          cdr->dstchannel, cdr->lastapp, cdr->lastdata,
00660          cdr->start.tv_sec, cdr->answer.tv_sec,
00661          cdr->end.tv_sec, cdr->duration, cdr->billsec,
00662          cdr->disposition, cdr->amaflags, cdr->accountcode,
00663          cdr->uniqueid, cdr->userfield);
00664 
00665    if (!query) {
00666       ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
00667       return 1;
00668    }
00669 
00670    ast_debug(1, "SQL query: %s\n", query);
00671 
00672    ast_mutex_lock(&mutex);
00673 
00674    RES_CONFIG_SQLITE_BEGIN
00675       error = sqlite_exec(db, query, NULL, NULL, &errormsg);
00676    RES_CONFIG_SQLITE_END(error)
00677 
00678    ast_mutex_unlock(&mutex);
00679 
00680    sqlite_freemem(query);
00681 
00682    if (error) {
00683       ast_log(LOG_ERROR, "%s\n", errormsg);
00684       sqlite_freemem(errormsg);
00685       return 1;
00686    }
00687 
00688    return 0;
00689 }
00690 
00691 static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
00692 {
00693    struct cfg_entry_args *args;
00694    struct ast_variable *var;
00695 
00696    if (argc != RES_CONFIG_SQLITE_CONFIG_COLUMNS) {
00697       ast_log(LOG_WARNING, "Corrupt table\n");
00698       return 1;
00699    }
00700 
00701    args = arg;
00702 
00703    if (!strcmp(argv[RES_CONFIG_SQLITE_CONFIG_VAR_NAME], "#include")) {
00704       struct ast_config *cfg;
00705       char *val;
00706 
00707       val = argv[RES_CONFIG_SQLITE_CONFIG_VAR_VAL];
00708       cfg = ast_config_internal_load(val, args->cfg, args->flags, "", args->who_asked);
00709 
00710       if (!cfg) {
00711          ast_log(LOG_WARNING, "Unable to include %s\n", val);
00712          return 1;
00713       } else {
00714          args->cfg = cfg;
00715          return 0;
00716       }
00717    }
00718 
00719    if (!args->cat_name || strcmp(args->cat_name, argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY])) {
00720       args->cat = ast_category_new(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY], "", 99999);
00721 
00722       if (!args->cat) {
00723          ast_log(LOG_WARNING, "Unable to allocate category\n");
00724          return 1;
00725       }
00726 
00727       ast_free(args->cat_name);
00728       args->cat_name = ast_strdup(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY]);
00729 
00730       if (!args->cat_name) {
00731          ast_category_destroy(args->cat);
00732          return 1;
00733       }
00734 
00735       ast_category_append(args->cfg, args->cat);
00736    }
00737 
00738    var = ast_variable_new(argv[RES_CONFIG_SQLITE_CONFIG_VAR_NAME], argv[RES_CONFIG_SQLITE_CONFIG_VAR_VAL], "");
00739 
00740    if (!var) {
00741       ast_log(LOG_WARNING, "Unable to allocate variable");
00742       return 1;
00743    }
00744 
00745    ast_variable_append(args->cat, var);
00746 
00747    return 0;
00748 }
00749 
00750 static struct ast_config *config_handler(const char *database, const char *table, const char *file,
00751    struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked)
00752 {
00753    struct cfg_entry_args args;
00754    char *query, *errormsg;
00755    int error;
00756 
00757    if (!config_table) {
00758       if (!table) {
00759          ast_log(LOG_ERROR, "Table name unspecified\n");
00760          return NULL;
00761       }
00762    } else
00763       table = config_table;
00764 
00765    query = sqlite_mprintf(sql_get_config_table, table, file);
00766 
00767    if (!query) {
00768       ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
00769       return NULL;
00770    }
00771 
00772    ast_debug(1, "SQL query: %s\n", query);
00773    args.cfg = cfg;
00774    args.cat = NULL;
00775    args.cat_name = NULL;
00776    args.flags = flags;
00777    args.who_asked = who_asked;
00778 
00779    ast_mutex_lock(&mutex);
00780 
00781    RES_CONFIG_SQLITE_BEGIN
00782       error = sqlite_exec(db, query, add_cfg_entry, &args, &errormsg);
00783    RES_CONFIG_SQLITE_END(error)
00784 
00785    ast_mutex_unlock(&mutex);
00786 
00787    ast_free(args.cat_name);
00788    sqlite_freemem(query);
00789 
00790    if (error) {
00791       ast_log(LOG_ERROR, "%s\n", errormsg);
00792       sqlite_freemem(errormsg);
00793       return NULL;
00794    }
00795 
00796    return cfg;
00797 }
00798 
00799 static size_t get_params(va_list ap, const char ***params_ptr, const char ***vals_ptr)
00800 {
00801    const char **tmp, *param, *val, **params, **vals;
00802    size_t params_count;
00803 
00804    params = NULL;
00805    vals = NULL;
00806    params_count = 0;
00807 
00808    while ((param = va_arg(ap, const char *)) && (val = va_arg(ap, const char *))) {
00809       if (!(tmp = ast_realloc(params, (params_count + 1) * sizeof(char *)))) {
00810          ast_free(params);
00811          ast_free(vals);
00812          return 0;
00813       }
00814       params = tmp;
00815 
00816       if (!(tmp = ast_realloc(vals, (params_count + 1) * sizeof(char *)))) {
00817          ast_free(params);
00818          ast_free(vals);
00819          return 0;
00820       }
00821       vals = tmp;
00822 
00823       params[params_count] = param;
00824       vals[params_count] = val;
00825       params_count++;
00826    }
00827 
00828    if (params_count > 0) {
00829       *params_ptr = params;
00830       *vals_ptr = vals;
00831    } else
00832       ast_log(LOG_WARNING, "1 parameter and 1 value at least required\n");
00833 
00834    return params_count;
00835 }
00836 
00837 static int add_rt_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
00838 {
00839    struct rt_cfg_entry_args *args;
00840    struct ast_variable *var;
00841    int i;
00842 
00843    args = arg;
00844 
00845    for (i = 0; i < argc; i++) {
00846       if (!argv[i])
00847          continue;
00848 
00849       if (!(var = ast_variable_new(columnNames[i], argv[i], "")))
00850          return 1;
00851 
00852       if (!args->var)
00853          args->var = var;
00854 
00855       if (!args->last)
00856          args->last = var;
00857       else {
00858          args->last->next = var;
00859          args->last = var;
00860       }
00861    }
00862 
00863    return 0;
00864 }
00865 
00866 static struct ast_variable * realtime_handler(const char *database, const char *table, va_list ap)
00867 {
00868    char *query, *errormsg, *op, *tmp_str;
00869    struct rt_cfg_entry_args args;
00870    const char **params, **vals;
00871    size_t params_count;
00872    int error;
00873 
00874    if (!table) {
00875       ast_log(LOG_WARNING, "Table name unspecified\n");
00876       return NULL;
00877    }
00878 
00879    params_count = get_params(ap, &params, &vals);
00880 
00881    if (params_count == 0)
00882       return NULL;
00883 
00884    op = (strchr(params[0], ' ') == NULL) ? " =" : "";
00885 
00886 /* \cond DOXYGEN_CAN_PARSE_THIS */
00887 #undef QUERY
00888 #define QUERY "SELECT * FROM '%q' WHERE commented = 0 AND %q%s '%q'"
00889 /* \endcond */
00890 
00891    query = sqlite_mprintf(QUERY, table, params[0], op, vals[0]);
00892 
00893    if (!query) {
00894       ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
00895       ast_free(params);
00896       ast_free(vals);
00897       return NULL;
00898    }
00899 
00900    if (params_count > 1) {
00901       size_t i;
00902 
00903       for (i = 1; i < params_count; i++) {
00904          op = (strchr(params[i], ' ') == NULL) ? " =" : "";
00905          tmp_str = sqlite_mprintf("%s AND %q%s '%q'", query, params[i], op, vals[i]);
00906          sqlite_freemem(query);
00907 
00908          if (!tmp_str) {
00909             ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
00910             ast_free(params);
00911             ast_free(vals);
00912             return NULL;
00913          }
00914 
00915          query = tmp_str;
00916       }
00917    }
00918 
00919    ast_free(params);
00920    ast_free(vals);
00921 
00922    tmp_str = sqlite_mprintf("%s LIMIT 1;", query);
00923    sqlite_freemem(query);
00924 
00925    if (!tmp_str) {
00926       ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
00927       return NULL;
00928    }
00929 
00930    query = tmp_str;
00931    ast_debug(1, "SQL query: %s\n", query);
00932    args.var = NULL;
00933    args.last = NULL;
00934 
00935    ast_mutex_lock(&mutex);
00936 
00937    RES_CONFIG_SQLITE_BEGIN
00938       error = sqlite_exec(db, query, add_rt_cfg_entry, &args, &errormsg);
00939    RES_CONFIG_SQLITE_END(error)
00940 
00941    ast_mutex_unlock(&mutex);
00942 
00943    sqlite_freemem(query);
00944 
00945    if (error) {
00946       ast_log(LOG_WARNING, "%s\n", errormsg);
00947       sqlite_freemem(errormsg);
00948       ast_variables_destroy(args.var);
00949       return NULL;
00950    }
00951 
00952    return args.var;
00953 }
00954 
00955 static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
00956 {
00957    struct rt_multi_cfg_entry_args *args;
00958    struct ast_category *cat;
00959    struct ast_variable *var;
00960    char *cat_name;
00961    size_t i;
00962 
00963    args = arg;
00964    cat_name = NULL;
00965 
00966    /*
00967     * cat_name should always be set here, since initfield is forged from
00968     * params[0] in realtime_multi_handler(), which is a search parameter
00969     * of the SQL query.
00970     */
00971    for (i = 0; i < argc; i++) {
00972       if (!strcmp(args->initfield, columnNames[i]))
00973          cat_name = argv[i];
00974    }
00975 
00976    if (!cat_name) {
00977       ast_log(LOG_ERROR, "Bogus SQL results, cat_name is NULL !\n");
00978       return 1;
00979    }
00980 
00981    if (!(cat = ast_category_new(cat_name, "", 99999))) {
00982       ast_log(LOG_WARNING, "Unable to allocate category\n");
00983       return 1;
00984    }
00985 
00986    ast_category_append(args->cfg, cat);
00987 
00988    for (i = 0; i < argc; i++) {
00989       if (!argv[i] || !strcmp(args->initfield, columnNames[i]))
00990          continue;
00991 
00992       if (!(var = ast_variable_new(columnNames[i], argv[i], ""))) {
00993          ast_log(LOG_WARNING, "Unable to allocate variable\n");
00994          return 1;
00995       }
00996 
00997       ast_variable_append(cat, var);
00998    }
00999 
01000    return 0;
01001 }
01002 
01003 static struct ast_config *realtime_multi_handler(const char *database,
01004    const char *table, va_list ap)
01005 {
01006    char *query, *errormsg, *op, *tmp_str, *initfield;
01007    struct rt_multi_cfg_entry_args args;
01008    const char **params, **vals;
01009    struct ast_config *cfg;
01010    size_t params_count;
01011    int error;
01012 
01013    if (!table) {
01014       ast_log(LOG_WARNING, "Table name unspecified\n");
01015       return NULL;
01016    }
01017 
01018    if (!(cfg = ast_config_new())) {
01019       ast_log(LOG_WARNING, "Unable to allocate configuration structure\n");
01020       return NULL;
01021    }
01022 
01023    if (!(params_count = get_params(ap, &params, &vals))) {
01024       ast_config_destroy(cfg);
01025       return NULL;
01026    }
01027 
01028    if (!(initfield = ast_strdup(params[0]))) {
01029       ast_config_destroy(cfg);
01030       ast_free(params);
01031       ast_free(vals);
01032       return NULL;
01033    }
01034 
01035    tmp_str = strchr(initfield, ' ');
01036 
01037    if (tmp_str)
01038       *tmp_str = '\0';
01039 
01040    op = (!strchr(params[0], ' ')) ? " =" : "";
01041 
01042    /*
01043     * Asterisk sends us an already escaped string when searching for
01044     * "exten LIKE" (uh!). Handle it separately.
01045     */
01046    tmp_str = (!strcmp(vals[0], "\\_%")) ? "_%" : (char *)vals[0];
01047 
01048 /* \cond DOXYGEN_CAN_PARSE_THIS */
01049 #undef QUERY
01050 #define QUERY "SELECT * FROM '%q' WHERE commented = 0 AND %q%s '%q'"
01051 /* \endcond */
01052 
01053    if (!(query = sqlite_mprintf(QUERY, table, params[0], op, tmp_str))) {
01054       ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
01055       ast_config_destroy(cfg);
01056       ast_free(params);
01057       ast_free(vals);
01058       ast_free(initfield);
01059       return NULL;
01060    }
01061 
01062    if (params_count > 1) {
01063       size_t i;
01064 
01065       for (i = 1; i < params_count; i++) {
01066          op = (!strchr(params[i], ' ')) ? " =" : "";
01067          tmp_str = sqlite_mprintf("%s AND %q%s '%q'", query, params[i], op, vals[i]);
01068          sqlite_freemem(query);
01069 
01070          if (!tmp_str) {
01071             ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
01072             ast_config_destroy(cfg);
01073             ast_free(params);
01074             ast_free(vals);
01075             ast_free(initfield);
01076             return NULL;
01077          }
01078 
01079          query = tmp_str;
01080       }
01081    }
01082 
01083    ast_free(params);
01084    ast_free(vals);
01085 
01086    if (!(tmp_str = sqlite_mprintf("%s ORDER BY %q;", query, initfield))) {
01087       ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
01088       sqlite_freemem(query);
01089       ast_config_destroy(cfg);
01090       ast_free(initfield);
01091       return NULL;
01092    }
01093 
01094    sqlite_freemem(query);
01095    query = tmp_str;
01096    ast_debug(1, "SQL query: %s\n", query);
01097    args.cfg = cfg;
01098    args.initfield = initfield;
01099 
01100    ast_mutex_lock(&mutex);
01101 
01102    RES_CONFIG_SQLITE_BEGIN
01103       error = sqlite_exec(db, query, add_rt_multi_cfg_entry, &args, &errormsg);
01104    RES_CONFIG_SQLITE_END(error)
01105 
01106    ast_mutex_unlock(&mutex);
01107 
01108    sqlite_freemem(query);
01109    ast_free(initfield);
01110 
01111    if (error) {
01112       ast_log(LOG_WARNING, "%s\n", errormsg);
01113       sqlite_freemem(errormsg);
01114       ast_config_destroy(cfg);
01115       return NULL;
01116    }
01117 
01118    return cfg;
01119 }
01120 
01121 static int realtime_update_handler(const char *database, const char *table,
01122    const char *keyfield, const char *entity, va_list ap)
01123 {
01124    char *query, *errormsg, *tmp_str;
01125    const char **params, **vals;
01126    size_t params_count;
01127    int error, rows_num;
01128 
01129    if (!table) {
01130       ast_log(LOG_WARNING, "Table name unspecified\n");
01131       return -1;
01132    }
01133 
01134    if (!(params_count = get_params(ap, &params, &vals)))
01135       return -1;
01136 
01137 /* \cond DOXYGEN_CAN_PARSE_THIS */
01138 #undef QUERY
01139 #define QUERY "UPDATE '%q' SET %q = '%q'"
01140 /* \endcond */
01141 
01142    if (!(query = sqlite_mprintf(QUERY, table, params[0], vals[0]))) {
01143       ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
01144       ast_free(params);
01145       ast_free(vals);
01146       return -1;
01147    }
01148 
01149    if (params_count > 1) {
01150       size_t i;
01151 
01152       for (i = 1; i < params_count; i++) {
01153          tmp_str = sqlite_mprintf("%s, %q = '%q'", query, params[i], vals[i]);
01154          sqlite_freemem(query);
01155 
01156          if (!tmp_str) {
01157             ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
01158             ast_free(params);
01159             ast_free(vals);
01160             return -1;
01161          }
01162 
01163          query = tmp_str;
01164       }
01165    }
01166 
01167    ast_free(params);
01168    ast_free(vals);
01169 
01170    if (!(tmp_str = sqlite_mprintf("%s WHERE %q = '%q';", query, keyfield, entity))) {
01171       ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
01172       sqlite_freemem(query);
01173       return -1;
01174    }
01175 
01176    sqlite_freemem(query);
01177    query = tmp_str;
01178    ast_debug(1, "SQL query: %s\n", query);
01179 
01180    ast_mutex_lock(&mutex);
01181 
01182    RES_CONFIG_SQLITE_BEGIN
01183       error = sqlite_exec(db, query, NULL, NULL, &errormsg);
01184    RES_CONFIG_SQLITE_END(error)
01185 
01186    if (!error)
01187       rows_num = sqlite_changes(db);
01188    else
01189       rows_num = -1;
01190 
01191    ast_mutex_unlock(&mutex);
01192 
01193    sqlite_freemem(query);
01194 
01195    if (error) {
01196       ast_log(LOG_WARNING, "%s\n", errormsg);
01197       sqlite_freemem(errormsg);
01198    }
01199 
01200    return rows_num;
01201 }
01202 
01203 static int realtime_store_handler(const char *database, const char *table, va_list ap)
01204 {
01205    char *errormsg, *tmp_str, *tmp_keys = NULL, *tmp_keys2 = NULL, *tmp_vals = NULL, *tmp_vals2 = NULL;
01206    const char **params, **vals;
01207    size_t params_count;
01208    int error, rows_id;
01209    size_t i;
01210 
01211    if (!table) {
01212       ast_log(LOG_WARNING, "Table name unspecified\n");
01213       return -1;
01214    }
01215 
01216    if (!(params_count = get_params(ap, &params, &vals)))
01217       return -1;
01218 
01219 /* \cond DOXYGEN_CAN_PARSE_THIS */
01220 #undef QUERY
01221 #define QUERY "INSERT into '%q' (%s) VALUES (%s);"
01222 /* \endcond */
01223 
01224    for (i = 0; i < params_count; i++) {
01225       if ( tmp_keys2 ) {
01226          tmp_keys = sqlite_mprintf("%s, %q", tmp_keys2, params[i]);
01227          sqlite_freemem(tmp_keys2);
01228       } else {
01229          tmp_keys = sqlite_mprintf("%q", params[i]);
01230       }
01231       if (!tmp_keys) {
01232          ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
01233          sqlite_freemem(tmp_vals);
01234          ast_free(params);
01235          ast_free(vals);
01236          return -1;
01237       }
01238 
01239       if ( tmp_vals2 ) {
01240          tmp_vals = sqlite_mprintf("%s, '%q'", tmp_vals2, params[i]);
01241          sqlite_freemem(tmp_vals2);
01242       } else {
01243          tmp_vals = sqlite_mprintf("'%q'", params[i]);
01244       }
01245       if (!tmp_vals) {
01246          ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
01247          sqlite_freemem(tmp_keys);
01248          ast_free(params);
01249          ast_free(vals);
01250          return -1;
01251       }
01252 
01253 
01254       tmp_keys2 = tmp_keys;
01255       tmp_vals2 = tmp_vals;
01256    }
01257 
01258    ast_free(params);
01259    ast_free(vals);
01260 
01261    if (!(tmp_str = sqlite_mprintf(QUERY, table, tmp_keys, tmp_vals))) {
01262       ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
01263       sqlite_freemem(tmp_keys);
01264       sqlite_freemem(tmp_vals);
01265       return -1;
01266    }
01267 
01268    sqlite_freemem(tmp_keys);
01269    sqlite_freemem(tmp_vals);
01270 
01271    ast_debug(1, "SQL query: %s\n", tmp_str);
01272 
01273    ast_mutex_lock(&mutex);
01274 
01275    RES_CONFIG_SQLITE_BEGIN
01276       error = sqlite_exec(db, tmp_str, NULL, NULL, &errormsg);
01277    RES_CONFIG_SQLITE_END(error)
01278 
01279    if (!error) {
01280       rows_id = sqlite_last_insert_rowid(db);
01281    } else {
01282       rows_id = -1;
01283    }
01284 
01285    ast_mutex_unlock(&mutex);
01286 
01287    sqlite_freemem(tmp_str);
01288 
01289    if (error) {
01290       ast_log(LOG_WARNING, "%s\n", errormsg);
01291       sqlite_freemem(errormsg);
01292    }
01293 
01294    return rows_id;
01295 }
01296 
01297 static int realtime_destroy_handler(const char *database, const char *table,
01298    const char *keyfield, const char *entity, va_list ap)
01299 {
01300    char *query, *errormsg, *tmp_str;
01301    const char **params, **vals;
01302    size_t params_count;
01303    int error, rows_num;
01304    size_t i;
01305 
01306    if (!table) {
01307       ast_log(LOG_WARNING, "Table name unspecified\n");
01308       return -1;
01309    }
01310 
01311    if (!(params_count = get_params(ap, &params, &vals)))
01312       return -1;
01313 
01314 /* \cond DOXYGEN_CAN_PARSE_THIS */
01315 #undef QUERY
01316 #define QUERY "DELETE FROM '%q' WHERE"
01317 /* \endcond */
01318 
01319    if (!(query = sqlite_mprintf(QUERY, table))) {
01320       ast_log(LOG_WARNING, "Unable to allocate SQL query\n");
01321       ast_free(params);
01322       ast_free(vals);
01323       return -1;
01324    }
01325 
01326    for (i = 0; i < params_count; i++) {
01327       tmp_str = sqlite_mprintf("%s %q = '%q' AND", query, params[i], vals[i]);
01328       sqlite_freemem(query);
01329 
01330       if (!tmp_str) {
01331          ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
01332          ast_free(params);
01333          ast_free(vals);
01334          return -1;
01335       }
01336 
01337       query = tmp_str;
01338    }
01339 
01340    ast_free(params);
01341    ast_free(vals);
01342    if (!(tmp_str = sqlite_mprintf("%s %q = '%q';", query, keyfield, entity))) {
01343       ast_log(LOG_WARNING, "Unable to reallocate SQL query\n");
01344       sqlite_freemem(query);
01345       return -1;
01346    }
01347    sqlite_freemem(query);
01348    query = tmp_str;
01349    ast_debug(1, "SQL query: %s\n", query);
01350 
01351    ast_mutex_lock(&mutex);
01352 
01353    RES_CONFIG_SQLITE_BEGIN
01354       error = sqlite_exec(db, query, NULL, NULL, &errormsg);
01355    RES_CONFIG_SQLITE_END(error)
01356 
01357    if (!error)
01358       rows_num = sqlite_changes(db);
01359    else
01360       rows_num = -1;
01361 
01362    ast_mutex_unlock(&mutex);
01363 
01364    sqlite_freemem(query);
01365 
01366    if (error) {
01367       ast_log(LOG_WARNING, "%s\n", errormsg);
01368       sqlite_freemem(errormsg);
01369    }
01370 
01371    return rows_num;
01372 }
01373 
01374 static char *handle_cli_show_sqlite_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01375 {
01376    switch (cmd) {
01377    case CLI_INIT:
01378       e->command = "sqlite show status";
01379       e->usage =
01380          "Usage: sqlite show status\n"
01381          "       Show status information about the SQLite 2 driver\n";
01382       return NULL;
01383    case CLI_GENERATE:
01384       return NULL;
01385    }
01386 
01387    if (a->argc != 3)
01388       return CLI_SHOWUSAGE;
01389 
01390    ast_cli(a->fd, "SQLite database path: %s\n", dbfile);
01391    ast_cli(a->fd, "config_table: ");
01392 
01393    if (!config_table)
01394       ast_cli(a->fd, "unspecified, must be present in extconfig.conf\n");
01395    else
01396       ast_cli(a->fd, "%s\n", config_table);
01397 
01398    ast_cli(a->fd, "cdr_table: ");
01399 
01400    if (!cdr_table)
01401       ast_cli(a->fd, "unspecified, CDR support disabled\n");
01402    else
01403       ast_cli(a->fd, "%s\n", cdr_table);
01404 
01405    return CLI_SUCCESS;
01406 }
01407 
01408 static int unload_module(void)
01409 {
01410    if (cli_status_registered)
01411       ast_cli_unregister_multiple(cli_status, sizeof(cli_status) / sizeof(struct ast_cli_entry));
01412 
01413    if (cdr_registered)
01414       ast_cdr_unregister(RES_CONFIG_SQLITE_NAME);
01415 
01416    ast_config_engine_deregister(&sqlite_engine);
01417 
01418    if (db)
01419       sqlite_close(db);
01420 
01421    unload_config();
01422 
01423    return 0;
01424 }
01425 
01426 static int load_module(void)
01427 {
01428    char *errormsg;
01429    int error;
01430 
01431    db = NULL;
01432    cdr_registered = 0;
01433    cli_status_registered = 0;
01434    dbfile = NULL;
01435    config_table = NULL;
01436    cdr_table = NULL;
01437    error = load_config();
01438 
01439    if (error)
01440       return AST_MODULE_LOAD_DECLINE;
01441 
01442    if (!(db = sqlite_open(dbfile, 0660, &errormsg))) {
01443       ast_log(LOG_ERROR, "%s\n", errormsg);
01444       sqlite_freemem(errormsg);
01445       unload_module();
01446       return 1;
01447    }
01448 
01449    ast_config_engine_register(&sqlite_engine);
01450 
01451    if (use_cdr) {
01452       char *query;
01453 
01454 /* \cond DOXYGEN_CAN_PARSE_THIS */
01455 #undef QUERY
01456 #define QUERY "SELECT COUNT(id) FROM %Q;"
01457 /* \endcond */
01458 
01459       query = sqlite_mprintf(QUERY, cdr_table);
01460 
01461       if (!query) {
01462          ast_log(LOG_ERROR, "Unable to allocate SQL query\n");
01463          unload_module();
01464          return 1;
01465       }
01466 
01467       ast_debug(1, "SQL query: %s\n", query);
01468 
01469       RES_CONFIG_SQLITE_BEGIN
01470          error = sqlite_exec(db, query, NULL, NULL, &errormsg);
01471       RES_CONFIG_SQLITE_END(error)
01472 
01473       sqlite_freemem(query);
01474 
01475       if (error) {
01476          /*
01477           * Unexpected error.
01478           */
01479          if (error != SQLITE_ERROR) {
01480             ast_log(LOG_ERROR, "%s\n", errormsg);
01481             sqlite_freemem(errormsg);
01482             unload_module();
01483             return 1;
01484          }
01485 
01486          sqlite_freemem(errormsg);
01487          query = sqlite_mprintf(sql_create_cdr_table, cdr_table);
01488 
01489          if (!query) {
01490             ast_log(LOG_ERROR, "Unable to allocate SQL query\n");
01491             unload_module();
01492             return 1;
01493          }
01494 
01495          ast_debug(1, "SQL query: %s\n", query);
01496 
01497          RES_CONFIG_SQLITE_BEGIN
01498             error = sqlite_exec(db, query, NULL, NULL, &errormsg);
01499          RES_CONFIG_SQLITE_END(error)
01500 
01501          sqlite_freemem(query);
01502 
01503          if (error) {
01504             ast_log(LOG_ERROR, "%s\n", errormsg);
01505             sqlite_freemem(errormsg);
01506             unload_module();
01507             return 1;
01508          }
01509       }
01510 
01511       error = ast_cdr_register(RES_CONFIG_SQLITE_NAME, RES_CONFIG_SQLITE_DESCRIPTION, cdr_handler);
01512 
01513       if (error) {
01514          unload_module();
01515          return 1;
01516       }
01517 
01518       cdr_registered = 1;
01519    }
01520 
01521    error = ast_cli_register_multiple(cli_status, sizeof(cli_status) / sizeof(struct ast_cli_entry));
01522 
01523    if (error) {
01524       unload_module();
01525       return 1;
01526    }
01527 
01528    cli_status_registered = 1;
01529 
01530    return 0;
01531 }
01532 
01533 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Realtime SQLite configuration",
01534       .load = load_module,
01535       .unload = unload_module,
01536 );

Generated on Thu Jul 9 13:40:39 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7