formatted logging module
authorElena-Ramona Modroiu <ramona@voice-system.ro>
Fri, 6 Jun 2003 14:54:13 +0000 (14:54 +0000)
committerElena-Ramona Modroiu <ramona@voice-system.ro>
Fri, 6 Jun 2003 14:54:13 +0000 (14:54 +0000)
modules_s/xlog/Makefile [new file with mode: 0644]
modules_s/xlog/README [new file with mode: 0644]
modules_s/xlog/xl_lib.c [new file with mode: 0644]
modules_s/xlog/xl_lib.h [new file with mode: 0644]
modules_s/xlog/xlog.c [new file with mode: 0644]

diff --git a/modules_s/xlog/Makefile b/modules_s/xlog/Makefile
new file mode 100644 (file)
index 0000000..b41665f
--- /dev/null
@@ -0,0 +1,12 @@
+# $Id$
+#
+# example module makefile
+#
+# 
+# WARNING: do not run this directly, it should be run by the master Makefile
+
+auto_gen=
+NAME=xlog.so
+LIBS=
+
+include ../../Makefile.modules
diff --git a/modules_s/xlog/README b/modules_s/xlog/README
new file mode 100644 (file)
index 0000000..b4464c5
--- /dev/null
@@ -0,0 +1,74 @@
+# $Id$
+XLOG - eXtended LOGging service for SER
+=======================================
+
+
+1.Description
+-------------
+This module provides the possibility to print user formatted log or debug
+messages from SER scripts. It is possible to define 10 different formats.
+Section '3.Implemented specifiers' shows what can be printed out.
+
+2.Exported symbols
+------------------
+Methods
+-------
+
+Parameters
+----------
+
+Name:          buf_size
+Type:          int
+Default:       4096
+Desc:          the max size of the log message
+
+
+Name:          f0
+Type:          string
+Default:       "XLOG{0}: [%Tf] method:<%rm> r-uri:<%ru>\n"
+Desc:          first log format
+
+
+Name:          f1, ..., f9
+Type:          string
+Default:       NULL
+Desc:          other log formats
+
+Methods
+-------
+
+Name:   xlog
+Params: - level: the level that will be used in LOG function
+        - format: the id of the format to be used to print the message (the
+                 digit after the 'f' of the module parameter name that represents the
+                 format to be used, e.g, 'xlog("1", "0")' will use the 'f0' format and
+                 will print the message with LOG(1, <log message>))
+Desc:   print a formated message using LOG function
+
+Name:   xdbg
+Params: - format: the id of the format to be used to print the message (the
+          digit after the 'f' of the module parameter name that represents the
+          format to be used, e.g, 'xdbg("0")' will use the 'f0' format and
+          will print the message with DBG(<log message>))
+Desc:   print a formatted message using DBG function
+
+               
+3.Implemented specifiers
+------------------------
+- %%  : '%'
+
+- %Ts : unix time stamp
+- %Tf : string formatted time
+
+- %ci : call-id
+- %cs : cseq
+- %ct : contact header
+- %fu : 'From' uri
+- %ft : 'From' tag
+- %rm : request's method
+- %ru : request's r-uri
+- %tu : 'To' uri
+- %tt : 'To' tag
+- %mi : SIP message id
+- %pp : process id (pid)
diff --git a/modules_s/xlog/xl_lib.c b/modules_s/xlog/xl_lib.c
new file mode 100644 (file)
index 0000000..129eb84
--- /dev/null
@@ -0,0 +1,543 @@
+/**\r
+ * $Id$
+ *
+ * XLOG module\r
+ *\r
+ * Copyright (C) 2001-2003 Fhg Fokus\r
+ *\r
+ * This file is part of ser, a free SIP server.\r
+ *\r
+ * ser is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version\r
+ *\r
+ * For a license to use the ser software under conditions\r
+ * other than those described here, or to purchase support for this\r
+ * software, please contact iptel.org by e-mail at the following addresses:\r
+ *    info@iptel.org\r
+ *\r
+ * ser is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License \r
+ * along with this program; if not, write to the Free Software \r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <time.h>\r
+#include <sys/types.h>\r
+#include <unistd.h>\r
+\r
+#include "../../dprint.h"\r
+#include "../../mem/mem.h"\r
+#include "../../ut.h" \r
+#include "../../trim.h" \r
+\r
+#include "../../parser/parse_from.h"\r
+#include "../../parser/parse_uri.h"\r
+\r
+#include "xl_lib.h"\r
+\r
+static str str_null = { "<null>", 6 };\r
+static str str_per = { "%", 1 };\r
+\r
+int msg_id = 0;\r
+time_t msg_tm = 0;\r
+int cld_pid = 0;\r
+\r
+static int xl_get_null(struct sip_msg *msg, str *res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+       \r
+       res->s = str_null.s;\r
+       res->len = str_null.len;\r
+       return 0;\r
+}\r
+\r
+static int xl_get_percent(struct sip_msg *msg, str *res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+       \r
+       res->s = str_per.s;\r
+       res->len = str_per.len;\r
+       return 0;\r
+}\r
+\r
+static int xl_get_pid(struct sip_msg *msg, str *res)\r
+{\r
+       int l = 0;\r
+       char *ch = NULL;\r
+\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+\r
+       if(cld_pid == 0)\r
+               cld_pid = (int)getpid();\r
+       ch = int2str(cld_pid, &l);\r
+\r
+       res->s = ch;\r
+       res->len = l;\r
+\r
+       return 0;\r
+}\r
+\r
+static int xl_get_times(struct sip_msg *msg, str *res)\r
+{\r
+       int l = 0;\r
+       char *ch = NULL;\r
+               \r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+\r
+       if(msg_id != msg->id)\r
+       {\r
+               msg_tm = time(NULL);\r
+               msg_id = msg->id;\r
+       }\r
+       ch = int2str(msg_tm, &l);\r
+       \r
+       res->s = ch;\r
+       res->len = l;\r
+\r
+       return 0;\r
+}\r
+static int xl_get_timef(struct sip_msg *msg, str *res)\r
+{\r
+       char *ch = NULL;\r
+       \r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+       if(msg_id != msg->id)\r
+       {\r
+               msg_tm = time(NULL);\r
+               msg_id = msg->id;\r
+       }\r
+       \r
+       ch = ctime(&msg_tm);\r
+       \r
+       res->s = ch;\r
+       res->len = strlen(ch)-1;\r
+\r
+       return 0;\r
+}\r
+\r
+static int xl_get_msgid(struct sip_msg *msg, str *res)\r
+{\r
+       int l = 0;\r
+       char *ch = NULL;\r
+\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+\r
+       ch = int2str(msg->id, &l);\r
+       res->s = ch;\r
+       res->len = l;\r
+\r
+       return 0;\r
+}\r
+\r
+static int xl_get_method(struct sip_msg *msg, str *res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+\r
+       if(msg->first_line.type == SIP_REQUEST)\r
+       {\r
+               res->s = msg->first_line.u.request.method.s;\r
+               res->len = msg->first_line.u.request.method.len;\r
+       }\r
+       else\r
+               return xl_get_null(msg, res);\r
+       \r
+       return 0;\r
+}\r
+\r
+static int xl_get_ruri(struct sip_msg *msg, str *res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+\r
+       if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0)\r
+       {\r
+               LOG(L_ERR, "XLOG: xl_get_ruri: ERROR while parsing the R-URI\n");\r
+               return xl_get_null(msg, res);\r
+       }\r
+       \r
+       res->s=msg->parsed_uri.user.len>0?msg->parsed_uri.user.s:msg->parsed_uri.host.s;\r
+       res->len = msg->parsed_uri.user.len+\r
+                               msg->parsed_uri.passwd.len+\r
+                               msg->parsed_uri.host.len+\r
+                               msg->parsed_uri.port.len+\r
+                               msg->parsed_uri.params.len+\r
+                               msg->parsed_uri.headers.len+\r
+                               (msg->parsed_uri.passwd.len>0?1:0)+\r
+                               (msg->parsed_uri.port.len>0?1:0)+\r
+                               (msg->parsed_uri.params.len>0?1:0)+\r
+                               (msg->parsed_uri.headers.len>0?1:0);\r
+       return 0;\r
+}\r
+\r
+static int xl_get_contact(struct sip_msg* msg, str* res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+\r
+       if(msg->contact==NULL || parse_headers(msg, HDR_CONTACT, 0)==-1 \r
+               || !msg->contact->body.s || msg->contact->body.len<=0)\r
+       {\r
+               DBG("XLOG: xl_get_contact: no contact header\n");\r
+               return xl_get_null(msg, res);\r
+       }\r
+       \r
+       res->s = msg->contact->body.s;\r
+       res->len = msg->contact->body.len;\r
+\r
+       \r
+//     res->s = ((struct to_body*)msg->contact->parsed)->uri.s;\r
+//     res->len = ((struct to_body*)msg->contact->parsed)->uri.len;\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+static int xl_get_from(struct sip_msg *msg, str *res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+\r
+       if(msg->from==NULL && parse_from_header(msg)==-1)\r
+       {\r
+               LOG(L_ERR, "XLOG: xl_get_from: ERROR cannot parse FROM header\n");\r
+               return xl_get_null(msg, res);\r
+       }\r
+       \r
+       if(msg->from==NULL || get_from(msg)==NULL)\r
+               return xl_get_null(msg, res);\r
+\r
+       res->s = get_from(msg)->uri.s;\r
+       res->len = get_from(msg)->uri.len; \r
+       \r
+       return 0;\r
+}\r
+\r
+static int xl_get_from_tag(struct sip_msg *msg, str *res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+\r
+       if(msg->from==NULL && parse_from_header(msg)==-1)\r
+       {\r
+               LOG(L_ERR, "XLOG: xl_get_from: ERROR cannot parse FROM header\n");\r
+               return xl_get_null(msg, res);\r
+       }\r
+       \r
+       \r
+       if(msg->from==NULL || get_from(msg)==NULL || get_from(msg)->tag_value.s==NULL)\r
+               return xl_get_null(msg, res);\r
+\r
+       res->s = get_from(msg)->uri.s;\r
+       res->len = get_from(msg)->uri.len; \r
+\r
+       return 0;\r
+}\r
+\r
+\r
+static int xl_get_to(struct sip_msg *msg, str *res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+\r
+       if(msg->to==NULL && parse_headers(msg, HDR_TO, 0)==-1)\r
+       {\r
+               LOG(L_ERR, "XLOG: xl_get_to: ERROR cannot parse TO header\n");\r
+               return xl_get_null(msg, res);\r
+       }\r
+       if(msg->to==NULL || get_to(msg)==NULL)\r
+               return xl_get_null(msg, res);\r
+\r
+       res->s = get_to(msg)->uri.s;\r
+       res->len = get_to(msg)->uri.len; \r
+       \r
+       return 0;\r
+}\r
+\r
+static int xl_get_to_tag(struct sip_msg* msg, str* res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+\r
+       if(msg->to==NULL && parse_headers(msg, HDR_TO, 0)==-1)\r
+       {\r
+               LOG(L_ERR, "XLOG: xl_get_to: ERROR cannot parse TO header\n");\r
+               return xl_get_null(msg, res);\r
+       }\r
+       \r
+       if (get_to(msg)->tag_value.len <= 0) \r
+               return xl_get_null(msg, res);\r
+       \r
+       res->s = get_to(msg)->tag_value.s;\r
+       res->len = get_to(msg)->tag_value.len;\r
+\r
+       return 0;\r
+}\r
+\r
+static int xl_get_cseq(struct sip_msg *msg, str *res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+       \r
+       if(msg->cseq==NULL && parse_headers(msg, HDR_CSEQ, 0)==-1)\r
+       {\r
+               LOG(L_ERR, "XLOG: xl_get_cseq: ERROR cannot parse CSEQ header\n");\r
+               return xl_get_null(msg, res);\r
+       }\r
+\r
+       res->s = get_cseq(msg)->number.s;\r
+       res->len = get_cseq(msg)->number.len;\r
+\r
+       return 0;\r
+}\r
+\r
+static int xl_get_callid(struct sip_msg *msg, str *res)\r
+{\r
+       if(msg==NULL || res==NULL)\r
+               return -1;\r
+       \r
+       if(msg->callid==NULL && parse_headers(msg, HDR_CALLID, 0)==-1)\r
+       {\r
+               LOG(L_ERR, "XLOG: xl_get_cseq: ERROR cannot parse Call-Id header\n");\r
+               return xl_get_null(msg, res);\r
+       }\r
+\r
+       res->s = msg->callid->body.s;\r
+       res->len = msg->callid->body.len;\r
+       trim(res);\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+int xl_parse_format(char *s, xl_elog_p *el)\r
+{\r
+       char *p;\r
+       int n = 0;\r
+       xl_elog_p e, e0;\r
+       \r
+       if(s==NULL || el==NULL)\r
+               return -1;\r
+\r
+       DBG("XLOG: xl_parse_format: parsing [%s]\n", s);\r
+       \r
+       p = s;\r
+       *el = NULL;\r
+       e = e0 = NULL;\r
+\r
+       while(*p)\r
+       {\r
+               e0 = e;\r
+               e = pkg_malloc(sizeof(xl_elog_t));\r
+               if(!e)\r
+                       goto error;\r
+               memset(e, 0, sizeof(xl_elog_t));\r
+               n++;\r
+               if(*el == NULL)\r
+                       *el = e;\r
+               if(e0)\r
+                       e0->next = e;\r
+       \r
+               e->text.s = p;\r
+               while(*p && *p!='%')\r
+                       p++;\r
+               e->text.len = p - e->text.s;\r
+               if(*p == '\0')\r
+                       break;\r
+\r
+               p++;\r
+               switch(*p)\r
+               {\r
+                       case 'c':\r
+                               p++;\r
+                               switch(*p)\r
+                               {\r
+                                       case 't':\r
+                                               e->itf = xl_get_contact;\r
+                                       break;\r
+                                       case 'i':\r
+                                               e->itf = xl_get_callid;\r
+                                       break;\r
+                                       case 's':\r
+                                               e->itf = xl_get_cseq;\r
+                                       break;\r
+                                       default:\r
+                                               e->itf = xl_get_null;\r
+                               }\r
+                       break;\r
+                       case 'f':\r
+                               p++;\r
+                               switch(*p)\r
+                               {\r
+                                       case 'u':\r
+                                               e->itf = xl_get_from;\r
+                                       break;\r
+                                       case 't':\r
+                                               e->itf = xl_get_from_tag;\r
+                                       break;\r
+                                       default:\r
+                                               e->itf = xl_get_null;\r
+                               }\r
+                       break;\r
+                       case 'm':\r
+                               p++;\r
+                               switch(*p)\r
+                               {\r
+                                       case 'i':\r
+                                               e->itf = xl_get_msgid;\r
+                                       break;\r
+                                       default:\r
+                                               e->itf = xl_get_null;\r
+                               }\r
+                               break;\r
+                       case 'p':\r
+                               p++;\r
+                               switch(*p)\r
+                               {\r
+                                       case 'p':\r
+                                               e->itf = xl_get_pid;\r
+                                       break;\r
+                                       default:\r
+                                               e->itf = xl_get_null;\r
+                               }\r
+                       break;\r
+                       case 'r':\r
+                               p++;\r
+                               switch(*p)\r
+                               {\r
+                                       case 'm':\r
+                                               e->itf = xl_get_method;\r
+                                       break;\r
+                                       case 'u':\r
+                                               e->itf = xl_get_ruri;\r
+                                       break;\r
+                                       default:\r
+                                               e->itf = xl_get_null;\r
+                               }\r
+                       break;\r
+                       case 't':\r
+                               p++;\r
+                               switch(*p)\r
+                               {\r
+                                       case 'u':\r
+                                               e->itf = xl_get_to;\r
+                                       break;\r
+                                       case 't':\r
+                                               e->itf = xl_get_to_tag;\r
+                                       break;\r
+                                       default:\r
+                                               e->itf = xl_get_null;\r
+                               }\r
+                       break;\r
+                       case 'T':\r
+                               p++;\r
+                               switch(*p)\r
+                               {\r
+                                       case 's':\r
+                                               e->itf = xl_get_times;\r
+                                       break;\r
+                                       case 'f':\r
+                                               e->itf = xl_get_timef;\r
+                                       break;\r
+                                       default:\r
+                                               e->itf = xl_get_null;\r
+                               }\r
+                       break;\r
+                       case '%':\r
+                               e->itf = xl_get_percent;\r
+                       break;\r
+                       default:\r
+                               e->itf = xl_get_null;\r
+               }\r
+\r
+               if(*p == '\0')\r
+                       break;\r
+               p++;\r
+       }\r
+       DBG("XLOG: xl_parse_format: format parsed OK: [%d] items\n", n);\r
+\r
+       return 0;\r
+\r
+error:\r
+       xl_elog_free_all(*el);\r
+       *el = NULL;\r
+       return -1;\r
+}\r
+\r
+int xl_print_log(struct sip_msg* msg, xl_elog_p log, char *buf, int *len)\r
+{\r
+       int n;\r
+       str tok;\r
+       xl_elog_p it;\r
+       \r
+       if(msg==NULL || log==NULL || buf==NULL || len==NULL)\r
+               return -1;\r
+\r
+       if(*len <= 0)\r
+               return -1;\r
+\r
+       it = log;\r
+       buf[0] = '\0';\r
+       n = 0;\r
+       while(it)\r
+       {\r
+               // put the text\r
+               if(it->text.s && it->text.len>0)\r
+               {\r
+                       if(n+it->text.len < *len)\r
+                       {\r
+                               strncat(buf, it->text.s, it->text.len);\r
+                               n+= it->text.len;\r
+                       }\r
+                       else\r
+                               goto overflow;\r
+               }\r
+               // put the value of the specifier\r
+               if(it->itf && !((*it->itf)(msg, &tok)))\r
+               {\r
+                       if(n+tok.len < *len)\r
+                       {\r
+                               strncat(buf, tok.s, tok.len);\r
+                               n += tok.len;\r
+                       }\r
+                       else\r
+                               goto overflow;\r
+               }\r
+               it = it->next;\r
+       }\r
+       goto done;\r
+       \r
+overflow:\r
+       DBG("XLOG: xl_print_log: buffer overflow ...\n");\r
+done:\r
+       DBG("XLOG: xl_print_log: final buffer length %d\n", n);\r
+       *len = n;\r
+       return 0;\r
+}\r
+\r
+int xl_elog_free_all(xl_elog_p log)\r
+{\r
+       xl_elog_p t;\r
+       while(log)\r
+       {\r
+               t = log;\r
+               log = log->next;\r
+               pkg_free(t);\r
+       }\r
+       return 0;\r
+}\r
+\r
diff --git a/modules_s/xlog/xl_lib.h b/modules_s/xlog/xl_lib.h
new file mode 100644 (file)
index 0000000..6c61574
--- /dev/null
@@ -0,0 +1,47 @@
+/**\r
+ * $Id$
+ *
+ * Copyright (C) 2001-2003 Fhg Fokus\r
+ *\r
+ * This file is part of ser, a free SIP server.\r
+ *\r
+ * ser is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version\r
+ *\r
+ * For a license to use the ser software under conditions\r
+ * other than those described here, or to purchase support for this\r
+ * software, please contact iptel.org by e-mail at the following addresses:\r
+ *    info@iptel.org\r
+ *\r
+ * ser is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License \r
+ * along with this program; if not, write to the Free Software \r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#ifndef _XL_LIB_H_\r
+#define _XL_LIB_H_\r
+\r
+#include "../../parser/msg_parser.h"\r
+\r
+typedef int (*item_func_t) (struct sip_msg*, str*);\r
+\r
+typedef struct _xl_elog\r
+{\r
+       str text;\r
+       item_func_t itf;\r
+       struct _xl_elog *next;\r
+} xl_elog_t, *xl_elog_p;\r
+\r
+int xl_elog_free_all(xl_elog_p log);\r
+int xl_parse_format(char *s, xl_elog_p *el);\r
+int xl_print_log(struct sip_msg* msg, xl_elog_p log, char *buf, int *len);\r
+\r
+#endif\r
+\r
diff --git a/modules_s/xlog/xlog.c b/modules_s/xlog/xlog.c
new file mode 100644 (file)
index 0000000..63d480a
--- /dev/null
@@ -0,0 +1,199 @@
+/**\r
+ * $Id$
+ *\r
+ * Copyright (C) 2001-2003 Fhg Fokus\r
+ *\r
+ * This file is part of ser, a free SIP server.\r
+ *\r
+ * ser is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version\r
+ *\r
+ * For a license to use the ser software under conditions\r
+ * other than those described here, or to purchase support for this\r
+ * software, please contact iptel.org by e-mail at the following addresses:\r
+ *    info@iptel.org\r
+ *\r
+ * ser is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License \r
+ * along with this program; if not, write to the Free Software \r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <sys/types.h>\r
+#include <sys/ipc.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+#include <time.h>\r
+\r
+#include "../../sr_module.h"\r
+#include "../../dprint.h"\r
+#include "../../mem/mem.h"\r
+\r
+#include "xl_lib.h"\r
+
+
+MODULE_VERSION
+
+\r
+#define MAX_FORMATS 10\r
+\r
+\r
+/** parameters */\r
+\r
+char *formats[MAX_FORMATS] = { \r
+               "XLOG{0}: [%Tf] method:<%rm> r-uri:<%ru>\n",\r
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };\r
+int buf_size=4096;\r
+\r
+char *log_buf = NULL;\r
+int  log_len = 0;\r
+xl_elog_t *models[MAX_FORMATS] = {\r
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };\r
+\r
+/** module functions */\r
+static int mod_init(void);\r
+static int child_init(int);\r
+\r
+static int xlog(struct sip_msg*, char*, char*);\r
+static int xdbg(struct sip_msg*, char*, char*);\r
+\r
+void destroy(void);\r
+\r
+static cmd_export_t cmds[]={\r
+       {"xlog",  xlog,  2, 0, REQUEST_ROUTE | FAILURE_ROUTE},\r
+       {"xdbg",  xdbg,  1, 0, REQUEST_ROUTE | FAILURE_ROUTE},\r
+       {0,0,0,0,0}\r
+};\r
+\r
+\r
+static param_export_t params[]={\r
+       {"f0",     STR_PARAM, &formats[0]},\r
+       {"f1",     STR_PARAM, &formats[1]},\r
+       {"f2",     STR_PARAM, &formats[2]},\r
+       {"f3",     STR_PARAM, &formats[3]},\r
+       {"f4",     STR_PARAM, &formats[4]},\r
+       {"f5",     STR_PARAM, &formats[5]},\r
+       {"f6",     STR_PARAM, &formats[6]},\r
+       {"f7",     STR_PARAM, &formats[7]},\r
+       {"f8",     STR_PARAM, &formats[8]},\r
+       {"f9",     STR_PARAM, &formats[9]},\r
+       {"buf_size",  INT_PARAM, &buf_size},\r
+       {0,0,0}\r
+};\r
+\r
+\r
+/** module exports */\r
+struct module_exports exports= {\r
+       "xlog",\r
+       cmds,\r
+       params,\r
+       \r
+       mod_init,   /* module initialization function */\r
+       (response_function) 0,\r
+       (destroy_function) destroy,\r
+       0,\r
+       child_init  /* per-child init function */\r
+};\r
+\r
+/**\r
+ * init module function\r
+ */\r
+static int mod_init(void)\r
+{\r
+       int i;\r
+       DBG("XLOG: initializing ...\n");\r
+       log_buf = (char*)pkg_malloc((buf_size+1)*sizeof(char));\r
+       if(log_buf==NULL)\r
+       {\r
+               LOG(L_ERR, "XLOG:mod_init: ERROR: no more memory\n");\r
+               return -1;\r
+       }\r
+       \r
+       for(i=0; i<MAX_FORMATS; i++)\r
+       {\r
+               if(formats[i])\r
+               {\r
+                       if(xl_parse_format(formats[i], &models[i])<0)\r
+                               LOG(L_ERR, "XLOG:mod_init: ERROR: wrong format[%d]\n", i);\r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * Initialize childs\r
+ */\r
+static int child_init(int rank)\r
+{\r
+       DBG("XLOG: init_child [%d]  pid [%d]\n", rank, getpid());\r
+       return 0;\r
+}\r
+\r
+/**\r
+ */\r
+static int xlog(struct sip_msg* msg, char* lev, char* frm)\r
+{\r
+       int l=0, f=0;\r
+       \r
+       if(lev && lev[0]>'0' && lev[0]<='9')\r
+               l = lev[0] - '0';\r
+       if(frm && frm[0]>'0' && frm[0]<='9')\r
+               f = frm[0] - '0';\r
+\r
+       DBG("XLOG:xlog: format[%d] level[%d] ...\n", f, l);\r
+       log_len = buf_size;\r
+\r
+       if(xl_print_log(msg, models[f], log_buf, &log_len)<0)\r
+               return -1;\r
+\r
+       log_buf[log_len] = '\0';\r
+       LOG(l, log_buf);\r
+\r
+       return 1;\r
+}\r
+\r
+/**\r
+ */\r
+static int xdbg(struct sip_msg* msg, char* frm, char* str2)\r
+{\r
+       int f=0;\r
+\r
+       if(frm && frm[0]>'0' && frm[0]<='9')\r
+               f = frm[0] - '0';\r
+\r
+       DBG("XLOG:xdbg: format[%d]  ...\n", f);\r
+       log_len = buf_size;\r
+\r
+       if(xl_print_log(msg, models[f], log_buf, &log_len)<0)\r
+               return -1;\r
+\r
+       log_buf[log_len] = '\0';\r
+       DBG(log_buf);\r
+\r
+       return 1;\r
+}\r
+\r
+/**\r
+ * destroy function\r
+ */\r
+void destroy(void)\r
+{\r
+       int i;\r
+       DBG("XLOG: destroy module ...\n");\r
+       if(log_buf)\r
+               pkg_free(log_buf);\r
+       for(i=0; i<MAX_FORMATS; i++)\r
+               if(models[i])\r
+                       xl_elog_free_all(models[i]);\r
+}\r
+\r