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 #include "asterisk.h"
00028
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 206807 $")
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <unistd.h>
00034 #include <string.h>
00035 #include <sys/types.h>
00036
00037 #include "asterisk/file.h"
00038 #include "asterisk/channel.h"
00039 #include "asterisk/pbx.h"
00040 #include "asterisk/options.h"
00041 #include "asterisk/config.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/lock.h"
00044 #include "asterisk/logger.h"
00045 #include "asterisk/utils.h"
00046 #include "asterisk/app.h"
00047
00048 static int function_realtime_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
00049 {
00050 struct ast_variable *var, *head;
00051 struct ast_module_user *u;
00052 char *results, *result_begin;
00053 size_t resultslen = 0;
00054 AST_DECLARE_APP_ARGS(args,
00055 AST_APP_ARG(family);
00056 AST_APP_ARG(fieldmatch);
00057 AST_APP_ARG(value);
00058 AST_APP_ARG(delim1);
00059 AST_APP_ARG(delim2);
00060 );
00061
00062
00063 if (ast_strlen_zero(data)) {
00064 ast_log(LOG_WARNING, "Syntax: REALTIME(family|fieldmatch[|value[|delim1[|delim2]]]) - missing argument!\n");
00065 return -1;
00066 }
00067
00068 u = ast_module_user_add(chan);
00069
00070 AST_STANDARD_APP_ARGS(args, data);
00071
00072 if (!args.delim1)
00073 args.delim1 = "|";
00074 if (!args.delim2)
00075 args.delim2 = "=";
00076
00077 if (chan)
00078 ast_autoservice_start(chan);
00079
00080 head = ast_load_realtime(args.family, args.fieldmatch, args.value, NULL);
00081
00082 if (!head) {
00083 ast_module_user_remove(u);
00084 if (chan)
00085 ast_autoservice_stop(chan);
00086 return -1;
00087 }
00088 for (var = head; var; var = var->next)
00089 resultslen += strlen(var->name) + strlen(var->value) + strlen(args.delim1) + strlen(args.delim2);
00090
00091 result_begin = results = alloca(resultslen);
00092 for (var = head; var; var = var->next)
00093 ast_build_string(&results, &resultslen, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1);
00094 ast_copy_string(buf, result_begin, len);
00095
00096 ast_variables_destroy(head);
00097
00098 ast_module_user_remove(u);
00099
00100 if (chan)
00101 ast_autoservice_stop(chan);
00102
00103 return 0;
00104 }
00105
00106 static int function_realtime_write(struct ast_channel *chan, char *cmd, char *data, const char *value)
00107 {
00108 struct ast_module_user *u = NULL;
00109 int res = 0;
00110 AST_DECLARE_APP_ARGS(args,
00111 AST_APP_ARG(family);
00112 AST_APP_ARG(fieldmatch);
00113 AST_APP_ARG(value);
00114 AST_APP_ARG(field);
00115 );
00116
00117 if (ast_strlen_zero(data)) {
00118 ast_log(LOG_WARNING, "Syntax: REALTIME(family|fieldmatch|value|newcol) - missing argument!\n");
00119 return -1;
00120 }
00121
00122 if (chan) {
00123 ast_autoservice_start(chan);
00124 u = ast_module_user_add(chan);
00125 }
00126
00127 AST_STANDARD_APP_ARGS(args, data);
00128
00129 res = ast_update_realtime(args.family, args.fieldmatch, args.value, args.field, (char *)value, NULL);
00130
00131 if (res < 0) {
00132 ast_log(LOG_WARNING, "Failed to update. Check the debug log for possible data repository related entries.\n");
00133 }
00134
00135 if (chan) {
00136 ast_module_user_remove(u);
00137 ast_autoservice_stop(chan);
00138 }
00139
00140 return 0;
00141 }
00142
00143 struct ast_custom_function realtime_function = {
00144 .name = "REALTIME",
00145 .synopsis = "RealTime Read/Write Functions",
00146 .syntax = "REALTIME(family|fieldmatch[|value[|delim1[|delim2]]]) on read\n"
00147 "REALTIME(family|fieldmatch|value|field) on write\n",
00148 .desc = "This function will read or write values from/to a RealTime repository.\n"
00149 "REALTIME(....) will read names/values from the repository, and \n"
00150 "REALTIME(....)= will write a new value/field to the repository. On a\n"
00151 "read, this function returns a delimited text string. The name/value \n"
00152 "pairs are delimited by delim1, and the name and value are delimited \n"
00153 "between each other with delim2. The default for delim1 is '|' and \n"
00154 "the default for delim2 is '='. If there is no match, NULL will be \n"
00155 "returned by the function. On a write, this function will always \n"
00156 "return NULL. \n",
00157 .read = function_realtime_read,
00158 .write = function_realtime_write,
00159 };
00160
00161 static int unload_module(void)
00162 {
00163 int res = ast_custom_function_unregister(&realtime_function);
00164
00165 ast_module_user_hangup_all();
00166
00167 return res;
00168 }
00169
00170 static int load_module(void)
00171 {
00172 int res = ast_custom_function_register(&realtime_function);
00173
00174 return res;
00175 }
00176
00177 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read/Write values from a RealTime repository");