00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00037 #include <time.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <errno.h>
00041 #include <sys/types.h>
00042 #include <signal.h>
00043
00044 #include "../../dprint.h"
00045 #include "../../globals.h"
00046 #include "../../ut.h"
00047 #include "../../pt.h"
00048 #include "../../mem/mem.h"
00049 #include "../../lib/kmi/mi.h"
00050 #include "../../ver.h"
00051 #include "../../cfg/cfg.h"
00052 #include "../../cfg/cfg_ctx.h"
00053
00054 #define BUILD_STR __FILE__ " compiled on "__TIME__ " " __DATE__ " with " COMPILER "\n"
00055 #define BUILD_STR_LEN (sizeof(BUILD_STR)-1)
00056
00057 #ifndef SVNREVISION
00058 #define SVNREVISION "unknown"
00059 #endif
00060
00061 static time_t kmi_up_since = 0;
00062 static str kmi_up_since_ctime = {0, 0};
00063 static cfg_ctx_t *_kex_cfg_ctx = NULL;
00064
00065 static int init_mi_uptime(void)
00066 {
00067 char *p;
00068
00069 if (kmi_up_since_ctime.s!=0)
00070 return 0;
00071 time(&kmi_up_since);
00072 p = ctime(&kmi_up_since);
00073 kmi_up_since_ctime.len = strlen(p)-1;
00074 kmi_up_since_ctime.s = (char*)pkg_malloc(kmi_up_since_ctime.len);
00075 if (kmi_up_since_ctime.s==0) {
00076 LM_ERR("no more pkg mem\n");
00077 return -1;
00078 }
00079 memcpy(kmi_up_since_ctime.s, p, kmi_up_since_ctime.len);
00080 return 0;
00081 }
00082
00083
00084 static struct mi_root *mi_uptime(struct mi_root *cmd, void *param)
00085 {
00086 struct mi_root *rpl_tree;
00087 struct mi_node *rpl;
00088 struct mi_node *node;
00089 time_t now;
00090 char *p;
00091
00092 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00093 if (rpl_tree==0)
00094 return 0;
00095 rpl = &rpl_tree->node;
00096
00097 time(&now);
00098 p = ctime(&now);
00099 node = add_mi_node_child( rpl, MI_DUP_VALUE, MI_SSTR("Now"),
00100 p, strlen(p)-1);
00101 if (node==0)
00102 goto error;
00103
00104 node = add_mi_node_child( rpl, 0, MI_SSTR("Up since"),
00105 kmi_up_since_ctime.s, kmi_up_since_ctime.len);
00106 if (node==0)
00107 goto error;
00108
00109 node = addf_mi_node_child( rpl, 0, MI_SSTR("Up time"),
00110 "%lu [sec]", (unsigned long)difftime(now, kmi_up_since) );
00111 if (node==0)
00112 goto error;
00113
00114 return rpl_tree;
00115 error:
00116 LM_ERR("failed to add node\n");
00117 free_mi_tree(rpl_tree);
00118 return 0;
00119 }
00120
00121 static struct mi_root *mi_version(struct mi_root *cmd, void *param)
00122 {
00123 struct mi_root *rpl_tree;
00124 struct mi_node *rpl;
00125 struct mi_node *node;
00126
00127 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00128 if (rpl_tree==0)
00129 return 0;
00130 rpl = &rpl_tree->node;
00131
00132 node = add_mi_node_child( rpl, 0, MI_SSTR("Server"), SERVER_HDR+8,
00133 SERVER_HDR_LEN-8);
00134 if (node==0)
00135 goto error;
00136
00137 node = add_mi_node_child( rpl, 0, MI_SSTR("Build"), BUILD_STR,
00138 BUILD_STR_LEN);
00139 if (node==0)
00140 goto error;
00141
00142 node = add_mi_node_child( rpl, 0, MI_SSTR("Flags"), (char*)ver_flags,
00143 strlen(ver_flags));
00144 if (node==0)
00145 goto error;
00146
00147 node = add_mi_node_child( rpl, 0, MI_SSTR("GIT"), (char*)repo_hash,
00148 strlen(repo_hash));
00149 if (node==0)
00150 goto error;
00151
00152
00153
00154 return rpl_tree;
00155 error:
00156 LM_ERR("failed to add node\n");
00157 free_mi_tree(rpl_tree);
00158 return 0;
00159
00160 }
00161
00162
00163
00164 static struct mi_root *mi_pwd(struct mi_root *cmd, void *param)
00165 {
00166 static int max_len = 0;
00167 static char *cwd_buf = 0;
00168 struct mi_root *rpl_tree;
00169 struct mi_node *rpl;
00170 struct mi_node *node;
00171
00172 if (cwd_buf==NULL) {
00173 max_len = pathmax();
00174 cwd_buf = pkg_malloc(max_len);
00175 if (cwd_buf==NULL) {
00176 LM_ERR("no more pkg mem\n");
00177 return 0;
00178 }
00179 }
00180
00181 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00182 if (rpl_tree==0)
00183 return 0;
00184 rpl = &rpl_tree->node;
00185
00186 if (getcwd(cwd_buf, max_len)==0) {
00187 LM_ERR("getcwd failed = %s\n",strerror(errno));
00188 goto error;
00189 }
00190
00191 node = add_mi_node_child( rpl, 0, MI_SSTR("WD"), cwd_buf,strlen(cwd_buf));
00192 if (node==0) {
00193 LM_ERR("failed to add node\n");
00194 goto error;
00195 }
00196
00197 return rpl_tree;
00198 error:
00199 free_mi_tree(rpl_tree);
00200 return 0;
00201 }
00202
00203
00204
00205 static struct mi_root *mi_arg(struct mi_root *cmd, void *param)
00206 {
00207 struct mi_root *rpl_tree;
00208 struct mi_node *rpl;
00209 struct mi_node *node;
00210 int n;
00211
00212 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00213 if (rpl_tree==0)
00214 return 0;
00215 rpl = &rpl_tree->node;
00216
00217 for ( n=0; n<my_argc ; n++ ) {
00218 node = add_mi_node_child(rpl, 0, 0, 0, my_argv[n], strlen(my_argv[n]));
00219 if (node==0) {
00220 LM_ERR("failed to add node\n");
00221 free_mi_tree(rpl_tree);
00222 return 0;
00223 }
00224 }
00225
00226 return rpl_tree;
00227 }
00228
00229
00230
00231 static struct mi_root *mi_which(struct mi_root *cmd, void *param)
00232 {
00233 struct mi_root *rpl_tree;
00234 struct mi_cmd *cmds;
00235 struct mi_node *rpl;
00236 struct mi_node *node;
00237 int size;
00238 int i;
00239
00240 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00241 if (rpl_tree==0)
00242 return 0;
00243 rpl = &rpl_tree->node;
00244
00245 get_mi_cmds( &cmds, &size);
00246 for ( i=0 ; i<size ; i++ ) {
00247 node = add_mi_node_child( rpl, 0, 0, 0, cmds[i].name.s,
00248 cmds[i].name.len);
00249 if (node==0) {
00250 LM_ERR("failed to add node\n");
00251 free_mi_tree(rpl_tree);
00252 return 0;
00253 }
00254 }
00255
00256 return rpl_tree;
00257 }
00258
00259
00260 static struct mi_root *mi_ps(struct mi_root *cmd, void *param)
00261 {
00262 struct mi_root *rpl_tree;
00263 struct mi_node *rpl;
00264 struct mi_node *node;
00265 struct mi_attr *attr;
00266 char *p;
00267 int len;
00268 int i;
00269
00270 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00271 if (rpl_tree==0)
00272 return 0;
00273 rpl = &rpl_tree->node;
00274
00275 for ( i=0 ; i<get_proc_no() ; i++ ) {
00276 node = add_mi_node_child(rpl, 0, MI_SSTR("Process"), 0, 0 );
00277 if (node==0)
00278 goto error;
00279
00280 p = int2str((unsigned long)i, &len);
00281 attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("ID"), p, len);
00282 if (attr==0)
00283 goto error;
00284
00285 p = int2str((unsigned long)pt[i].pid, &len);
00286 attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("PID"), p, len);
00287 if (attr==0)
00288 goto error;
00289
00290 attr = add_mi_attr( node, 0, MI_SSTR("Type"),
00291 pt[i].desc, strlen(pt[i].desc));
00292 if (attr==0)
00293 goto error;
00294 }
00295
00296 return rpl_tree;
00297 error:
00298 LM_ERR("failed to add node\n");
00299 free_mi_tree(rpl_tree);
00300 return 0;
00301 }
00302
00303
00304 static struct mi_root *mi_kill(struct mi_root *cmd, void *param)
00305 {
00306 kill(0, SIGTERM);
00307
00308 return 0;
00309 }
00310
00311
00312 static struct mi_root *mi_debug(struct mi_root *cmd, void *param)
00313 {
00314 struct mi_root *rpl_tree;
00315 struct mi_node *node;
00316 char *p;
00317 int len;
00318 int new_debug = 0;
00319 str group_name = {"core", 4};
00320 str var_name = {"debug", 5};
00321 void *vval = 0;
00322 int set = 0;
00323 unsigned int val_type;
00324
00325 node = cmd->node.kids;
00326 if (node!=NULL) {
00327 if (str2sint( &node->value, &new_debug) < 0)
00328 return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM));
00329 set = 1;
00330 } else {
00331 if(cfg_get_by_name(_kex_cfg_ctx, &group_name, NULL , &var_name, &vval,
00332 &val_type)!=0)
00333 return init_mi_tree( 500, MI_SSTR(MI_INTERNAL_ERR));
00334 new_debug = (int)(long)vval;
00335 }
00336 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00337 if (rpl_tree==0)
00338 return 0;
00339
00340 p = sint2str((long)new_debug, &len);
00341 node = add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE,
00342 MI_SSTR("DEBUG"),p, len);
00343 if (node==0) {
00344 free_mi_tree(rpl_tree);
00345 return 0;
00346 }
00347
00348 if(set==1) {
00349 cfg_set_now(_kex_cfg_ctx, &group_name, NULL , &var_name,
00350 (void *)(long)new_debug, CFG_VAR_INT);
00351 }
00352
00353 return rpl_tree;
00354 }
00355
00356
00357 static mi_export_t mi_core_cmds[] = {
00358 { "uptime", mi_uptime, MI_NO_INPUT_FLAG, 0, init_mi_uptime },
00359 { "version", mi_version, MI_NO_INPUT_FLAG, 0, 0 },
00360 { "pwd", mi_pwd, MI_NO_INPUT_FLAG, 0, 0 },
00361 { "arg", mi_arg, MI_NO_INPUT_FLAG, 0, 0 },
00362 { "which", mi_which, MI_NO_INPUT_FLAG, 0, 0 },
00363 { "kill", mi_kill, MI_NO_INPUT_FLAG, 0, 0 },
00364 { "ps", mi_ps, MI_NO_INPUT_FLAG, 0, 0 },
00365 { "debug", mi_debug, 0, 0, 0 },
00366 { 0, 0, 0, 0, 0}
00367 };
00368
00369
00370
00371 int init_mi_core(void)
00372 {
00373 if (cfg_register_ctx(&_kex_cfg_ctx, NULL)) {
00374 LM_ERR("failed to register cfg context\n");
00375 return -1;
00376 }
00377
00378 if (register_mi_mod( "core", mi_core_cmds)<0) {
00379 LM_ERR("unable to register core MI cmds\n");
00380 return -1;
00381 }
00382
00383 if(init_mi_uptime()<0) {
00384 return -1;
00385 }
00386
00387 return 0;
00388 }