Update groupcount / db documentation (bug #4200, etc)
[asterisk/asterisk.git] / apps / app_groupcount.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Group Manipulation Applications
5  *
6  * Copyright (c) 2004 - 2005, Digium Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include <sys/types.h>
19 #include <regex.h>
20
21 #include "asterisk/file.h"
22 #include "asterisk/logger.h"
23 #include "asterisk/options.h"
24 #include "asterisk/channel.h"
25 #include "asterisk/pbx.h"
26 #include "asterisk/module.h"
27 #include "asterisk/utils.h"
28 #include "asterisk/cli.h"
29 #include "asterisk/app.h"
30
31 STANDARD_LOCAL_USER;
32
33 LOCAL_USER_DECL;
34
35 static int group_count_exec(struct ast_channel *chan, void *data)
36 {
37         int res = 0;
38         int count;
39         struct localuser *u;
40         char group[80] = "";
41         char category[80] = "";
42         char ret[80] = "";
43         char *grp;
44         static int deprecation_warning = 0;
45
46         LOCAL_USER_ADD(u);
47
48         if (!deprecation_warning) {
49                 ast_log(LOG_WARNING, "The GetGroupCount application has been deprecated, please use the GROUP_COUNT function.\n");
50                 deprecation_warning = 1;
51         }
52
53         ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category));
54
55         if (ast_strlen_zero(group)) {
56                 grp = pbx_builtin_getvar_helper(chan, category);
57                 strncpy(group, grp, sizeof(group) - 1);
58         }
59
60         count = ast_app_group_get_count(group, category);
61         snprintf(ret, sizeof(ret), "%d", count);
62         pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
63
64         LOCAL_USER_REMOVE(u);
65
66         return res;
67 }
68
69 static int group_match_count_exec(struct ast_channel *chan, void *data)
70 {
71         int res = 0;
72         int count;
73         struct localuser *u;
74         char group[80] = "";
75         char category[80] = "";
76         char ret[80] = "";
77         static int deprecation_warning = 0;
78
79         LOCAL_USER_ADD(u);
80
81         if (!deprecation_warning) {
82                 ast_log(LOG_WARNING, "The GetGroupMatchCount application has been deprecated, please use the GROUP_MATCH_COUNT function.\n");
83                 deprecation_warning = 1;
84         }
85
86         ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category));
87
88         if (!ast_strlen_zero(group)) {
89                 count = ast_app_group_match_get_count(group, category);
90                 snprintf(ret, sizeof(ret), "%d", count);
91                 pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
92         }
93
94         LOCAL_USER_REMOVE(u);
95
96         return res;
97 }
98
99 static int group_set_exec(struct ast_channel *chan, void *data)
100 {
101         int res = 0;
102         struct localuser *u;
103         static int deprecation_warning = 0;
104
105         if (!deprecation_warning) {
106                 ast_log(LOG_WARNING, "The SetGroup application has been deprecated, please use the GROUP() function.\n");
107                 deprecation_warning = 1;
108         }
109
110         LOCAL_USER_ADD(u);
111
112         if (ast_app_group_set_channel(chan, data))
113                 ast_log(LOG_WARNING, "SetGroup requires an argument (group name)\n");
114
115         LOCAL_USER_REMOVE(u);
116         return res;
117 }
118
119 static int group_check_exec(struct ast_channel *chan, void *data)
120 {
121         int res = 0;
122         int max, count;
123         struct localuser *u;
124         char limit[80]="";
125         char category[80]="";
126         static int deprecation_warning = 0;
127
128         LOCAL_USER_ADD(u);
129
130         if (!deprecation_warning) {
131                 ast_log(LOG_WARNING, "The CheckGroup application has been deprecated, please use a combination of the GotoIf application and the GROUP_COUNT() function.\n");
132                 deprecation_warning = 1;
133         }
134
135         if (!data || ast_strlen_zero(data)) {
136                 ast_log(LOG_WARNING, "CheckGroup requires an argument(max[@category])\n");
137                 return res;
138         }
139
140         ast_app_group_split_group(data, limit, sizeof(limit), category, sizeof(category));
141
142         if ((sscanf(limit, "%d", &max) == 1) && (max > -1)) {
143                 count = ast_app_group_get_count(pbx_builtin_getvar_helper(chan, category), category);
144                 if (count > max) {
145                         if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num))
146                                 chan->priority += 100;
147                         else
148                                 res = -1;
149                 }
150         } else
151                 ast_log(LOG_WARNING, "CheckGroup requires a positive integer argument (max)\n");
152
153         LOCAL_USER_REMOVE(u);
154         return res;
155 }
156
157 static int group_show_channels(int fd, int argc, char *argv[])
158 {
159 #define FORMAT_STRING  "%-25s  %-20s  %-20s\n"
160
161         struct ast_channel *c = NULL;
162         int numchans = 0;
163         struct ast_var_t *current;
164         struct varshead *headp;
165         regex_t regexbuf;
166         int havepattern = 0;
167
168         if (argc < 3 || argc > 4)
169                 return RESULT_SHOWUSAGE;
170         
171         if (argc == 4) {
172                 if (regcomp(&regexbuf, argv[3], REG_EXTENDED | REG_NOSUB))
173                         return RESULT_SHOWUSAGE;
174                 havepattern = 1;
175         }
176
177         c = ast_channel_walk_locked(NULL);
178         ast_cli(fd, FORMAT_STRING, "Channel", "Group", "Category");
179         while(c) {
180                 headp=&c->varshead;
181                 AST_LIST_TRAVERSE(headp,current,entries) {
182                         if (!strncmp(ast_var_name(current), GROUP_CATEGORY_PREFIX "_", strlen(GROUP_CATEGORY_PREFIX) + 1)) {
183                                 if (!havepattern || !regexec(&regexbuf, ast_var_value(current), 0, NULL, 0)) {
184                                         ast_cli(fd, FORMAT_STRING, c->name, ast_var_value(current),
185                                                 (ast_var_name(current) + strlen(GROUP_CATEGORY_PREFIX) + 1));
186                                         numchans++;
187                                 }
188                         } else if (!strcmp(ast_var_name(current), GROUP_CATEGORY_PREFIX)) {
189                                 if (!havepattern || !regexec(&regexbuf, ast_var_value(current), 0, NULL, 0)) {
190                                         ast_cli(fd, FORMAT_STRING, c->name, ast_var_value(current), "(default)");
191                                         numchans++;
192                                 }
193                         }
194                 }
195                 numchans++;
196                 ast_mutex_unlock(&c->lock);
197                 c = ast_channel_walk_locked(c);
198         }
199
200         if (havepattern)
201                 regfree(&regexbuf);
202
203         ast_cli(fd, "%d active channel(s)\n", numchans);
204         return RESULT_SUCCESS;
205 }
206
207 static char *tdesc = "Group Management Routines";
208
209 static char *app_group_count = "GetGroupCount";
210 static char *app_group_set = "SetGroup";
211 static char *app_group_check = "CheckGroup";
212 static char *app_group_match_count = "GetGroupMatchCount";
213
214 static char *group_count_synopsis = "Get the channel count of a group";
215 static char *group_set_synopsis = "Set the channel's group";
216 static char *group_check_synopsis = "Check the channel count of a group against a limit";
217 static char *group_match_count_synopsis = "Get the channel count of all groups that match a pattern";
218
219 static char *group_count_descrip =
220 "Usage: GetGroupCount([groupname][@category])\n"
221 "  Calculates the group count for the specified group, or uses\n"
222 "the current channel's group if not specifed (and non-empty).\n"
223 "Stores result in GROUPCOUNT.  Always returns 0.\n"
224 "This application has been deprecated, please use the function\n"
225 "GroupCount.\n";
226
227 static char *group_set_descrip =
228 "Usage: SetGroup(groupname[@category])\n"
229 "  Sets the channel group to the specified value.  Equivalent to\n"
230 "SetVar(GROUP=group).  Always returns 0.\n";
231
232 static char *group_check_descrip =
233 "Usage: CheckGroup(max[@category])\n"
234 "  Checks that the current number of total channels in the\n"
235 "current channel's group does not exceed 'max'.  If the number\n"
236 "does not exceed 'max', we continue to the next step. If the\n"
237 "number does in fact exceed max, if priority n+101 exists, then\n"
238 "execution continues at that step, otherwise -1 is returned.\n";
239
240 static char *group_match_count_descrip =
241 "Usage: GetGroupMatchCount(groupmatch[@category])\n"
242 "  Calculates the group count for all groups that match the specified\n"
243 "pattern. Uses standard regular expression matching (see regex(7)).\n"
244 "Stores result in GROUPCOUNT.  Always returns 0.\n"
245 "This application has been deprecated, please use the function\n"
246 "GroupMatchCount.\n";
247
248 static char show_channels_usage[] = 
249 "Usage: group show channels [pattern]\n"
250 "       Lists all currently active channels with channel group(s) specified.\n       Optional regular expression pattern is matched to group names for each channel.\n";
251
252 static struct ast_cli_entry  cli_show_channels =
253         { { "group", "show", "channels", NULL }, group_show_channels, "Show active channels with group(s)", show_channels_usage};
254
255 int unload_module(void)
256 {
257         int res;
258         STANDARD_HANGUP_LOCALUSERS;
259         ast_cli_unregister(&cli_show_channels);
260         res = ast_unregister_application(app_group_count);
261         res |= ast_unregister_application(app_group_set);
262         res |= ast_unregister_application(app_group_check);
263         res |= ast_unregister_application(app_group_match_count);
264         return res;
265 }
266
267 int load_module(void)
268 {
269         int res;
270         res = ast_register_application(app_group_count, group_count_exec, group_count_synopsis, group_count_descrip);
271         res |= ast_register_application(app_group_set, group_set_exec, group_set_synopsis, group_set_descrip);
272         res |= ast_register_application(app_group_check, group_check_exec, group_check_synopsis, group_check_descrip);
273         res |= ast_register_application(app_group_match_count, group_match_count_exec, group_match_count_synopsis, group_match_count_descrip);
274         ast_cli_register(&cli_show_channels);
275         return res;
276 }
277
278 char *description(void)
279 {
280         return tdesc;
281 }
282
283 int usecount(void)
284 {
285         int res;
286         STANDARD_USECOUNT(res);
287         return res;
288 }
289
290 char *key()
291 {
292         return ASTERISK_GPL_KEY;
293 }