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