Allow multiple groups (group categories)
[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 Digium
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 <asterisk/file.h>
19 #include <asterisk/logger.h>
20 #include <asterisk/options.h>
21 #include <asterisk/channel.h>
22 #include <asterisk/pbx.h>
23 #include <asterisk/module.h>
24 #include <asterisk/utils.h>
25
26 static char *tdesc = "Group Management Routines";
27
28 static char *app_group_count = "GetGroupCount";
29 static char *app_group_set = "SetGroup";
30 static char *app_group_check = "CheckGroup";
31
32 static char *group_count_synopsis = "GetGroupCount([groupname][@category])";
33 static char *group_set_synopsis = "SetGroup(groupname[@category])";
34 static char *group_check_synopsis = "CheckGroup(max[@category])";
35
36 static char *group_count_descrip =
37 "GetGroupCount([group][@category])\n"
38 "  Calculates the group count for the specified group, or uses\n"
39 "the current channel's group if not specifed (and non-empty).\n"
40 "Stores result in GROUPCOUNT.  Always returns 0.\n";
41
42 static char *group_set_descrip =
43 "SetGroup(group)\n"
44 "  Sets the channel group to the specified value.  Equivalent to\n"
45 "SetVar(GROUP=group).  Always returns 0.\n";
46
47 static char *group_check_descrip =
48 "CheckGroup(max)\n"
49 "  Checks that the current number of total channels in the\n"
50 "current channel's group does not exceed 'max'.  If the number\n"
51 "does not exceed 'max', we continue to the next step. If the\n"
52 "number does in fact exceed max, if priority n+101 exists, then\n"
53 "execution continues at that step, otherwise -1 is returned.\n";
54
55 STANDARD_LOCAL_USER;
56
57 LOCAL_USER_DECL;
58
59 #define DEFAULT_CATEGORY "GROUP"
60
61 static int group_get_count(char *group, char *category)
62 {
63         struct ast_channel *chan;
64         int count = 0;
65         char *test;
66         if (group && !ast_strlen_zero(group)) {
67                 chan = ast_channel_walk_locked(NULL);
68                 while(chan) {
69                         test = pbx_builtin_getvar_helper(chan, category);
70                         if (test && !strcasecmp(test, group))
71                                 count++;
72                         ast_mutex_unlock(&chan->lock);
73                         chan = ast_channel_walk_locked(chan);
74                 }
75         }
76         return count;
77 }
78
79 static int group_count_exec(struct ast_channel *chan, void *data)
80 {
81         int res=0;
82         int count;
83         struct localuser *u;
84         char *group=NULL;
85         char *cat = NULL;
86         char ret[80]="";
87         char tmp[256]="";
88
89         LOCAL_USER_ADD(u);
90
91         /* Check and parse arguments */
92         if (data && !ast_strlen_zero(data)) {
93                 strncpy(tmp, data, sizeof(tmp) - 1);
94                 group = tmp;
95                 cat = strchr(tmp, '@');
96                 if (cat) {
97                         *cat = '\0';
98                         cat++;
99                 }
100         }
101         if (cat)
102                 snprintf(ret, sizeof(ret), "GROUP_%s", cat);
103         else
104                 strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
105
106         if (!group || ast_strlen_zero(group)) {
107                 group = pbx_builtin_getvar_helper(chan, ret);
108         }
109         count = group_get_count(group, ret);
110         snprintf(ret, sizeof(ret), "%d", count);
111         pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
112         LOCAL_USER_REMOVE(u);
113         return res;
114 }
115
116 static int group_set_exec(struct ast_channel *chan, void *data)
117 {
118         int res=0;
119         struct localuser *u;
120         char ret[80] = "";
121         char tmp[256] = "";
122         char *cat=NULL, *group=NULL;
123
124         LOCAL_USER_ADD(u);
125
126         /* Check and parse arguments */
127         if (data && !ast_strlen_zero(data)) {
128                 strncpy(tmp, data, sizeof(tmp) - 1);
129                 group = tmp;
130                 cat = strchr(tmp, '@');
131                 if (cat) {
132                         *cat = '\0';
133                         cat++;
134                 }
135         }
136         if (cat)
137                 snprintf(ret, sizeof(ret), "GROUP_%s", cat);
138         else
139                 strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
140
141         if (group && !ast_strlen_zero(group)) {
142                 pbx_builtin_setvar_helper(chan, ret, group);
143         } else
144                 ast_log(LOG_WARNING, "SetGroup requires an argument (group name)\n");
145
146         LOCAL_USER_REMOVE(u);
147         return res;
148 }
149
150 static int group_check_exec(struct ast_channel *chan, void *data)
151 {
152         int res=0;
153         int max, count;
154         struct localuser *u;
155         char ret[80] = "";
156         char tmp[256] = "";
157         char *cat, *group;
158
159         LOCAL_USER_ADD(u);
160
161         if (data && !ast_strlen_zero(data)) {
162                 strncpy(tmp, data, sizeof(tmp) - 1);
163                 group = tmp;
164                 cat = strchr(tmp, '@');
165                 if (cat) {
166                         *cat = '\0';
167                         cat++;
168                 }
169                 if ((sscanf((char *)tmp, "%i", &max) == 1) && (max > -1)) {
170                         if (cat)
171                                 snprintf(ret, sizeof(ret), "GROUP_%s", cat);
172                         else
173                                 strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
174                         
175                         count = group_get_count(pbx_builtin_getvar_helper(chan, ret), ret);
176                         if (count > max) {
177                                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
178                                         chan->priority += 100;
179                                 else
180                                         res = -1;
181                         }
182                 } else
183                         ast_log(LOG_WARNING, "CheckGroup requires a positive integer argument (max)\n");
184         } else
185                 ast_log(LOG_WARNING, "CheckGroup requires an argument(max)\n");
186         LOCAL_USER_REMOVE(u);
187         return res;
188 }
189
190 int unload_module(void)
191 {
192         int res;
193         STANDARD_HANGUP_LOCALUSERS;
194         res = ast_unregister_application(app_group_count);
195         res |= ast_unregister_application(app_group_set);
196         res |= ast_unregister_application(app_group_check);
197         return res;
198 }
199
200 int load_module(void)
201 {
202         int res;
203         res = ast_register_application(app_group_count, group_count_exec, group_count_synopsis, group_count_descrip);
204         res |= ast_register_application(app_group_set, group_set_exec, group_set_synopsis, group_set_descrip);
205         res |= ast_register_application(app_group_check, group_check_exec, group_check_synopsis, group_check_descrip);
206         return res;
207 }
208
209 char *description(void)
210 {
211         return tdesc;
212 }
213
214 int usecount(void)
215 {
216         int res;
217         STANDARD_USECOUNT(res);
218         return res;
219 }
220
221 char *key()
222 {
223         return ASTERISK_GPL_KEY;
224 }