mi_core.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * $Id: mi_core.c 4762 2008-08-28 11:27:31Z henningw $
  3. *
  4. * Copyright (C) 2006 Voice Sistem SRL
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21. *
  22. *
  23. * history:
  24. * ---------
  25. * 2006-09-08 first version (bogdan)
  26. */
  27. /*!
  28. * \file
  29. * \brief MI :: Core
  30. * \ingroup mi
  31. */
  32. #include <time.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <errno.h>
  36. #include <sys/types.h>
  37. #include <signal.h>
  38. #include "../../dprint.h"
  39. #include "../../globals.h"
  40. #include "../../ut.h"
  41. #include "../../pt.h"
  42. #include "../../mem/mem.h"
  43. #include "../../lib/kmi/mi.h"
  44. #include "../../ver.h"
  45. #include "../../cfg/cfg.h"
  46. #include "../../cfg/cfg_ctx.h"
  47. #define BUILD_STR __FILE__ " compiled on "__TIME__ " " __DATE__ " with " COMPILER "\n"
  48. #define BUILD_STR_LEN (sizeof(BUILD_STR)-1)
  49. #ifndef SVNREVISION
  50. #define SVNREVISION "unknown"
  51. #endif
  52. static time_t kmi_up_since = 0;
  53. static str kmi_up_since_ctime = {0, 0};
  54. static cfg_ctx_t *_kex_cfg_ctx = NULL;
  55. static int init_mi_uptime(void)
  56. {
  57. char *p;
  58. if (kmi_up_since_ctime.s!=0)
  59. return 0;
  60. time(&kmi_up_since);
  61. p = ctime(&kmi_up_since);
  62. kmi_up_since_ctime.len = strlen(p)-1;
  63. kmi_up_since_ctime.s = (char*)pkg_malloc(kmi_up_since_ctime.len);
  64. if (kmi_up_since_ctime.s==0) {
  65. LM_ERR("no more pkg mem\n");
  66. return -1;
  67. }
  68. memcpy(kmi_up_since_ctime.s, p, kmi_up_since_ctime.len);
  69. return 0;
  70. }
  71. static struct mi_root *mi_uptime(struct mi_root *cmd, void *param)
  72. {
  73. struct mi_root *rpl_tree;
  74. struct mi_node *rpl;
  75. struct mi_node *node;
  76. time_t now;
  77. char *p;
  78. rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
  79. if (rpl_tree==0)
  80. return 0;
  81. rpl = &rpl_tree->node;
  82. time(&now);
  83. p = ctime(&now);
  84. node = add_mi_node_child( rpl, MI_DUP_VALUE, MI_SSTR("Now"),
  85. p, strlen(p)-1);
  86. if (node==0)
  87. goto error;
  88. node = add_mi_node_child( rpl, 0, MI_SSTR("Up since"),
  89. kmi_up_since_ctime.s, kmi_up_since_ctime.len);
  90. if (node==0)
  91. goto error;
  92. node = addf_mi_node_child( rpl, 0, MI_SSTR("Up time"),
  93. "%lu [sec]", (unsigned long)difftime(now, kmi_up_since) );
  94. if (node==0)
  95. goto error;
  96. return rpl_tree;
  97. error:
  98. LM_ERR("failed to add node\n");
  99. free_mi_tree(rpl_tree);
  100. return 0;
  101. }
  102. static struct mi_root *mi_version(struct mi_root *cmd, void *param)
  103. {
  104. struct mi_root *rpl_tree;
  105. struct mi_node *rpl;
  106. struct mi_node *node;
  107. rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
  108. if (rpl_tree==0)
  109. return 0;
  110. rpl = &rpl_tree->node;
  111. node = add_mi_node_child( rpl, 0, MI_SSTR("Server"), SERVER_HDR+8,
  112. SERVER_HDR_LEN-8);
  113. if (node==0)
  114. goto error;
  115. node = add_mi_node_child( rpl, 0, MI_SSTR("Build"), BUILD_STR,
  116. BUILD_STR_LEN);
  117. if (node==0)
  118. goto error;
  119. node = add_mi_node_child( rpl, 0, MI_SSTR("Flags"), (char*)ver_flags,
  120. strlen(ver_flags));
  121. if (node==0)
  122. goto error;
  123. node = add_mi_node_child( rpl, 0, MI_SSTR("GIT"), (char*)repo_hash,
  124. strlen(repo_hash));
  125. if (node==0)
  126. goto error;
  127. return rpl_tree;
  128. error:
  129. LM_ERR("failed to add node\n");
  130. free_mi_tree(rpl_tree);
  131. return 0;
  132. }
  133. static struct mi_root *mi_pwd(struct mi_root *cmd, void *param)
  134. {
  135. static int max_len = 0;
  136. static char *cwd_buf = 0;
  137. struct mi_root *rpl_tree;
  138. struct mi_node *rpl;
  139. struct mi_node *node;
  140. if (cwd_buf==NULL) {
  141. max_len = pathmax();
  142. cwd_buf = pkg_malloc(max_len);
  143. if (cwd_buf==NULL) {
  144. LM_ERR("no more pkg mem\n");
  145. return 0;
  146. }
  147. }
  148. rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
  149. if (rpl_tree==0)
  150. return 0;
  151. rpl = &rpl_tree->node;
  152. if (getcwd(cwd_buf, max_len)==0) {
  153. LM_ERR("getcwd failed = %s\n",strerror(errno));
  154. goto error;
  155. }
  156. node = add_mi_node_child( rpl, 0, MI_SSTR("WD"), cwd_buf,strlen(cwd_buf));
  157. if (node==0) {
  158. LM_ERR("failed to add node\n");
  159. goto error;
  160. }
  161. return rpl_tree;
  162. error:
  163. free_mi_tree(rpl_tree);
  164. return 0;
  165. }
  166. static struct mi_root *mi_arg(struct mi_root *cmd, void *param)
  167. {
  168. struct mi_root *rpl_tree;
  169. struct mi_node *rpl;
  170. struct mi_node *node;
  171. int n;
  172. rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
  173. if (rpl_tree==0)
  174. return 0;
  175. rpl = &rpl_tree->node;
  176. for ( n=0; n<my_argc ; n++ ) {
  177. node = add_mi_node_child(rpl, 0, 0, 0, my_argv[n], strlen(my_argv[n]));
  178. if (node==0) {
  179. LM_ERR("failed to add node\n");
  180. free_mi_tree(rpl_tree);
  181. return 0;
  182. }
  183. }
  184. return rpl_tree;
  185. }
  186. static struct mi_root *mi_which(struct mi_root *cmd, void *param)
  187. {
  188. struct mi_root *rpl_tree;
  189. struct mi_cmd *cmds;
  190. struct mi_node *rpl;
  191. struct mi_node *node;
  192. int size;
  193. int i;
  194. rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
  195. if (rpl_tree==0)
  196. return 0;
  197. rpl = &rpl_tree->node;
  198. get_mi_cmds( &cmds, &size);
  199. for ( i=0 ; i<size ; i++ ) {
  200. node = add_mi_node_child( rpl, 0, 0, 0, cmds[i].name.s,
  201. cmds[i].name.len);
  202. if (node==0) {
  203. LM_ERR("failed to add node\n");
  204. free_mi_tree(rpl_tree);
  205. return 0;
  206. }
  207. }
  208. return rpl_tree;
  209. }
  210. static struct mi_root *mi_ps(struct mi_root *cmd, void *param)
  211. {
  212. struct mi_root *rpl_tree;
  213. struct mi_node *rpl;
  214. struct mi_node *node;
  215. struct mi_attr *attr;
  216. char *p;
  217. int len;
  218. int i;
  219. rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
  220. if (rpl_tree==0)
  221. return 0;
  222. rpl = &rpl_tree->node;
  223. for ( i=0 ; i<get_proc_no() ; i++ ) {
  224. node = add_mi_node_child(rpl, 0, MI_SSTR("Process"), 0, 0 );
  225. if (node==0)
  226. goto error;
  227. p = int2str((unsigned long)i, &len);
  228. attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("ID"), p, len);
  229. if (attr==0)
  230. goto error;
  231. p = int2str((unsigned long)pt[i].pid, &len);
  232. attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("PID"), p, len);
  233. if (attr==0)
  234. goto error;
  235. attr = add_mi_attr( node, 0, MI_SSTR("Type"),
  236. pt[i].desc, strlen(pt[i].desc));
  237. if (attr==0)
  238. goto error;
  239. }
  240. return rpl_tree;
  241. error:
  242. LM_ERR("failed to add node\n");
  243. free_mi_tree(rpl_tree);
  244. return 0;
  245. }
  246. static struct mi_root *mi_kill(struct mi_root *cmd, void *param)
  247. {
  248. kill(0, SIGTERM);
  249. return 0;
  250. }
  251. static struct mi_root *mi_debug(struct mi_root *cmd, void *param)
  252. {
  253. struct mi_root *rpl_tree;
  254. struct mi_node *node;
  255. char *p;
  256. int len;
  257. int new_debug = 0;
  258. str group_name = {"core", 4};
  259. str var_name = {"debug", 5};
  260. void *vval = 0;
  261. int set = 0;
  262. unsigned int val_type;
  263. node = cmd->node.kids;
  264. if (node!=NULL) {
  265. if (str2sint( &node->value, &new_debug) < 0)
  266. return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM));
  267. set = 1;
  268. } else {
  269. if(cfg_get_by_name(_kex_cfg_ctx, &group_name, NULL /* group id */, &var_name, &vval,
  270. &val_type)!=0)
  271. return init_mi_tree( 500, MI_SSTR(MI_INTERNAL_ERR));
  272. new_debug = (int)(long)vval;
  273. }
  274. rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
  275. if (rpl_tree==0)
  276. return 0;
  277. p = sint2str((long)new_debug, &len);
  278. node = add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE,
  279. MI_SSTR("DEBUG"),p, len);
  280. if (node==0) {
  281. free_mi_tree(rpl_tree);
  282. return 0;
  283. }
  284. if(set==1) {
  285. cfg_set_now(_kex_cfg_ctx, &group_name, NULL /* group id */, &var_name,
  286. (void *)(long)new_debug, CFG_VAR_INT);
  287. }
  288. return rpl_tree;
  289. }
  290. static mi_export_t mi_core_cmds[] = {
  291. { "uptime", mi_uptime, MI_NO_INPUT_FLAG, 0, init_mi_uptime },
  292. { "version", mi_version, MI_NO_INPUT_FLAG, 0, 0 },
  293. { "pwd", mi_pwd, MI_NO_INPUT_FLAG, 0, 0 },
  294. { "arg", mi_arg, MI_NO_INPUT_FLAG, 0, 0 },
  295. { "which", mi_which, MI_NO_INPUT_FLAG, 0, 0 },
  296. { "kill", mi_kill, MI_NO_INPUT_FLAG, 0, 0 },
  297. { "ps", mi_ps, MI_NO_INPUT_FLAG, 0, 0 },
  298. { "debug", mi_debug, 0, 0, 0 },
  299. { 0, 0, 0, 0, 0}
  300. };
  301. int init_mi_core(void)
  302. {
  303. if (cfg_register_ctx(&_kex_cfg_ctx, NULL)) {
  304. LM_ERR("failed to register cfg context\n");
  305. return -1;
  306. }
  307. if (register_mi_mod( "core", mi_core_cmds)<0) {
  308. LM_ERR("unable to register core MI cmds\n");
  309. return -1;
  310. }
  311. if(init_mi_uptime()<0) {
  312. return -1;
  313. }
  314. return 0;
  315. }