]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/message.c
Fix seg fault in SQlite driver
[bacula/bacula] / bacula / src / lib / message.c
index 2b624f823595163ccfad674c98d10a5f88d2d88f..5791f6b51b95a43be565ad351630d7e48dd24029 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2009 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.
@@ -20,7 +20,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of Kern Sibbald.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
  *
  *   Kern Sibbald, April 2000
  *
- *   Version $Id$
- *
  */
 
-
 #include "bacula.h"
 #include "jcr.h"
 
@@ -51,9 +48,11 @@ const char *working_directory = NULL;       /* working directory path stored her
 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 */
+bool prt_kaboom = false;              /* Print kaboom output */
+utime_t daemon_start_time = 0;        /* Daemon start time */
 const char *version = VERSION " (" BDATE ")";
 char my_name[30];                     /* daemon name is stored here */
+char host_name[50];                   /* host machine name */
 char *exepath = (char *)NULL;
 char *exename = (char *)NULL;
 int console_msg_pending = false;
@@ -64,12 +63,12 @@ brwlock_t con_lock;                   /* Console lock structure */
 /* Forward referenced functions */
 
 /* Imported functions */
-
+void create_jcr_key();
 
 /* Static storage */
 
-/* Used to allow only one thread close the daemon messages at a time */
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+/* Allow only one thread to tweak d->fd at a time */
+static pthread_mutex_t fides_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;
@@ -108,6 +107,9 @@ void my_name_is(int argc, char *argv[], const char *name)
    char cpath[1024];
    int len;
 
+   if (gethostname(host_name, sizeof(host_name)) != 0) {
+      bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
+   }
    bstrncpy(my_name, name, sizeof(my_name));
    if (argc>0 && argv && argv[0]) {
       /* strip trailing filename and save exepath */
@@ -184,6 +186,10 @@ init_msg(JCR *jcr, MSGS *msg)
 
    if (jcr == NULL && msg == NULL) {
       init_last_jobs_list();
+      /* Create a daemon key then set invalid jcr */
+      /* Maybe we should give the daemon a jcr??? */
+      create_jcr_key();
+      set_jcr_in_tsd(INVALID_JCR);
    }
 
 #if !defined(HAVE_WIN32)
@@ -362,10 +368,10 @@ static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
 {
    if (jcr) {
       Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
-                 jcr->Job, (int)(long)d);
+                 jcr->Job, (int)(intptr_t)d);
    } else {
       Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
-                 my_name, (int)(long)d);
+                 my_name, (int)(intptr_t)d);
    }
    Dmsg1(850, "mailname=%s\n", name);
 }
@@ -384,17 +390,16 @@ static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
    }
    fflush(stdout);
 
-   if (!(bpipe = open_bpipe(cmd, 120, "rw"))) {
+   if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
+      /* If we had to use sendmail, add subject */
+      if (!d->mail_cmd) {
+         fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
+      }
+   } else {
       berrno be;
       Jmsg(jcr, M_ERROR, 0, _("open mail pipe %s failed: ERR=%s\n"),
          cmd, be.bstrerror());
    }
-
-   /* If we had to use sendmail, add subject */
-   if (!d->mail_cmd) {
-       fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
-   }
-
    return bpipe;
 }
 
@@ -414,7 +419,6 @@ void close_msg(JCR *jcr)
 
    if (jcr == NULL) {                /* NULL -> global chain */
       msgs = daemon_msgs;
-      P(mutex);                       /* only one thread walking the chain */
    } else {
       msgs = jcr->jcr_msgs;
       jcr->jcr_msgs = NULL;
@@ -422,6 +426,7 @@ void close_msg(JCR *jcr)
    if (msgs == NULL) {
       return;
    }
+   P(fides_mutex);
    Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
    cmd = get_pool_memory(PM_MESSAGE);
    for (d=msgs->dest_chain; d; ) {
@@ -443,11 +448,11 @@ void close_msg(JCR *jcr)
             }
             if (
                 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
-                 jcr->JobStatus == JS_Terminated
+                  (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)
                 ||
                 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
                  jcr->JobStatus == JS_ErrorTerminated)
-                ){
+                ) {
                goto rem_temp_file;
             }
 
@@ -475,7 +480,7 @@ void close_msg(JCR *jcr)
             if (msgs != daemon_msgs) {
                /* read what mail prog returned -- should be nothing */
                while (fgets(line, len, bpipe->rfd)) {
-                  Jmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line);
+                  Qmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line);
                }
             }
 
@@ -484,7 +489,7 @@ void close_msg(JCR *jcr)
                berrno be;
                be.set_errno(stat);
                Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
-               Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
+               Qmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
                                         "CMD=%s\n"
                                         "ERR=%s\n"), cmd, be.bstrerror());
             }
@@ -505,13 +510,12 @@ rem_temp_file:
       }
       d = d->next;                    /* point to next buffer */
    }
+   V(fides_mutex);
    free_pool_memory(cmd);
    Dmsg0(850, "Done walking message chain.\n");
    if (jcr) {
       free_msgs_res(msgs);
       msgs = NULL;
-   } else {
-      V(mutex);
    }
    Dmsg0(850, "===End close msg resource\n");
 }
@@ -593,7 +597,7 @@ static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
 /*
  * Handle sending the message to the appropriate place
  */
-void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
+void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
 {
     DEST *d;
     char dt[MAX_TIME_LENGTH];
@@ -609,7 +613,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
      * Most messages are prefixed by a date and time. If mtime is
      *  zero, then we use the current time.  If mtime is 1 (special
      *  kludge), we do not prefix the date and time. Otherwise,
-     *  we assume mtime is a time_t and use it.
+     *  we assume mtime is a utime_t and use it.
      */
     if (mtime == 0) {
        mtime = time(NULL);
@@ -617,6 +621,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
     if (mtime == 1) {
        *dt = 0;
        dtlen = 0;
+       mtime = time(NULL);      /* get time for SQL log */
     } else {
        bstrftime_ny(dt, sizeof(dt), mtime);
        dtlen = strlen(dt);
@@ -634,6 +639,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
        fputs(dt, stdout);
        fputs(msg, stdout);         /* print this here to INSURE that it is printed */
        fflush(stdout);
+       syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
     }
 
 
@@ -729,6 +735,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
              case MD_MAIL_ON_ERROR:
              case MD_MAIL_ON_SUCCESS:
                 Dmsg1(850, "MAIL for following msg: %s", msg);
+                P(fides_mutex);
                 if (!d->fd) {
                    POOLMEM *name = get_pool_memory(PM_MESSAGE);
                    make_unique_mail_filename(jcr, name, d);
@@ -740,6 +747,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
                             be.bstrerror());
                       d->fd = NULL;
                       free_pool_memory(name);
+                      V(fides_mutex);
                       break;
                    }
                    d->mail_filename = name;
@@ -750,6 +758,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
                    d->max_len = len;      /* keep max line length */
                 }
                 fputs(msg, d->fd);
+                V(fides_mutex);
                 break;
              case MD_APPEND:
                 Dmsg1(850, "APPEND for following msg: %s", msg);
@@ -759,7 +768,9 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
                 Dmsg1(850, "FILE for following msg: %s", msg);
                 mode = "w+b";
 send_to_file:
+                P(fides_mutex);
                 if (!d->fd && !open_dest_file(jcr, d, mode)) {
+                   V(fides_mutex);
                    break;
                 }
                 fputs(dt, d->fd);
@@ -773,12 +784,15 @@ send_to_file:
                       fputs(msg, d->fd);
                    }
                 }
+                V(fides_mutex);
                 break;
              case MD_DIRECTOR:
                 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
                 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
-                   bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s",
+                   jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
                       jcr->Job, type, mtime, msg);
+                } else {
+                   Dmsg1(800, "no jcr for following msg: %s", msg);
                 }
                 break;
              case MD_STDOUT:
@@ -844,7 +858,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;
+    utime_t   mtime;
 
     if (level < 0) {
        details = false;
@@ -882,7 +896,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/%s.trace", working_directory ? working_directory : ".", my_name);
+             bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
              trace_fd = fopen(fn, "a+b");
           }
           if (trace_fd) {
@@ -1003,8 +1017,6 @@ t_msg(const char *file, int line, int level, const char *fmt,...)
    }
 }
 
-
-
 /* *********************************************************
  *
  * print an error message
@@ -1078,7 +1090,7 @@ e_msg(const char *file, int line, int type, int level, const char *fmt,...)
  *
  */
 void
-Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
+Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
 {
     char     rbuf[5000];
     va_list   arg_ptr;
@@ -1139,11 +1151,14 @@ Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
     case M_ERROR:
        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
        if (jcr) {
-          jcr->Errors++;
+          jcr->JobErrors++;
        }
        break;
     case M_WARNING:
        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
+       if (jcr) {
+          jcr->JobWarnings++;
+       }
        break;
     case M_SECURITY:
        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "), 
@@ -1175,7 +1190,7 @@ Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
  * If we come here, prefix the message with the file:line-number,
  *  then pass it on to the normal Jmsg routine.
  */
-void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
+void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
 {
    va_list   arg_ptr;
    int i, len, maxlen;
@@ -1309,8 +1324,6 @@ int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
 }
 
 
-static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
-
 /*
  * We queue messages rather than print them directly. This
  *  is generally used in low level routines (msg handler, bnet)
@@ -1318,7 +1331,7 @@ static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
  *  sending a message, it is a bit messy to recursively call
  *  yourself when the bnet packet is not reentrant).
  */
-void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
+void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
 {
    va_list   arg_ptr;
    int len, maxlen;
@@ -1345,16 +1358,15 @@ void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
    if (!jcr) {
       jcr = get_jcr_from_tsd();
    }
-   /* If no jcr or dequeuing send to daemon to avoid recursion */
-   if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
-      /* jcr==NULL => daemon message, safe to send now */
-      Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
+   /* If no jcr or no queue or dequeuing send to syslog */
+   if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
+      syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
       free(item);
    } else {
       /* Queue message for later sending */
-      P(msg_queue_mutex);
+      P(jcr->msg_queue_mutex);
       jcr->msg_queue->append(item);
-      V(msg_queue_mutex);
+      V(jcr->msg_queue_mutex);
    }
    free_memory(pool_buf);
 }
@@ -1365,19 +1377,18 @@ void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
 void dequeue_messages(JCR *jcr)
 {
    MQUEUE_ITEM *item;
-   P(msg_queue_mutex);
    if (!jcr->msg_queue) {
-      goto bail_out;
+      return;
    }
-   jcr->dequeuing = true;
+   P(jcr->msg_queue_mutex);
+   jcr->dequeuing_msgs = true;
    foreach_dlist(item, jcr->msg_queue) {
       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
    }
+   /* Remove messages just sent */
    jcr->msg_queue->destroy();
-   jcr->dequeuing = false;
-
-bail_out:
-   V(msg_queue_mutex);
+   jcr->dequeuing_msgs = false;
+   V(jcr->msg_queue_mutex);
 }
 
 
@@ -1385,7 +1396,7 @@ bail_out:
  * If we come here, prefix the message with the file:line-number,
  *  then pass it on to the normal Qmsg routine.
  */
-void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
+void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
 {
    va_list   arg_ptr;
    int i, len, maxlen;