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