xlog.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. /**
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <sys/types.h>
  26. #include <sys/ipc.h>
  27. #include <unistd.h>
  28. #include <fcntl.h>
  29. #include <time.h>
  30. #include <ctype.h>
  31. #include "../../sr_module.h"
  32. #include "../../dprint.h"
  33. #include "../../error.h"
  34. #include "../../mem/mem.h"
  35. #include "../../parser/parse_param.h"
  36. #include "xl_lib.h"
  37. #include "../../pvar.h"
  38. #define NOFACILITY -1
  39. MODULE_VERSION
  40. char *_xlog_buf = NULL;
  41. char *_xlog_prefix = "<script>: ";
  42. /** parameters */
  43. static int buf_size=4096;
  44. static int force_color=0;
  45. static int long_format=0;
  46. static int xlog_facility = DEFAULT_FACILITY;
  47. static char *xlog_facility_name = NULL;
  48. /** module functions */
  49. static int mod_init(void);
  50. static int xlog_1(struct sip_msg*, char*, char*);
  51. static int xlog_2(struct sip_msg*, char*, char*);
  52. static int xlog_3(struct sip_msg*, char*, char*, char*);
  53. static int xdbg(struct sip_msg*, char*, char*);
  54. static int xlogl_1(struct sip_msg*, char*, char*);
  55. static int xlogl_2(struct sip_msg*, char*, char*);
  56. static int xlogl_3(struct sip_msg*, char*, char*, char*);
  57. static int xdbgl(struct sip_msg*, char*, char*);
  58. static int xlog_fixup(void** param, int param_no);
  59. static int xlog3_fixup(void** param, int param_no);
  60. static int xdbg_fixup(void** param, int param_no);
  61. static int xlogl_fixup(void** param, int param_no);
  62. static int xlogl3_fixup(void** param, int param_no);
  63. static int xdbgl_fixup(void** param, int param_no);
  64. static void destroy(void);
  65. static int xlog_log_colors_param(modparam_t type, void *val);
  66. int pv_parse_color_name(pv_spec_p sp, str *in);
  67. static int pv_get_color(struct sip_msg *msg, pv_param_t *param,
  68. pv_value_t *res);
  69. typedef struct _xl_level
  70. {
  71. int type;
  72. union {
  73. long level;
  74. pv_spec_t sp;
  75. } v;
  76. } xl_level_t, *xl_level_p;
  77. typedef struct _xl_msg
  78. {
  79. pv_elem_t *m;
  80. struct action *a;
  81. } xl_msg_t;
  82. static pv_export_t mod_items[] = {
  83. { {"C", sizeof("C")-1}, PVT_OTHER, pv_get_color, 0,
  84. pv_parse_color_name, 0, 0, 0 },
  85. { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
  86. };
  87. static cmd_export_t cmds[]={
  88. {"xlog", (cmd_function)xlog_1, 1, xdbg_fixup, 0, ANY_ROUTE},
  89. {"xlog", (cmd_function)xlog_2, 2, xlog_fixup, 0, ANY_ROUTE},
  90. {"xlog", (cmd_function)xlog_3, 3, xlog3_fixup, 0, ANY_ROUTE},
  91. {"xdbg", (cmd_function)xdbg, 1, xdbg_fixup, 0, ANY_ROUTE},
  92. {"xlogl", (cmd_function)xlogl_1, 1, xdbgl_fixup, 0, ANY_ROUTE},
  93. {"xlogl", (cmd_function)xlogl_2, 2, xlogl_fixup, 0, ANY_ROUTE},
  94. {"xlogl", (cmd_function)xlogl_3, 3, xlogl3_fixup,0, ANY_ROUTE},
  95. {"xdbgl", (cmd_function)xdbgl, 1, xdbgl_fixup, 0, ANY_ROUTE},
  96. {0,0,0,0,0,0}
  97. };
  98. static param_export_t params[]={
  99. {"buf_size", INT_PARAM, &buf_size},
  100. {"force_color", INT_PARAM, &force_color},
  101. {"long_format", INT_PARAM, &long_format},
  102. {"prefix", PARAM_STRING, &_xlog_prefix},
  103. {"log_facility", PARAM_STRING, &xlog_facility_name},
  104. {"log_colors", PARAM_STRING|USE_FUNC_PARAM, (void*)xlog_log_colors_param},
  105. {0,0,0}
  106. };
  107. /** module exports */
  108. struct module_exports exports= {
  109. "xlog",
  110. DEFAULT_DLFLAGS, /* dlopen flags */
  111. cmds,
  112. params,
  113. 0, /* exported statistics */
  114. 0 , /* exported MI functions */
  115. mod_items, /* exported pseudo-variables */
  116. 0, /* extra processes */
  117. mod_init, /* module initialization function */
  118. 0,
  119. (destroy_function) destroy,
  120. 0 /* per-child init function */
  121. };
  122. /**
  123. * init module function
  124. */
  125. static int mod_init(void)
  126. {
  127. int lf;
  128. if (xlog_facility_name!=NULL) {
  129. lf = str2facility(xlog_facility_name);
  130. if (lf != -1) {
  131. xlog_facility = lf;
  132. } else {
  133. LM_ERR("invalid syslog facility %s\n", xlog_facility_name);
  134. return -1;
  135. }
  136. }
  137. _xlog_buf = (char*)pkg_malloc((buf_size+1)*sizeof(char));
  138. if(_xlog_buf==NULL)
  139. {
  140. LM_ERR("no pkg memory left\n");
  141. return -1;
  142. }
  143. return 0;
  144. }
  145. static inline int xlog_helper(struct sip_msg* msg, xl_msg_t *xm,
  146. int level, int line, int facility)
  147. {
  148. str txt;
  149. txt.len = buf_size;
  150. if(xl_print_log(msg, xm->m, _xlog_buf, &txt.len)<0)
  151. return -1;
  152. txt.s = _xlog_buf;
  153. /* if facility is not explicitely defined use the xlog default facility */
  154. if (facility==NOFACILITY) {
  155. facility = xlog_facility;
  156. }
  157. if(line>0)
  158. if(long_format==1)
  159. LOG_(facility, level, _xlog_prefix,
  160. "%s:%d:%.*s",
  161. (xm->a)?(((xm->a->cfile)?xm->a->cfile:"")):"",
  162. (xm->a)?xm->a->cline:0, txt.len, txt.s);
  163. else
  164. LOG_(facility, level, _xlog_prefix,
  165. "%d:%.*s", (xm->a)?xm->a->cline:0, txt.len, txt.s);
  166. else
  167. LOG_(facility, level, _xlog_prefix,
  168. "%.*s", txt.len, txt.s);
  169. return 1;
  170. }
  171. /**
  172. * print log message to L_ERR level
  173. */
  174. static int xlog_1_helper(struct sip_msg* msg, char* frm, char* str2, int mode, int facility)
  175. {
  176. if(!is_printable(L_ERR))
  177. return 1;
  178. return xlog_helper(msg, (xl_msg_t*)frm, L_ERR, mode, facility);
  179. }
  180. static int xlog_1(struct sip_msg* msg, char* frm, char* str2)
  181. {
  182. return xlog_1_helper(msg, frm, str2, 0, NOFACILITY);
  183. }
  184. /**
  185. * print log message to L_ERR level along with cfg line
  186. */
  187. static int xlogl_1(struct sip_msg* msg, char* frm, char* str2)
  188. {
  189. return xlog_1_helper(msg, frm, str2, 1, NOFACILITY);
  190. }
  191. static int xlog_2_helper(struct sip_msg* msg, char* lev, char* frm, int mode, int facility)
  192. {
  193. long level;
  194. xl_level_p xlp;
  195. pv_value_t value;
  196. xlp = (xl_level_p)lev;
  197. if(xlp->type==1)
  198. {
  199. if(pv_get_spec_value(msg, &xlp->v.sp, &value)!=0
  200. || value.flags&PV_VAL_NULL || !(value.flags&PV_VAL_INT))
  201. {
  202. LM_ERR("invalid log level value [%d]\n", value.flags);
  203. return -1;
  204. }
  205. level = (long)value.ri;
  206. } else {
  207. level = xlp->v.level;
  208. }
  209. if(!is_printable((int)level))
  210. return 1;
  211. return xlog_helper(msg, (xl_msg_t*)frm, (int)level, mode, facility);
  212. }
  213. /**
  214. * print log message to level given in parameter
  215. */
  216. static int xlog_2(struct sip_msg* msg, char* lev, char* frm)
  217. {
  218. return xlog_2_helper(msg, lev, frm, 0, NOFACILITY);
  219. }
  220. /**
  221. * print log message to level given in parameter along with cfg line
  222. */
  223. static int xlogl_2(struct sip_msg* msg, char* lev, char* frm)
  224. {
  225. return xlog_2_helper(msg, lev, frm, 1, NOFACILITY);
  226. }
  227. static int xlog_3_helper(struct sip_msg* msg, char* fac, char* lev, char* frm, int mode)
  228. {
  229. long level;
  230. int facility;
  231. xl_level_p xlp;
  232. pv_value_t value;
  233. xlp = (xl_level_p)lev;
  234. if(xlp->type==1)
  235. {
  236. if(pv_get_spec_value(msg, &xlp->v.sp, &value)!=0
  237. || value.flags&PV_VAL_NULL || !(value.flags&PV_VAL_INT))
  238. {
  239. LM_ERR("invalid log level value [%d]\n", value.flags);
  240. return -1;
  241. }
  242. level = (long)value.ri;
  243. } else {
  244. level = xlp->v.level;
  245. }
  246. facility = *(int*)fac;
  247. if(!is_printable((int)level))
  248. return 1;
  249. return xlog_helper(msg, (xl_msg_t*)frm, (int)level, mode, facility);
  250. }
  251. /**
  252. * print log message to level given in parameter
  253. * add dedicated logfacility
  254. */
  255. static int xlog_3(struct sip_msg* msg, char* fac, char* lev, char* frm)
  256. {
  257. return xlog_3_helper(msg, fac, lev, frm, 0);
  258. }
  259. /**
  260. * print log message to level given in parameter along with cfg line
  261. * add dedicated logfacility
  262. */
  263. static int xlogl_3(struct sip_msg* msg, char* fac, char* lev, char* frm)
  264. {
  265. return xlog_3_helper(msg, fac, lev, frm, 1);
  266. }
  267. static int xdbg_helper(struct sip_msg* msg, char* frm, char* str2, int mode, int facility)
  268. {
  269. if(!is_printable(L_DBG))
  270. return 1;
  271. return xlog_helper(msg, (xl_msg_t*)frm, L_DBG, mode, facility);
  272. }
  273. /**
  274. * print log message to L_DBG level
  275. */
  276. static int xdbg(struct sip_msg* msg, char* frm, char* str2)
  277. {
  278. return xdbg_helper(msg, frm, str2, 0, NOFACILITY);
  279. }
  280. /**
  281. * print log message to L_DBG level along with cfg line
  282. */
  283. static int xdbgl(struct sip_msg* msg, char* frm, char* str2)
  284. {
  285. return xdbg_helper(msg, frm, str2, 1, NOFACILITY);
  286. }
  287. /**
  288. * module destroy function
  289. */
  290. static void destroy(void)
  291. {
  292. if(_xlog_buf)
  293. pkg_free(_xlog_buf);
  294. }
  295. static int xdbg_fixup_helper(void** param, int param_no, int mode)
  296. {
  297. xl_msg_t *xm;
  298. str s;
  299. xm = (xl_msg_t*)pkg_malloc(sizeof(xl_msg_t));
  300. if(xm==NULL)
  301. {
  302. LM_ERR("no more pkg\n");
  303. return -1;
  304. }
  305. memset(xm, 0, sizeof(xl_msg_t));
  306. if(mode==1)
  307. xm->a = get_action_from_param(param, param_no);
  308. s.s = (char*)(*param); s.len = strlen(s.s);
  309. if(pv_parse_format(&s, &xm->m)<0)
  310. {
  311. LM_ERR("wrong format[%s]\n", (char*)(*param));
  312. return E_UNSPEC;
  313. }
  314. *param = (void*)xm;
  315. return 0;
  316. }
  317. static int xlog_fixup_helper(void** param, int param_no, int mode)
  318. {
  319. xl_level_p xlp;
  320. str s;
  321. if(param_no==1)
  322. {
  323. s.s = (char*)(*param);
  324. if(s.s==NULL || strlen(s.s)<2)
  325. {
  326. LM_ERR("wrong log level\n");
  327. return E_UNSPEC;
  328. }
  329. xlp = (xl_level_p)pkg_malloc(sizeof(xl_level_t));
  330. if(xlp == NULL)
  331. {
  332. LM_ERR("no more memory\n");
  333. return E_UNSPEC;
  334. }
  335. memset(xlp, 0, sizeof(xl_level_t));
  336. if(s.s[0]==PV_MARKER)
  337. {
  338. xlp->type = 1;
  339. s.len = strlen(s.s);
  340. if(pv_parse_spec(&s, &xlp->v.sp)==NULL)
  341. {
  342. LM_ERR("invalid level param\n");
  343. return E_UNSPEC;
  344. }
  345. } else {
  346. xlp->type = 0;
  347. switch(((char*)(*param))[2])
  348. {
  349. case 'A': xlp->v.level = L_ALERT; break;
  350. case 'B': xlp->v.level = L_BUG; break;
  351. case 'C': xlp->v.level = L_CRIT2; break;
  352. case 'E': xlp->v.level = L_ERR; break;
  353. case 'W': xlp->v.level = L_WARN; break;
  354. case 'N': xlp->v.level = L_NOTICE; break;
  355. case 'I': xlp->v.level = L_INFO; break;
  356. case 'D': xlp->v.level = L_DBG; break;
  357. default:
  358. LM_ERR("unknown log level\n");
  359. return E_UNSPEC;
  360. }
  361. }
  362. pkg_free(*param);
  363. *param = (void*)xlp;
  364. return 0;
  365. }
  366. if(param_no==2)
  367. return xdbg_fixup_helper(param, 2, mode);
  368. return 0;
  369. }
  370. /*
  371. * fixup log facility
  372. */
  373. static int xlog3_fixup_helper(void** param, int param_no)
  374. {
  375. int *facility;
  376. str s;
  377. s.s = (char*)(*param);
  378. if(s.s==NULL)
  379. {
  380. LM_ERR("wrong log facility\n");
  381. return E_UNSPEC;
  382. }
  383. facility = (int*)pkg_malloc(sizeof(int));
  384. if(facility == NULL)
  385. {
  386. LM_ERR("no more memory\n");
  387. return E_UNSPEC;
  388. }
  389. *facility = str2facility(s.s);
  390. if (*facility == -1) {
  391. LM_ERR("invalid syslog facility %s\n", s.s);
  392. pkg_free(facility);
  393. return E_UNSPEC;
  394. }
  395. pkg_free(*param);
  396. *param = (void*)facility;
  397. return 0;
  398. }
  399. static int xlog_fixup(void** param, int param_no)
  400. {
  401. if(param==NULL || *param==NULL)
  402. {
  403. LM_ERR("invalid parameter number %d\n", param_no);
  404. return E_UNSPEC;
  405. }
  406. return xlog_fixup_helper(param, param_no, 0);
  407. }
  408. static int xlog3_fixup(void** param, int param_no)
  409. {
  410. if(param==NULL || *param==NULL)
  411. {
  412. LM_ERR("invalid parameter number %d\n", param_no);
  413. return E_UNSPEC;
  414. }
  415. /* fixup loglevel */
  416. if (param_no == 2) {
  417. return xlog_fixup_helper(param, 1, 0);
  418. }
  419. /* fixup log message */
  420. if (param_no == 3) {
  421. return xdbg_fixup_helper(param, 3, 0);
  422. }
  423. /* fixup facility */
  424. return xlog3_fixup_helper(param, param_no);
  425. }
  426. static int xdbg_fixup(void** param, int param_no)
  427. {
  428. if(param_no!=1 || param==NULL || *param==NULL)
  429. {
  430. LM_ERR("invalid parameter number %d\n", param_no);
  431. return E_UNSPEC;
  432. }
  433. return xdbg_fixup_helper(param, param_no, 0);
  434. }
  435. static int xlogl3_fixup(void** param, int param_no)
  436. {
  437. if(param==NULL || *param==NULL)
  438. {
  439. LM_ERR("invalid parameter number %d\n", param_no);
  440. return E_UNSPEC;
  441. }
  442. /* fixup loglevel */
  443. if (param_no == 2) {
  444. return xlog_fixup_helper(param, 1, 1);
  445. }
  446. /* fixup log message */
  447. if (param_no == 3) {
  448. return xdbg_fixup_helper(param, 3, 1);
  449. }
  450. /* fixup facility */
  451. return xlog3_fixup_helper(param, param_no);
  452. }
  453. static int xlogl_fixup(void** param, int param_no)
  454. {
  455. if(param==NULL || *param==NULL)
  456. {
  457. LM_ERR("invalid parameter number %d\n", param_no);
  458. return E_UNSPEC;
  459. }
  460. return xlog_fixup_helper(param, param_no, 1);
  461. }
  462. static int xdbgl_fixup(void** param, int param_no)
  463. {
  464. if(param_no!=1 || param==NULL || *param==NULL)
  465. {
  466. LM_ERR("invalid parameter number %d\n", param_no);
  467. return E_UNSPEC;
  468. }
  469. return xdbg_fixup_helper(param, param_no, 1);
  470. }
  471. int pv_parse_color_name(pv_spec_p sp, str *in)
  472. {
  473. if(in==NULL || in->s==NULL || sp==NULL)
  474. return -1;
  475. if(in->len != 2)
  476. {
  477. LM_ERR("color name must have two chars\n");
  478. return -1;
  479. }
  480. /* foreground */
  481. switch(in->s[0])
  482. {
  483. case 'x':
  484. case 's': case 'r': case 'g':
  485. case 'y': case 'b': case 'p':
  486. case 'c': case 'w': case 'S':
  487. case 'R': case 'G': case 'Y':
  488. case 'B': case 'P': case 'C':
  489. case 'W':
  490. break;
  491. default:
  492. goto error;
  493. }
  494. /* background */
  495. switch(in->s[1])
  496. {
  497. case 'x':
  498. case 's': case 'r': case 'g':
  499. case 'y': case 'b': case 'p':
  500. case 'c': case 'w':
  501. break;
  502. default:
  503. goto error;
  504. }
  505. sp->pvp.pvn.type = PV_NAME_INTSTR;
  506. sp->pvp.pvn.u.isname.type = AVP_NAME_STR;
  507. sp->pvp.pvn.u.isname.name.s = *in;
  508. sp->getf = pv_get_color;
  509. /* force the color PV type */
  510. sp->type = PVT_COLOR;
  511. return 0;
  512. error:
  513. LM_ERR("invalid color name\n");
  514. return -1;
  515. }
  516. static int pv_get_color(struct sip_msg *msg, pv_param_t *param,
  517. pv_value_t *res)
  518. {
  519. str s = {"", 0};
  520. if(log_stderr==0 && force_color==0)
  521. {
  522. LM_DBG("ignoring colors\n");
  523. return pv_get_strval(msg, param, res, &s);
  524. }
  525. dprint_term_color(param->pvn.u.isname.name.s.s[0],
  526. param->pvn.u.isname.name.s.s[1], &s);
  527. return pv_get_strval(msg, param, res, &s);
  528. }
  529. /**
  530. *
  531. */
  532. static int xlog_log_colors_param(modparam_t type, void *val)
  533. {
  534. param_t* params_list = NULL;
  535. param_hooks_t phooks;
  536. param_t *pit=NULL;
  537. str s;
  538. int level;
  539. if(val==NULL)
  540. goto error;
  541. s.s = (char*)val;
  542. s.len = strlen(s.s);
  543. if(s.len<=0)
  544. goto error;
  545. if(s.s[s.len-1]==';')
  546. s.len--;
  547. if (parse_params(&s, CLASS_ANY, &phooks, &params_list)<0)
  548. goto error;
  549. for (pit = params_list; pit; pit=pit->next)
  550. {
  551. if (pit->name.len==7
  552. && strncasecmp(pit->name.s, "l_alert", 7)==0) {
  553. level = L_ALERT;
  554. } else if (pit->name.len==5
  555. && strncasecmp(pit->name.s, "l_bug", 5)==0) {
  556. level = L_BUG;
  557. } else if (pit->name.len==7
  558. && strncasecmp(pit->name.s, "l_crit2", 7)==0) {
  559. level = L_CRIT2;
  560. } else if (pit->name.len==6
  561. && strncasecmp(pit->name.s, "l_crit", 6)==0) {
  562. level = L_CRIT;
  563. } else if (pit->name.len==5
  564. && strncasecmp(pit->name.s, "l_err", 5)==0) {
  565. level = L_ERR;
  566. } else if (pit->name.len==6
  567. && strncasecmp(pit->name.s, "l_warn", 6)==0) {
  568. level = L_WARN;
  569. } else if (pit->name.len==8
  570. && strncasecmp(pit->name.s, "l_notice", 8)==0) {
  571. level = L_NOTICE;
  572. } else if (pit->name.len==6
  573. && strncasecmp(pit->name.s, "l_info", 6)==0) {
  574. level = L_INFO;
  575. } else if (pit->name.len==5
  576. && strncasecmp(pit->name.s, "l_dbg", 5)==0) {
  577. level = L_DBG;
  578. } else {
  579. LM_ERR("invalid level name %.*s\n",
  580. pit->name.len, pit->name.s);
  581. goto error;
  582. }
  583. if(pit->body.len!=2) {
  584. LM_ERR("invalid color spec for level %.*s (%.*s)\n",
  585. pit->name.len, pit->name.s,
  586. pit->body.len, pit->body.s);
  587. goto error;
  588. }
  589. dprint_color_update(level, pit->body.s[0], pit->body.s[1]);
  590. }
  591. if(params_list!=NULL)
  592. free_params(params_list);
  593. return 0;
  594. error:
  595. if(params_list!=NULL)
  596. free_params(params_list);
  597. return -1;
  598. }