modules_k/xlog/xlog.c

00001 
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 #define NOFACILITY -1
00043 
00044 MODULE_VERSION
00045 
00046 char *_xlog_buf = NULL;
00047 char *_xlog_prefix = "<script>: ";
00048 
00050 static int buf_size=4096;
00051 static int force_color=0;
00052 static int long_format=0;
00053 static int xlog_facility = DEFAULT_FACILITY;
00054 static char *xlog_facility_name = NULL;
00055 
00057 static int mod_init(void);
00058 
00059 static int xlog_1(struct sip_msg*, char*, char*);
00060 static int xlog_2(struct sip_msg*, char*, char*);
00061 static int xlog_3(struct sip_msg*, char*, char*, char*);
00062 static int xdbg(struct sip_msg*, char*, char*);
00063 
00064 static int xlogl_1(struct sip_msg*, char*, char*);
00065 static int xlogl_2(struct sip_msg*, char*, char*);
00066 static int xlogl_3(struct sip_msg*, char*, char*, char*);
00067 static int xdbgl(struct sip_msg*, char*, char*);
00068 
00069 static int xlog_fixup(void** param, int param_no);
00070 static int xlog3_fixup(void** param, int param_no);
00071 static int xdbg_fixup(void** param, int param_no);
00072 static int xlogl_fixup(void** param, int param_no);
00073 static int xlogl3_fixup(void** param, int param_no);
00074 static int xdbgl_fixup(void** param, int param_no);
00075 
00076 static void destroy(void);
00077 
00078 int pv_parse_color_name(pv_spec_p sp, str *in);
00079 static int pv_get_color(struct sip_msg *msg, pv_param_t *param, 
00080                 pv_value_t *res);
00081 
00082 typedef struct _xl_level
00083 {
00084         int type;
00085         union {
00086                 long level;
00087                 pv_spec_t sp;
00088         } v;
00089 } xl_level_t, *xl_level_p;
00090 
00091 typedef struct _xl_msg
00092 {
00093         pv_elem_t *m;
00094         struct action *a;
00095 } xl_msg_t;
00096 
00097 static pv_export_t mod_items[] = {
00098         { {"C", sizeof("C")-1}, PVT_OTHER, pv_get_color, 0,
00099                 pv_parse_color_name, 0, 0, 0 },
00100         { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
00101 };
00102 
00103 
00104 static cmd_export_t cmds[]={
00105         {"xlog",   (cmd_function)xlog_1,   1, xdbg_fixup,  0, ANY_ROUTE},
00106         {"xlog",   (cmd_function)xlog_2,   2, xlog_fixup,  0, ANY_ROUTE},
00107         {"xlog",   (cmd_function)xlog_3,   3, xlog3_fixup, 0, ANY_ROUTE},
00108         {"xdbg",   (cmd_function)xdbg,     1, xdbg_fixup,  0, ANY_ROUTE},
00109         {"xlogl",  (cmd_function)xlogl_1,  1, xdbgl_fixup, 0, ANY_ROUTE},
00110         {"xlogl",  (cmd_function)xlogl_2,  2, xlogl_fixup, 0, ANY_ROUTE},
00111         {"xlogl",  (cmd_function)xlogl_3,  3, xlogl3_fixup,0, ANY_ROUTE},
00112         {"xdbgl",  (cmd_function)xdbgl,    1, xdbgl_fixup, 0, ANY_ROUTE},
00113         {0,0,0,0,0,0}
00114 };
00115 
00116 
00117 static param_export_t params[]={
00118         {"buf_size",     INT_PARAM, &buf_size},
00119         {"force_color",  INT_PARAM, &force_color},
00120         {"long_format",  INT_PARAM, &long_format},
00121         {"prefix",       STR_PARAM, &_xlog_prefix},
00122         {"log_facility", STR_PARAM, &xlog_facility_name},
00123         {0,0,0}
00124 };
00125 
00126 
00128 struct module_exports exports= {
00129         "xlog",
00130         DEFAULT_DLFLAGS, /* dlopen flags */
00131         cmds,
00132         params,
00133         0,          /* exported statistics */
00134         0  ,        /* exported MI functions */
00135         mod_items,  /* exported pseudo-variables */
00136         0,          /* extra processes */
00137         mod_init,   /* module initialization function */
00138         0,
00139         (destroy_function) destroy,
00140         0           /* per-child init function */
00141 };
00142 
00146 static int mod_init(void)
00147 {
00148         int lf;
00149         if (xlog_facility_name!=NULL) {
00150                 lf = str2facility(xlog_facility_name);
00151                 if (lf != -1) {
00152                         xlog_facility = lf;
00153                 } else {
00154                         LM_ERR("invalid syslog facility %s\n", xlog_facility_name);
00155                         return -1;
00156                 }
00157         }
00158 
00159         _xlog_buf = (char*)pkg_malloc((buf_size+1)*sizeof(char));
00160         if(_xlog_buf==NULL)
00161         {
00162                 LM_ERR("no pkg memory left\n");
00163                 return -1;
00164         }
00165         return 0;
00166 }
00167 
00168 static inline int xlog_helper(struct sip_msg* msg, xl_msg_t *xm,
00169                 int level, int line, int facility)
00170 {
00171         str txt;
00172 
00173         txt.len = buf_size;
00174 
00175         if(xl_print_log(msg, xm->m, _xlog_buf, &txt.len)<0)
00176                 return -1;
00177         txt.s = _xlog_buf;
00178         /* if facility is not explicitely defined use the xlog default facility */
00179         if (facility==NOFACILITY) {
00180                 facility = xlog_facility;
00181         } 
00182 
00183         if(line>0)
00184                 if(long_format==1)
00185                         LOG_(facility, level, _xlog_prefix,
00186                                 "%s:%d:%.*s",
00187                                 (xm->a)?(((xm->a->cfile)?xm->a->cfile:"")):"",
00188                                 (xm->a)?xm->a->cline:0, txt.len, txt.s);
00189                 else
00190                         LOG_(facility, level, _xlog_prefix,
00191                                 "%d:%.*s", (xm->a)?xm->a->cline:0, txt.len, txt.s);
00192         else
00193                 LOG_(facility, level, _xlog_prefix,
00194                         "%.*s", txt.len, txt.s);
00195         return 1;
00196 }
00197 
00201 static int xlog_1_helper(struct sip_msg* msg, char* frm, char* str2, int mode, int facility)
00202 {
00203         if(!is_printable(L_ERR))
00204                 return 1;
00205 
00206         return xlog_helper(msg, (xl_msg_t*)frm, L_ERR, mode, facility);
00207 }
00208 static int xlog_1(struct sip_msg* msg, char* frm, char* str2)
00209 {
00210         return xlog_1_helper(msg, frm, str2, 0, NOFACILITY);
00211 }
00212 
00216 static int xlogl_1(struct sip_msg* msg, char* frm, char* str2)
00217 {
00218         return xlog_1_helper(msg, frm, str2, 1, NOFACILITY);
00219 }
00220 
00221 static int xlog_2_helper(struct sip_msg* msg, char* lev, char* frm, int mode, int facility)
00222 {
00223         long level;
00224         xl_level_p xlp;
00225         pv_value_t value;
00226 
00227         xlp = (xl_level_p)lev;
00228         if(xlp->type==1)
00229         {
00230                 if(pv_get_spec_value(msg, &xlp->v.sp, &value)!=0 
00231                         || value.flags&PV_VAL_NULL || !(value.flags&PV_VAL_INT))
00232                 {
00233                         LM_ERR("invalid log level value [%d]\n", value.flags);
00234                         return -1;
00235                 }
00236                 level = (long)value.ri;
00237         } else {
00238                 level = xlp->v.level;
00239         }
00240 
00241         if(!is_printable((int)level))
00242                 return 1;
00243 
00244         return xlog_helper(msg, (xl_msg_t*)frm, (int)level, mode, facility);
00245 }
00246 
00250 static int xlog_2(struct sip_msg* msg, char* lev, char* frm)
00251 {
00252         return xlog_2_helper(msg, lev, frm, 0, NOFACILITY);
00253 }
00254 
00258 static int xlogl_2(struct sip_msg* msg, char* lev, char* frm)
00259 {
00260         return xlog_2_helper(msg, lev, frm, 1, NOFACILITY);
00261 }
00262 
00263 static int xlog_3_helper(struct sip_msg* msg, char* fac, char* lev, char* frm, int mode)
00264 {
00265         long level;
00266         int facility;
00267         xl_level_p xlp;
00268         pv_value_t value;
00269 
00270         xlp = (xl_level_p)lev;
00271         if(xlp->type==1)
00272         {
00273                 if(pv_get_spec_value(msg, &xlp->v.sp, &value)!=0 
00274                         || value.flags&PV_VAL_NULL || !(value.flags&PV_VAL_INT))
00275                 {
00276                         LM_ERR("invalid log level value [%d]\n", value.flags);
00277                         return -1;
00278                 }
00279                 level = (long)value.ri;
00280         } else {
00281                 level = xlp->v.level;
00282         }
00283         facility = *(int*)fac;
00284 
00285         if(!is_printable((int)level))
00286                 return 1;
00287 
00288         return xlog_helper(msg, (xl_msg_t*)frm, (int)level, mode, facility);
00289 }
00290 
00295 static int xlog_3(struct sip_msg* msg, char* fac, char* lev, char* frm)
00296 {
00297         return xlog_3_helper(msg, fac, lev, frm, 0);
00298 }
00299 
00304 static int xlogl_3(struct sip_msg* msg, char* fac, char* lev, char* frm)
00305 {
00306         return xlog_3_helper(msg, fac, lev, frm, 1);
00307 }
00308 
00309 static int xdbg_helper(struct sip_msg* msg, char* frm, char* str2, int mode, int facility)
00310 {
00311         if(!is_printable(L_DBG))
00312                 return 1;
00313         return xlog_helper(msg, (xl_msg_t*)frm, L_DBG, mode, facility);
00314 }
00315 
00319 static int xdbg(struct sip_msg* msg, char* frm, char* str2)
00320 {
00321         return xdbg_helper(msg, frm, str2, 0, NOFACILITY);
00322 }
00323 
00327 static int xdbgl(struct sip_msg* msg, char* frm, char* str2)
00328 {
00329         return xdbg_helper(msg, frm, str2, 1, NOFACILITY);
00330 }
00331 
00335 static void destroy(void)
00336 {
00337         if(_xlog_buf)
00338                 pkg_free(_xlog_buf);
00339 }
00340 
00341 static int xdbg_fixup_helper(void** param, int param_no, int mode)
00342 {
00343         xl_msg_t *xm;
00344         str s;
00345 
00346         xm = (xl_msg_t*)pkg_malloc(sizeof(xl_msg_t));
00347         if(xm==NULL)
00348         {
00349                 LM_ERR("no more pkg\n");
00350                 return -1;
00351         }
00352         memset(xm, 0, sizeof(xl_msg_t));
00353         if(mode==1)
00354                 xm->a = get_action_from_param(param, param_no);
00355         s.s = (char*)(*param); s.len = strlen(s.s);
00356 
00357         if(pv_parse_format(&s, &xm->m)<0)
00358         {
00359                 LM_ERR("wrong format[%s]\n", (char*)(*param));
00360                 return E_UNSPEC;
00361         }
00362         *param = (void*)xm;
00363         return 0;
00364 }
00365 
00366 static int xlog_fixup_helper(void** param, int param_no, int mode)
00367 {
00368         xl_level_p xlp;
00369         str s;
00370         
00371         if(param_no==1)
00372         {
00373                 s.s = (char*)(*param);
00374                 if(s.s==NULL || strlen(s.s)<2)
00375                 {
00376                         LM_ERR("wrong log level\n");
00377                         return E_UNSPEC;
00378                 }
00379 
00380                 xlp = (xl_level_p)pkg_malloc(sizeof(xl_level_t));
00381                 if(xlp == NULL)
00382                 {
00383                         LM_ERR("no more memory\n");
00384                         return E_UNSPEC;
00385                 }
00386                 memset(xlp, 0, sizeof(xl_level_t));
00387                 if(s.s[0]==PV_MARKER)
00388                 {
00389                         xlp->type = 1;
00390                         s.len = strlen(s.s);
00391                         if(pv_parse_spec(&s, &xlp->v.sp)==NULL)
00392                         {
00393                                 LM_ERR("invalid level param\n");
00394                                 return E_UNSPEC;
00395                         }
00396                 } else {
00397                         xlp->type = 0;
00398                         switch(((char*)(*param))[2])
00399                         {
00400                                 case 'A': xlp->v.level = L_ALERT; break;
00401                                 case 'B': xlp->v.level = L_BUG; break;
00402                                 case 'C': xlp->v.level = L_CRIT2; break;
00403                                 case 'E': xlp->v.level = L_ERR; break;
00404                                 case 'W': xlp->v.level = L_WARN; break;
00405                                 case 'N': xlp->v.level = L_NOTICE; break;
00406                                 case 'I': xlp->v.level = L_INFO; break;
00407                                 case 'D': xlp->v.level = L_DBG; break;
00408                                 default:
00409                                         LM_ERR("unknown log level\n");
00410                                         return E_UNSPEC;
00411                         }
00412                 }
00413                 pkg_free(*param);
00414                 *param = (void*)xlp;
00415                 return 0;
00416         }
00417 
00418         if(param_no==2)
00419                 return xdbg_fixup_helper(param, 2, mode);
00420 
00421         return 0;
00422 }
00423 
00424 /*
00425  * fixup log facility
00426  */
00427 static int xlog3_fixup_helper(void** param, int param_no)
00428 {
00429         int *facility;
00430         str s;
00431 
00432         s.s = (char*)(*param);
00433         if(s.s==NULL)
00434         {
00435                 LM_ERR("wrong log facility\n");
00436                 return E_UNSPEC;
00437         }
00438         facility = (int*)pkg_malloc(sizeof(int));
00439         if(facility == NULL)
00440         {
00441                 LM_ERR("no more memory\n");
00442                 return E_UNSPEC;
00443         }
00444         *facility = str2facility(s.s);
00445         if (*facility == -1) {
00446                 LM_ERR("invalid syslog facility %s\n", s.s);
00447                 return E_UNSPEC;
00448         }
00449 
00450         pkg_free(*param);
00451         *param = (void*)facility;
00452         return 0;
00453 }
00454 
00455 static int xlog_fixup(void** param, int param_no)
00456 {
00457         if(param==NULL || *param==NULL)
00458         {
00459                 LM_ERR("invalid parameter number %d\n", param_no);
00460                 return E_UNSPEC;
00461         }
00462         return xlog_fixup_helper(param, param_no, 0);
00463 }
00464 
00465 static int xlog3_fixup(void** param, int param_no)
00466 {
00467         if(param==NULL || *param==NULL)
00468         {
00469                 LM_ERR("invalid parameter number %d\n", param_no);
00470                 return E_UNSPEC;
00471         }
00472         /* fixup loglevel */
00473         if (param_no == 2) {
00474                 return xlog_fixup_helper(param, 1, 0);
00475         }
00476         /* fixup log message */
00477         if (param_no == 3) {
00478                 return xdbg_fixup_helper(param, 3, 0);
00479         }
00480         /* fixup facility */
00481         return xlog3_fixup_helper(param, param_no);
00482 }
00483 
00484 static int xdbg_fixup(void** param, int param_no)
00485 {
00486         if(param_no!=1 || param==NULL || *param==NULL)
00487         {
00488                 LM_ERR("invalid parameter number %d\n", param_no);
00489                 return E_UNSPEC;
00490         }
00491         return xdbg_fixup_helper(param, param_no, 0);
00492 }
00493 
00494 static int xlogl3_fixup(void** param, int param_no)
00495 {
00496         if(param==NULL || *param==NULL)
00497         {
00498                 LM_ERR("invalid parameter number %d\n", param_no);
00499                 return E_UNSPEC;
00500         }
00501         /* fixup loglevel */
00502         if (param_no == 2) {
00503                 return xlog_fixup_helper(param, 1, 1);
00504         }
00505         /* fixup log message */
00506         if (param_no == 3) {
00507                 return xdbg_fixup_helper(param, 3, 1);
00508         }
00509         /* fixup facility */
00510         return xlog3_fixup_helper(param, param_no);
00511 }
00512 
00513 static int xlogl_fixup(void** param, int param_no)
00514 {
00515         if(param==NULL || *param==NULL)
00516         {
00517                 LM_ERR("invalid parameter number %d\n", param_no);
00518                 return E_UNSPEC;
00519         }
00520         return xlog_fixup_helper(param, param_no, 1);
00521 }
00522 
00523 static int xdbgl_fixup(void** param, int param_no)
00524 {
00525         if(param_no!=1 || param==NULL || *param==NULL)
00526         {
00527                 LM_ERR("invalid parameter number %d\n", param_no);
00528                 return E_UNSPEC;
00529         }
00530         return xdbg_fixup_helper(param, param_no, 1);
00531 }
00532 
00533 int pv_parse_color_name(pv_spec_p sp, str *in)
00534 {
00535 
00536         if(in==NULL || in->s==NULL || sp==NULL)
00537                 return -1;
00538 
00539         if(in->len != 2)
00540         {
00541                 LM_ERR("color name must have two chars\n");
00542                 return -1;
00543         }
00544         
00545         /* foreground */
00546         switch(in->s[0])
00547         {
00548                 case 'x':
00549                 case 's': case 'r': case 'g':
00550                 case 'y': case 'b': case 'p':
00551                 case 'c': case 'w': case 'S':
00552                 case 'R': case 'G': case 'Y':
00553                 case 'B': case 'P': case 'C':
00554                 case 'W':
00555                 break;
00556                 default: 
00557                         goto error;
00558         }
00559                                
00560         /* background */
00561         switch(in->s[1])
00562         {
00563                 case 'x':
00564                 case 's': case 'r': case 'g':
00565                 case 'y': case 'b': case 'p':
00566                 case 'c': case 'w':
00567                 break;   
00568                 default: 
00569                         goto error;
00570         }
00571         
00572         sp->pvp.pvn.type = PV_NAME_INTSTR;
00573         sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
00574         sp->pvp.pvn.u.isname.name.s = *in;
00575 
00576         sp->getf = pv_get_color;
00577 
00578         /* force the color PV type */
00579         sp->type = PVT_COLOR;
00580         return 0;
00581 error:
00582         LM_ERR("invalid color name\n");
00583         return -1;
00584 }
00585 
00586 #define COL_BUF 10
00587 
00588 #define append_sstring(p, end, s) \
00589         do{\
00590                 if ((p)+(sizeof(s)-1)<=(end)){\
00591                         memcpy((p), s, sizeof(s)-1); \
00592                         (p)+=sizeof(s)-1; \
00593                 }else{ \
00594                         /* overflow */ \
00595                         LM_ERR("append_sstring overflow\n"); \
00596                         goto error;\
00597                 } \
00598         } while(0) 
00599 
00600 
00601 static int pv_get_color(struct sip_msg *msg, pv_param_t *param,
00602                 pv_value_t *res)
00603 {
00604         static char color[COL_BUF];
00605         char* p;
00606         char* end;
00607         str s;
00608 
00609         if(log_stderr==0 && force_color==0)
00610         {
00611                 s.s = "";
00612                 s.len = 0;
00613                 return pv_get_strval(msg, param, res, &s);
00614         }
00615 
00616         p = color;
00617         end = p + COL_BUF;
00618         
00619         /* excape sequenz */
00620         append_sstring(p, end, "\033[");
00621         
00622         if(param->pvn.u.isname.name.s.s[0]!='_')
00623         {
00624                 if (islower((int)param->pvn.u.isname.name.s.s[0]))
00625                 {
00626                         /* normal font */
00627                         append_sstring(p, end, "0;");
00628                 } else {
00629                         /* bold font */
00630                         append_sstring(p, end, "1;");
00631                         param->pvn.u.isname.name.s.s[0] += 32;
00632                 }
00633         }
00634          
00635         /* foreground */
00636         switch(param->pvn.u.isname.name.s.s[0])
00637         {
00638                 case 'x':
00639                         append_sstring(p, end, "39;");
00640                 break;
00641                 case 's':
00642                         append_sstring(p, end, "30;");
00643                 break;
00644                 case 'r':
00645                         append_sstring(p, end, "31;");
00646                 break;
00647                 case 'g':
00648                         append_sstring(p, end, "32;");
00649                 break;
00650                 case 'y':
00651                         append_sstring(p, end, "33;");
00652                 break;
00653                 case 'b':
00654                         append_sstring(p, end, "34;");
00655                 break;
00656                 case 'p':
00657                         append_sstring(p, end, "35;");
00658                 break;
00659                 case 'c':
00660                         append_sstring(p, end, "36;");
00661                 break;
00662                 case 'w':
00663                         append_sstring(p, end, "37;");
00664                 break;
00665                 default:
00666                         LM_ERR("invalid foreground\n");
00667                         return pv_get_null(msg, param, res);
00668         }
00669          
00670         /* background */
00671         switch(param->pvn.u.isname.name.s.s[1])
00672         {
00673                 case 'x':
00674                         append_sstring(p, end, "49");
00675                 break;
00676                 case 's':
00677                         append_sstring(p, end, "40");
00678                 break;
00679                 case 'r':
00680                         append_sstring(p, end, "41");
00681                 break;
00682                 case 'g':
00683                         append_sstring(p, end, "42");
00684                 break;
00685                 case 'y':
00686                         append_sstring(p, end, "43");
00687                 break;
00688                 case 'b':
00689                         append_sstring(p, end, "44");
00690                 break;
00691                 case 'p':
00692                         append_sstring(p, end, "45");
00693                 break;
00694                 case 'c':
00695                         append_sstring(p, end, "46");
00696                 break;
00697                 case 'w':
00698                         append_sstring(p, end, "47");
00699                 break;
00700                 default:
00701                         LM_ERR("invalid background\n");
00702                         return pv_get_null(msg, param, res);
00703         }
00704 
00705         /* end */
00706         append_sstring(p, end, "m");
00707 
00708         s.s = color;
00709         s.len = p-color;
00710         return pv_get_strval(msg, param, res, &s);
00711 
00712 error:
00713         return -1;
00714 }
00715