func_groupcount.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2006, Digium, Inc.
  5. *
  6. * See http://www.asterisk.org for more information about
  7. * the Asterisk project. Please do not directly contact
  8. * any of the maintainers of this project for assistance;
  9. * the project provides a web site, mailing lists and IRC
  10. * channels for your use.
  11. *
  12. * This program is free software, distributed under the terms of
  13. * the GNU General Public License Version 2. See the LICENSE file
  14. * at the top of the source tree.
  15. */
  16. /*! \file
  17. *
  18. * \brief Channel group related dialplan functions
  19. *
  20. * \ingroup functions
  21. */
  22. /*** MODULEINFO
  23. <support_level>core</support_level>
  24. ***/
  25. #include "asterisk.h"
  26. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  27. #include "asterisk/module.h"
  28. #include "asterisk/channel.h"
  29. #include "asterisk/pbx.h"
  30. #include "asterisk/utils.h"
  31. #include "asterisk/app.h"
  32. /*** DOCUMENTATION
  33. <function name="GROUP_COUNT" language="en_US">
  34. <synopsis>
  35. Counts the number of channels in the specified group.
  36. </synopsis>
  37. <syntax argsep="@">
  38. <parameter name="groupname">
  39. <para>Group name.</para>
  40. </parameter>
  41. <parameter name="category">
  42. <para>Category name</para>
  43. </parameter>
  44. </syntax>
  45. <description>
  46. <para>Calculates the group count for the specified group, or uses the
  47. channel's current group if not specified (and non-empty).</para>
  48. </description>
  49. </function>
  50. <function name="GROUP_MATCH_COUNT" language="en_US">
  51. <synopsis>
  52. Counts the number of channels in the groups matching the specified pattern.
  53. </synopsis>
  54. <syntax argsep="@">
  55. <parameter name="groupmatch" required="true">
  56. <para>A standard regular expression used to match a group name.</para>
  57. </parameter>
  58. <parameter name="category">
  59. <para>A standard regular expression used to match a category name.</para>
  60. </parameter>
  61. </syntax>
  62. <description>
  63. <para>Calculates the group count for all groups that match the specified pattern.
  64. Note: category matching is applied after matching based on group.
  65. Uses standard regular expression matching on both (see regex(7)).</para>
  66. </description>
  67. </function>
  68. <function name="GROUP" language="en_US">
  69. <synopsis>
  70. Gets or sets the channel group.
  71. </synopsis>
  72. <syntax>
  73. <parameter name="category">
  74. <para>Category name.</para>
  75. </parameter>
  76. </syntax>
  77. <description>
  78. <para><replaceable>category</replaceable> can be employed for more fine grained group management. Each channel
  79. can only be member of exactly one group per <replaceable>category</replaceable>.</para>
  80. </description>
  81. </function>
  82. <function name="GROUP_LIST" language="en_US">
  83. <synopsis>
  84. Gets a list of the groups set on a channel.
  85. </synopsis>
  86. <syntax />
  87. <description>
  88. <para>Gets a list of the groups set on a channel.</para>
  89. </description>
  90. </function>
  91. ***/
  92. static int group_count_function_read(struct ast_channel *chan, const char *cmd,
  93. char *data, char *buf, size_t len)
  94. {
  95. int ret = -1;
  96. int count = -1;
  97. char group[80] = "", category[80] = "";
  98. if (!chan) {
  99. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
  100. return -1;
  101. }
  102. ast_app_group_split_group(data, group, sizeof(group), category,
  103. sizeof(category));
  104. /* If no group has been provided let's find one */
  105. if (ast_strlen_zero(group)) {
  106. struct ast_group_info *gi = NULL;
  107. ast_app_group_list_rdlock();
  108. for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
  109. if (gi->chan != chan)
  110. continue;
  111. if (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))
  112. break;
  113. }
  114. if (gi) {
  115. ast_copy_string(group, gi->group, sizeof(group));
  116. if (!ast_strlen_zero(gi->category))
  117. ast_copy_string(category, gi->category, sizeof(category));
  118. }
  119. ast_app_group_list_unlock();
  120. }
  121. if ((count = ast_app_group_get_count(group, category)) == -1) {
  122. ast_log(LOG_NOTICE, "No group could be found for channel '%s'\n", ast_channel_name(chan));
  123. } else {
  124. snprintf(buf, len, "%d", count);
  125. ret = 0;
  126. }
  127. return ret;
  128. }
  129. static struct ast_custom_function group_count_function = {
  130. .name = "GROUP_COUNT",
  131. .read = group_count_function_read,
  132. .read_max = 12,
  133. };
  134. static int group_match_count_function_read(struct ast_channel *chan,
  135. const char *cmd, char *data, char *buf,
  136. size_t len)
  137. {
  138. char group[80] = "";
  139. char category[80] = "";
  140. ast_app_group_split_group(data, group, sizeof(group), category,
  141. sizeof(category));
  142. if (!ast_strlen_zero(group)) {
  143. int count;
  144. count = ast_app_group_match_get_count(group, category);
  145. snprintf(buf, len, "%d", count);
  146. return 0;
  147. }
  148. return -1;
  149. }
  150. static struct ast_custom_function group_match_count_function = {
  151. .name = "GROUP_MATCH_COUNT",
  152. .read = group_match_count_function_read,
  153. .read_max = 12,
  154. .write = NULL,
  155. };
  156. static int group_function_read(struct ast_channel *chan, const char *cmd,
  157. char *data, char *buf, size_t len)
  158. {
  159. int ret = -1;
  160. struct ast_group_info *gi = NULL;
  161. if (!chan) {
  162. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
  163. return -1;
  164. }
  165. ast_app_group_list_rdlock();
  166. for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
  167. if (gi->chan != chan)
  168. continue;
  169. if (ast_strlen_zero(data))
  170. break;
  171. if (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, data))
  172. break;
  173. }
  174. if (gi) {
  175. ast_copy_string(buf, gi->group, len);
  176. ret = 0;
  177. }
  178. ast_app_group_list_unlock();
  179. return ret;
  180. }
  181. static int group_function_write(struct ast_channel *chan, const char *cmd,
  182. char *data, const char *value)
  183. {
  184. char grpcat[256];
  185. if (!chan) {
  186. ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
  187. return -1;
  188. }
  189. if (!value) {
  190. return -1;
  191. }
  192. if (!ast_strlen_zero(data)) {
  193. snprintf(grpcat, sizeof(grpcat), "%s@%s", value, data);
  194. } else {
  195. ast_copy_string(grpcat, value, sizeof(grpcat));
  196. }
  197. if (ast_app_group_set_channel(chan, grpcat))
  198. ast_log(LOG_WARNING,
  199. "Setting a group requires an argument (group name)\n");
  200. return 0;
  201. }
  202. static struct ast_custom_function group_function = {
  203. .name = "GROUP",
  204. .read = group_function_read,
  205. .write = group_function_write,
  206. };
  207. static int group_list_function_read(struct ast_channel *chan, const char *cmd,
  208. char *data, char *buf, size_t len)
  209. {
  210. struct ast_group_info *gi = NULL;
  211. char tmp1[1024] = "";
  212. char tmp2[1024] = "";
  213. if (!chan)
  214. return -1;
  215. ast_app_group_list_rdlock();
  216. for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
  217. if (gi->chan != chan)
  218. continue;
  219. if (!ast_strlen_zero(tmp1)) {
  220. ast_copy_string(tmp2, tmp1, sizeof(tmp2));
  221. if (!ast_strlen_zero(gi->category))
  222. snprintf(tmp1, sizeof(tmp1), "%s %s@%s", tmp2, gi->group, gi->category);
  223. else
  224. snprintf(tmp1, sizeof(tmp1), "%s %s", tmp2, gi->group);
  225. } else {
  226. if (!ast_strlen_zero(gi->category))
  227. snprintf(tmp1, sizeof(tmp1), "%s@%s", gi->group, gi->category);
  228. else
  229. snprintf(tmp1, sizeof(tmp1), "%s", gi->group);
  230. }
  231. }
  232. ast_app_group_list_unlock();
  233. ast_copy_string(buf, tmp1, len);
  234. return 0;
  235. }
  236. static struct ast_custom_function group_list_function = {
  237. .name = "GROUP_LIST",
  238. .read = group_list_function_read,
  239. .write = NULL,
  240. };
  241. static int unload_module(void)
  242. {
  243. int res = 0;
  244. res |= ast_custom_function_unregister(&group_count_function);
  245. res |= ast_custom_function_unregister(&group_match_count_function);
  246. res |= ast_custom_function_unregister(&group_list_function);
  247. res |= ast_custom_function_unregister(&group_function);
  248. return res;
  249. }
  250. static int load_module(void)
  251. {
  252. int res = 0;
  253. res |= ast_custom_function_register(&group_count_function);
  254. res |= ast_custom_function_register(&group_match_count_function);
  255. res |= ast_custom_function_register(&group_list_function);
  256. res |= ast_custom_function_register(&group_function);
  257. return res;
  258. }
  259. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel group dialplan functions");