mi_core.c

Go to the documentation of this file.
00001 /*
00002  * $Id: mi_core.c 4762 2008-08-28 11:27:31Z henningw $
00003  *
00004  * Copyright (C) 2006 Voice Sistem SRL
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00021  *
00022  *
00023  * history:
00024  * ---------
00025  *  2006-09-08  first version (bogdan)
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 /* group id */, &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 /* group id */, &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 }