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: 153365 $")
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
00138 if (ast_strlen_zero(data)) {
00139 ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
00140 return -1;
00141 }
00142
00143 AST_STANDARD_APP_ARGS(args, data);
00144
00145 if (!ast_strlen_zero(args.chan)) {
00146 char *prefix = alloca(strlen(args.chan) + 2);
00147 sprintf(prefix, "%s-", args.chan);
00148 if (!(chan = ast_get_channel_by_name_locked(args.chan)) && !(chan = ast_get_channel_by_name_prefix_locked(prefix, strlen(prefix)))) {
00149 ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' will be blank.\n", args.chan, args.var);
00150 return -1;
00151 }
00152 } else
00153 ast_channel_lock(chan);
00154
00155 if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
00156 ast_channel_unlock(chan);
00157 return -1;
00158 }
00159
00160 varshead = varstore->data;
00161 *buf = '\0';
00162
00163
00164 AST_LIST_TRAVERSE(varshead, var, entries) {
00165 if (!strcmp(args.var, ast_var_name(var))) {
00166 ast_copy_string(buf, ast_var_value(var), len);
00167 break;
00168 }
00169 }
00170
00171 ast_channel_unlock(chan);
00172
00173 return 0;
00174 }
00175
00176 static int shared_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00177 {
00178 struct ast_datastore *varstore;
00179 struct varshead *varshead;
00180 struct ast_var_t *var;
00181 AST_DECLARE_APP_ARGS(args,
00182 AST_APP_ARG(var);
00183 AST_APP_ARG(chan);
00184 );
00185
00186 if (ast_strlen_zero(data)) {
00187 ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
00188 return -1;
00189 }
00190
00191 AST_STANDARD_APP_ARGS(args, data);
00192
00193 if (!ast_strlen_zero(args.chan)) {
00194 char *prefix = alloca(strlen(args.chan) + 2);
00195 sprintf(prefix, "%s-", args.chan);
00196 if (!(chan = ast_get_channel_by_name_locked(args.chan)) && !(chan = ast_get_channel_by_name_prefix_locked(prefix, strlen(prefix)))) {
00197 ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' not set to '%s'.\n", args.chan, args.var, value);
00198 return -1;
00199 }
00200 } else
00201 ast_channel_lock(chan);
00202
00203 if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
00204 if (!(varstore = ast_datastore_alloc(&shared_variable_info, NULL))) {
00205 ast_log(LOG_ERROR, "Unable to allocate new datastore. Shared variable not set.\n");
00206 ast_channel_unlock(chan);
00207 return -1;
00208 }
00209
00210 if (!(varshead = ast_calloc(1, sizeof(*varshead)))) {
00211 ast_log(LOG_ERROR, "Unable to allocate variable structure. Shared variable not set.\n");
00212 ast_datastore_free(varstore);
00213 ast_channel_unlock(chan);
00214 return -1;
00215 }
00216
00217 varstore->data = varshead;
00218 ast_channel_datastore_add(chan, varstore);
00219 }
00220 varshead = varstore->data;
00221
00222
00223 AST_LIST_TRAVERSE(varshead, var, entries) {
00224
00225 if (!strcmp(args.var, ast_var_name(var))) {
00226 AST_LIST_REMOVE(varshead, var, entries);
00227 ast_var_delete(var);
00228 break;
00229 }
00230 }
00231
00232 var = ast_var_assign(args.var, S_OR(value, ""));
00233 AST_LIST_INSERT_HEAD(varshead, var, entries);
00234 manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
00235 "Channel: %s\r\n"
00236 "Variable: SHARED(%s)\r\n"
00237 "Value: %s\r\n"
00238 "Uniqueid: %s\r\n",
00239 chan ? chan->name : "none", args.var, value,
00240 chan ? chan->uniqueid : "none");
00241
00242 ast_channel_unlock(chan);
00243
00244 return 0;
00245 }
00246
00247 static struct ast_custom_function shared_function = {
00248 .name = "SHARED",
00249 .read = shared_read,
00250 .write = shared_write,
00251 };
00252
00253 static int unload_module(void)
00254 {
00255 int res = 0;
00256
00257 res |= ast_custom_function_unregister(&global_function);
00258 res |= ast_custom_function_unregister(&shared_function);
00259
00260 return res;
00261 }
00262
00263 static int load_module(void)
00264 {
00265 int res = 0;
00266
00267 res |= ast_custom_function_register(&global_function);
00268 res |= ast_custom_function_register(&shared_function);
00269
00270 return res;
00271 }
00272
00273 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Variable dialplan functions");