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