cli.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * David M. Lee, II <dlee@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Command line for ARI.
  21. * \author David M. Lee, II <dlee@digium.com>
  22. */
  23. #include "asterisk.h"
  24. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  25. #include "asterisk/astobj2.h"
  26. #include "asterisk/cli.h"
  27. #include "asterisk/stasis_app.h"
  28. #include "internal.h"
  29. static char *ari_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  30. {
  31. RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
  32. switch (cmd) {
  33. case CLI_INIT:
  34. e->command = "ari show status";
  35. e->usage =
  36. "Usage: ari show status\n"
  37. " Shows all ARI settings\n";
  38. return NULL;
  39. case CLI_GENERATE:
  40. return NULL;
  41. default:
  42. break;
  43. }
  44. if (a->argc != 3) {
  45. return CLI_SHOWUSAGE;
  46. }
  47. conf = ast_ari_config_get();
  48. if (!conf) {
  49. ast_cli(a->fd, "Error getting ARI configuration\n");
  50. return CLI_FAILURE;
  51. }
  52. ast_cli(a->fd, "ARI Status:\n");
  53. ast_cli(a->fd, "Enabled: %s\n", AST_CLI_YESNO(conf->general->enabled));
  54. ast_cli(a->fd, "Output format: ");
  55. switch (conf->general->format) {
  56. case AST_JSON_COMPACT:
  57. ast_cli(a->fd, "compact");
  58. break;
  59. case AST_JSON_PRETTY:
  60. ast_cli(a->fd, "pretty");
  61. break;
  62. }
  63. ast_cli(a->fd, "\n");
  64. ast_cli(a->fd, "Auth realm: %s\n", conf->general->auth_realm);
  65. ast_cli(a->fd, "Allowed Origins: %s\n", conf->general->allowed_origins);
  66. ast_cli(a->fd, "User count: %d\n", ao2_container_count(conf->users));
  67. return CLI_SUCCESS;
  68. }
  69. static int show_users_cb(void *obj, void *arg, int flags)
  70. {
  71. struct ast_ari_conf_user *user = obj;
  72. struct ast_cli_args *a = arg;
  73. ast_cli(a->fd, "%-4s %s\n",
  74. AST_CLI_YESNO(user->read_only),
  75. user->username);
  76. return 0;
  77. }
  78. static char *ari_show_users(struct ast_cli_entry *e, int cmd,
  79. struct ast_cli_args *a)
  80. {
  81. RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
  82. switch (cmd) {
  83. case CLI_INIT:
  84. e->command = "ari show users";
  85. e->usage =
  86. "Usage: ari show users\n"
  87. " Shows all ARI users\n";
  88. return NULL;
  89. case CLI_GENERATE:
  90. return NULL;
  91. default:
  92. break;
  93. }
  94. if (a->argc != 3) {
  95. return CLI_SHOWUSAGE;
  96. }
  97. conf = ast_ari_config_get();
  98. if (!conf) {
  99. ast_cli(a->fd, "Error getting ARI configuration\n");
  100. return CLI_FAILURE;
  101. }
  102. ast_cli(a->fd, "r/o? Username\n");
  103. ast_cli(a->fd, "---- --------\n");
  104. ao2_callback(conf->users, OBJ_NODATA, show_users_cb, a);
  105. return CLI_SUCCESS;
  106. }
  107. struct user_complete {
  108. /*! Nth user to search for */
  109. int state;
  110. /*! Which user currently on */
  111. int which;
  112. };
  113. static int complete_ari_user_search(void *obj, void *arg, void *data, int flags)
  114. {
  115. struct user_complete *search = data;
  116. if (++search->which > search->state) {
  117. return CMP_MATCH;
  118. }
  119. return 0;
  120. }
  121. static char *complete_ari_user(struct ast_cli_args *a)
  122. {
  123. RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
  124. RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
  125. struct user_complete search = {
  126. .state = a->n,
  127. };
  128. conf = ast_ari_config_get();
  129. if (!conf) {
  130. ast_cli(a->fd, "Error getting ARI configuration\n");
  131. return CLI_FAILURE;
  132. }
  133. user = ao2_callback_data(conf->users,
  134. ast_strlen_zero(a->word) ? 0 : OBJ_PARTIAL_KEY,
  135. complete_ari_user_search, (char*)a->word, &search);
  136. return user ? ast_strdup(user->username) : NULL;
  137. }
  138. static char *complete_ari_show_user(struct ast_cli_args *a)
  139. {
  140. if (a->pos == 3) {
  141. return complete_ari_user(a);
  142. }
  143. return NULL;
  144. }
  145. static char *ari_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  146. {
  147. RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
  148. RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
  149. switch (cmd) {
  150. case CLI_INIT:
  151. e->command = "ari show user";
  152. e->usage =
  153. "Usage: ari show user <username>\n"
  154. " Shows a specific ARI user\n";
  155. return NULL;
  156. case CLI_GENERATE:
  157. return complete_ari_show_user(a);
  158. default:
  159. break;
  160. }
  161. if (a->argc != 4) {
  162. return CLI_SHOWUSAGE;
  163. }
  164. conf = ast_ari_config_get();
  165. if (!conf) {
  166. ast_cli(a->fd, "Error getting ARI configuration\n");
  167. return CLI_FAILURE;
  168. }
  169. user = ao2_find(conf->users, a->argv[3], OBJ_KEY);
  170. if (!user) {
  171. ast_cli(a->fd, "User '%s' not found\n", a->argv[3]);
  172. return CLI_SUCCESS;
  173. }
  174. ast_cli(a->fd, "Username: %s\n", user->username);
  175. ast_cli(a->fd, "Read only?: %s\n", AST_CLI_YESNO(user->read_only));
  176. return CLI_SUCCESS;
  177. }
  178. static char *ari_mkpasswd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  179. {
  180. RAII_VAR(char *, crypted, NULL, ast_free);
  181. switch (cmd) {
  182. case CLI_INIT:
  183. e->command = "ari mkpasswd";
  184. e->usage =
  185. "Usage: ari mkpasswd <password>\n"
  186. " Encrypts a password for use in ari.conf\n"
  187. " Be aware that the password will be shown in the\n"
  188. " command line history. The mkpasswd shell command\n"
  189. " may be preferable.\n"
  190. ;
  191. return NULL;
  192. case CLI_GENERATE:
  193. return NULL;
  194. default:
  195. break;
  196. }
  197. if (a->argc != 3) {
  198. return CLI_SHOWUSAGE;
  199. }
  200. crypted = ast_crypt_encrypt(a->argv[2]);
  201. if (!crypted) {
  202. ast_cli(a->fd, "Failed to encrypt password\n");
  203. return CLI_FAILURE;
  204. }
  205. ast_cli(a->fd,
  206. "; Copy the following two lines into ari.conf\n");
  207. ast_cli(a->fd, "password_format = crypt\n");
  208. ast_cli(a->fd, "password = %s\n", crypted);
  209. return CLI_SUCCESS;
  210. }
  211. static char *ari_show_apps(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  212. {
  213. struct ao2_container *apps;
  214. struct ao2_iterator it_apps;
  215. char *app;
  216. switch (cmd) {
  217. case CLI_INIT:
  218. e->command = "ari show apps";
  219. e->usage =
  220. "Usage: ari show apps\n"
  221. " Lists all registered applications.\n"
  222. ;
  223. return NULL;
  224. case CLI_GENERATE:
  225. return NULL;
  226. default:
  227. break;
  228. }
  229. if (a->argc != 3) {
  230. return CLI_SHOWUSAGE;
  231. }
  232. apps = stasis_app_get_all();
  233. if (!apps) {
  234. ast_cli(a->fd, "Unable to retrieve registered applications!\n");
  235. return CLI_FAILURE;
  236. }
  237. ast_cli(a->fd, "Application Name \n");
  238. ast_cli(a->fd, "=========================\n");
  239. it_apps = ao2_iterator_init(apps, 0);
  240. while ((app = ao2_iterator_next(&it_apps))) {
  241. ast_cli(a->fd, "%-25.25s\n", app);
  242. ao2_ref(app, -1);
  243. }
  244. ao2_iterator_destroy(&it_apps);
  245. ao2_ref(apps, -1);
  246. return CLI_SUCCESS;
  247. }
  248. struct app_complete {
  249. /*! Nth app to search for */
  250. int state;
  251. /*! Which app currently on */
  252. int which;
  253. };
  254. static int complete_ari_app_search(void *obj, void *arg, void *data, int flags)
  255. {
  256. struct app_complete *search = data;
  257. if (++search->which > search->state) {
  258. return CMP_MATCH;
  259. }
  260. return 0;
  261. }
  262. static char *complete_ari_app(struct ast_cli_args *a, int include_all)
  263. {
  264. RAII_VAR(struct ao2_container *, apps, stasis_app_get_all(), ao2_cleanup);
  265. RAII_VAR(char *, app, NULL, ao2_cleanup);
  266. struct app_complete search = {
  267. .state = a->n,
  268. };
  269. if (a->pos != 3) {
  270. return NULL;
  271. }
  272. if (!apps) {
  273. ast_cli(a->fd, "Error getting ARI applications\n");
  274. return CLI_FAILURE;
  275. }
  276. if (include_all && ast_strlen_zero(a->word)) {
  277. ast_str_container_add(apps, " all");
  278. }
  279. app = ao2_callback_data(apps,
  280. ast_strlen_zero(a->word) ? 0 : OBJ_SEARCH_PARTIAL_KEY,
  281. complete_ari_app_search, (char*)a->word, &search);
  282. return app ? ast_strdup(app) : NULL;
  283. }
  284. static char *ari_show_app(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  285. {
  286. void *app;
  287. switch (cmd) {
  288. case CLI_INIT:
  289. e->command = "ari show app";
  290. e->usage =
  291. "Usage: ari show app <application>\n"
  292. " Provide detailed information about a registered application.\n"
  293. ;
  294. return NULL;
  295. case CLI_GENERATE:
  296. return complete_ari_app(a, 0);
  297. default:
  298. break;
  299. }
  300. if (a->argc != 4) {
  301. return CLI_SHOWUSAGE;
  302. }
  303. app = stasis_app_get_by_name(a->argv[3]);
  304. if (!app) {
  305. return CLI_FAILURE;
  306. }
  307. stasis_app_to_cli(app, a);
  308. ao2_ref(app, -1);
  309. return CLI_SUCCESS;
  310. }
  311. static char *ari_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  312. {
  313. void *app;
  314. int debug;
  315. switch (cmd) {
  316. case CLI_INIT:
  317. e->command = "ari set debug";
  318. e->usage =
  319. "Usage: ari set debug <application|all> <on|off>\n"
  320. " Enable or disable debugging on a specific application.\n"
  321. ;
  322. return NULL;
  323. case CLI_GENERATE:
  324. return complete_ari_app(a, 1);
  325. default:
  326. break;
  327. }
  328. if (a->argc != 5) {
  329. return CLI_SHOWUSAGE;
  330. }
  331. debug = !strcmp(a->argv[4], "on");
  332. if (!strcmp(a->argv[3], "all")) {
  333. stasis_app_set_global_debug(debug);
  334. ast_cli(a->fd, "Debugging on all applications %s\n",
  335. debug ? "enabled" : "disabled");
  336. return CLI_SUCCESS;
  337. }
  338. app = stasis_app_get_by_name(a->argv[3]);
  339. if (!app) {
  340. return CLI_FAILURE;
  341. }
  342. stasis_app_set_debug(app, debug);
  343. ast_cli(a->fd, "Debugging on '%s' %s\n",
  344. stasis_app_name(app),
  345. debug ? "enabled" : "disabled");
  346. ao2_ref(app, -1);
  347. return CLI_SUCCESS;
  348. }
  349. static struct ast_cli_entry cli_ari[] = {
  350. AST_CLI_DEFINE(ari_show, "Show ARI settings"),
  351. AST_CLI_DEFINE(ari_show_users, "List ARI users"),
  352. AST_CLI_DEFINE(ari_show_user, "List single ARI user"),
  353. AST_CLI_DEFINE(ari_mkpasswd, "Encrypts a password"),
  354. AST_CLI_DEFINE(ari_show_apps, "List registered ARI applications"),
  355. AST_CLI_DEFINE(ari_show_app, "Display details of a registered ARI application"),
  356. AST_CLI_DEFINE(ari_set_debug, "Enable/disable debugging of an ARI application"),
  357. };
  358. int ast_ari_cli_register(void) {
  359. return ast_cli_register_multiple(cli_ari, ARRAY_LEN(cli_ari));
  360. }
  361. void ast_ari_cli_unregister(void) {
  362. ast_cli_unregister_multiple(cli_ari, ARRAY_LEN(cli_ari));
  363. }