LCR now runs as a user.
[lcr.git] / main.c
diff --git a/main.c b/main.c
index 1a5cb75..59343ae 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,6 +1,6 @@
 /*****************************************************************************\
 **                                                                           **
-** PBX4Linux                                                                 **
+** Linux Call Router                                                         **
 **                                                                           **
 **---------------------------------------------------------------------------**
 ** Copyright: Andreas Eversberg                                              **
@@ -9,26 +9,11 @@
 **                                                                           **
 \*****************************************************************************/ 
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/file.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <sys/resource.h>
 #include "main.h"
 
 MESSAGES
 
-double now_d;
+double now_d, last_d;
 time_t now;
 struct tm *now_tm;
 struct timeval now_tv;
@@ -40,14 +25,18 @@ struct timezone now_tz;
                now = now_tv.tv_sec; \
                now_tm = localtime(&now); \
        }
-//#define DEBUG_DURATION
 
-int global_debug = 0;
+FILE *debug_fp = NULL;
 int quit=0;
 
+#if 0
+struct lcr_fdset lcr_fdset[FD_SETSIZE];
+#endif
+
 pthread_mutex_t mutexd; // debug output mutex
-pthread_mutex_t mutexl; // log output mutex
+pthread_mutex_t mutext; // trace output mutex
 pthread_mutex_t mutexe; // error output mutex
+//pthread_mutex_t mutex_lcr; // lcr process mutex
 
 int memuse = 0;
 int mmemuse = 0;
@@ -66,7 +55,12 @@ int last_debug = 0;
 int debug_newline = 1;
 int nooutput = 0;
 
-static void debug(const char *function, int line, char *prefix, char *buffer)
+void debug_usleep(int msec, char *file, int line, int hour, int min, int sec)
+{
+       usleep(msec);
+}
+
+void debug(const char *function, int line, char *prefix, char *buffer)
 {
        /* if we have a new debug count, we add a mark */
        if (last_debug != debug_count)
@@ -74,8 +68,8 @@ static void debug(const char *function, int line, char *prefix, char *buffer)
                last_debug = debug_count;
                if (!nooutput)
                        printf("\033[34m--------------------- %04d.%02d.%02d %02d:%02d:%02d %06d\033[36m\n", now_tm->tm_year+1900, now_tm->tm_mon+1, now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec, debug_count%1000000);
-               if (options.deb&DEBUG_LOG && global_debug)
-                       dprint(DBGM_MAN, 0, "--------------------- %04d.%02d.%02d %02d:%02d:%02d %06d\n", now_tm->tm_year+1900, now_tm->tm_mon+1, now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec, debug_count%1000000);
+               if (debug_fp)
+                       fprintf(debug_fp, "--------------------- %04d.%02d.%02d %02d:%02d:%02d %06d\n", now_tm->tm_year+1900, now_tm->tm_mon+1, now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec, debug_count%1000000);
        }
 
        if (!nooutput)
@@ -88,14 +82,14 @@ static void debug(const char *function, int line, char *prefix, char *buffer)
                        printf("%s", buffer);
        }
 
-       if (options.deb&DEBUG_LOG && global_debug)
+       if (debug_fp)
        {
                if (debug_newline)
                {
                        if (function)
-                               dprint(DBGM_MAN, 0, "%s%s(in %s() line %d): %s", prefix?prefix:"", prefix?" ":"", function, line, buffer);
+                               fprintf(debug_fp, "%s%s(in %s() line %d): %s", prefix?prefix:"", prefix?" ":"", function, line, buffer);
                        else
-                               dprint(DBGM_MAN, 0, "%s%s: %s", prefix?prefix:"", prefix?" ":"", buffer);
+                               fprintf(debug_fp, "%s%s: %s", prefix?prefix:"", prefix?" ":"", buffer);
                }
        }
 
@@ -105,37 +99,8 @@ static void debug(const char *function, int line, char *prefix, char *buffer)
                        debug_newline = 1;
 }
 
-void printlog(const char *fmt, ...)
-{
-       char buffer[4096];
-       va_list args;
-       FILE *fp;
-
-       pthread_mutex_lock(&mutexl);
 
-       va_start(args,fmt);
-       VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
-       buffer[sizeof(buffer)-1]=0;
-       va_end(args);
-
-       if (options.log[0])
-       {
-               if (options.deb & DEBUG_LOG)
-                       debug(NULL, 0, "LOG ->", buffer);
-
-               if ((fp = fopen(options.log, "a")))
-               {
-                       fduse++;
-                       fprintf(fp, "%04d.%02d.%02d %02d:%02d:%02d %s", now_tm->tm_year+1900, now_tm->tm_mon+1, now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec, buffer);
-                       fclose(fp);
-                       fduse--;
-               }
-       }
-
-       pthread_mutex_unlock(&mutexl);
-}
-
-void _printdebug(const char *function, int line, unsigned long mask, const char *fmt, ...)
+void _printdebug(const char *function, int line, unsigned int mask, const char *fmt, ...)
 {
        char buffer[4096];
        va_list args;
@@ -190,7 +155,7 @@ void sighandler(int sigset)
                return;
        if (!quit)
        {
-               quit=1;
+               quit = sigset;
                /* set scheduler & priority */
                if (options.schedule > 1)
                {
@@ -198,8 +163,8 @@ void sighandler(int sigset)
                        schedp.sched_priority = 0;
                        sched_setscheduler(0, SCHED_OTHER, &schedp);
                }
-               fprintf(stderr, "PBX: Signal received: %d\n", sigset);
-               PERROR("Signal received: %d\n", sigset);
+               fprintf(stderr, "LCR: Signal received: %d\n", sigset);
+               PDEBUG(DEBUG_LOG, "Signal received: %d\n", sigset);
        }
 }
 
@@ -207,38 +172,32 @@ void sighandler(int sigset)
 /*
  * the main
  */
-#ifdef VOIP
-#define ARGC (args.GetCount()+1)
-#define ARGV(a) (args[a-1])
-void PBXMain::Main(void)
-{
-       PArgList &args = GetArguments();
-#else
-#define ARGC (argc)
-#define ARGV(a) (argv[a])
 int main(int argc, char *argv[])
 {
-#endif
        int                     ret = -1;
        int                     lockfd = -1; /* file lock */
-       struct message          *message;
+       struct lcr_msg          *message;
        class Port              *port;
        class Endpoint          *epoint;
-       class Call              *call;
+       class Join              *join;
        int                     i;
        int                     all_idle;
        char                    prefix_string[64];
        struct sched_param      schedp;
        char                    *debug_prefix = "alloc";
-       int                     created_mutexd = 0, created_mutexl = 0, created_mutexe = 0,
-                               created_lock = 0, created_signal = 0, created_debug = 0;
-#ifdef DEBUG_DURATION
-       time_t                  durationupdate;
-       double                  idle_duration, isdn_duration, port_duration, epoint_duration, call_duration, message_duration, admin_duration;
-       double                  start_d;
-#endif
+       int                     created_mutexd = 0,/* created_mutext = 0,*/ created_mutexe = 0,
+                               created_lock = 0, created_signal = 0, created_debug = 0,
+                               created_misdn = 0;
        int                     idletime = 0, idlecheck = 0;
-       char                    debug_log[128];
+       char                    tracetext[256], lock[128];
+
+#if 0
+       /* init fdset */
+       memset(lcr_fdset, 0, sizeof(lcr_fdset));
+#endif
+
+       /* lock LCR process */
+//     pthread_mutex_lock(&mutex_lcr);
 
        /* current time */
        GET_NOW();
@@ -247,40 +206,26 @@ int main(int argc, char *argv[])
        printf("\n** %s  Version %s\n\n", NAME, VERSION_STRING);
 
        /* show options */
-       if (ARGC <= 1)
+       if (argc <= 1)
        {
                usage:
                printf("\n");
-               printf("Usage: pbx (query | start | fork | rules | route)\n");
+               printf("Usage: lcr (query | start | fork | rules | route)\n");
                printf("query     = Show available isdn ports.\n");
-               printf("start     = Run pbx normally, abort with CTRL+C.\n");
+               printf("start     = Run lcr normally, abort with CTRL+C.\n");
                printf("fork      = Do daemon fork and run as background process.\n");
                printf("interface = Get help of available interface syntax.\n");
                printf("rules     = Get help of available routing rule syntax.\n");
                printf("rules [action] = Get individual help for given action.\n");
 //             printf("route = Show current routing as it is parsed.\n");
                printf("\n");
-               ret = 0;
-               goto free;
-       }
-
-       /* check if we have a jitter limit that makes sense */
-       if (ISDN_JITTERLIMIT < 256)
-       {
-               fprintf(stderr, "The ISDN_JITTERLIMIT must be at least 256 samples.\n");
+               ret = 999;
                goto free;
        }
 
        /* init crc */
        crc_init();
 
-       /* check for root (real or effective) */
-       if (getuid() && geteuid())
-       {
-               fprintf(stderr, "Please run %s as super-user.\n", NAME);
-               goto free;
-       }
-
        /* the mutex init */
        if (pthread_mutex_init(&mutexd, NULL))
        {
@@ -288,12 +233,12 @@ int main(int argc, char *argv[])
                goto free;
        }
        created_mutexd = 1;
-       if (pthread_mutex_init(&mutexl, NULL))
-       {
-               fprintf(stderr, "cannot create 'printlog' mutex\n");
-               goto free;
-       }
-       created_mutexl = 1;
+//     if (pthread_mutex_init(&mutext, NULL))
+//     {
+//             fprintf(stderr, "cannot create 'trace' mutex\n");
+//             goto free;
+//     }
+//     created_mutext = 1;
        if (pthread_mutex_init(&mutexe, NULL))
        {
                fprintf(stderr, "cannot create 'PERROR' mutex\n");
@@ -302,7 +247,7 @@ int main(int argc, char *argv[])
        created_mutexe = 1;
 
        /* show interface */
-       if (!(strcasecmp(ARGV(1),"interface")))
+       if (!(strcasecmp(argv[1],"interface")))
        {
                doc_interface();
                ret = 0;
@@ -310,44 +255,38 @@ int main(int argc, char *argv[])
        }
 
        /* show rules */
-       if (!(strcasecmp(ARGV(1),"rules")))
+       if (!(strcasecmp(argv[1],"rules")))
        {
-               if (ARGC <= 2)
+               if (argc <= 2)
                        doc_rules(NULL);
                else
-                       doc_rules(ARGV(2));
+                       doc_rules(argv[2]);
                ret = 0;
                goto free;
        }
 
        /* query available isdn ports */
-       if (!(strcasecmp(ARGV(1),"query")))
+       if (!(strcasecmp(argv[1],"query")))
        {
-               mISDN_port_info();
+               fprintf(stderr, "-> Using 'isdninfo'\n");
+               system("isdninfo");
                ret = 0;
                goto free;
        }
 
        /* read options */
        if (read_options() == 0)
+       {
+               PERROR("%s", options_error);
                goto free;
+       }
 
-       /* initialize stuff of the NT lib */
-       if (options.deb & DEBUG_STACK)
-       {
-               global_debug = 0xffffffff & ~DBGM_MSG;
-//             global_debug = DBGM_L3DATA;
-       } else
-               global_debug = DBGM_MAN;
-       SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
-       if (options.deb & DEBUG_LOG)
-               debug_init(global_debug, debug_log, debug_log, debug_log);
-       else
-               debug_init(global_debug, NULL, NULL, NULL);
+       /* init mISDN */
+       if (mISDN_initialize() < 0)
+               goto free;
+       created_misdn = 1;
        created_debug = 1;
 
-       msg_init();
-
        /* read ruleset(s) */
        if (!(ruleset_first = ruleset_parse()))
                goto free;
@@ -363,7 +302,7 @@ int main(int argc, char *argv[])
 
 #if 0
        /* query available isdn ports */
-       if (!(strcasecmp(ARGV(1),"route")))
+       if (!(strcasecmp(argv[1],"route")))
        {
                ruleset_debug(ruleset_first);
                ret = 0;
@@ -372,7 +311,7 @@ int main(int argc, char *argv[])
 #endif
 
        /* do fork in special cases */
-       if (!(strcasecmp(ARGV(1),"fork")))
+       if (!(strcasecmp(argv[1],"fork")))
        {
                pid_t pid;
 
@@ -401,27 +340,29 @@ int main(int argc, char *argv[])
                }
                if (pid != 0)
                {
-                       printf("PBX: Starting daemon.\n");
+                       printf("LCR: Starting daemon.\n");
                        exit(0);
                }
                nooutput = 1;
        } else
        /* if not start */
-       if (!!strcasecmp(ARGV(1),"start"))
+       if (!!strcasecmp(argv[1],"start"))
        {
                goto usage;
        }
 
        /* create lock and lock! */
-       if ((lockfd = open("/var/run/pbx.lock", O_CREAT, 0)) < 0)
+       SPRINT(lock, "%s/lcr.lock", options.lock);
+       if ((lockfd = open(lock, O_CREAT | O_WRONLY)) < 0)
        {
-               fprintf(stderr, "Cannot create lock file: /var/run/pbx.lock\n");
+               fprintf(stderr, "Cannot create lock file: %s\n", lock);
+               fprintf(stderr, "Check options.conf to change to path with permissions for you.\n");
                goto free;
        }
        if (flock(lockfd, LOCK_EX|LOCK_NB) < 0)
        {
                if (errno == EWOULDBLOCK)
-                       fprintf(stderr, "PBX: Another PBX process is running. Please kill the other one.\n");
+                       fprintf(stderr, "LCR: Another LCR process is running. Please kill the other one.\n");
                else    fprintf(stderr, "Locking process failed: errno=%d\n", errno);
                goto free;
        }
@@ -453,7 +394,6 @@ int main(int argc, char *argv[])
        }
        relink_interfaces();
        interface_first = interface_newlist;
-       free_interfaces(interface_newlist);
        interface_newlist = NULL;
        
        /* locking memory paging */
@@ -470,18 +410,17 @@ int main(int argc, char *argv[])
                switch(errno)
                {
                        case ENOMEM:
-                       fprintf(stderr, "Not enough memory to lock paging, exitting...\n");
+                       fprintf(stderr, "Warning: Not enough memory to lock paging, exitting...\n");
                        break;
                        case EPERM:
-                       fprintf(stderr, "No permission to lock paging, exitting...\n");
+                       fprintf(stderr, "Warning: No permission to lock paging, exitting...\n");
                        break;
                        case EFAULT:
-                       fprintf(stderr, "'Bad address' while locking paging, exitting...\n");
+                       fprintf(stderr, "Warning: 'Bad address' while locking paging, exitting...\n");
                        break;
                        default:
-                       fprintf(stderr, "Unknown error %d while locking paging, exitting...\n", errno);
+                       fprintf(stderr, "Warning: Unknown error %d while locking paging, exitting...\n", errno);
                }
-               goto free;
        }
 
        /* set real time scheduler & priority */
@@ -505,29 +444,34 @@ int main(int argc, char *argv[])
        created_signal = 1;
 
        /*** main loop ***/
-       printf("%s %s started, waiting for calls...\n", NAME, VERSION_STRING);
-       printlog("%s %s started, waiting for calls...\n", NAME, VERSION_STRING);
+       SPRINT(tracetext, "%s %s started, waiting for calls...", NAME, VERSION_STRING);
+       start_trace(0, NULL, NULL, NULL, 0, 0, 0, tracetext);
+       printf("%s\n", tracetext);
+       end_trace();
        GET_NOW();
-#ifdef DEBUG_DURATION
-       start_d = now_d;
-       durationupdate = now;
-       idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
-#endif
        quit = 0;
        while(!quit)
        {
+
+               last_d = now_d;
+               GET_NOW();
+               if (now_d-last_d > 1.0)
+               {
+                       PERROR("LCR was stalling %d.%d seconds\n", ((int)((now_d-last_d)*10.0))/10, (int)((now_d-last_d)*10.0));
+               }
                /* all loops must be counted from the beginning since nodes might get freed during handler */
                all_idle = 1;
 
+//#warning debugging usleep crash
+//             debug_usleep(1, __FILE__, __LINE__, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec);
+
                /* handle mISDN messages from kernel */
                debug_prefix = "ISDN";
                if (mISDN_handler())
                        all_idle = 0;
-#ifdef DEBUG_DURATION
-               GET_NOW();
-               isdn_duration += (now_d - start_d);
-               start_d = now_d;
-#endif
+//#warning debugging usleep crash
+//             debug_usleep(1, __FILE__, __LINE__, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec);
+
 BUDETECT
 
                /* loop through all port ports and call their handler */
@@ -544,11 +488,6 @@ BUDETECT
                                goto port_again;
                        port = port->next;
                }
-#ifdef DEBUG_DURATION
-               GET_NOW();
-               port_duration += (now_d - start_d);
-               start_d = now_d;
-#endif
 
                /* loop through all epoint and call their handler */
                epoint_again:
@@ -565,31 +504,21 @@ BUDETECT
                                goto epoint_again;
                        epoint = epoint->next;
                }
-#ifdef DEBUG_DURATION
-               GET_NOW();
-               epoint_duration += (now_d - start_d);
-               start_d = now_d;
-#endif
 
-               /* loop through all calls and call their handler */
-               call_again:
-               call = call_first;
-               while(call)
+               /* loop through all joins and call their handler */
+               join_again:
+               join = join_first;
+               while(join)
                {
-                       debug_prefix = "call";
+                       debug_prefix = "join";
                        debug_count++;
-                       ret = call->handler();
+                       ret = join->handler();
                        if (ret)
                                all_idle = 0;
-                       if (ret < 0) /* call has been destroyed */
-                               goto call_again;
-                       call = call->next;
+                       if (ret < 0) /* join has been destroyed */
+                               goto join_again;
+                       join = join->next;
                }
-#ifdef DEBUG_DURATION
-               GET_NOW();
-               call_duration += (now_d - start_d);
-               start_d = now_d;
-#endif
 
                debug_prefix = 0;
 
@@ -619,33 +548,33 @@ BUDETECT
                                }
                                break;
 
-                               case EPOINT_TO_CALL:
-                               debug_prefix = "msg epoint->call";
-                               call = find_call_id(message->id_to);
-                               if (call)
+                               case EPOINT_TO_JOIN:
+                               debug_prefix = "msg epoint->join";
+                               join = find_join_id(message->id_to);
+                               if (join)
                                {
-                                       call->message_epoint(message->id_from, message->type, &message->param);
+                                       join->message_epoint(message->id_from, message->type, &message->param);
                                } else
                                {
-                                       PDEBUG(DEBUG_MSG, "Warning: message %s from endpoint %d to call %d. call doesn't exist anymore\n", messages_txt[message->type], message->id_from, message->id_to);
+                                       PDEBUG(DEBUG_MSG, "Warning: message %s from endpoint %d to join %d. join doesn't exist anymore\n", messages_txt[message->type], message->id_from, message->id_to);
                                }
                                break;
 
-                               case CALL_TO_EPOINT:
-                               debug_prefix = "msg call->epoint";
+                               case JOIN_TO_EPOINT:
+                               debug_prefix = "msg join->epoint";
                                epoint = find_epoint_id(message->id_to);
                                if (epoint)
                                {
                                        if (epoint->ep_app)
                                        {
-                                               epoint->ep_app->ea_message_call(message->id_from, message->type, &message->param);
+                                               epoint->ep_app->ea_message_join(message->id_from, message->type, &message->param);
                                        } else
                                        {
-                                               PDEBUG(DEBUG_MSG, "Warning: message %s from call %d to endpoint %d. endpoint doesn't have an application.\n", messages_txt[message->type], message->id_from, message->id_to);
+                                               PDEBUG(DEBUG_MSG, "Warning: message %s from join %d to endpoint %d. endpoint doesn't have an application.\n", messages_txt[message->type], message->id_from, message->id_to);
                                        }
                                } else
                                {
-                                       PDEBUG(DEBUG_MSG, "Warning: message %s from call %d to endpoint %d. endpoint doesn't exist anymore.\n", messages_txt[message->type], message->id_from, message->id_to);
+                                       PDEBUG(DEBUG_MSG, "Warning: message %s from join %d to endpoint %d. endpoint doesn't exist anymore.\n", messages_txt[message->type], message->id_from, message->id_to);
                                }
                                break;
 
@@ -669,21 +598,11 @@ BUDETECT
                        debug_count++;
                        debug_prefix = "message";
                }
-#ifdef DEBUG_DURATION
-               GET_NOW();
-               message_duration += (now_d - start_d);
-               start_d = now_d;
-#endif
 BUDETECT
 
                /* handle socket */
                if (admin_handle())
                        all_idle = 0;
-#ifdef DEBUG_DURATION
-               GET_NOW();
-               admin_duration += (now_d - start_d);
-               start_d = now_d;
-#endif
 BUDETECT
 
 #if 0
@@ -694,6 +613,8 @@ BUDETECT
                        all_idle = 0;
                }
 #endif
+//#warning debugging usleep crash
+//             debug_usleep(1, __FILE__, __LINE__, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec);
 
                /* do idle checking */
                if (idlecheck != now)
@@ -702,35 +623,22 @@ BUDETECT
                        idletime = 0;
                        idlecheck = now;
                }
-#ifdef DEBUG_DURATION
-               GET_NOW();
-               idle_duration += (now_d - start_d);
-               start_d = now_d;
-               if (durationupdate != now)
-               {
-                       durationupdate = now;
-                       printf("Idle:%3d ISDN:%3d Port:%3d Epoint:%3d Call:%3d Message:%3d Admin:%3d\n",
-                               (int)(idle_duration*100),
-                               (int)(isdn_duration*100),
-                               (int)(port_duration*100),
-                               (int)(epoint_duration*100),
-                               (int)(call_duration*100),
-                               (int)(message_duration*100),
-                               (int)(admin_duration*100));
-                       idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
-               }
-#else
-               GET_NOW();
-#endif
 
                /* did we do nothing? so we wait to give time to other processes */
                if (all_idle)
                {
-                       usleep(4000); /* wait 32 samples */
+//                     pthread_mutex_unlock(&mutex_lcr); // unlock LCR
+                       debug_usleep(4000, __FILE__, __LINE__, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec);
+//                     pthread_mutex_lock(&mutex_lcr); // lock LCR
                        idletime += 4000;
                }
        }
-       printlog("PBX terminated\n");
+       SPRINT(tracetext, "%s terminated", NAME);
+       printf("%s\n", tracetext);
+       start_trace(0, NULL, NULL, NULL, 0, 0, 0, tracetext);
+       if (quit)
+               add_trace("signal", NULL, "%d", quit);
+       end_trace();
        ret=0;
 
        /* free all */
@@ -742,7 +650,7 @@ free:
        if (options.schedule > 1)
        {
                memset(&schedp, 0, sizeof(schedp));
-               schedp.sched_priority = 0;
+               schedp.sched_priority = options.schedule;
                sched_setscheduler(0, SCHED_OTHER, &schedp);
        }
        /* reset signals */
@@ -769,7 +677,7 @@ free:
        }
        epoint_first = NULL;
        debug_count++;
-       call_free();
+       join_free();
 
        /* free interfaces */
        if (interface_first)
@@ -803,7 +711,11 @@ free:
        if (created_lock)
                flock(lockfd, LOCK_UN);
        if (lockfd >= 0)
+       {
+               chmod(lock, 0700);
+               unlink(lock);
                close(lockfd);
+       }
 
        /* free rulesets */
        if (ruleset_first)
@@ -814,31 +726,34 @@ free:
        if (created_mutexe)
                if (pthread_mutex_destroy(&mutexe))
                        fprintf(stderr, "cannot destroy 'PERROR' mutex\n");
-       if (created_mutexl)
-               if (pthread_mutex_destroy(&mutexl))
-                       fprintf(stderr, "cannot destroy 'printlog' mutex\n");
+//     if (created_mutext)
+//             if (pthread_mutex_destroy(&mutext))
+//                     fprintf(stderr, "cannot destroy 'trace' mutex\n");
        if (created_mutexd)
                if (pthread_mutex_destroy(&mutexd))
                        fprintf(stderr, "cannot destroy 'PDEBUG' mutex\n");
 
-       /* close debug */
-       if (created_debug)
-               debug_close();
-       global_debug = 0;
+       /* deinitialize mISDN */
+       if (created_misdn)
+               mISDN_deinitialize();
 
        /* display memory leak */
 #define MEMCHECK(a, b) \
        if (b) \
        { \
+               SPRINT(tracetext, a, NAME); \
+               start_trace(0, NULL, NULL, NULL, 0, 0, 0, tracetext); \
+               if (ret) add_trace("blocks", NULL, "%d", b); \
+               end_trace(); \
                printf("\n******************************\n\007"); \
                printf("\nERROR: %d %s\n", b, a); \
                printf("\n******************************\n"); \
                ret = -1; \
        }
        MEMCHECK("",memuse)
-       MEMCHECK("memory block(s) left (port.cpp)",pmemuse)
-       MEMCHECK("memory block(s) left (epoint.cpp)",ememuse)
-       MEMCHECK("memory block(s) left (call.cpp)",cmemuse)
+       MEMCHECK("memory block(s) left (port.cpp ...)",pmemuse)
+       MEMCHECK("memory block(s) left (epoint*.cpp ...)",ememuse)
+       MEMCHECK("memory block(s) left (join*.cpp)",cmemuse)
        MEMCHECK("memory block(s) left (message.c)",mmemuse)
        MEMCHECK("memory block(s) left (route.c)",rmemuse)
        MEMCHECK("memory block(s) left (args)",amemuse)
@@ -846,14 +761,11 @@ free:
        MEMCHECK("file descriptor(s) left",fduse)
        MEMCHECK("file handler(s) left",fhuse)
 
+       /* unlock LCR process */
+//     pthread_mutex_unlock(&mutex_lcr);
+
        /* take me out */
-       if (ret)
-               printf("PBX: Exit (code %d)\n", ret);
-#ifdef VOIP
-       return;
-#else
        return(ret);
-#endif
 }