xlog.c

Go to the documentation of this file.
00001 /**
00002  * $Id: xlog.c 5276 2008-11-27 15:31:51Z anomarme $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
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 #include <stdio.h>
00024 #include <string.h>
00025 #include <stdlib.h>
00026 #include <sys/types.h>
00027 #include <sys/ipc.h>
00028 #include <unistd.h>
00029 #include <fcntl.h>
00030 #include <time.h>
00031 #include <ctype.h>
00032 
00033 #include "../../sr_module.h"
00034 #include "../../dprint.h"
00035 #include "../../error.h"
00036 #include "../../mem/mem.h"
00037 
00038 #include "xl_lib.h"
00039 
00040 #include "../../pvar.h"
00041 
00042 
00043 MODULE_VERSION
00044 
00045 char *log_buf = NULL;
00046 
00047 /** parameters */
00048 int buf_size=4096;
00049 int force_color=0;
00050 
00051 /** module functions */
00052 static int mod_init(void);
00053 
00054 static int xlog_1(struct sip_msg*, char*, char*);
00055 static int xlog_2(struct sip_msg*, char*, char*);
00056 static int xdbg(struct sip_msg*, char*, char*);
00057 
00058 static int xlog_fixup(void** param, int param_no); 
00059 static int xdbg_fixup(void** param, int param_no); 
00060 
00061 void destroy(void);
00062 
00063 int pv_parse_color_name(pv_spec_p sp, str *in);
00064 static int pv_get_color(struct sip_msg *msg, pv_param_t *param, 
00065       pv_value_t *res);
00066 
00067 typedef struct _xl_level
00068 {
00069    int type;
00070    union {
00071       long level;
00072       pv_spec_t sp;
00073    } v;
00074 } xl_level_t, *xl_level_p;
00075 
00076 static pv_export_t mod_items[] = {
00077    { {"C", sizeof("C")-1}, PVT_OTHER, pv_get_color, 0,
00078       pv_parse_color_name, 0, 0, 0 },
00079    { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
00080 };
00081 
00082 
00083 static cmd_export_t cmds[]={
00084    {"xlog",  (cmd_function)xlog_1,  1, xdbg_fixup, 0, 
00085       REQUEST_ROUTE | FAILURE_ROUTE |
00086       ONREPLY_ROUTE | BRANCH_ROUTE | ERROR_ROUTE | LOCAL_ROUTE},
00087    {"xlog",  (cmd_function)xlog_2,  2, xlog_fixup, 0, 
00088       REQUEST_ROUTE | FAILURE_ROUTE |
00089       ONREPLY_ROUTE | BRANCH_ROUTE | ERROR_ROUTE | LOCAL_ROUTE},
00090    {"xdbg",  (cmd_function)xdbg,    1, xdbg_fixup, 0, 
00091       REQUEST_ROUTE | FAILURE_ROUTE | 
00092       ONREPLY_ROUTE | BRANCH_ROUTE | ERROR_ROUTE | LOCAL_ROUTE},
00093    {0,0,0,0,0,0}
00094 };
00095 
00096 
00097 static param_export_t params[]={
00098    {"buf_size",     INT_PARAM, &buf_size},
00099    {"force_color",  INT_PARAM, &force_color},
00100    {0,0,0}
00101 };
00102 
00103 
00104 /** module exports */
00105 struct module_exports exports= {
00106    "xlog",
00107    DEFAULT_DLFLAGS, /* dlopen flags */
00108    cmds,
00109    params,
00110    0,          /* exported statistics */
00111    0  ,        /* exported MI functions */
00112    mod_items,  /* exported pseudo-variables */
00113    0,          /* extra processes */
00114    mod_init,   /* module initialization function */
00115    0,
00116    (destroy_function) destroy,
00117    0           /* per-child init function */
00118 };
00119 
00120 /**
00121  * init module function
00122  */
00123 static int mod_init(void)
00124 {
00125    log_buf = (char*)pkg_malloc((buf_size+1)*sizeof(char));
00126    if(log_buf==NULL)
00127    {
00128       LM_ERR("no pkg memory left\n");
00129       return -1;
00130    }
00131    return 0;
00132 }
00133 
00134 /**
00135  */
00136 static int xlog_1(struct sip_msg* msg, char* frm, char* str2)
00137 {
00138    int log_len;
00139 
00140    if(!is_printable(L_ERR))
00141       return 1;
00142 
00143    log_len = buf_size;
00144 
00145    if(xl_print_log(msg, (pv_elem_t*)frm, log_buf, &log_len)<0)
00146       return -1;
00147 
00148    /* log_buf[log_len] = '\0'; */
00149    LM_GEN1(L_ERR, "%.*s", log_len, log_buf);
00150 
00151    return 1;
00152 }
00153 
00154 /**
00155  */
00156 static int xlog_2(struct sip_msg* msg, char* lev, char* frm)
00157 {
00158    int log_len;
00159    long level;
00160    xl_level_p xlp;
00161    pv_value_t value;
00162 
00163    xlp = (xl_level_p)lev;
00164    if(xlp->type==1)
00165    {
00166       if(pv_get_spec_value(msg, &xlp->v.sp, &value)!=0 
00167          || value.flags&PV_VAL_NULL || !(value.flags&PV_VAL_INT))
00168       {
00169          LM_ERR("invalid log level value [%d]\n", value.flags);
00170          return -1;
00171       }
00172       level = (long)value.ri;
00173    } else {
00174       level = xlp->v.level;
00175    }
00176 
00177    if(!is_printable((int)level))
00178       return 1;
00179 
00180    log_len = buf_size;
00181 
00182    if(xl_print_log(msg, (pv_elem_t*)frm, log_buf, &log_len)<0)
00183       return -1;
00184 
00185    /* log_buf[log_len] = '\0'; */
00186    LM_GEN1((int)level, "%.*s", log_len, log_buf);
00187 
00188    return 1;
00189 }
00190 
00191 /**
00192  */
00193 static int xdbg(struct sip_msg* msg, char* frm, char* str2)
00194 {
00195    int log_len;
00196 
00197    if(!is_printable(L_DBG))
00198       return 1;
00199 
00200    log_len = buf_size;
00201 
00202    if(xl_print_log(msg, (pv_elem_t*)frm, log_buf, &log_len)<0)
00203       return -1;
00204 
00205    /* log_buf[log_len] = '\0'; */
00206    LM_GEN1(L_DBG, "%.*s", log_len, log_buf);
00207 
00208    return 1;
00209 }
00210 
00211 /**
00212  * destroy function
00213  */
00214 void destroy(void)
00215 {
00216    if(log_buf)
00217       pkg_free(log_buf);
00218 }
00219 
00220 static int xlog_fixup(void** param, int param_no)
00221 {
00222    xl_level_p xlp;
00223    str s;
00224    
00225    if(param_no==1)
00226    {
00227       s.s = (char*)(*param);
00228       if(s.s==NULL || strlen(s.s)<2)
00229       {
00230          LM_ERR("wrong log level\n");
00231          return E_UNSPEC;
00232       }
00233 
00234       xlp = (xl_level_p)pkg_malloc(sizeof(xl_level_t));
00235       if(xlp == NULL)
00236       {
00237          LM_ERR("no more memory\n");
00238          return E_UNSPEC;
00239       }
00240       memset(xlp, 0, sizeof(xl_level_t));
00241       if(s.s[0]==PV_MARKER)
00242       {
00243          xlp->type = 1;
00244          s.len = strlen(s.s);
00245          if(pv_parse_spec(&s, &xlp->v.sp)==NULL)
00246          {
00247             LM_ERR("invalid level param\n");
00248             return E_UNSPEC;
00249          }
00250       } else {
00251          xlp->type = 0;
00252          switch(((char*)(*param))[2])
00253          {
00254             case 'A': xlp->v.level = L_ALERT; break;
00255             case 'C': xlp->v.level = L_CRIT; break;
00256             case 'E': xlp->v.level = L_ERR; break;
00257             case 'W': xlp->v.level = L_WARN; break;
00258             case 'N': xlp->v.level = L_NOTICE; break;
00259             case 'I': xlp->v.level = L_INFO; break;
00260             case 'D': xlp->v.level = L_DBG; break;
00261             default:
00262                LM_ERR("unknown log level\n");
00263                return E_UNSPEC;
00264          }
00265       }
00266       pkg_free(*param);
00267       *param = (void*)xlp;
00268       return 0;
00269    }
00270 
00271    if(param_no==2)
00272       return xdbg_fixup(param, 1);
00273 
00274    return 0;
00275 }
00276 
00277 static int xdbg_fixup(void** param, int param_no)
00278 {
00279    pv_elem_t *model;
00280    str s;
00281 
00282    if(param_no==1)
00283    {
00284       if(*param)
00285       {
00286          s.s = (char*)(*param); s.len = strlen(s.s);
00287          if(log_stderr!=0 || (log_stderr==0 && force_color!=0))
00288          {
00289             if(pv_parse_format(&s, &model)<0)
00290             {
00291                LM_ERR("wrong format[%s]\n",
00292                   (char*)(*param));
00293                return E_UNSPEC;
00294             }
00295          } else {
00296             if(pv_parse_format(&s, &model)<0)
00297             {
00298                LM_ERR("wrong format[%s]!\n",
00299                   (char*)(*param));
00300                return E_UNSPEC;
00301             }
00302          }
00303          
00304          *param = (void*)model;
00305          return 0;
00306       }
00307       else
00308       {
00309          LM_ERR("null format\n");
00310          return E_UNSPEC;
00311       }
00312    }
00313 
00314    return 0;
00315 }
00316 
00317 
00318 int pv_parse_color_name(pv_spec_p sp, str *in)
00319 {
00320 
00321    if(in==NULL || in->s==NULL || sp==NULL)
00322       return -1;
00323 
00324    if(in->len != 2)
00325    {
00326       LM_ERR("color name must have two chars\n");
00327       return -1;
00328    }
00329    
00330    /* foreground */
00331    switch(in->s[0])
00332    {
00333       case 'x':
00334       case 's': case 'r': case 'g':
00335       case 'y': case 'b': case 'p':
00336       case 'c': case 'w': case 'S':
00337       case 'R': case 'G': case 'Y':
00338       case 'B': case 'P': case 'C':
00339       case 'W':
00340       break;
00341       default: 
00342          goto error;
00343    }
00344                                
00345    /* background */
00346    switch(in->s[1])
00347    {
00348       case 'x':
00349       case 's': case 'r': case 'g':
00350       case 'y': case 'b': case 'p':
00351       case 'c': case 'w':
00352       break;   
00353       default: 
00354          goto error;
00355    }
00356    
00357    sp->pvp.pvn.type = PV_NAME_INTSTR;
00358    sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
00359    sp->pvp.pvn.u.isname.name.s = *in;
00360 
00361    sp->getf = pv_get_color;
00362 
00363    /* force the color PV type */
00364    sp->type = PVT_COLOR;
00365    return 0;
00366 error:
00367    LM_ERR("invalid color name\n");
00368    return -1;
00369 }
00370 
00371 #define COL_BUF 10
00372 
00373 #define append_sstring(p, end, s) \
00374         do{\
00375                 if ((p)+(sizeof(s)-1)<=(end)){\
00376                         memcpy((p), s, sizeof(s)-1); \
00377                         (p)+=sizeof(s)-1; \
00378                 }else{ \
00379                         /* overflow */ \
00380                         LM_ERR("append_sstring overflow\n"); \
00381                         goto error;\
00382                 } \
00383         } while(0) 
00384 
00385 
00386 static int pv_get_color(struct sip_msg *msg, pv_param_t *param,
00387       pv_value_t *res)
00388 {
00389    static char color[COL_BUF];
00390    char* p;
00391    char* end;
00392    str s;
00393 
00394    if(log_stderr==0 && force_color==0)
00395    {
00396       s.s = "";
00397       s.len = 0;
00398       return pv_get_strval(msg, param, res, &s);
00399    }
00400 
00401    p = color;
00402    end = p + COL_BUF;
00403         
00404    /* excape sequenz */
00405    append_sstring(p, end, "\033[");
00406         
00407    if(param->pvn.u.isname.name.s.s[0]!='_')
00408    {
00409       if (islower((int)param->pvn.u.isname.name.s.s[0]))
00410       {
00411          /* normal font */
00412          append_sstring(p, end, "0;");
00413       } else {
00414          /* bold font */
00415          append_sstring(p, end, "1;");
00416          param->pvn.u.isname.name.s.s[0] += 32;
00417       }
00418    }
00419          
00420    /* foreground */
00421    switch(param->pvn.u.isname.name.s.s[0])
00422    {
00423       case 'x':
00424          append_sstring(p, end, "39;");
00425       break;
00426       case 's':
00427          append_sstring(p, end, "30;");
00428       break;
00429       case 'r':
00430          append_sstring(p, end, "31;");
00431       break;
00432       case 'g':
00433          append_sstring(p, end, "32;");
00434       break;
00435       case 'y':
00436          append_sstring(p, end, "33;");
00437       break;
00438       case 'b':
00439          append_sstring(p, end, "34;");
00440       break;
00441       case 'p':
00442          append_sstring(p, end, "35;");
00443       break;
00444       case 'c':
00445          append_sstring(p, end, "36;");
00446       break;
00447       case 'w':
00448          append_sstring(p, end, "37;");
00449       break;
00450       default:
00451          LM_ERR("invalid foreground\n");
00452          return pv_get_null(msg, param, res);
00453    }
00454          
00455    /* background */
00456    switch(param->pvn.u.isname.name.s.s[1])
00457    {
00458       case 'x':
00459          append_sstring(p, end, "49");
00460       break;
00461       case 's':
00462          append_sstring(p, end, "40");
00463       break;
00464       case 'r':
00465          append_sstring(p, end, "41");
00466       break;
00467       case 'g':
00468          append_sstring(p, end, "42");
00469       break;
00470       case 'y':
00471          append_sstring(p, end, "43");
00472       break;
00473       case 'b':
00474          append_sstring(p, end, "44");
00475       break;
00476       case 'p':
00477          append_sstring(p, end, "45");
00478       break;
00479       case 'c':
00480          append_sstring(p, end, "46");
00481       break;
00482       case 'w':
00483          append_sstring(p, end, "47");
00484       break;
00485       default:
00486          LM_ERR("invalid background\n");
00487          return pv_get_null(msg, param, res);
00488    }
00489 
00490    /* end */
00491    append_sstring(p, end, "m");
00492 
00493    s.s = color;
00494    s.len = p-color;
00495    return pv_get_strval(msg, param, res, &s);
00496 
00497 error:
00498    return -1;
00499 }
00500 

Generated on Fri May 25 00:00:35 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6