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: 153365 $")
00033
00034 #include "asterisk/module.h"
00035 #include "asterisk/channel.h"
00036 #include "asterisk/pbx.h"
00037 #include "asterisk/app.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 struct config_item {
00057 AST_RWLIST_ENTRY(config_item) entry;
00058 struct ast_config *cfg;
00059 char filename[0];
00060 };
00061
00062 static AST_RWLIST_HEAD_STATIC(configs, config_item);
00063
00064 static int config_function_read(struct ast_channel *chan, const char *cmd, char *data,
00065 char *buf, size_t len)
00066 {
00067 struct ast_config *cfg;
00068 struct ast_flags cfg_flags = { CONFIG_FLAG_FILEUNCHANGED };
00069 const char *val;
00070 char *parse;
00071 struct config_item *cur;
00072 AST_DECLARE_APP_ARGS(args,
00073 AST_APP_ARG(filename);
00074 AST_APP_ARG(category);
00075 AST_APP_ARG(variable);
00076 AST_APP_ARG(index);
00077 );
00078
00079 if (ast_strlen_zero(data)) {
00080 ast_log(LOG_ERROR, "AST_CONFIG() requires an argument\n");
00081 return -1;
00082 }
00083
00084 parse = ast_strdupa(data);
00085 AST_STANDARD_APP_ARGS(args, parse);
00086
00087 if (ast_strlen_zero(args.filename)) {
00088 ast_log(LOG_ERROR, "AST_CONFIG() requires a filename\n");
00089 return -1;
00090 }
00091
00092 if (ast_strlen_zero(args.category)) {
00093 ast_log(LOG_ERROR, "AST_CONFIG() requires a category\n");
00094 return -1;
00095 }
00096
00097 if (ast_strlen_zero(args.variable)) {
00098 ast_log(LOG_ERROR, "AST_CONFIG() requires a variable\n");
00099 return -1;
00100 }
00101
00102 if (!(cfg = ast_config_load(args.filename, cfg_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
00103 return -1;
00104 }
00105
00106 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00107
00108 AST_RWLIST_RDLOCK(&configs);
00109 AST_RWLIST_TRAVERSE(&configs, cur, entry) {
00110 if (!strcmp(cur->filename, args.filename)) {
00111 break;
00112 }
00113 }
00114
00115 if (!cur) {
00116
00117 AST_RWLIST_UNLOCK(&configs);
00118 AST_RWLIST_WRLOCK(&configs);
00119 if (!(cur = ast_malloc(sizeof(*cur) + strlen(args.filename) + 1))) {
00120 AST_RWLIST_UNLOCK(&configs);
00121 return -1;
00122 }
00123
00124 strcpy(cur->filename, args.filename);
00125
00126 ast_clear_flag(&cfg_flags, CONFIG_FLAG_FILEUNCHANGED);
00127 if (!(cfg = ast_config_load(args.filename, cfg_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
00128 ast_free(cur);
00129 AST_RWLIST_UNLOCK(&configs);
00130 return -1;
00131 }
00132
00133 cur->cfg = cfg;
00134 AST_RWLIST_INSERT_TAIL(&configs, cur, entry);
00135 }
00136
00137 cfg = cur->cfg;
00138 } else {
00139
00140 AST_RWLIST_WRLOCK(&configs);
00141 AST_RWLIST_TRAVERSE(&configs, cur, entry) {
00142 if (!strcmp(cur->filename, args.filename)) {
00143 break;
00144 }
00145 }
00146
00147 if (!cur) {
00148 if (!(cur = ast_malloc(sizeof(*cur) + strlen(args.filename) + 1))) {
00149 AST_RWLIST_UNLOCK(&configs);
00150 return -1;
00151 }
00152
00153 strcpy(cur->filename, args.filename);
00154 cur->cfg = cfg;
00155
00156 AST_RWLIST_INSERT_TAIL(&configs, cur, entry);
00157 } else {
00158 ast_config_destroy(cur->cfg);
00159 cur->cfg = cfg;
00160 }
00161 }
00162
00163 if (!(val = ast_variable_retrieve(cfg, args.category, args.variable))) {
00164 ast_log(LOG_ERROR, "'%s' not found in [%s] of '%s'\n", args.variable,
00165 args.category, args.filename);
00166 AST_RWLIST_UNLOCK(&configs);
00167 return -1;
00168 }
00169
00170 ast_copy_string(buf, val, len);
00171
00172
00173 AST_RWLIST_UNLOCK(&configs);
00174
00175 return 0;
00176 }
00177
00178 static struct ast_custom_function config_function = {
00179 .name = "AST_CONFIG",
00180 .read = config_function_read,
00181 };
00182
00183 static int unload_module(void)
00184 {
00185 struct config_item *current;
00186 int res = ast_custom_function_unregister(&config_function);
00187
00188 AST_RWLIST_WRLOCK(&configs);
00189 while ((current = AST_RWLIST_REMOVE_HEAD(&configs, entry))) {
00190 ast_config_destroy(current->cfg);
00191 ast_free(current);
00192 }
00193 AST_RWLIST_UNLOCK(&configs);
00194
00195 return res;
00196 }
00197
00198 static int load_module(void)
00199 {
00200 return ast_custom_function_register(&config_function);
00201 }
00202
00203 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Asterisk configuration file variable access");