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,
00131 cmds,
00132 params,
00133 0,
00134 0 ,
00135 mod_items,
00136 0,
00137 mod_init,
00138 0,
00139 (destroy_function) destroy,
00140 0
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
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
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
00473 if (param_no == 2) {
00474 return xlog_fixup_helper(param, 1, 0);
00475 }
00476
00477 if (param_no == 3) {
00478 return xdbg_fixup_helper(param, 3, 0);
00479 }
00480
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
00502 if (param_no == 2) {
00503 return xlog_fixup_helper(param, 1, 1);
00504 }
00505
00506 if (param_no == 3) {
00507 return xdbg_fixup_helper(param, 3, 1);
00508 }
00509
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
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
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
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 \
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
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
00627 append_sstring(p, end, "0;");
00628 } else {
00629
00630 append_sstring(p, end, "1;");
00631 param->pvn.u.isname.name.s.s[0] += 32;
00632 }
00633 }
00634
00635
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
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
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