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 #include "asterisk.h"
00029
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 190423 $")
00031
00032 #include <sys/stat.h>
00033
00034 #include "asterisk/module.h"
00035 #include "asterisk/pbx.h"
00036 #include "asterisk/channel.h"
00037 #include "asterisk/app.h"
00038 #include "asterisk/manager.h"
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 static void shared_variable_free(void *data);
00086
00087 static struct ast_datastore_info shared_variable_info = {
00088 .type = "SHARED_VARIABLES",
00089 .destroy = shared_variable_free,
00090 };
00091
00092 static void shared_variable_free(void *data)
00093 {
00094 struct varshead *varshead = data;
00095 struct ast_var_t *var;
00096
00097 while ((var = AST_LIST_REMOVE_HEAD(varshead, entries))) {
00098 ast_var_delete(var);
00099 }
00100 ast_free(varshead);
00101 }
00102
00103 static int global_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00104 {
00105 const char *var = pbx_builtin_getvar_helper(NULL, data);
00106
00107 *buf = '\0';
00108
00109 if (var)
00110 ast_copy_string(buf, var, len);
00111
00112 return 0;
00113 }
00114
00115 static int global_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00116 {
00117 pbx_builtin_setvar_helper(NULL, data, value);
00118
00119 return 0;
00120 }
00121
00122 static struct ast_custom_function global_function = {
00123 .name = "GLOBAL",
00124 .read = global_read,
00125 .write = global_write,
00126 };
00127
00128 static int shared_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00129 {
00130 struct ast_datastore *varstore;
00131 struct varshead *varshead;
00132 struct ast_var_t *var;
00133 AST_DECLARE_APP_ARGS(args,
00134 AST_APP_ARG(var);
00135 AST_APP_ARG(chan);
00136 );
00137 struct ast_channel *c_ref = NULL;
00138
00139 if (ast_strlen_zero(data)) {
00140 ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
00141 return -1;
00142 }
00143
00144 AST_STANDARD_APP_ARGS(args, data);
00145
00146 if (!ast_strlen_zero(args.chan)) {
00147 char *prefix = alloca(strlen(args.chan) + 2);
00148 sprintf(prefix, "%s-", args.chan);
00149 if (!(c_ref = ast_channel_get_by_name(args.chan)) && !(c_ref = ast_channel_get_by_name_prefix(prefix, strlen(prefix)))) {
00150 ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' will be blank.\n", args.chan, args.var);
00151 return -1;
00152 }
00153 chan = c_ref;
00154 }
00155
00156 ast_channel_lock(chan);
00157
00158 if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
00159 ast_channel_unlock(chan);
00160 if (c_ref) {
00161 c_ref = ast_channel_unref(c_ref);
00162 }
00163 return -1;
00164 }
00165
00166 varshead = varstore->data;
00167 *buf = '\0';
00168
00169
00170 AST_LIST_TRAVERSE(varshead, var, entries) {
00171 if (!strcmp(args.var, ast_var_name(var))) {
00172 ast_copy_string(buf, ast_var_value(var), len);
00173 break;
00174 }
00175 }
00176
00177 ast_channel_unlock(chan);
00178
00179 if (c_ref) {
00180 c_ref = ast_channel_unref(c_ref);
00181 }
00182
00183 return 0;
00184 }
00185
00186 static int shared_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00187 {
00188 struct ast_datastore *varstore;
00189 struct varshead *varshead;
00190 struct ast_var_t *var;
00191 AST_DECLARE_APP_ARGS(args,
00192 AST_APP_ARG(var);
00193 AST_APP_ARG(chan);
00194 );
00195 struct ast_channel *c_ref = NULL;
00196
00197 if (ast_strlen_zero(data)) {
00198 ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
00199 return -1;
00200 }
00201
00202 AST_STANDARD_APP_ARGS(args, data);
00203
00204 if (!ast_strlen_zero(args.chan)) {
00205 char *prefix = alloca(strlen(args.chan) + 2);
00206 sprintf(prefix, "%s-", args.chan);
00207 if (!(c_ref = ast_channel_get_by_name(args.chan)) && !(c_ref = ast_channel_get_by_name_prefix(prefix, strlen(prefix)))) {
00208 ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' not set to '%s'.\n", args.chan, args.var, value);
00209 return -1;
00210 }
00211 chan = c_ref;
00212 }
00213
00214 ast_channel_lock(chan);
00215
00216 if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
00217 if (!(varstore = ast_datastore_alloc(&shared_variable_info, NULL))) {
00218 ast_log(LOG_ERROR, "Unable to allocate new datastore. Shared variable not set.\n");
00219 ast_channel_unlock(chan);
00220 if (c_ref) {
00221 c_ref = ast_channel_unref(c_ref);
00222 }
00223 return -1;
00224 }
00225
00226 if (!(varshead = ast_calloc(1, sizeof(*varshead)))) {
00227 ast_log(LOG_ERROR, "Unable to allocate variable structure. Shared variable not set.\n");
00228 ast_datastore_free(varstore);
00229 ast_channel_unlock(chan);
00230 if (c_ref) {
00231 c_ref = ast_channel_unref(c_ref);
00232 }
00233 return -1;
00234 }
00235
00236 varstore->data = varshead;
00237 ast_channel_datastore_add(chan, varstore);
00238 }
00239 varshead = varstore->data;
00240
00241
00242 AST_LIST_TRAVERSE(varshead, var, entries) {
00243
00244 if (!strcmp(args.var, ast_var_name(var))) {
00245 AST_LIST_REMOVE(varshead, var, entries);
00246 ast_var_delete(var);
00247 break;
00248 }
00249 }
00250
00251 var = ast_var_assign(args.var, S_OR(value, ""));
00252 AST_LIST_INSERT_HEAD(varshead, var, entries);
00253 manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
00254 "Channel: %s\r\n"
00255 "Variable: SHARED(%s)\r\n"
00256 "Value: %s\r\n"
00257 "Uniqueid: %s\r\n",
00258 chan ? chan->name : "none", args.var, value,
00259 chan ? chan->uniqueid : "none");
00260
00261 ast_channel_unlock(chan);
00262
00263 if (c_ref) {
00264 c_ref = ast_channel_unref(c_ref);
00265 }
00266
00267 return 0;
00268 }
00269
00270 static struct ast_custom_function shared_function = {
00271 .name = "SHARED",
00272 .read = shared_read,
00273 .write = shared_write,
00274 };
00275
00276 static int unload_module(void)
00277 {
00278 int res = 0;
00279
00280 res |= ast_custom_function_unregister(&global_function);
00281 res |= ast_custom_function_unregister(&shared_function);
00282
00283 return res;
00284 }
00285
00286 static int load_module(void)
00287 {
00288 int res = 0;
00289
00290 res |= ast_custom_function_register(&global_function);
00291 res |= ast_custom_function_register(&shared_function);
00292
00293 return res;
00294 }
00295
00296 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Variable dialplan functions");