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