func_groupcount.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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 specifed (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. ast_app_group_split_group(data, group, sizeof(group), category,
  99. sizeof(category));
  100. /* If no group has been provided let's find one */
  101. if (ast_strlen_zero(group)) {
  102. struct ast_group_info *gi = NULL;
  103. ast_app_group_list_rdlock();
  104. for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
  105. if (gi->chan != chan)
  106. continue;
  107. if (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))
  108. break;
  109. }
  110. if (gi) {
  111. ast_copy_string(group, gi->group, sizeof(group));
  112. if (!ast_strlen_zero(gi->category))
  113. ast_copy_string(category, gi->category, sizeof(category));
  114. }
  115. ast_app_group_list_unlock();
  116. }
  117. if ((count = ast_app_group_get_count(group, category)) == -1) {
  118. ast_log(LOG_NOTICE, "No group could be found for channel '%s'\n", chan->name);
  119. } else {
  120. snprintf(buf, len, "%d", count);
  121. ret = 0;
  122. }
  123. return ret;
  124. }
  125. static struct ast_custom_function group_count_function = {
  126. .name = "GROUP_COUNT",
  127. .read = group_count_function_read,
  128. .read_max = 12,
  129. };
  130. static int group_match_count_function_read(struct ast_channel *chan,
  131. const char *cmd, char *data, char *buf,
  132. size_t len)
  133. {
  134. int count;
  135. char group[80] = "";
  136. char category[80] = "";
  137. ast_app_group_split_group(data, group, sizeof(group), category,
  138. sizeof(category));
  139. if (!ast_strlen_zero(group)) {
  140. count = ast_app_group_match_get_count(group, category);
  141. snprintf(buf, len, "%d", count);
  142. return 0;
  143. }
  144. return -1;
  145. }
  146. static struct ast_custom_function group_match_count_function = {
  147. .name = "GROUP_MATCH_COUNT",
  148. .read = group_match_count_function_read,
  149. .read_max = 12,
  150. .write = NULL,
  151. };
  152. static int group_function_read(struct ast_channel *chan, const char *cmd,
  153. char *data, char *buf, size_t len)
  154. {
  155. int ret = -1;
  156. struct ast_group_info *gi = NULL;
  157. ast_app_group_list_rdlock();
  158. for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
  159. if (gi->chan != chan)
  160. continue;
  161. if (ast_strlen_zero(data))
  162. break;
  163. if (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, data))
  164. break;
  165. }
  166. if (gi) {
  167. ast_copy_string(buf, gi->group, len);
  168. ret = 0;
  169. }
  170. ast_app_group_list_unlock();
  171. return ret;
  172. }
  173. static int group_function_write(struct ast_channel *chan, const char *cmd,
  174. char *data, const char *value)
  175. {
  176. char grpcat[256];
  177. if (!value) {
  178. return -1;
  179. }
  180. if (!ast_strlen_zero(data)) {
  181. snprintf(grpcat, sizeof(grpcat), "%s@%s", value, data);
  182. } else {
  183. ast_copy_string(grpcat, value, sizeof(grpcat));
  184. }
  185. if (ast_app_group_set_channel(chan, grpcat))
  186. ast_log(LOG_WARNING,
  187. "Setting a group requires an argument (group name)\n");
  188. return 0;
  189. }
  190. static struct ast_custom_function group_function = {
  191. .name = "GROUP",
  192. .read = group_function_read,
  193. .write = group_function_write,
  194. };
  195. static int group_list_function_read(struct ast_channel *chan, const char *cmd,
  196. char *data, char *buf, size_t len)
  197. {
  198. struct ast_group_info *gi = NULL;
  199. char tmp1[1024] = "";
  200. char tmp2[1024] = "";
  201. if (!chan)
  202. return -1;
  203. ast_app_group_list_rdlock();
  204. for (gi = ast_app_group_list_head(); gi; gi = AST_LIST_NEXT(gi, group_list)) {
  205. if (gi->chan != chan)
  206. continue;
  207. if (!ast_strlen_zero(tmp1)) {
  208. ast_copy_string(tmp2, tmp1, sizeof(tmp2));
  209. if (!ast_strlen_zero(gi->category))
  210. snprintf(tmp1, sizeof(tmp1), "%s %s@%s", tmp2, gi->group, gi->category);
  211. else
  212. snprintf(tmp1, sizeof(tmp1), "%s %s", tmp2, gi->group);
  213. } else {
  214. if (!ast_strlen_zero(gi->category))
  215. snprintf(tmp1, sizeof(tmp1), "%s@%s", gi->group, gi->category);
  216. else
  217. snprintf(tmp1, sizeof(tmp1), "%s", gi->group);
  218. }
  219. }
  220. ast_app_group_list_unlock();
  221. ast_copy_string(buf, tmp1, len);
  222. return 0;
  223. }
  224. static struct ast_custom_function group_list_function = {
  225. .name = "GROUP_LIST",
  226. .read = group_list_function_read,
  227. .write = NULL,
  228. };
  229. static int unload_module(void)
  230. {
  231. int res = 0;
  232. res |= ast_custom_function_unregister(&group_count_function);
  233. res |= ast_custom_function_unregister(&group_match_count_function);
  234. res |= ast_custom_function_unregister(&group_list_function);
  235. res |= ast_custom_function_unregister(&group_function);
  236. return res;
  237. }
  238. static int load_module(void)
  239. {
  240. int res = 0;
  241. res |= ast_custom_function_register(&group_count_function);
  242. res |= ast_custom_function_register(&group_match_count_function);
  243. res |= ast_custom_function_register(&group_list_function);
  244. res |= ast_custom_function_register(&group_function);
  245. return res;
  246. }
  247. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel group dialplan functions");