00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00048 int buf_size=4096;
00049 int force_color=0;
00050
00051
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
00105 struct module_exports exports= {
00106 "xlog",
00107 DEFAULT_DLFLAGS,
00108 cmds,
00109 params,
00110 0,
00111 0 ,
00112 mod_items,
00113 0,
00114 mod_init,
00115 0,
00116 (destroy_function) destroy,
00117 0
00118 };
00119
00120
00121
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
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
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
00206 LM_GEN1(L_DBG, "%.*s", log_len, log_buf);
00207
00208 return 1;
00209 }
00210
00211
00212
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
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
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
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 \
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
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
00412 append_sstring(p, end, "0;");
00413 } else {
00414
00415 append_sstring(p, end, "1;");
00416 param->pvn.u.isname.name.s.s[0] += 32;
00417 }
00418 }
00419
00420
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
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
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