Add -lncurses to LDD flags
[lcr.git] / trace.c
diff --git a/trace.c b/trace.c
index bb63ec2..caa1e40 100644 (file)
--- a/trace.c
+++ b/trace.c
 #include "main.h"
 
 struct trace trace;
-char trace_string[MX_TRACE_ELEMENTS * 100 + 400];
-
-static char *spaces[11] = {
-       "          ",
-       "         ",
-       "        ",
-       "       ",
-       "      ",
-       "     ",
-       "    ",
-       "   ",
-       "  ",
-       " ",
-       "",
-};
+char trace_string[MAX_TRACE_ELEMENTS * 100 + 400];
+
+static const char *spaces = "          ";
 
 /*
  * initializes a new trace
  * all values will be reset
  */
-void start_trace(int port, char *interface, char *caller, char *dialing, int direction, char *category, char *name);
+void _start_trace(const char *__file, int __line, int port, struct interface *interface, const char *caller, const char *dialing, int direction, int category, int serial, const char *name)
 {
+       struct timeval current_time;
+
        if (trace.name[0])
-               PERROR("trace already started (name=%s)\n", trace.name);
-       memset(trace, 0, sizeof(struct trace));
+               PERROR("trace already started (name=%s) in file %s line %d\n", trace.name, __file, __line);
+       memset(&trace, 0, sizeof(struct trace));
        trace.port = port;
-       if (interface) if (interface[0])
-               SCPY(trace.interface, interface);
+       if (interface)
+               SCPY(trace.interface, interface->name);
        if (caller) if (caller[0])
                SCPY(trace.caller, caller);
        if (dialing) if (dialing[0])
                SCPY(trace.dialing, dialing);
        trace.direction = direction;
-       if (category) if (category[0])
-               SCPY(trace.category, category);
+       trace.category = category;
+       trace.serial = serial;
        if (name) if (name[0])
                SCPY(trace.name, name);
-       trace.sec = now_tv.tv_sec;
-       trace.usec = now_tv.tv_usec;
+       if (!trace.name[0])
+               SCPY(trace.name, "<unknown>");
+       gettimeofday(&current_time, NULL);
+       trace.sec = current_time.tv_sec;
+       trace.usec = current_time.tv_usec;
 }
 
 
@@ -59,20 +52,19 @@ void start_trace(int port, char *interface, char *caller, char *dialing, int dir
  * if subelement is given, element will also contain a subelement
  * if multiple subelements belong to same element, name must be equal for all subelements
  */
-void add_trace(char *name, char *sub, const char *fmt, ...);
+void _add_trace(const char *__file, int __line, const char *name, const char *sub, const char *fmt, ...)
 {
        va_list args;
 
        if (!trace.name[0])
-               PERROR("trace not started\n");
+               PERROR("trace not started in file %s line %d\n", __file, __line);
        
        /* check for required name value */
        if (!name)
                goto nostring;
-       if (!name[0])
-       {
+       if (!name[0]) {
                nostring:
-               PERROR("trace with name=%s gets element with no string\n", trace->name);
+               PERROR("trace with name=%s gets element with no string\n", trace.name);
                return;
        }
        
@@ -80,10 +72,9 @@ void add_trace(char *name, char *sub, const char *fmt, ...);
        SCPY(trace.element[trace.elements].name, name);
        if (sub) if (sub[0])
                SCPY(trace.element[trace.elements].sub, sub);
-       if (fmt) if (fmt[0])
-       {
+       if (fmt) if (fmt[0]) {
                va_start(args, fmt);
-               VUNPRINT(trace.element[trace.element].value, sizeof(trace.element[trace.elements].value)-1, fmt, args);
+               VUNPRINT(trace.element[trace.elements].value, sizeof(trace.element[trace.elements].value)-1, fmt, args);
                va_end(args);
        }
 
@@ -93,81 +84,68 @@ void add_trace(char *name, char *sub, const char *fmt, ...);
 
 
 /*
- * trace ends
- * this function will put the trace to sockets and logfile, if requested
- */
-void end_trace(void);
-{
-       if (!trace.name[0])
-               PERROR("trace not started\n");
-       
-       /* process log file */
-       if (options.log[0])
-       {
-               string = print_trace(1, 0, NULL, NULL, NULL, -1, "AP", NULL);
-               fwrite(string, strlen(string), 1, fp);
-       }
-
-       memset(trace, 0, sizeof(struct trace));
-}
-
-
-/*
  * prints trace to socket or log
  * detail: 1 = brief, 2=short, 3=long
  */
-static char *print_trace(int detail, int port, char *interface, char *caller, char *dialing, char *category);
+static char *print_trace(int detail, int port, char *interface, char *caller, char *dialing, int category)
 {
-       trace_string[0] = '\0';
        char buffer[256];
+       time_t ti = trace.sec;
        struct tm *tm;
+#ifdef WITH_MISDN
+       struct mISDNport *mISDNport;
+#endif
+       int i;
+
+       trace_string[0] = '\0'; // always clear string
 
        if (detail < 1)
-               return;
+               return(NULL);
 
        /* filter trace */
-       if (port && trace.port)
-               if (port != trace.port) return;
-       if (interface && interface[0] && trace.interface[0])
-               if (!!strcasecmp(interface, trace.interface)) return;
-       if (caller && caller[0] && trace.caller[0])
-               if (!!strcasecmp(caller, trace.caller)) return;
-       if (dialing && dialing[0] && trace.dialing[0])
-               if (!!strcasecmp(dialing, trace.dialing)) return;
-       if (category && category[0] && trace.category[0])
-               if (!!strcasecmp(category, trace.category)) return;
+       if (port >= 0 && trace.port >= 0)
+               if (port != trace.port) return(NULL);
+       if (interface) if (interface[0] && trace.interface[0])
+               if (!!strcasecmp(interface, trace.interface)) return(NULL);
+       if (caller) if (caller[0] && trace.caller[0])
+               if (!!strncasecmp(caller, trace.caller, strlen(trace.caller))) return(NULL);
+       if (dialing) if (dialing[0] && trace.dialing[0])
+               if (!!strncasecmp(dialing, trace.dialing, strlen(trace.dialing))) return(NULL);
+       if (category && trace.category)
+               if (!(category & trace.category)) return(NULL);
 
        /* head */
-       if (detail >= 3)
-       {
+       if (detail >= 3) {
+               SCAT(trace_string, "------------------------------------------------------------------------------\n");
+#ifdef WITH_MISDN
                /* "Port: 1 (BRI PTMP TE)" */
-               if (port)
-               {
+               if (trace.port >= 0) {
                        mISDNport = mISDNport_first;
-                       while(mISDNport)
-                       {
-                               if (mISDNport->number == trace.port)
+                       while(mISDNport) {
+                               if (mISDNport->portnum == trace.port)
                                        break;
                                mISDNport = mISDNport->next;
                        }
-                       if (mISDNport)
-                               SPRINT(buffer, "Port: %d (%s %s %s)", port, (mISDNport->pri)?"PRI":"BRI", (mISDNport->ptp)?"PTP":"PTMP", (mISDNport->nt)?"NT":"TE");
-                       else
-                               SPRINT(buffer, "Port: %d (does not exist}\n", port);
+                       if (mISDNport) {
+                               SPRINT(buffer, "Port: %d (%s %s %s)", trace.port, (mISDNport->pri)?"PRI":"BRI", (mISDNport->ptp)?"PTP":"PTMP", (mISDNport->ntmode)?"NT":"TE");
+                               /* copy interface, if we have a port */
+                               if (mISDNport->ifport) if (mISDNport->ifport->interface)
+                               SCPY(trace.interface, mISDNport->ifport->interface->name);
+                       } else
+                               SPRINT(buffer, "Port: %d (does not exist)\n", trace.port);
                        SCAT(trace_string, buffer);
                } else
+#endif
                        SCAT(trace_string, "Port: ---");
 
-               if (trace.interface[0])
-               {
+               if (trace.interface[0]) {
                        /* "  Interface: 'Ext'" */
                        SPRINT(buffer, "  Interface: '%s'", trace.interface);
                        SCAT(trace_string, buffer);
                } else
                        SCAT(trace_string, "  Interface: ---");
                        
-               if (trace.caller[0])
-               {
+               if (trace.caller[0]) {
                        /* "  Caller: '021256493'" */
                        SPRINT(buffer, "  Caller: '%s'\n", trace.caller);
                        SCAT(trace_string, buffer);
@@ -175,20 +153,18 @@ static char *print_trace(int detail, int port, char *interface, char *caller, ch
                        SCAT(trace_string, "  Caller: ---\n");
 
                /* "Time: 25.08.73 05:14:39.282" */
-               tm = localtime(&trace.sec);
-               SPRINT(buffer, "Time: %02d.%02d.%02d %02d:%02d:%02d.%03d", tm->tm_mday, tm->tm_mon+1, tm->tm_year%100, tm->tm_hour, tm->tm_min, tm->tm_sec, trace->usec/1000);
+               tm = localtime(&ti);
+               SPRINT(buffer, "Time: %02d.%02d.%02d %02d:%02d:%02d.%03d", tm->tm_mday, tm->tm_mon+1, tm->tm_year%100, tm->tm_hour, tm->tm_min, tm->tm_sec, trace.usec/1000);
                SCAT(trace_string, buffer);
 
-               if (trace.direction)
-               {
+               if (trace.direction) {
                        /* "  Direction: out" */
                        SPRINT(buffer, "  Direction: %s", (trace.direction==DIRECTION_OUT)?"OUT":"IN");
                        SCAT(trace_string, buffer);
                } else
                        SCAT(trace_string, "  Direction: ---");
 
-               if (trace.dialing[0])
-               {
+               if (trace.dialing[0]) {
                        /* "  Dialing: '57077'" */
                        SPRINT(buffer, "  Dialing: '%s'\n", trace.dialing);
                        SCAT(trace_string, buffer);
@@ -198,30 +174,53 @@ static char *print_trace(int detail, int port, char *interface, char *caller, ch
                SCAT(trace_string, "------------------------------------------------------------------------------\n");
        }
 
-       /* "L3: CC_SETUP (net->user)" */
-       SPRINT(buffer, "%s: %s", trace.category[0]?trace.category:"--", trace.name[0]?trace.name:"<unknown>");
+       if (detail < 3) {
+               tm = localtime(&ti);
+               SPRINT(buffer, "%02d.%02d.%02d %02d:%02d:%02d.%03d ", tm->tm_mday, tm->tm_mon+1, tm->tm_year%100, tm->tm_hour, tm->tm_min, tm->tm_sec, trace.usec/1000);
+               SCAT(trace_string, buffer);
+       }
+
+       /* "CH(45): CC_SETUP (net->user)" */
+       switch (trace.category) {
+               case CATEGORY_CH:
+               SCAT(trace_string, "CH");
+               break;
+
+               case CATEGORY_EP:
+               SCAT(trace_string, "EP");
+               break;
+
+               default:
+               SCAT(trace_string, "--");
+       }
+       if (trace.serial)
+               SPRINT(buffer, "(%lu): %s", trace.serial, trace.name[0]?trace.name:"<unknown>");
+       else
+               SPRINT(buffer, ": %s", trace.name[0]?trace.name:"<unknown>");
        SCAT(trace_string, buffer);
 
        /* elements */
-       switch(detail)
-       {
+       switch(detail) {
                case 1: /* brief */
+               if (trace.port >= 0) {
+                       SPRINT(buffer, "  port %d", trace.port);
+                       SCAT(trace_string, buffer);
+               }
                i = 0;
-               while(i < trace.elements)
-               {
+               while(i < trace.elements) {
                        SPRINT(buffer, "  %s", trace.element[i].name);
                        if (i) if (!strcmp(trace.element[i].name, trace.element[i-1].name))
                                buffer[0] = '\0';
                        SCAT(trace_string, buffer);
                        if (trace.element[i].sub[0])
-                               SPRINT(buffer, " %s=", trace.element[i].sub, value);
+                               SPRINT(buffer, " %s=", trace.element[i].sub);
                        else
-                               SPRINT(buffer, " ", value);
+                               SPRINT(buffer, " ");
                        SCAT(trace_string, buffer);
-                       if (strchr(value, ' '))
-                               SPRINT(buffer, "'%s'", value);
+                       if (strchr(trace.element[i].value, ' '))
+                               SPRINT(buffer, "'%s'", trace.element[i].value);
                        else
-                               SPRINT(buffer, "%s", value);
+                               SPRINT(buffer, "%s", trace.element[i].value);
                        SCAT(trace_string, buffer);
                        i++;
                }
@@ -232,21 +231,20 @@ static char *print_trace(int detail, int port, char *interface, char *caller, ch
                case 3: /* long */
                SCAT(trace_string, "\n");
                i = 0;
-               while(i < trace.elements)
-               {
-                       SPRINT(buffer, " %s%s", trace.element[i].name, spaces[strlen(trace.element[i].name)]);
+               while(i < trace.elements) {
+                       SPRINT(buffer, " %s%s", trace.element[i].name, &spaces[strlen(trace.element[i].name)]);
                        if (i) if (!strcmp(trace.element[i].name, trace.element[i-1].name))
                                SPRINT(buffer, "           ");
                        SCAT(trace_string, buffer);
                        if (trace.element[i].sub[0])
-                               SPRINT(buffer, " : %s%s = ", trace.element[i].sub, spaces[strlen(trace.element[i].sub)], value);
+                               SPRINT(buffer, " : %s%s = ", trace.element[i].sub, &spaces[strlen(trace.element[i].sub)]);
                        else
-                               SPRINT(buffer, " :              ", value);
+                               SPRINT(buffer, " :              ");
                        SCAT(trace_string, buffer);
-                       if (strchr(value, ' '))
-                               SPRINT(buffer, "'%s'\n", value);
+                       if (strchr(trace.element[i].value, ' '))
+                               SPRINT(buffer, "'%s'\n", trace.element[i].value);
                        else
-                               SPRINT(buffer, "%s\n", value);
+                               SPRINT(buffer, "%s\n", trace.element[i].value);
                        SCAT(trace_string, buffer);
                        i++;
                }
@@ -256,12 +254,77 @@ static char *print_trace(int detail, int port, char *interface, char *caller, ch
        /* end */
        if (detail >= 3)
                SCAT(trace_string, "\n");
+       return(trace_string);
 }
 
 
+/*
+ * trace ends
+ * this function will put the trace to sockets and logfile, if requested
+ */
+void _end_trace(const char *__file, int __line)
+{
+       char *string;
+       FILE *fp;
+       struct admin_list       *admin;
+       struct admin_queue      *response, **responsep; /* response pointer */
+       int __attribute__((__unused__)) ret;
+
+       if (!trace.name[0])
+               PERROR("trace not started in file %s line %d\n", __file, __line);
+       
+       if (options.deb || options.log[0]) {
+               string = print_trace(1, -1, NULL, NULL, NULL, 0);
+               if (string) {
+                       /* process debug */
+                       if (options.deb)
+                               debug(NULL, NULL, 0, "TRACE", string);
+                       /* process log */
+                       if (options.log[0]) {
+                               fp = fopen(options.log, "a");
+                               if (fp) {
+                                       ret = fwrite(string, strlen(string), 1, fp);
+                                       fclose(fp);
+                               }
+                       }
+               }
+       }
+
+       /* process admin */
+       admin = admin_first;
+       while(admin) {
+               if (admin->trace.detail) {
+                       string = print_trace(admin->trace.detail, admin->trace.port, admin->trace.interface, admin->trace.caller, admin->trace.dialing, admin->trace.category);
+                       if (string) {
+                               /* seek to end of response list */
+                               response = admin->response;
+                               responsep = &admin->response;
+                               while(response) {
+                                       responsep = &response->next;
+                                       response = response->next;
+                               }
+
+                               /* create state response */
+                               response = (struct admin_queue *)MALLOC(sizeof(struct admin_queue)+sizeof(admin_message));
+                               memuse++;
+                               response->num = 1;
+                               /* message */
+                               response->am[0].message = ADMIN_TRACE_RESPONSE;
+                               SCPY(response->am[0].u.trace_rsp.text, string);
+
+                               /* attach to response chain */
+                               *responsep = response;
+                               responsep = &response->next;
+                               admin->fd.when |= LCR_FD_WRITE;
+                       }
+               }
+               admin = admin->next;
+       }
+//     fwrite(string, strlen(string), 1, fp);
+
+       memset(&trace, 0, sizeof(struct trace));
+}
+
 
-^todo:
-socket
-file open