]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/message.c
Backport new lock calls + debug for SD
[bacula/bacula] / bacula / src / lib / message.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Bacula message handling routines
30  *
31  * NOTE: don't use any Jmsg or Qmsg calls within this file,
32  *   except in q_msg or j_msg (setup routines), 
33  *   otherwise you may get into recursive calls if there are
34  *   errors, and that can lead to looping or deadlocks.
35  *
36  *   Kern Sibbald, April 2000
37  *
38  */
39
40 #include "bacula.h"
41 #include "jcr.h"
42
43 sql_query_func p_sql_query = NULL;
44 sql_escape_func p_sql_escape = NULL;
45
46 #define FULL_LOCATION 1               /* set for file:line in Debug messages */
47
48 /*
49  *  This is where we define "Globals" because all the
50  *    daemons include this file.
51  */
52 const char *working_directory = NULL;       /* working directory path stored here */
53 const char *assert_msg = (char *)NULL; /* ASSERT2 error message */
54 int verbose = 0;                      /* increase User messages */
55 int debug_level = 0;                  /* debug level */
56 bool dbg_timestamp = false;           /* print timestamp in debug output */
57 bool prt_kaboom = false;              /* Print kaboom output */
58 utime_t daemon_start_time = 0;        /* Daemon start time */
59 const char *version = VERSION " (" BDATE ")";
60 const char *dist_name = DISTNAME " " DISTVER;
61 int beef = BEEF;
62 char my_name[30] = {0};               /* daemon name is stored here */
63 char host_name[50] = {0};             /* host machine name */
64 char *exepath = (char *)NULL;
65 char *exename = (char *)NULL;
66 int console_msg_pending = false;
67 char con_fname[500];                  /* Console filename */
68 FILE *con_fd = NULL;                  /* Console file descriptor */
69 brwlock_t con_lock;                   /* Console lock structure */
70
71 /* Forward referenced functions */
72
73 /* Imported functions */
74 void create_jcr_key();
75
76 /* Static storage */
77
78 /* Exclude spaces but require .mail at end */
79 #define MAIL_REGEX "^[^ ]+\\.mail$"
80
81 /* Allow only one thread to tweak d->fd at a time */
82 static pthread_mutex_t fides_mutex = PTHREAD_MUTEX_INITIALIZER;
83 static MSGS *daemon_msgs;              /* global messages */
84 static char *catalog_db = NULL;       /* database type */
85 static void (*message_callback)(int type, char *msg) = NULL;
86 static FILE *trace_fd = NULL;
87 #if defined(HAVE_WIN32)
88 static bool trace = true;
89 #else
90 static bool trace = false;
91 #endif
92 static int hangup = 0;
93
94 /* Constants */
95 const char *host_os = HOST_OS;
96 const char *distname = DISTNAME;
97 const char *distver = DISTVER;
98
99 /*
100  * Walk back in a string from end looking for a
101  *  path separator.  
102  *  This routine is passed the start of the string and
103  *  the end of the string, it returns either the beginning
104  *  of the string or where it found a path separator.
105  */
106 static const char *bstrrpath(const char *start, const char *end)
107 {
108    while ( end > start ) {
109       end--;   
110       if (IsPathSeparator(*end)) {
111          break;
112       }
113    }
114    return end;
115 }
116
117 /* Some message class methods */
118 void MSGS::lock()
119 {
120    P(fides_mutex);
121 }
122
123 void MSGS::unlock()
124 {
125    V(fides_mutex);
126 }
127
128 /*
129  * Wait for not in use variable to be clear
130  */
131 void MSGS::wait_not_in_use()     /* leaves fides_mutex set */
132 {
133    lock();
134    while (m_in_use || m_closing) {
135       unlock();
136       bmicrosleep(0, 200);         /* wait */
137       lock();
138    }
139 }
140
141 /*
142  * Handle message delivery errors
143  */
144 static void delivery_error(const char *fmt,...)
145 {
146    va_list   arg_ptr;
147    int i, len, maxlen;
148    POOLMEM *pool_buf;
149    char dt[MAX_TIME_LENGTH];
150    int dtlen;
151
152    pool_buf = get_pool_memory(PM_EMSG);
153
154    bstrftime_ny(dt, sizeof(dt), time(NULL));
155    dtlen = strlen(dt);
156    dt[dtlen++] = ' ';
157    dt[dtlen] = 0;
158
159    i = Mmsg(pool_buf, "%s Message delivery ERROR: ", dt);
160
161    for (;;) {
162       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
163       va_start(arg_ptr, fmt);
164       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
165       va_end(arg_ptr);
166       if (len < 0 || len >= (maxlen-5)) {
167          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
168          continue;
169       }
170       break;
171    }
172
173    fputs(pool_buf, stdout);  /* print this here to INSURE that it is printed */
174    fflush(stdout);
175    syslog(LOG_DAEMON|LOG_ERR, "%s", pool_buf);
176    free_memory(pool_buf);
177 }                 
178
179 void register_message_callback(void msg_callback(int type, char *msg))
180 {
181    message_callback = msg_callback;
182 }
183
184
185 /*
186  * Set daemon name. Also, find canonical execution
187  *  path.  Note, exepath has spare room for tacking on
188  *  the exename so that we can reconstruct the full name.
189  *
190  * Note, this routine can get called multiple times
191  *  The second time is to put the name as found in the
192  *  Resource record. On the second call, generally,
193  *  argv is NULL to avoid doing the path code twice.
194  */
195 void my_name_is(int argc, char *argv[], const char *name)
196 {
197    char *l, *p, *q;
198    char cpath[1024];
199    int len;
200
201    if (gethostname(host_name, sizeof(host_name)) != 0) {
202       bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
203    }
204    bstrncpy(my_name, name, sizeof(my_name));
205    if (argc>0 && argv && argv[0]) {
206       /* strip trailing filename and save exepath */
207       for (l=p=argv[0]; *p; p++) {
208          if (IsPathSeparator(*p)) {
209             l = p;                       /* set pos of last slash */
210          }
211       }
212       if (IsPathSeparator(*l)) {
213          l++;
214       } else {
215          l = argv[0];
216 #if defined(HAVE_WIN32)
217          /* On Windows allow c: drive specification */
218          if (l[1] == ':') {
219             l += 2;
220          }
221 #endif
222       }
223       len = strlen(l) + 1;
224       if (exename) {
225          free(exename);
226       }
227       exename = (char *)malloc(len);
228       strcpy(exename, l);
229
230       if (exepath) {
231          free(exepath);
232       }
233       exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
234       for (p=argv[0],q=exepath; p < l; ) {
235          *q++ = *p++;
236       }
237       *q = 0;
238       if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
239          if (getcwd(cpath, sizeof(cpath))) {
240             free(exepath);
241             exepath = (char *)malloc(strlen(cpath) + 1 + len);
242             strcpy(exepath, cpath);
243          }
244       }
245       Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
246    }
247 }
248
249 void
250 set_db_type(const char *name)
251 {
252    if (catalog_db != NULL) {
253       free(catalog_db);
254    }
255    catalog_db = bstrdup(name);
256 }
257
258 /*
259  * Initialize message handler for a daemon or a Job
260  *   We make a copy of the MSGS resource passed, so it belows
261  *   to the job or daemon and thus can be modified.
262  *
263  *   NULL for jcr -> initialize global messages for daemon
264  *   non-NULL     -> initialize jcr using Message resource
265  */
266 void
267 init_msg(JCR *jcr, MSGS *msg)
268 {
269    DEST *d, *dnew, *temp_chain = NULL;
270    int i;
271
272    if (jcr == NULL && msg == NULL) {
273       init_last_jobs_list();
274       /* Create a daemon key then set invalid jcr */
275       /* Maybe we should give the daemon a jcr??? */
276       create_jcr_key();
277       set_jcr_in_tsd(INVALID_JCR);
278    }
279
280 #if !defined(HAVE_WIN32)
281    /*
282     * Make sure we have fd's 0, 1, 2 open
283     *  If we don't do this one of our sockets may open
284     *  there and if we then use stdout, it could
285     *  send total garbage to our socket.
286     *
287     */
288    int fd;
289    fd = open("/dev/null", O_RDONLY, 0644);
290    if (fd > 2) {
291       close(fd);
292    } else {
293       for(i=1; fd + i <= 2; i++) {
294          dup2(fd, fd+i);
295       }
296    }
297
298 #endif
299    /*
300     * If msg is NULL, initialize global chain for STDOUT and syslog
301     */
302    if (msg == NULL) {
303       daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
304       memset(daemon_msgs, 0, sizeof(MSGS));
305       for (i=1; i<=M_MAX; i++) {
306          add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
307       }
308       Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
309       return;
310    }
311
312    /*
313     * Walk down the message resource chain duplicating it
314     * for the current Job.
315     */
316    for (d=msg->dest_chain; d; d=d->next) {
317       dnew = (DEST *)malloc(sizeof(DEST));
318       memcpy(dnew, d, sizeof(DEST));
319       dnew->next = temp_chain;
320       dnew->fd = NULL;
321       dnew->mail_filename = NULL;
322       if (d->mail_cmd) {
323          dnew->mail_cmd = bstrdup(d->mail_cmd);
324       }
325       if (d->where) {
326          dnew->where = bstrdup(d->where);
327       }
328       temp_chain = dnew;
329    }
330
331    if (jcr) {
332       jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
333       memset(jcr->jcr_msgs, 0, sizeof(MSGS));
334       jcr->jcr_msgs->dest_chain = temp_chain;
335       memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
336    } else {
337       /* If we have default values, release them now */
338       if (daemon_msgs) {
339          free_msgs_res(daemon_msgs);
340       }
341       daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
342       memset(daemon_msgs, 0, sizeof(MSGS));
343       daemon_msgs->dest_chain = temp_chain;
344       memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
345    }
346
347    Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
348
349 }
350
351 /* Initialize so that the console (User Agent) can
352  * receive messages -- stored in a file.
353  */
354 void init_console_msg(const char *wd)
355 {
356    int fd;
357
358    bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
359    fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
360    if (fd == -1) {
361       berrno be;
362       Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
363           con_fname, be.bstrerror());
364    }
365    if (lseek(fd, 0, SEEK_END) > 0) {
366       console_msg_pending = 1;
367    }
368    close(fd);
369    con_fd = fopen(con_fname, "a+b");
370    if (!con_fd) {
371       berrno be;
372       Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
373           con_fname, be.bstrerror());
374    }
375    if (rwl_init(&con_lock) != 0) {
376       berrno be;
377       Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
378          be.bstrerror());
379    }
380 }
381
382 /*
383  * Called only during parsing of the config file.
384  *
385  * Add a message destination. I.e. associate a message type with
386  *  a destination (code).
387  * Note, where in the case of dest_code FILE is a filename,
388  *  but in the case of MAIL is a space separated list of
389  *  email addresses, ...
390  */
391 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
392 {
393    DEST *d;
394    /*
395     * First search the existing chain and see if we
396     * can simply add this msg_type to an existing entry.
397     */
398    for (d=msg->dest_chain; d; d=d->next) {
399       if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
400                      (strcmp(where, d->where) == 0))) {
401          Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
402              d, msg_type, dest_code, NPRT(where));
403          set_bit(msg_type, d->msg_types);
404          set_bit(msg_type, msg->send_msg);  /* set msg_type bit in our local */
405          return;
406       }
407    }
408    /* Not found, create a new entry */
409    d = (DEST *)malloc(sizeof(DEST));
410    memset(d, 0, sizeof(DEST));
411    d->next = msg->dest_chain;
412    d->dest_code = dest_code;
413    set_bit(msg_type, d->msg_types);      /* set type bit in structure */
414    set_bit(msg_type, msg->send_msg);     /* set type bit in our local */
415    if (where) {
416       d->where = bstrdup(where);
417    }
418    if (mail_cmd) {
419       d->mail_cmd = bstrdup(mail_cmd);
420    }
421    Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
422           d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
423    msg->dest_chain = d;
424 }
425
426 /*
427  * Called only during parsing of the config file.
428  *
429  * Remove a message destination
430  */
431 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
432 {
433    DEST *d;
434
435    for (d=msg->dest_chain; d; d=d->next) {
436       Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
437       if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
438           ((where == NULL && d->where == NULL) ||
439                      (strcmp(where, d->where) == 0))) {
440          Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
441                d, msg_type, dest_code);
442          clear_bit(msg_type, d->msg_types);
443          Dmsg0(850, "Return rem_msg_dest\n");
444          return;
445       }
446    }
447 }
448
449
450 /*
451  * Create a unique filename for the mail command
452  */
453 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
454 {
455    if (jcr) {
456       Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
457                  jcr->Job, (int)(intptr_t)d);
458    } else {
459       Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
460                  my_name, (int)(intptr_t)d);
461    }
462    Dmsg1(850, "mailname=%s\n", name);
463 }
464
465 /*
466  * Open a mail pipe
467  */
468 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
469 {
470    BPIPE *bpipe;
471
472    if (d->mail_cmd) {
473       cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
474    } else {
475       Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
476    }
477    fflush(stdout);
478
479    if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
480       /* If we had to use sendmail, add subject */
481       if (!d->mail_cmd) {
482          fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
483       }
484    } else {
485       berrno be;
486       delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
487          cmd, be.bstrerror());
488    }
489    return bpipe;
490 }
491
492 /*
493  * Close the messages for this Messages resource, which means to close
494  *  any open files, and dispatch any pending email messages.
495  */
496 void close_msg(JCR *jcr)
497 {
498    MSGS *msgs;
499    DEST *d;
500    BPIPE *bpipe;
501    POOLMEM *cmd, *line;
502    int len, stat;
503
504    Dmsg1(580, "Close_msg jcr=%p\n", jcr);
505
506    if (jcr == NULL) {                /* NULL -> global chain */
507       msgs = daemon_msgs;
508    } else {
509       msgs = jcr->jcr_msgs;
510       jcr->jcr_msgs = NULL;
511    }
512    if (msgs == NULL) {
513       return;
514    }
515
516    /* Wait for item to be not in use, then mark closing */
517    if (msgs->is_closing()) {
518       return;
519    }
520    msgs->wait_not_in_use();          /* leaves fides_mutex set */
521    /* Note get_closing() does not lock because we are already locked */
522    if (msgs->get_closing()) {
523       msgs->unlock();
524       return;
525    }
526    msgs->set_closing();
527    msgs->unlock();
528
529    Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
530    cmd = get_pool_memory(PM_MESSAGE);
531    for (d=msgs->dest_chain; d; ) {
532       if (d->fd) {
533          switch (d->dest_code) {
534          case MD_FILE:
535          case MD_APPEND:
536             if (d->fd) {
537                fclose(d->fd);            /* close open file descriptor */
538                d->fd = NULL;
539             }
540             break;
541          case MD_MAIL:
542          case MD_MAIL_ON_ERROR:
543          case MD_MAIL_ON_SUCCESS:
544             Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
545             if (!d->fd) {
546                break;
547             }
548
549             switch (d->dest_code) {
550             case MD_MAIL_ON_ERROR:
551                if (jcr) {
552                   switch (jcr->JobStatus) {
553                   case JS_Terminated:
554                   case JS_Warnings:
555                      goto rem_temp_file;
556                   default:
557                      break;
558                   }
559                }
560                break;
561             case MD_MAIL_ON_SUCCESS:
562                if (jcr) {
563                   switch (jcr->JobStatus) {
564                   case JS_Terminated:
565                   case JS_Warnings:
566                      break;
567                   default:
568                      goto rem_temp_file;
569                   }
570                }
571                break;
572             default:
573                break;
574             }
575
576             if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
577                Pmsg0(000, _("open mail pipe failed.\n"));
578                goto rem_temp_file;
579             }
580
581             Dmsg0(850, "Opened mail pipe\n");
582             len = d->max_len+10;
583             line = get_memory(len);
584             rewind(d->fd);
585             while (fgets(line, len, d->fd)) {
586                fputs(line, bpipe->wfd);
587             }
588             if (!close_wpipe(bpipe)) {       /* close write pipe sending mail */
589                berrno be;
590                Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
591             }
592
593             /*
594              * Since we are closing all messages, before "recursing"
595              * make sure we are not closing the daemon messages, otherwise
596              * kaboom.
597              */
598             if (msgs != daemon_msgs) {
599                /* read what mail prog returned -- should be nothing */
600                while (fgets(line, len, bpipe->rfd)) {
601                   delivery_error(_("Mail prog: %s"), line);
602                }
603             }
604
605             stat = close_bpipe(bpipe);
606             if (stat != 0 && msgs != daemon_msgs) {
607                berrno be;
608                be.set_errno(stat);
609                Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
610                delivery_error(_("Mail program terminated in error.\n"
611                                  "CMD=%s\n"
612                                  "ERR=%s\n"), cmd, be.bstrerror());
613             }
614             free_memory(line);
615 rem_temp_file:
616             /* Remove temp file */
617             if (d->fd) {
618                fclose(d->fd);
619                d->fd = NULL;
620             }
621             if (d->mail_filename) {
622                /* Exclude spaces in mail_filename */
623                safer_unlink(d->mail_filename, MAIL_REGEX);
624                free_pool_memory(d->mail_filename);
625                d->mail_filename = NULL;
626             }
627             Dmsg0(850, "end mail or mail on error\n");
628             break;
629          default:
630             break;
631          }
632          d->fd = NULL;
633       }
634       d = d->next;                    /* point to next buffer */
635    }
636    free_pool_memory(cmd);
637    Dmsg0(850, "Done walking message chain.\n");
638    if (jcr) {
639       free_msgs_res(msgs);
640       msgs = NULL;
641    } else {
642       msgs->clear_closing();
643    }
644    Dmsg0(850, "===End close msg resource\n");
645 }
646
647 /*
648  * Free memory associated with Messages resource
649  */
650 void free_msgs_res(MSGS *msgs)
651 {
652    DEST *d, *old;
653
654    /* Walk down the message chain releasing allocated buffers */
655    for (d=msgs->dest_chain; d; ) {
656       if (d->where) {
657          free(d->where);
658       }
659       if (d->mail_cmd) {
660          free(d->mail_cmd);
661       }
662       old = d;                        /* save pointer to release */
663       d = d->next;                    /* point to next buffer */
664       free(old);                      /* free the destination item */
665    }
666    msgs->dest_chain = NULL;
667    free(msgs);                        /* free the head */
668 }
669
670
671 /*
672  * Terminate the message handler for good.
673  * Release the global destination chain.
674  *
675  * Also, clean up a few other items (cons, exepath). Note,
676  *   these really should be done elsewhere.
677  */
678 void term_msg()
679 {
680    Dmsg0(850, "Enter term_msg\n");
681    close_msg(NULL);                   /* close global chain */
682    free_msgs_res(daemon_msgs);        /* free the resources */
683    daemon_msgs = NULL;
684    if (con_fd) {
685       fflush(con_fd);
686       fclose(con_fd);
687       con_fd = NULL;
688    }
689    if (exepath) {
690       free(exepath);
691       exepath = NULL;
692    }
693    if (exename) {
694       free(exename);
695       exename = NULL;
696    }
697    if (trace_fd) {
698       fclose(trace_fd);
699       trace_fd = NULL;
700    }
701    if (catalog_db) {
702       free(catalog_db);
703       catalog_db = NULL;
704    }
705    term_last_jobs_list();
706 }
707
708 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode) 
709 {
710    d->fd = fopen(d->where, mode);
711    if (!d->fd) {
712       berrno be;
713       delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
714       return false;
715    }
716    return true;
717 }
718
719 /* Split the output for syslog (it converts \n to ' ' and is
720  *   limited to 1024 characters per syslog message
721  */
722 static void send_to_syslog(int mode, const char *msg)
723 {
724    int len;
725    char buf[1024];
726    const char *p2;
727    const char *p = msg;
728
729    while (*p && ((p2 = strchr(p, '\n')) != NULL)) {
730       len = MIN((int)sizeof(buf) - 1, p2 - p + 1); /* Add 1 to keep \n */
731       strncpy(buf, p, len);
732       buf[len] = 0;
733       syslog(mode, "%s", buf);
734       p = p2+1;                 /* skip \n */
735    }
736    if (*p != 0) {               /* no \n at the end ? */
737       syslog(mode, "%s", p);
738    }
739 }
740
741 /*
742  * Handle sending the message to the appropriate place
743  */
744 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
745 {
746     DEST *d;
747     char dt[MAX_TIME_LENGTH];
748     POOLMEM *mcmd;
749     int len, dtlen;
750     MSGS *msgs;
751     BPIPE *bpipe;
752     const char *mode;
753
754     Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
755
756     /*
757      * Most messages are prefixed by a date and time. If mtime is
758      *  zero, then we use the current time.  If mtime is 1 (special
759      *  kludge), we do not prefix the date and time. Otherwise,
760      *  we assume mtime is a utime_t and use it.
761      */
762     if (mtime == 0) {
763        mtime = time(NULL);
764     }
765     if (mtime == 1) {
766        *dt = 0;
767        dtlen = 0;
768        mtime = time(NULL);      /* get time for SQL log */
769     } else {
770        bstrftime_ny(dt, sizeof(dt), mtime);
771        dtlen = strlen(dt);
772        dt[dtlen++] = ' ';
773        dt[dtlen] = 0;
774     }
775
776     /* If the program registered a callback, send it there */
777     if (message_callback) {
778        message_callback(type, msg);
779        return;
780     }
781
782     /* For serious errors make sure message is printed or logged */
783     if (type == M_ABORT || type == M_ERROR_TERM) {
784        fputs(dt, stdout);
785        fputs(msg, stdout);
786        fflush(stdout);
787        if (type == M_ABORT) {
788           syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
789        }
790     }
791
792
793     /* Now figure out where to send the message */
794     msgs = NULL;
795     if (!jcr) {
796        jcr = get_jcr_from_tsd();
797     }
798     if (jcr) {
799        msgs = jcr->jcr_msgs;
800     }
801     if (msgs == NULL) {
802        msgs = daemon_msgs;
803     }
804     /*
805      * If closing this message resource, print and send to syslog,
806      *   then get out.
807      */
808     if (msgs->is_closing()) {
809        fputs(dt, stdout);
810        fputs(msg, stdout);
811        fflush(stdout);
812        syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
813        return;
814     }
815
816     for (d=msgs->dest_chain; d; d=d->next) {
817        if (bit_is_set(type, d->msg_types)) {
818           switch (d->dest_code) {
819              case MD_CATALOG:
820                 char ed1[50];
821                 if (!jcr || !jcr->db) {
822                    break;
823                 }
824                 if (p_sql_query && p_sql_escape) {
825                    POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
826                    POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
827                    
828                    int len = strlen(msg) + 1;
829                    esc_msg = check_pool_memory_size(esc_msg, len * 2 + 1);
830                    if (p_sql_escape(jcr, jcr->db, esc_msg, msg, len)) {
831                       bstrutime(dt, sizeof(dt), mtime);
832                       Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
833                             edit_int64(jcr->JobId, ed1), dt, esc_msg);
834                       if (!p_sql_query(jcr, cmd)) {
835                          delivery_error(_("Msg delivery error: Unable to store data in database.\n"));
836                       }
837                    } else {
838                       delivery_error(_("Msg delivery error: Unable to store data in database.\n"));
839                    }
840                    
841                    free_pool_memory(cmd);
842                    free_pool_memory(esc_msg);
843                 }
844                 break;
845              case MD_CONSOLE:
846                 Dmsg1(850, "CONSOLE for following msg: %s", msg);
847                 if (!con_fd) {
848                    con_fd = fopen(con_fname, "a+b");
849                    Dmsg0(850, "Console file not open.\n");
850                 }
851                 if (con_fd) {
852                    Pw(con_lock);      /* get write lock on console message file */
853                    errno = 0;
854                    if (dtlen) {
855                       (void)fwrite(dt, dtlen, 1, con_fd);
856                    }
857                    len = strlen(msg);
858                    if (len > 0) {
859                       (void)fwrite(msg, len, 1, con_fd);
860                       if (msg[len-1] != '\n') {
861                          (void)fwrite("\n", 2, 1, con_fd);
862                       }
863                    } else {
864                       (void)fwrite("\n", 2, 1, con_fd);
865                    }
866                    fflush(con_fd);
867                    console_msg_pending = true;
868                    Vw(con_lock);
869                 }
870                 break;
871              case MD_SYSLOG:
872                 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
873                 /*
874                  * We really should do an openlog() here.
875                  */
876                 send_to_syslog(LOG_DAEMON|LOG_ERR, msg);
877                 break;
878              case MD_OPERATOR:
879                 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
880                 mcmd = get_pool_memory(PM_MESSAGE);
881                 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
882                    int stat;
883                    fputs(dt, bpipe->wfd);
884                    fputs(msg, bpipe->wfd);
885                    /* Messages to the operator go one at a time */
886                    stat = close_bpipe(bpipe);
887                    if (stat != 0) {
888                       berrno be;
889                       be.set_errno(stat);
890                       delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
891                             "CMD=%s\n"
892                             "ERR=%s\n"), mcmd, be.bstrerror());
893                    }
894                 }
895                 free_pool_memory(mcmd);
896                 break;
897              case MD_MAIL:
898              case MD_MAIL_ON_ERROR:
899              case MD_MAIL_ON_SUCCESS:
900                 Dmsg1(850, "MAIL for following msg: %s", msg);
901                 if (msgs->is_closing()) {
902                    break;
903                 }
904                 msgs->set_in_use();
905                 if (!d->fd) {
906                    POOLMEM *name = get_pool_memory(PM_MESSAGE);
907                    make_unique_mail_filename(jcr, name, d);
908                    d->fd = fopen(name, "w+b");
909                    if (!d->fd) {
910                       berrno be;
911                       delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
912                             be.bstrerror());
913                       free_pool_memory(name);
914                       msgs->clear_in_use();
915                       break;
916                    }
917                    d->mail_filename = name;
918                 }
919                 fputs(dt, d->fd);
920                 len = strlen(msg) + dtlen;;
921                 if (len > d->max_len) {
922                    d->max_len = len;      /* keep max line length */
923                 }
924                 fputs(msg, d->fd);
925                 msgs->clear_in_use();
926                 break;
927              case MD_APPEND:
928                 Dmsg1(850, "APPEND for following msg: %s", msg);
929                 mode = "ab";
930                 goto send_to_file;
931              case MD_FILE:
932                 Dmsg1(850, "FILE for following msg: %s", msg);
933                 mode = "w+b";
934 send_to_file:
935                 if (msgs->is_closing()) {
936                    break;
937                 }
938                 msgs->set_in_use();
939                 if (!d->fd && !open_dest_file(jcr, d, mode)) {
940                    msgs->clear_in_use();
941                    break;
942                 }
943                 fputs(dt, d->fd);
944                 fputs(msg, d->fd);
945                 /* On error, we close and reopen to handle log rotation */
946                 if (ferror(d->fd)) {
947                    fclose(d->fd);
948                    d->fd = NULL;
949                    if (open_dest_file(jcr, d, mode)) {
950                       fputs(dt, d->fd);
951                       fputs(msg, d->fd);
952                    }
953                 }
954                 msgs->clear_in_use();
955                 break;
956              case MD_DIRECTOR:
957                 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
958                 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
959                    jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
960                       jcr->Job, type, mtime, msg);
961                 } else {
962                    Dmsg1(800, "no jcr for following msg: %s", msg);
963                 }
964                 break;
965              case MD_STDOUT:
966                 Dmsg1(850, "STDOUT for following msg: %s", msg);
967                 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
968                    fputs(dt, stdout);
969                    fputs(msg, stdout);
970                    fflush(stdout);
971                 }
972                 break;
973              case MD_STDERR:
974                 Dmsg1(850, "STDERR for following msg: %s", msg);
975                 fputs(dt, stderr);
976                 fputs(msg, stderr);
977                 fflush(stdout);
978                 break;
979              default:
980                 break;
981           }
982        }
983     }
984 }
985
986 /*********************************************************************
987  *
988  *  This subroutine returns the filename portion of a path.  
989  *  It is used because some compilers set __FILE__ 
990  *  to the full path.  Try to return base + next higher path.
991  */
992
993 const char *get_basename(const char *pathname)
994 {
995    const char *basename;
996    
997    if ((basename = bstrrpath(pathname, pathname+strlen(pathname))) == pathname) {
998       /* empty */
999    } else if ((basename = bstrrpath(pathname, basename-1)) == pathname) {
1000       /* empty */
1001    } else {
1002       basename++;
1003    }
1004    return basename;
1005 }
1006
1007 /*
1008  * print or write output to trace file 
1009  */
1010 static void pt_out(char *buf)
1011 {
1012     /*
1013      * Used the "trace on" command in the console to turn on
1014      *  output to the trace file.  "trace off" will close the file.
1015      */
1016     if (trace) {
1017        if (!trace_fd) {
1018           char fn[200];
1019           bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
1020           trace_fd = fopen(fn, "a+b");
1021        }
1022        if (trace_fd) {
1023           fputs(buf, trace_fd);
1024           fflush(trace_fd);
1025           return;
1026        } else {
1027           /* Some problem, turn off tracing */
1028           trace = false;
1029        }
1030     }
1031     /* not tracing */
1032     fputs(buf, stdout);
1033     fflush(stdout);
1034 }
1035
1036 /*********************************************************************
1037  *
1038  *  This subroutine prints a debug message if the level number
1039  *  is less than or equal the debug_level. File and line numbers
1040  *  are included for more detail if desired, but not currently
1041  *  printed.
1042  *
1043  *  If the level is negative, the details of file and line number
1044  *  are not printed.
1045  */
1046 void
1047 d_msg(const char *file, int line, int level, const char *fmt,...)
1048 {
1049     char      buf[5000];
1050     int       len;
1051     va_list   arg_ptr;
1052     bool      details = true;
1053     utime_t   mtime;
1054
1055     if (level < 0) {
1056        details = false;
1057        level = -level;
1058     }
1059
1060     if (level <= debug_level) {
1061        if (dbg_timestamp) {
1062           mtime = time(NULL);
1063           bstrftimes(buf, sizeof(buf), mtime);
1064           len = strlen(buf);
1065           buf[len++] = ' ';
1066           buf[len] = 0;
1067           pt_out(buf);
1068        }
1069     
1070 #ifdef FULL_LOCATION
1071        if (details) {
1072           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ", 
1073                 my_name, get_basename(file), line, get_jobid_from_tsd());
1074        } else {
1075           len = 0;
1076        }
1077 #else
1078        len = 0;
1079 #endif
1080        va_start(arg_ptr, fmt);
1081        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1082        va_end(arg_ptr);
1083
1084        pt_out(buf);
1085     }
1086 }
1087
1088 /*
1089  * Set trace flag on/off. If argument is negative, there is no change
1090  */
1091 void set_trace(int trace_flag)
1092 {
1093    if (trace_flag < 0) {
1094       return;
1095    } else if (trace_flag > 0) {
1096       trace = true;
1097    } else {
1098       trace = false;
1099    }
1100    if (!trace && trace_fd) {
1101       FILE *ltrace_fd = trace_fd;
1102       trace_fd = NULL;
1103       bmicrosleep(0, 100000);         /* yield to prevent seg faults */
1104       fclose(ltrace_fd);
1105    }
1106 }
1107
1108 void set_hangup(int hangup_value)
1109 {
1110    if (hangup_value < 0) {
1111       return;
1112    } else {
1113       hangup = hangup_value;
1114    }
1115 }
1116
1117 int get_hangup(void)
1118 {
1119    return hangup;
1120 }
1121
1122 bool get_trace(void)
1123 {
1124    return trace;
1125 }
1126
1127 /*********************************************************************
1128  *
1129  *  This subroutine prints a message regardless of the debug level
1130  *
1131  *  If the level is negative, the details of file and line number
1132  *  are not printed.
1133  */
1134 void
1135 p_msg(const char *file, int line, int level, const char *fmt,...)
1136 {
1137     char      buf[5000];
1138     int       len;
1139     va_list   arg_ptr;
1140
1141 #ifdef FULL_LOCATION
1142     if (level >= 0) {
1143        len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ", 
1144              my_name, get_basename(file), line, get_jobid_from_tsd());
1145     } else {
1146        len = 0;
1147     }
1148 #else
1149        len = 0;
1150 #endif
1151
1152     va_start(arg_ptr, fmt);
1153     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1154     va_end(arg_ptr);
1155
1156     pt_out(buf);     
1157 }
1158
1159
1160 /*********************************************************************
1161  *
1162  *  subroutine writes a debug message to the trace file if the level number
1163  *  is less than or equal the debug_level. File and line numbers
1164  *  are included for more detail if desired, but not currently
1165  *  printed.
1166  *
1167  *  If the level is negative, the details of file and line number
1168  *  are not printed.
1169  */
1170 void
1171 t_msg(const char *file, int line, int level, const char *fmt,...)
1172 {
1173     char      buf[5000];
1174     int       len;
1175     va_list   arg_ptr;
1176     int       details = TRUE;
1177
1178     if (level < 0) {
1179        details = FALSE;
1180        level = -level;
1181     }
1182
1183     if (level <= debug_level) {
1184        if (!trace_fd) {
1185           bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1186           trace_fd = fopen(buf, "a+b");
1187        }
1188
1189 #ifdef FULL_LOCATION
1190        if (details) {
1191           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1192        } else {
1193           len = 0;
1194        }
1195 #else
1196        len = 0;
1197 #endif
1198        va_start(arg_ptr, fmt);
1199        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1200        va_end(arg_ptr);
1201        if (trace_fd != NULL) {
1202            fputs(buf, trace_fd);
1203            fflush(trace_fd);
1204        }
1205    }
1206 }
1207
1208 /* *********************************************************
1209  *
1210  * print an error message
1211  *
1212  */
1213 void
1214 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1215 {
1216     char     buf[5000];
1217     va_list   arg_ptr;
1218     int len;
1219
1220     /*
1221      * Check if we have a message destination defined.
1222      * We always report M_ABORT and M_ERROR_TERM
1223      */
1224     if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1225                          !bit_is_set(type, daemon_msgs->send_msg))) {
1226        return;                        /* no destination */
1227     }
1228     switch (type) {
1229     case M_ABORT:
1230        len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1231                my_name, get_basename(file), line);
1232        break;
1233     case M_ERROR_TERM:
1234        len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1235                my_name, get_basename(file), line);
1236        break;
1237     case M_FATAL:
1238        if (level == -1)            /* skip details */
1239           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1240        else
1241           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1242        break;
1243     case M_ERROR:
1244        if (level == -1)            /* skip details */
1245           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1246        else
1247           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1248        break;
1249     case M_WARNING:
1250        len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1251        break;
1252     case M_SECURITY:
1253        len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1254        break;
1255     default:
1256        len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1257        break;
1258     }
1259
1260     va_start(arg_ptr, fmt);
1261     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1262     va_end(arg_ptr);
1263
1264     dispatch_message(NULL, type, 0, buf);
1265
1266     if (type == M_ABORT) {
1267        char *p = 0;
1268        p[0] = 0;                      /* generate segmentation violation */
1269     }
1270     if (type == M_ERROR_TERM) {
1271        exit(1);
1272     }
1273 }
1274
1275 /* *********************************************************
1276  *
1277  * Generate a Job message
1278  *
1279  */
1280 void
1281 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1282 {
1283     char     rbuf[5000];
1284     va_list   arg_ptr;
1285     int len;
1286     MSGS *msgs;
1287     uint32_t JobId = 0;
1288
1289
1290     Dmsg1(850, "Enter Jmsg type=%d\n", type);
1291
1292     /* Special case for the console, which has a dir_bsock and JobId==0,
1293      *  in that case, we send the message directly back to the
1294      *  dir_bsock.
1295      */
1296     if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1297        BSOCK *dir = jcr->dir_bsock;
1298        va_start(arg_ptr, fmt);
1299        dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1300                                 fmt, arg_ptr);
1301        va_end(arg_ptr);
1302        jcr->dir_bsock->send();
1303        return;
1304     }
1305
1306     /* The watchdog thread can't use Jmsg directly, we always queued it */
1307     if (is_watchdog()) {
1308        va_start(arg_ptr, fmt);
1309        bvsnprintf(rbuf,  sizeof(rbuf), fmt, arg_ptr);
1310        va_end(arg_ptr);
1311        Qmsg(jcr, type, mtime, "%s", rbuf);
1312        return;
1313     }
1314
1315     msgs = NULL;
1316     if (!jcr) {
1317        jcr = get_jcr_from_tsd();
1318     }
1319     if (jcr) {
1320        if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1321           /* Dequeue messages to keep the original order  */
1322           dequeue_messages(jcr); 
1323        }
1324        msgs = jcr->jcr_msgs;
1325        JobId = jcr->JobId;
1326     }
1327     if (!msgs) {
1328        msgs = daemon_msgs;            /* if no jcr, we use daemon handler */
1329     }
1330
1331     /*
1332      * Check if we have a message destination defined.
1333      * We always report M_ABORT and M_ERROR_TERM
1334      */
1335     if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1336          !bit_is_set(type, msgs->send_msg)) {
1337        return;                        /* no destination */
1338     }
1339     switch (type) {
1340     case M_ABORT:
1341        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1342        break;
1343     case M_ERROR_TERM:
1344        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1345        break;
1346     case M_FATAL:
1347        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1348        if (jcr) {
1349           jcr->setJobStatus(JS_FatalError);
1350        }
1351        if (jcr && jcr->JobErrors == 0) {
1352           jcr->JobErrors = 1;
1353        }
1354        break;
1355     case M_ERROR:
1356        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1357        if (jcr) {
1358           jcr->JobErrors++;
1359        }
1360        break;
1361     case M_WARNING:
1362        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1363        if (jcr) {
1364           jcr->JobWarnings++;
1365        }
1366        break;
1367     case M_SECURITY:
1368        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "), 
1369                my_name, JobId);
1370        break;
1371     default:
1372        len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1373        break;
1374     }
1375
1376     va_start(arg_ptr, fmt);
1377     bvsnprintf(rbuf+len,  sizeof(rbuf)-len, fmt, arg_ptr);
1378     va_end(arg_ptr);
1379
1380     dispatch_message(jcr, type, mtime, rbuf);
1381
1382     if (type == M_ABORT){
1383        char *p = 0;
1384        printf("Bacula forced SEG FAULT to obtain traceback.\n");
1385        syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1386        p[0] = 0;                      /* generate segmentation violation */
1387     }
1388     if (type == M_ERROR_TERM) {
1389        exit(1);
1390     }
1391 }
1392
1393 /*
1394  * If we come here, prefix the message with the file:line-number,
1395  *  then pass it on to the normal Jmsg routine.
1396  */
1397 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1398 {
1399    va_list   arg_ptr;
1400    int i, len, maxlen;
1401    POOLMEM *pool_buf;
1402
1403    pool_buf = get_pool_memory(PM_EMSG);
1404    i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1405
1406    for (;;) {
1407       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1408       va_start(arg_ptr, fmt);
1409       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1410       va_end(arg_ptr);
1411       if (len < 0 || len >= (maxlen-5)) {
1412          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1413          continue;
1414       }
1415       break;
1416    }
1417
1418    Jmsg(jcr, type, mtime, "%s", pool_buf);
1419    free_memory(pool_buf);
1420 }
1421
1422
1423 /*
1424  * Edit a message into a Pool memory buffer, with file:lineno
1425  */
1426 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1427 {
1428    va_list   arg_ptr;
1429    int i, len, maxlen;
1430
1431    i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1432
1433    for (;;) {
1434       maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1435       va_start(arg_ptr, fmt);
1436       len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1437       va_end(arg_ptr);
1438       if (len < 0 || len >= (maxlen-5)) {
1439          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1440          continue;
1441       }
1442       break;
1443    }
1444    return len;
1445 }
1446
1447 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1448 {
1449    va_list   arg_ptr;
1450    int i, len, maxlen;
1451
1452    i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1453
1454    for (;;) {
1455       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1456       va_start(arg_ptr, fmt);
1457       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1458       va_end(arg_ptr);
1459       if (len < 0 || len >= (maxlen-5)) {
1460          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1461          continue;
1462       }
1463       break;
1464    }
1465    return len;
1466 }
1467
1468
1469 /*
1470  * Edit a message into a Pool Memory buffer NO file:lineno
1471  *  Returns: string length of what was edited.
1472  */
1473 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1474 {
1475    va_list   arg_ptr;
1476    int len, maxlen;
1477
1478    for (;;) {
1479       maxlen = sizeof_pool_memory(*pool_buf) - 1;
1480       va_start(arg_ptr, fmt);
1481       len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1482       va_end(arg_ptr);
1483       if (len < 0 || len >= (maxlen-5)) {
1484          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1485          continue;
1486       }
1487       break;
1488    }
1489    return len;
1490 }
1491
1492 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1493 {
1494    va_list   arg_ptr;
1495    int len, maxlen;
1496
1497    for (;;) {
1498       maxlen = sizeof_pool_memory(pool_buf) - 1;
1499       va_start(arg_ptr, fmt);
1500       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1501       va_end(arg_ptr);
1502       if (len < 0 || len >= (maxlen-5)) {
1503          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1504          continue;
1505       }
1506       break;
1507    }
1508    return len;
1509 }
1510
1511 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1512 {
1513    va_list   arg_ptr;
1514    int len, maxlen;
1515
1516    for (;;) {
1517       maxlen = pool_buf.max_size() - 1;
1518       va_start(arg_ptr, fmt);
1519       len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1520       va_end(arg_ptr);
1521       if (len < 0 || len >= (maxlen-5)) {
1522          pool_buf.realloc_pm(maxlen + maxlen/2);
1523          continue;
1524       }
1525       break;
1526    }
1527    return len;
1528 }
1529
1530
1531 /*
1532  * We queue messages rather than print them directly. This
1533  *  is generally used in low level routines (msg handler, bnet)
1534  *  to prevent recursion (i.e. if you are in the middle of
1535  *  sending a message, it is a bit messy to recursively call
1536  *  yourself when the bnet packet is not reentrant).
1537  */
1538 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1539 {
1540    va_list   arg_ptr;
1541    int len, maxlen;
1542    POOLMEM *pool_buf;
1543    MQUEUE_ITEM *item;
1544
1545    pool_buf = get_pool_memory(PM_EMSG);
1546
1547    for (;;) {
1548       maxlen = sizeof_pool_memory(pool_buf) - 1;
1549       va_start(arg_ptr, fmt);
1550       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1551       va_end(arg_ptr);
1552       if (len < 0 || len >= (maxlen-5)) {
1553          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1554          continue;
1555       }
1556       break;
1557    }
1558    item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1559    item->type = type;
1560    item->mtime = time(NULL);
1561    strcpy(item->msg, pool_buf);
1562    if (!jcr) {
1563       jcr = get_jcr_from_tsd();
1564    }
1565    /* If no jcr or no queue or dequeuing send to syslog */
1566    if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1567       syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1568       free(item);
1569    } else {
1570       /* Queue message for later sending */
1571       P(jcr->msg_queue_mutex);
1572       jcr->msg_queue->append(item);
1573       V(jcr->msg_queue_mutex);
1574    }
1575    free_memory(pool_buf);
1576 }
1577
1578 /*
1579  * Dequeue messages
1580  */
1581 void dequeue_messages(JCR *jcr)
1582 {
1583    MQUEUE_ITEM *item;
1584    if (!jcr->msg_queue) {
1585       return;
1586    }
1587    P(jcr->msg_queue_mutex);
1588    jcr->dequeuing_msgs = true;
1589    foreach_dlist(item, jcr->msg_queue) {
1590       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1591    }
1592    /* Remove messages just sent */
1593    jcr->msg_queue->destroy();
1594    jcr->dequeuing_msgs = false;
1595    V(jcr->msg_queue_mutex);
1596 }
1597
1598
1599 /*
1600  * If we come here, prefix the message with the file:line-number,
1601  *  then pass it on to the normal Qmsg routine.
1602  */
1603 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1604 {
1605    va_list   arg_ptr;
1606    int i, len, maxlen;
1607    POOLMEM *pool_buf;
1608
1609    pool_buf = get_pool_memory(PM_EMSG);
1610    i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1611
1612    for (;;) {
1613       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1614       va_start(arg_ptr, fmt);
1615       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1616       va_end(arg_ptr);
1617       if (len < 0 || len >= (maxlen-5)) {
1618          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1619          continue;
1620       }
1621       break;
1622    }
1623
1624    Qmsg(jcr, type, mtime, "%s", pool_buf);
1625    free_memory(pool_buf);
1626 }