00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
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
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
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");