]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/message.c
Suppress incorrect 'Will not descend from x into y' messages
[bacula/bacula] / bacula / src / lib / message.c
old mode 100755 (executable)
new mode 100644 (file)
index 44070a7..2b624f8
@@ -1,3 +1,30 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation and included
+   in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 /*
  * Bacula message handling routines
  *
  *   Version $Id$
  *
  */
-/*
-   Copyright (C) 2000-2006 Kern Sibbald
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   version 2 as amended with additional clauses defined in the
-   file LICENSE in the main source directory.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
-   the file LICENSE for additional details.
-
- */
-
 
 
 #include "bacula.h"
 #include "jcr.h"
 
 sql_query p_sql_query = NULL;
+sql_escape p_sql_escape = NULL;
 
 #define FULL_LOCATION 1               /* set for file:line in Debug messages */
 
@@ -37,30 +50,29 @@ sql_query p_sql_query = NULL;
 const char *working_directory = NULL;       /* working directory path stored here */
 int verbose = 0;                      /* increase User messages */
 int debug_level = 0;                  /* debug level */
+bool dbg_timestamp = false;           /* print timestamp in debug output */
 time_t daemon_start_time = 0;         /* Daemon start time */
 const char *version = VERSION " (" BDATE ")";
 char my_name[30];                     /* daemon name is stored here */
 char *exepath = (char *)NULL;
 char *exename = (char *)NULL;
-int console_msg_pending = 0;
+int console_msg_pending = false;
 char con_fname[500];                  /* Console filename */
 FILE *con_fd = NULL;                  /* Console file descriptor */
 brwlock_t con_lock;                   /* Console lock structure */
 
+/* Forward referenced functions */
 
-#if defined(HAVE_POSTGRESQL)
-char catalog_db[] = "PostgreSQL";
-#elif defined(HAVE_MYSQL)
-char catalog_db[] = "MySQL";
-#elif defined(HAVE_SQLITE)
-char catalog_db[] = "SQLite";
-#else
-char catalog_db[] = "Internal";
-#endif
+/* Imported functions */
 
-const char *host_os = HOST_OS;
-const char *distname = DISTNAME;
-const char *distver = DISTVER;
+
+/* Static storage */
+
+/* Used to allow only one thread close the daemon messages at a time */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static MSGS *daemon_msgs;              /* global messages */
+static char *catalog_db = NULL;       /* database type */
+static void (*message_callback)(int type, char *msg) = NULL;
 static FILE *trace_fd = NULL;
 #if defined(HAVE_WIN32)
 static bool trace = true;
@@ -68,16 +80,16 @@ static bool trace = true;
 static bool trace = false;
 #endif
 
-/* Forward referenced functions */
-
-/* Imported functions */
-
+/* Constants */
+const char *host_os = HOST_OS;
+const char *distname = DISTNAME;
+const char *distver = DISTVER;
 
-/* Static storage */
 
-/* Used to allow only one thread close the daemon messages at a time */
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static MSGS *daemon_msgs;              /* global messages */
+void register_message_callback(void msg_callback(int type, char *msg))
+{
+   message_callback = msg_callback;
+}
 
 
 /*
@@ -90,7 +102,6 @@ static MSGS *daemon_msgs;              /* global messages */
  *  Resource record. On the second call, generally,
  *  argv is NULL to avoid doing the path code twice.
  */
-#define BTRACE_EXTRA 20
 void my_name_is(int argc, char *argv[], const char *name)
 {
    char *l, *p, *q;
@@ -101,11 +112,11 @@ void my_name_is(int argc, char *argv[], const char *name)
    if (argc>0 && argv && argv[0]) {
       /* strip trailing filename and save exepath */
       for (l=p=argv[0]; *p; p++) {
-         if (*p == '/') {
+         if (IsPathSeparator(*p)) {
             l = p;                       /* set pos of last slash */
          }
       }
-      if (*l == '/') {
+      if (IsPathSeparator(*l)) {
          l++;
       } else {
          l = argv[0];
@@ -131,7 +142,7 @@ void my_name_is(int argc, char *argv[], const char *name)
          *q++ = *p++;
       }
       *q = 0;
-      if (strchr(exepath, '.') || exepath[0] != '/') {
+      if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
          if (getcwd(cpath, sizeof(cpath))) {
             free(exepath);
             exepath = (char *)malloc(strlen(cpath) + 1 + len);
@@ -142,6 +153,21 @@ void my_name_is(int argc, char *argv[], const char *name)
    }
 }
 
+const char *
+get_db_type(void)
+{
+   return catalog_db != NULL ? catalog_db : "unknown";
+}
+
+void
+set_db_type(const char *name)
+{
+   if (catalog_db != NULL) {
+      free(catalog_db);
+   }
+   catalog_db = bstrdup(name);
+}
+
 /*
  * Initialize message handler for a daemon or a Job
  *   We make a copy of the MSGS resource passed, so it belows
@@ -154,6 +180,7 @@ void
 init_msg(JCR *jcr, MSGS *msg)
 {
    DEST *d, *dnew, *temp_chain = NULL;
+   int i;
 
    if (jcr == NULL && msg == NULL) {
       init_last_jobs_list();
@@ -168,7 +195,6 @@ init_msg(JCR *jcr, MSGS *msg)
     *
     */
    int fd;
-   int i;
    fd = open("/dev/null", O_RDONLY, 0644);
    if (fd > 2) {
       close(fd);
@@ -185,11 +211,9 @@ init_msg(JCR *jcr, MSGS *msg)
    if (msg == NULL) {
       daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
       memset(daemon_msgs, 0, sizeof(MSGS));
-#if !defined(HAVE_WIN32)
       for (i=1; i<=M_MAX; i++) {
          add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
       }
-#endif
       Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
       return;
    }
@@ -239,12 +263,12 @@ void init_console_msg(const char *wd)
 {
    int fd;
 
-   bsnprintf(con_fname, sizeof(con_fname), "%s/%s.conmsg", wd, my_name);
+   bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
    fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
    if (fd == -1) {
       berrno be;
       Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
-          con_fname, be.strerror());
+          con_fname, be.bstrerror());
    }
    if (lseek(fd, 0, SEEK_END) > 0) {
       console_msg_pending = 1;
@@ -254,12 +278,12 @@ void init_console_msg(const char *wd)
    if (!con_fd) {
       berrno be;
       Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
-          con_fname, be.strerror());
+          con_fname, be.bstrerror());
    }
    if (rwl_init(&con_lock) != 0) {
       berrno be;
       Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
-         be.strerror());
+         be.bstrerror());
    }
 }
 
@@ -363,7 +387,7 @@ static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
    if (!(bpipe = open_bpipe(cmd, 120, "rw"))) {
       berrno be;
       Jmsg(jcr, M_ERROR, 0, _("open mail pipe %s failed: ERR=%s\n"),
-         cmd, be.strerror());
+         cmd, be.bstrerror());
    }
 
    /* If we had to use sendmail, add subject */
@@ -407,16 +431,23 @@ void close_msg(JCR *jcr)
          case MD_APPEND:
             if (d->fd) {
                fclose(d->fd);            /* close open file descriptor */
+               d->fd = NULL;
             }
             break;
          case MD_MAIL:
          case MD_MAIL_ON_ERROR:
-            Dmsg0(850, "Got MD_MAIL or MD_MAIL_ON_ERROR\n");
+         case MD_MAIL_ON_SUCCESS:
+            Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
             if (!d->fd) {
                break;
             }
-            if (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
-                jcr->JobStatus == JS_Terminated) {
+            if (
+                (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
+                 jcr->JobStatus == JS_Terminated) 
+                ||
+                (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
+                 jcr->JobStatus == JS_ErrorTerminated)
+                ){
                goto rem_temp_file;
             }
 
@@ -433,7 +464,7 @@ void close_msg(JCR *jcr)
             }
             if (!close_wpipe(bpipe)) {       /* close write pipe sending mail */
                berrno be;
-               Pmsg1(000, _("close error: ERR=%s\n"), be.strerror());
+               Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
             }
 
             /*
@@ -455,12 +486,13 @@ void close_msg(JCR *jcr)
                Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
                Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
                                         "CMD=%s\n"
-                                        "ERR=%s\n"), cmd, be.strerror());
+                                        "ERR=%s\n"), cmd, be.bstrerror());
             }
             free_memory(line);
 rem_temp_file:
             /* Remove temp file */
             fclose(d->fd);
+            d->fd = NULL;
             unlink(d->mail_filename);
             free_pool_memory(d->mail_filename);
             d->mail_filename = NULL;
@@ -538,10 +570,25 @@ void term_msg()
       fclose(trace_fd);
       trace_fd = NULL;
    }
+   if (catalog_db) {
+      free(catalog_db);
+      catalog_db = NULL;
+   }
    term_last_jobs_list();
 }
 
-
+static bool open_dest_file(JCR *jcr, DEST *d, const char *mode) 
+{
+   d->fd = fopen(d->where, mode);
+   if (!d->fd) {
+      berrno be;
+      d->fd = stdout;
+      Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
+      d->fd = NULL;
+      return false;
+   }
+   return true;
+}
 
 /*
  * Handle sending the message to the appropriate place
@@ -554,6 +601,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
     int len, dtlen;
     MSGS *msgs;
     BPIPE *bpipe;
+    const char *mode;
 
     Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
 
@@ -576,16 +624,24 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
        dt[dtlen] = 0;
     }
 
+    /* If the program registered a callback, send it there */
+    if (message_callback) {
+       message_callback(type, msg);
+       return;
+    }
+
     if (type == M_ABORT || type == M_ERROR_TERM) {
-#if !defined(HAVE_WIN32)
        fputs(dt, stdout);
        fputs(msg, stdout);         /* print this here to INSURE that it is printed */
        fflush(stdout);
-#endif
     }
 
+
     /* Now figure out where to send the message */
     msgs = NULL;
+    if (!jcr) {
+       jcr = get_jcr_from_tsd();
+    }
     if (jcr) {
        msgs = jcr->jcr_msgs;
     }
@@ -600,12 +656,21 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
                 if (!jcr || !jcr->db) {
                    break;
                 }
-                if (p_sql_query) {
-                   POOL_MEM cmd(PM_MESSAGE);
-                   bstrftimes(dt, sizeof(dt), mtime);
+                if (p_sql_query && p_sql_escape) {
+                   POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
+                   POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
+                   
+                   int len = strlen(msg) + 1;
+                   esc_msg = check_pool_memory_size(esc_msg, len*2+1);
+                   p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
+
+                   bstrutime(dt, sizeof(dt), mtime);
                    Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
-                         edit_int64(jcr->JobId, ed1), dt, msg);
-                   p_sql_query(jcr, cmd.c_str());
+                         edit_int64(jcr->JobId, ed1), dt, esc_msg);
+                   p_sql_query(jcr, cmd);
+                   
+                   free_pool_memory(cmd);
+                   free_pool_memory(esc_msg);
                 }
                 break;
              case MD_CONSOLE:
@@ -630,7 +695,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
                       (void)fwrite("\n", 2, 1, con_fd);
                    }
                    fflush(con_fd);
-                   console_msg_pending = TRUE;
+                   console_msg_pending = true;
                    Vw(con_lock);
                 }
                 break;
@@ -655,13 +720,14 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
                       be.set_errno(stat);
                       Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n"
                             "CMD=%s\n"
-                            "ERR=%s\n"), mcmd, be.strerror());
+                            "ERR=%s\n"), mcmd, be.bstrerror());
                    }
                 }
                 free_pool_memory(mcmd);
                 break;
              case MD_MAIL:
              case MD_MAIL_ON_ERROR:
+             case MD_MAIL_ON_SUCCESS:
                 Dmsg1(850, "MAIL for following msg: %s", msg);
                 if (!d->fd) {
                    POOLMEM *name = get_pool_memory(PM_MESSAGE);
@@ -671,7 +737,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
                       berrno be;
                       d->fd = stdout;
                       Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), name,
-                            be.strerror());
+                            be.bstrerror());
                       d->fd = NULL;
                       free_pool_memory(name);
                       break;
@@ -685,37 +751,28 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
                 }
                 fputs(msg, d->fd);
                 break;
+             case MD_APPEND:
+                Dmsg1(850, "APPEND for following msg: %s", msg);
+                mode = "ab";
+                goto send_to_file;
              case MD_FILE:
                 Dmsg1(850, "FILE for following msg: %s", msg);
-                if (!d->fd) {
-                   d->fd = fopen(d->where, "w+b");
-                   if (!d->fd) {
-                      berrno be;
-                      d->fd = stdout;
-                      Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where,
-                            be.strerror());
-                      d->fd = NULL;
-                      break;
-                   }
+                mode = "w+b";
+send_to_file:
+                if (!d->fd && !open_dest_file(jcr, d, mode)) {
+                   break;
                 }
                 fputs(dt, d->fd);
                 fputs(msg, d->fd);
-                break;
-             case MD_APPEND:
-                Dmsg1(850, "APPEND for following msg: %s", msg);
-                if (!d->fd) {
-                   d->fd = fopen(d->where, "ab");
-                   if (!d->fd) {
-                      berrno be;
-                      d->fd = stdout;
-                      Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where,
-                            be.strerror());
-                      d->fd = NULL;
-                      break;
+                /* On error, we close and reopen to handle log rotation */
+                if (ferror(d->fd)) {
+                   fclose(d->fd);
+                   d->fd = NULL;
+                   if (open_dest_file(jcr, d, mode)) {
+                      fputs(dt, d->fd);
+                      fputs(msg, d->fd);
                    }
                 }
-                fputs(dt, d->fd);
-                fputs(msg, d->fd);
                 break;
              case MD_DIRECTOR:
                 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
@@ -729,12 +786,14 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
                 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
                    fputs(dt, stdout);
                    fputs(msg, stdout);
+                   fflush(stdout);
                 }
                 break;
              case MD_STDERR:
                 Dmsg1(850, "STDERR for following msg: %s", msg);
                 fputs(dt, stderr);
                 fputs(msg, stderr);
+                fflush(stdout);
                 break;
              default:
                 break;
@@ -743,6 +802,30 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
     }
 }
 
+/*********************************************************************
+ *
+ *  This subroutine returns the filename portion of a Windows 
+ *  path.  It is used because Microsoft Visual Studio sets __FILE__ 
+ *  to the full path.
+ */
+
+inline const char *
+get_basename(const char *pathname)
+{
+#if defined(_MSC_VER)
+   const char *basename;
+   
+   if ((basename = strrchr(pathname, '\\')) == NULL) {
+      basename = pathname;
+   } else {
+      basename++;
+   }
+
+   return basename;
+#else
+   return pathname;
+#endif
+}
 
 /*********************************************************************
  *
@@ -761,6 +844,7 @@ d_msg(const char *file, int line, int level, const char *fmt,...)
     int       len;
     va_list   arg_ptr;
     bool      details = true;
+    time_t    mtime;
 
     if (level < 0) {
        details = false;
@@ -768,19 +852,19 @@ d_msg(const char *file, int line, int level, const char *fmt,...)
     }
 
     if (level <= debug_level) {
+       if (dbg_timestamp) {
+          mtime = time(NULL);
+          bstrftimes(buf, sizeof(buf), mtime);
+          len = strlen(buf);
+          buf[len++] = ' ';
+          buf[len] = 0;
+          fputs(buf, stdout);
+       }
+    
 #ifdef FULL_LOCATION
        if (details) {
-          /* visual studio passes the whole path to the file as well
-           * which makes for very long lines
-           */
-          const char *basename;
-
-          if ((basename = strrchr(file, '\\')) == NULL) {
-             basename = file;
-          } else {
-             basename++;
-          }
-          len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, basename, line);
+          len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ", 
+                my_name, get_basename(file), line, get_jobid_from_tsd());
        } else {
           len = 0;
        }
@@ -798,7 +882,7 @@ d_msg(const char *file, int line, int level, const char *fmt,...)
        if (trace) {
           if (!trace_fd) {
              char fn[200];
-             bsnprintf(fn, sizeof(fn), "%s/bacula.trace", working_directory ? working_directory : ".");
+             bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
              trace_fd = fopen(fn, "a+b");
           }
           if (trace_fd) {
@@ -810,6 +894,7 @@ d_msg(const char *file, int line, int level, const char *fmt,...)
           }
        } else {   /* not tracing */
           fputs(buf, stdout);
+          fflush(stdout);
        }
     }
 }
@@ -855,14 +940,7 @@ p_msg(const char *file, int line, int level, const char *fmt,...)
 
 #ifdef FULL_LOCATION
     if (level >= 0) {
-       const char *basename;
-
-       if ((basename = strrchr(file, '\\')) == NULL) {
-          basename = file;
-       } else {
-          basename++;
-       }
-       len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, basename, line);
+       len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
     } else {
        len = 0;
     }
@@ -873,6 +951,7 @@ p_msg(const char *file, int line, int level, const char *fmt,...)
     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
     va_end(arg_ptr);
     fputs(buf, stdout);
+    fflush(stdout);
 }
 
 
@@ -901,20 +980,13 @@ t_msg(const char *file, int line, int level, const char *fmt,...)
 
     if (level <= debug_level) {
        if (!trace_fd) {
-          bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory);
+          bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
           trace_fd = fopen(buf, "a+b");
        }
 
 #ifdef FULL_LOCATION
        if (details) {
-          const char *basename;
-
-          if ((basename = strrchr(file, '\\')) == NULL) {
-             basename = file;
-          } else {
-             basename++;
-          }
-          len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, basename, line);
+          len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
        } else {
           len = 0;
        }
@@ -945,14 +1017,6 @@ e_msg(const char *file, int line, int type, int level, const char *fmt,...)
     va_list   arg_ptr;
     int len;
 
-    const char *basename;
-
-    if ((basename = strrchr(file, '\\')) == NULL) {
-       basename = file;
-    } else {
-       basename++;
-    }
-
     /*
      * Check if we have a message destination defined.
      * We always report M_ABORT and M_ERROR_TERM
@@ -964,23 +1028,23 @@ e_msg(const char *file, int line, int type, int level, const char *fmt,...)
     switch (type) {
     case M_ABORT:
        len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
-               my_name, basename, line);
+               my_name, get_basename(file), line);
        break;
     case M_ERROR_TERM:
        len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
-               my_name, basename, line);
+               my_name, get_basename(file), line);
        break;
     case M_FATAL:
        if (level == -1)            /* skip details */
           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
        else
-          len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, basename, line);
+          len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
        break;
     case M_ERROR:
        if (level == -1)            /* skip details */
           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
        else
-          len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, basename, line);
+          len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
        break;
     case M_WARNING:
        len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
@@ -1020,7 +1084,7 @@ Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
     va_list   arg_ptr;
     int len;
     MSGS *msgs;
-    const char *job;
+    uint32_t JobId = 0;
 
 
     Dmsg1(850, "Enter Jmsg type=%d\n", type);
@@ -1035,22 +1099,21 @@ Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
        dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
                                 fmt, arg_ptr);
        va_end(arg_ptr);
-       bnet_send(jcr->dir_bsock);
+       jcr->dir_bsock->send();
        return;
     }
 
     msgs = NULL;
-    job = NULL;
+    if (!jcr) {
+       jcr = get_jcr_from_tsd();
+    }
     if (jcr) {
        msgs = jcr->jcr_msgs;
-       job = jcr->Job;
+       JobId = jcr->JobId;
     }
     if (!msgs) {
        msgs = daemon_msgs;            /* if no jcr, we use daemon handler */
     }
-    if (!job) {
-       job = "";                      /* Set null job name if none */
-    }
 
     /*
      * Check if we have a message destination defined.
@@ -1068,25 +1131,26 @@ Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
        break;
     case M_FATAL:
-       len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Fatal error: "), my_name, job);
+       len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
        if (jcr) {
           set_jcr_job_status(jcr, JS_FatalError);
        }
        break;
     case M_ERROR:
-       len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Error: "), my_name, job);
+       len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
        if (jcr) {
           jcr->Errors++;
        }
        break;
     case M_WARNING:
-       len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Warning: "), my_name, job);
+       len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
        break;
     case M_SECURITY:
-       len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Security violation: "), my_name, job);
+       len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "), 
+               my_name, JobId);
        break;
     default:
-       len = bsnprintf(rbuf, sizeof(rbuf), "%s: ", my_name);
+       len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
        break;
     }
 
@@ -1098,6 +1162,8 @@ Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
 
     if (type == M_ABORT){
        char *p = 0;
+       printf("Bacula forced SEG FAULT to obtain traceback.\n");
+       syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
        p[0] = 0;                      /* generate segmentation violation */
     }
     if (type == M_ERROR_TERM) {
@@ -1114,16 +1180,9 @@ void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const c
    va_list   arg_ptr;
    int i, len, maxlen;
    POOLMEM *pool_buf;
-   const char *basename;
-
-   if ((basename = strrchr(file, '\\')) == NULL) {
-      basename = file;
-   } else {
-      basename++;
-   }
 
    pool_buf = get_pool_memory(PM_EMSG);
-   i = Mmsg(pool_buf, "%s:%d ", basename, line);
+   i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
 
    for (;;) {
       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
@@ -1150,15 +1209,7 @@ int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
    va_list   arg_ptr;
    int i, len, maxlen;
 
-   const char *basename;
-
-   if ((basename = strrchr(file, '\\')) == NULL) {
-      basename = file;
-   } else {
-      basename++;
-   }
-
-   i = sprintf(*pool_buf, "%s:%d ", basename, line);
+   i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
 
    for (;;) {
       maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
@@ -1179,15 +1230,7 @@ int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
    va_list   arg_ptr;
    int i, len, maxlen;
 
-   const char *basename;
-
-   if ((basename = strrchr(file, '\\')) == NULL) {
-      basename = file;
-   } else {
-      basename++;
-   }
-
-   i = sprintf(pool_buf, "%s:%d ", basename, line);
+   i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
 
    for (;;) {
       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
@@ -1299,10 +1342,13 @@ void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
    item->type = type;
    item->mtime = time(NULL);
    strcpy(item->msg, pool_buf);
+   if (!jcr) {
+      jcr = get_jcr_from_tsd();
+   }
    /* If no jcr or dequeuing send to daemon to avoid recursion */
-   if (!jcr || jcr->dequeuing) {
+   if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
       /* jcr==NULL => daemon message, safe to send now */
-      Jmsg(NULL, item->type, item->mtime, "%s", item->msg);
+      Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
       free(item);
    } else {
       /* Queue message for later sending */
@@ -1320,12 +1366,17 @@ void dequeue_messages(JCR *jcr)
 {
    MQUEUE_ITEM *item;
    P(msg_queue_mutex);
+   if (!jcr->msg_queue) {
+      goto bail_out;
+   }
    jcr->dequeuing = true;
    foreach_dlist(item, jcr->msg_queue) {
       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
    }
    jcr->msg_queue->destroy();
    jcr->dequeuing = false;
+
+bail_out:
    V(msg_queue_mutex);
 }