Wed Oct 28 11:51:04 2009

Asterisk developer's documentation


func_config.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2008, Digium, Inc.
00005  *
00006  * Russell Bryant <russell@digium.com>
00007  * Tilghman Lesher <func_config__200803@the-tilghman.com>
00008  *
00009  * See http://www.asterisk.org for more information about
00010  * the Asterisk project. Please do not directly contact
00011  * any of the maintainers of this project for assistance;
00012  * the project provides a web site, mailing lists and IRC
00013  * channels for your use.
00014  *
00015  * This program is free software, distributed under the terms of
00016  * the GNU General Public License Version 2. See the LICENSE file
00017  * at the top of the source tree.
00018  */
00019 
00020 /*! \file
00021  *
00022  * \brief A function to retrieve variables from an Asterisk configuration file
00023  *
00024  * \author Russell Bryant <russell@digium.com>
00025  * \author Tilghman Lesher <func_config__200803@the-tilghman.com>
00026  * 
00027  * \ingroup functions
00028  */
00029 
00030 #include "asterisk.h"
00031 
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 136302 $")
00033 
00034 #include "asterisk/module.h"
00035 #include "asterisk/channel.h"
00036 #include "asterisk/pbx.h"
00037 #include "asterisk/app.h"
00038 
00039 struct config_item {
00040    AST_RWLIST_ENTRY(config_item) entry;
00041    struct ast_config *cfg;
00042    char filename[0];
00043 };
00044 
00045 static AST_RWLIST_HEAD_STATIC(configs, config_item);
00046 
00047 static int config_function_read(struct ast_channel *chan, const char *cmd, char *data, 
00048    char *buf, size_t len) 
00049 {
00050    struct ast_config *cfg;
00051    struct ast_flags cfg_flags = { CONFIG_FLAG_FILEUNCHANGED };
00052    const char *val;
00053    char *parse;
00054    struct config_item *cur;
00055    AST_DECLARE_APP_ARGS(args,
00056       AST_APP_ARG(filename);
00057       AST_APP_ARG(category);
00058       AST_APP_ARG(variable);
00059       AST_APP_ARG(index);
00060    );
00061 
00062    if (ast_strlen_zero(data)) {
00063       ast_log(LOG_ERROR, "AST_CONFIG() requires an argument\n");
00064       return -1;
00065    }
00066 
00067    parse = ast_strdupa(data);
00068    AST_STANDARD_APP_ARGS(args, parse);
00069 
00070    if (ast_strlen_zero(args.filename)) {
00071       ast_log(LOG_ERROR, "AST_CONFIG() requires a filename\n");
00072       return -1;
00073    }
00074 
00075    if (ast_strlen_zero(args.category)) {
00076       ast_log(LOG_ERROR, "AST_CONFIG() requires a category\n");
00077       return -1;
00078    }
00079    
00080    if (ast_strlen_zero(args.variable)) {
00081       ast_log(LOG_ERROR, "AST_CONFIG() requires a variable\n");
00082       return -1;
00083    }
00084 
00085    if (!(cfg = ast_config_load(args.filename, cfg_flags))) {
00086       return -1;
00087    }
00088 
00089    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00090       /* Retrieve cfg from list */
00091       AST_RWLIST_RDLOCK(&configs);
00092       AST_RWLIST_TRAVERSE(&configs, cur, entry) {
00093          if (!strcmp(cur->filename, args.filename)) {
00094             break;
00095          }
00096       }
00097 
00098       if (!cur) {
00099          /* At worst, we might leak an entry while upgrading locks */
00100          AST_RWLIST_UNLOCK(&configs);
00101          AST_RWLIST_WRLOCK(&configs);
00102          if (!(cur = ast_malloc(sizeof(*cur) + strlen(args.filename) + 1))) {
00103             AST_RWLIST_UNLOCK(&configs);
00104             return -1;
00105          }
00106 
00107          strcpy(cur->filename, args.filename);
00108 
00109          ast_clear_flag(&cfg_flags, CONFIG_FLAG_FILEUNCHANGED);
00110          if (!(cfg = ast_config_load(args.filename, cfg_flags))) {
00111             ast_free(cur);
00112             AST_RWLIST_UNLOCK(&configs);
00113             return -1;
00114          }
00115 
00116          cur->cfg = cfg;
00117          AST_RWLIST_INSERT_TAIL(&configs, cur, entry);
00118       }
00119 
00120       cfg = cur->cfg;
00121    } else {
00122       /* Replace cfg in list */
00123       AST_RWLIST_WRLOCK(&configs);
00124       AST_RWLIST_TRAVERSE(&configs, cur, entry) {
00125          if (!strcmp(cur->filename, args.filename)) {
00126             break;
00127          }
00128       }
00129 
00130       if (!cur) {
00131          if (!(cur = ast_malloc(sizeof(*cur) + strlen(args.filename) + 1))) {
00132             AST_RWLIST_UNLOCK(&configs);
00133             return -1;
00134          }
00135 
00136          strcpy(cur->filename, args.filename);
00137          cur->cfg = cfg;
00138 
00139          AST_RWLIST_INSERT_TAIL(&configs, cur, entry);
00140       } else {
00141          ast_config_destroy(cur->cfg);
00142          cur->cfg = cfg;
00143       }
00144    }
00145 
00146    if (!(val = ast_variable_retrieve(cfg, args.category, args.variable))) {
00147       ast_log(LOG_ERROR, "'%s' not found in [%s] of '%s'\n", args.variable, 
00148          args.category, args.filename);
00149       AST_RWLIST_UNLOCK(&configs);
00150       return -1;
00151    }
00152 
00153    ast_copy_string(buf, val, len);
00154 
00155    /* Unlock down here, so there's no chance the struct goes away while we're using it. */
00156    AST_RWLIST_UNLOCK(&configs);
00157 
00158    return 0;
00159 }
00160 
00161 static struct ast_custom_function config_function = {
00162    .name = "AST_CONFIG",
00163    .syntax = "AST_CONFIG(config_file,category,variable_name)",
00164    .synopsis = "Retrieve a variable from a configuration file",
00165    .desc = 
00166    "   This function reads a variable from an Asterisk configuration file.\n"
00167    "",
00168    .read = config_function_read,
00169 };
00170 
00171 static int unload_module(void)
00172 {
00173    struct config_item *current;
00174    int res = ast_custom_function_unregister(&config_function);
00175 
00176    AST_RWLIST_WRLOCK(&configs);
00177    while ((current = AST_RWLIST_REMOVE_HEAD(&configs, entry))) {
00178       ast_config_destroy(current->cfg);
00179       ast_free(current);
00180    }
00181    AST_RWLIST_UNLOCK(&configs);
00182 
00183    return res;
00184 }
00185 
00186 static int load_module(void)
00187 {
00188    return ast_custom_function_register(&config_function);
00189 }
00190 
00191 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Asterisk configuration file variable access");

Generated on Wed Oct 28 11:51:04 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6