1f67fcb464086cc27c4af32e5ebcb051f3c74998
[asterisk/asterisk.git] / funcs / func_realtime.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2005-2006, BJ Weschke. All rights reserved.
5  * 
6  * BJ Weschke <bweschke@btwtech.com>
7  * 
8  * This code is released by the author with no restrictions on usage. 
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  */
17
18 /*! \file
19  *
20  * \brief REALTIME dialplan function
21  * 
22  * \author BJ Weschke <bweschke@btwtech.com>
23  * 
24  * \ingroup functions
25  */
26
27 #include "asterisk.h"
28
29 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <sys/types.h>
36
37 #include "asterisk/file.h"
38 #include "asterisk/channel.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/options.h"
41 #include "asterisk/config.h"
42 #include "asterisk/module.h"
43 #include "asterisk/lock.h"
44 #include "asterisk/logger.h"
45 #include "asterisk/utils.h"
46 #include "asterisk/app.h"
47
48 static int function_realtime_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) 
49 {
50         struct ast_variable *var, *head;
51         struct ast_str *out;
52         size_t resultslen;
53         int n;
54         AST_DECLARE_APP_ARGS(args,
55                 AST_APP_ARG(family);
56                 AST_APP_ARG(fieldmatch);
57                 AST_APP_ARG(value);
58                 AST_APP_ARG(delim1);
59                 AST_APP_ARG(delim2);
60         );
61
62         if (ast_strlen_zero(data)) {
63                 ast_log(LOG_WARNING, "Syntax: REALTIME(family,fieldmatch[,value[,delim1[,delim2]]]) - missing argument!\n");
64                 return -1;
65         }
66
67         AST_STANDARD_APP_ARGS(args, data);
68
69         if (!args.delim1)
70                 args.delim1 = ",";
71         if (!args.delim2)
72                 args.delim2 = "=";
73
74         head = ast_load_realtime_all(args.family, args.fieldmatch, args.value, NULL);
75
76         if (!head)
77                 return -1;
78
79         resultslen = 0;
80         n = 0;
81         for (var = head; var; n++, var = var->next)
82                 resultslen += strlen(var->name) + strlen(var->value);
83         /* add space for delimiters and final '\0' */
84         resultslen += n * (strlen(args.delim1) + strlen(args.delim2)) + 1;
85
86         out = ast_str_alloca(resultslen);
87         for (var = head; var; var = var->next)
88                 ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1);
89         ast_copy_string(buf, out->str, len);
90
91         return 0;
92 }
93
94 static int function_realtime_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
95 {
96         int res = 0;
97         AST_DECLARE_APP_ARGS(args,
98                 AST_APP_ARG(family);
99                 AST_APP_ARG(fieldmatch);
100                 AST_APP_ARG(value);
101                 AST_APP_ARG(field);
102         );
103
104         if (ast_strlen_zero(data)) {
105                 ast_log(LOG_WARNING, "Syntax: REALTIME(family,fieldmatch,value,newcol) - missing argument!\n");
106                 return -1;
107         }
108
109         AST_STANDARD_APP_ARGS(args, data);
110
111         res = ast_update_realtime(args.family, args.fieldmatch, args.value, args.field, (char *)value, NULL);
112
113         if (res < 0) {
114                 ast_log(LOG_WARNING, "Failed to update. Check the debug log for possible data repository related entries.\n");
115         }
116
117         return 0;
118 }
119
120 struct ast_custom_function realtime_function = {
121         .name = "REALTIME",
122         .synopsis = "RealTime Read/Write Functions",
123         .syntax = "REALTIME(family,fieldmatch[,value[,delim1[,delim2]]]) on read\n"
124                   "REALTIME(family,fieldmatch,value,field) on write",
125         .desc = "This function will read or write values from/to a RealTime repository.\n"
126                 "REALTIME(....) will read names/values from the repository, and \n"
127                 "REALTIME(....)= will write a new value/field to the repository. On a\n"
128                 "read, this function returns a delimited text string. The name/value \n"
129                 "pairs are delimited by delim1, and the name and value are delimited \n"
130                 "between each other with delim2. The default for delim1 is ',' and   \n"
131                 "the default for delim2 is '='. If there is no match, NULL will be   \n"
132                 "returned by the function. On a write, this function will always     \n"
133                 "return NULL. \n",
134         .read = function_realtime_read,
135         .write = function_realtime_write,
136 };
137
138 static int unload_module(void)
139 {
140         return ast_custom_function_unregister(&realtime_function);
141 }
142
143 static int load_module(void)
144 {
145         return ast_custom_function_register(&realtime_function);
146 }
147
148 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read/Write values from a RealTime repository");