]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/message.c
ebl update new "bactrace" option to dump information into
[bacula/bacula] / bacula / src / lib / message.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2008 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 time_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 /* Used to allow only one thread close the daemon messages at a time */
73 static pthread_mutex_t 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)(long)d);
374    } else {
375       Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
376                  my_name, (int)(long)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       P(mutex);                       /* only one thread walking the chain */
425    } else {
426       msgs = jcr->jcr_msgs;
427       jcr->jcr_msgs = NULL;
428    }
429    if (msgs == NULL) {
430       return;
431    }
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) 
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    free_pool_memory(cmd);
516    Dmsg0(850, "Done walking message chain.\n");
517    if (jcr) {
518       free_msgs_res(msgs);
519       msgs = NULL;
520    } else {
521       V(mutex);
522    }
523    Dmsg0(850, "===End close msg resource\n");
524 }
525
526 /*
527  * Free memory associated with Messages resource
528  */
529 void free_msgs_res(MSGS *msgs)
530 {
531    DEST *d, *old;
532
533    /* Walk down the message chain releasing allocated buffers */
534    for (d=msgs->dest_chain; d; ) {
535       if (d->where) {
536          free(d->where);
537       }
538       if (d->mail_cmd) {
539          free(d->mail_cmd);
540       }
541       old = d;                        /* save pointer to release */
542       d = d->next;                    /* point to next buffer */
543       free(old);                      /* free the destination item */
544    }
545    msgs->dest_chain = NULL;
546    free(msgs);                        /* free the head */
547 }
548
549
550 /*
551  * Terminate the message handler for good.
552  * Release the global destination chain.
553  *
554  * Also, clean up a few other items (cons, exepath). Note,
555  *   these really should be done elsewhere.
556  */
557 void term_msg()
558 {
559    Dmsg0(850, "Enter term_msg\n");
560    close_msg(NULL);                   /* close global chain */
561    free_msgs_res(daemon_msgs);        /* free the resources */
562    daemon_msgs = NULL;
563    if (con_fd) {
564       fflush(con_fd);
565       fclose(con_fd);
566       con_fd = NULL;
567    }
568    if (exepath) {
569       free(exepath);
570       exepath = NULL;
571    }
572    if (exename) {
573       free(exename);
574       exename = NULL;
575    }
576    if (trace_fd) {
577       fclose(trace_fd);
578       trace_fd = NULL;
579    }
580    if (catalog_db) {
581       free(catalog_db);
582       catalog_db = NULL;
583    }
584    term_last_jobs_list();
585 }
586
587 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode) 
588 {
589    d->fd = fopen(d->where, mode);
590    if (!d->fd) {
591       berrno be;
592       d->fd = stdout;
593       Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
594       d->fd = NULL;
595       return false;
596    }
597    return true;
598 }
599
600 /*
601  * Handle sending the message to the appropriate place
602  */
603 void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
604 {
605     DEST *d;
606     char dt[MAX_TIME_LENGTH];
607     POOLMEM *mcmd;
608     int len, dtlen;
609     MSGS *msgs;
610     BPIPE *bpipe;
611     const char *mode;
612
613     Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
614
615     /*
616      * Most messages are prefixed by a date and time. If mtime is
617      *  zero, then we use the current time.  If mtime is 1 (special
618      *  kludge), we do not prefix the date and time. Otherwise,
619      *  we assume mtime is a time_t and use it.
620      */
621     if (mtime == 0) {
622        mtime = time(NULL);
623     }
624     if (mtime == 1) {
625        *dt = 0;
626        dtlen = 0;
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                 if (!d->fd) {
740                    POOLMEM *name = get_pool_memory(PM_MESSAGE);
741                    make_unique_mail_filename(jcr, name, d);
742                    d->fd = fopen(name, "w+b");
743                    if (!d->fd) {
744                       berrno be;
745                       d->fd = stdout;
746                       Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), name,
747                             be.bstrerror());
748                       d->fd = NULL;
749                       free_pool_memory(name);
750                       break;
751                    }
752                    d->mail_filename = name;
753                 }
754                 fputs(dt, d->fd);
755                 len = strlen(msg) + dtlen;;
756                 if (len > d->max_len) {
757                    d->max_len = len;      /* keep max line length */
758                 }
759                 fputs(msg, d->fd);
760                 break;
761              case MD_APPEND:
762                 Dmsg1(850, "APPEND for following msg: %s", msg);
763                 mode = "ab";
764                 goto send_to_file;
765              case MD_FILE:
766                 Dmsg1(850, "FILE for following msg: %s", msg);
767                 mode = "w+b";
768 send_to_file:
769                 if (!d->fd && !open_dest_file(jcr, d, mode)) {
770                    break;
771                 }
772                 fputs(dt, d->fd);
773                 fputs(msg, d->fd);
774                 /* On error, we close and reopen to handle log rotation */
775                 if (ferror(d->fd)) {
776                    fclose(d->fd);
777                    d->fd = NULL;
778                    if (open_dest_file(jcr, d, mode)) {
779                       fputs(dt, d->fd);
780                       fputs(msg, d->fd);
781                    }
782                 }
783                 break;
784              case MD_DIRECTOR:
785                 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
786                 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
787                    bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s",
788                       jcr->Job, type, mtime, msg);
789                 }
790                 break;
791              case MD_STDOUT:
792                 Dmsg1(850, "STDOUT for following msg: %s", msg);
793                 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
794                    fputs(dt, stdout);
795                    fputs(msg, stdout);
796                    fflush(stdout);
797                 }
798                 break;
799              case MD_STDERR:
800                 Dmsg1(850, "STDERR for following msg: %s", msg);
801                 fputs(dt, stderr);
802                 fputs(msg, stderr);
803                 fflush(stdout);
804                 break;
805              default:
806                 break;
807           }
808        }
809     }
810 }
811
812 /*********************************************************************
813  *
814  *  This subroutine returns the filename portion of a Windows 
815  *  path.  It is used because Microsoft Visual Studio sets __FILE__ 
816  *  to the full path.
817  */
818
819 inline const char *
820 get_basename(const char *pathname)
821 {
822 #if defined(_MSC_VER)
823    const char *basename;
824    
825    if ((basename = strrchr(pathname, '\\')) == NULL) {
826       basename = pathname;
827    } else {
828       basename++;
829    }
830
831    return basename;
832 #else
833    return pathname;
834 #endif
835 }
836
837 /*********************************************************************
838  *
839  *  This subroutine prints a debug message if the level number
840  *  is less than or equal the debug_level. File and line numbers
841  *  are included for more detail if desired, but not currently
842  *  printed.
843  *
844  *  If the level is negative, the details of file and line number
845  *  are not printed.
846  */
847 void
848 d_msg(const char *file, int line, int level, const char *fmt,...)
849 {
850     char      buf[5000];
851     int       len;
852     va_list   arg_ptr;
853     bool      details = true;
854     time_t    mtime;
855
856     if (level < 0) {
857        details = false;
858        level = -level;
859     }
860
861     if (level <= debug_level) {
862        if (dbg_timestamp) {
863           mtime = time(NULL);
864           bstrftimes(buf, sizeof(buf), mtime);
865           len = strlen(buf);
866           buf[len++] = ' ';
867           buf[len] = 0;
868           fputs(buf, stdout);
869        }
870     
871 #ifdef FULL_LOCATION
872        if (details) {
873           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ", 
874                 my_name, get_basename(file), line, get_jobid_from_tsd());
875        } else {
876           len = 0;
877        }
878 #else
879        len = 0;
880 #endif
881        va_start(arg_ptr, fmt);
882        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
883        va_end(arg_ptr);
884
885        /*
886         * Used the "trace on" command in the console to turn on
887         *  output to the trace file.  "trace off" will close the file.
888         */
889        if (trace) {
890           if (!trace_fd) {
891              char fn[200];
892              bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
893              trace_fd = fopen(fn, "a+b");
894           }
895           if (trace_fd) {
896              fputs(buf, trace_fd);
897              fflush(trace_fd);
898           } else {
899              /* Some problem, turn off tracing */
900              trace = false;
901           }
902        } else {   /* not tracing */
903           fputs(buf, stdout);
904           fflush(stdout);
905        }
906     }
907 }
908
909 /*
910  * Set trace flag on/off. If argument is negative, there is no change
911  */
912 void set_trace(int trace_flag)
913 {
914    if (trace_flag < 0) {
915       return;
916    } else if (trace_flag > 0) {
917       trace = true;
918    } else {
919       trace = false;
920    }
921    if (!trace && trace_fd) {
922       FILE *ltrace_fd = trace_fd;
923       trace_fd = NULL;
924       bmicrosleep(0, 100000);         /* yield to prevent seg faults */
925       fclose(ltrace_fd);
926    }
927 }
928
929 bool get_trace(void)
930 {
931    return trace;
932 }
933
934 /*********************************************************************
935  *
936  *  This subroutine prints a message regardless of the debug level
937  *
938  *  If the level is negative, the details of file and line number
939  *  are not printed.
940  */
941 void
942 p_msg(const char *file, int line, int level, const char *fmt,...)
943 {
944     char      buf[5000];
945     int       len;
946     va_list   arg_ptr;
947
948 #ifdef FULL_LOCATION
949     if (level >= 0) {
950        len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
951     } else {
952        len = 0;
953     }
954 #else
955     len = 0;
956 #endif
957     va_start(arg_ptr, fmt);
958     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
959     va_end(arg_ptr);
960     fputs(buf, stdout);
961     fflush(stdout);
962 }
963
964
965 /*********************************************************************
966  *
967  *  subroutine writes a debug message to the trace file 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 t_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     int       details = TRUE;
982
983     if (level < 0) {
984        details = FALSE;
985        level = -level;
986     }
987
988     if (level <= debug_level) {
989        if (!trace_fd) {
990           bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
991           trace_fd = fopen(buf, "a+b");
992        }
993
994 #ifdef FULL_LOCATION
995        if (details) {
996           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
997        } else {
998           len = 0;
999        }
1000 #else
1001        len = 0;
1002 #endif
1003        va_start(arg_ptr, fmt);
1004        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1005        va_end(arg_ptr);
1006        if (trace_fd != NULL) {
1007            fputs(buf, trace_fd);
1008            fflush(trace_fd);
1009        }
1010    }
1011 }
1012
1013 /* *********************************************************
1014  *
1015  * print an error message
1016  *
1017  */
1018 void
1019 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1020 {
1021     char     buf[5000];
1022     va_list   arg_ptr;
1023     int len;
1024
1025     /*
1026      * Check if we have a message destination defined.
1027      * We always report M_ABORT and M_ERROR_TERM
1028      */
1029     if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1030                          !bit_is_set(type, daemon_msgs->send_msg))) {
1031        return;                        /* no destination */
1032     }
1033     switch (type) {
1034     case M_ABORT:
1035        len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1036                my_name, get_basename(file), line);
1037        break;
1038     case M_ERROR_TERM:
1039        len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1040                my_name, get_basename(file), line);
1041        break;
1042     case M_FATAL:
1043        if (level == -1)            /* skip details */
1044           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1045        else
1046           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1047        break;
1048     case M_ERROR:
1049        if (level == -1)            /* skip details */
1050           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1051        else
1052           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1053        break;
1054     case M_WARNING:
1055        len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1056        break;
1057     case M_SECURITY:
1058        len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1059        break;
1060     default:
1061        len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1062        break;
1063     }
1064
1065     va_start(arg_ptr, fmt);
1066     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1067     va_end(arg_ptr);
1068
1069     dispatch_message(NULL, type, 0, buf);
1070
1071     if (type == M_ABORT) {
1072        char *p = 0;
1073        p[0] = 0;                      /* generate segmentation violation */
1074     }
1075     if (type == M_ERROR_TERM) {
1076        exit(1);
1077     }
1078 }
1079
1080 /* *********************************************************
1081  *
1082  * Generate a Job message
1083  *
1084  */
1085 void
1086 Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1087 {
1088     char     rbuf[5000];
1089     va_list   arg_ptr;
1090     int len;
1091     MSGS *msgs;
1092     uint32_t JobId = 0;
1093
1094
1095     Dmsg1(850, "Enter Jmsg type=%d\n", type);
1096
1097     /* Special case for the console, which has a dir_bsock and JobId==0,
1098      *  in that case, we send the message directly back to the
1099      *  dir_bsock.
1100      */
1101     if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1102        BSOCK *dir = jcr->dir_bsock;
1103        va_start(arg_ptr, fmt);
1104        dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1105                                 fmt, arg_ptr);
1106        va_end(arg_ptr);
1107        jcr->dir_bsock->send();
1108        return;
1109     }
1110
1111     msgs = NULL;
1112     if (!jcr) {
1113        jcr = get_jcr_from_tsd();
1114     }
1115     if (jcr) {
1116        msgs = jcr->jcr_msgs;
1117        JobId = jcr->JobId;
1118     }
1119     if (!msgs) {
1120        msgs = daemon_msgs;            /* if no jcr, we use daemon handler */
1121     }
1122
1123     /*
1124      * Check if we have a message destination defined.
1125      * We always report M_ABORT and M_ERROR_TERM
1126      */
1127     if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1128          !bit_is_set(type, msgs->send_msg)) {
1129        return;                        /* no destination */
1130     }
1131     switch (type) {
1132     case M_ABORT:
1133        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1134        break;
1135     case M_ERROR_TERM:
1136        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1137        break;
1138     case M_FATAL:
1139        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1140        if (jcr) {
1141           set_jcr_job_status(jcr, JS_FatalError);
1142        }
1143        break;
1144     case M_ERROR:
1145        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1146        if (jcr) {
1147           jcr->Errors++;
1148        }
1149        break;
1150     case M_WARNING:
1151        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1152        break;
1153     case M_SECURITY:
1154        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "), 
1155                my_name, JobId);
1156        break;
1157     default:
1158        len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1159        break;
1160     }
1161
1162     va_start(arg_ptr, fmt);
1163     bvsnprintf(rbuf+len,  sizeof(rbuf)-len, fmt, arg_ptr);
1164     va_end(arg_ptr);
1165
1166     dispatch_message(jcr, type, mtime, rbuf);
1167
1168     if (type == M_ABORT){
1169        char *p = 0;
1170        printf("Bacula forced SEG FAULT to obtain traceback.\n");
1171        syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1172        p[0] = 0;                      /* generate segmentation violation */
1173     }
1174     if (type == M_ERROR_TERM) {
1175        exit(1);
1176     }
1177 }
1178
1179 /*
1180  * If we come here, prefix the message with the file:line-number,
1181  *  then pass it on to the normal Jmsg routine.
1182  */
1183 void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1184 {
1185    va_list   arg_ptr;
1186    int i, len, maxlen;
1187    POOLMEM *pool_buf;
1188
1189    pool_buf = get_pool_memory(PM_EMSG);
1190    i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1191
1192    for (;;) {
1193       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1194       va_start(arg_ptr, fmt);
1195       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1196       va_end(arg_ptr);
1197       if (len < 0 || len >= (maxlen-5)) {
1198          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1199          continue;
1200       }
1201       break;
1202    }
1203
1204    Jmsg(jcr, type, mtime, "%s", pool_buf);
1205    free_memory(pool_buf);
1206 }
1207
1208
1209 /*
1210  * Edit a message into a Pool memory buffer, with file:lineno
1211  */
1212 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1213 {
1214    va_list   arg_ptr;
1215    int i, len, maxlen;
1216
1217    i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1218
1219    for (;;) {
1220       maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1221       va_start(arg_ptr, fmt);
1222       len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1223       va_end(arg_ptr);
1224       if (len < 0 || len >= (maxlen-5)) {
1225          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1226          continue;
1227       }
1228       break;
1229    }
1230    return len;
1231 }
1232
1233 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1234 {
1235    va_list   arg_ptr;
1236    int i, len, maxlen;
1237
1238    i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1239
1240    for (;;) {
1241       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1242       va_start(arg_ptr, fmt);
1243       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1244       va_end(arg_ptr);
1245       if (len < 0 || len >= (maxlen-5)) {
1246          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1247          continue;
1248       }
1249       break;
1250    }
1251    return len;
1252 }
1253
1254
1255 /*
1256  * Edit a message into a Pool Memory buffer NO file:lineno
1257  *  Returns: string length of what was edited.
1258  */
1259 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1260 {
1261    va_list   arg_ptr;
1262    int len, maxlen;
1263
1264    for (;;) {
1265       maxlen = sizeof_pool_memory(*pool_buf) - 1;
1266       va_start(arg_ptr, fmt);
1267       len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1268       va_end(arg_ptr);
1269       if (len < 0 || len >= (maxlen-5)) {
1270          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1271          continue;
1272       }
1273       break;
1274    }
1275    return len;
1276 }
1277
1278 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1279 {
1280    va_list   arg_ptr;
1281    int len, maxlen;
1282
1283    for (;;) {
1284       maxlen = sizeof_pool_memory(pool_buf) - 1;
1285       va_start(arg_ptr, fmt);
1286       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1287       va_end(arg_ptr);
1288       if (len < 0 || len >= (maxlen-5)) {
1289          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1290          continue;
1291       }
1292       break;
1293    }
1294    return len;
1295 }
1296
1297 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1298 {
1299    va_list   arg_ptr;
1300    int len, maxlen;
1301
1302    for (;;) {
1303       maxlen = pool_buf.max_size() - 1;
1304       va_start(arg_ptr, fmt);
1305       len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1306       va_end(arg_ptr);
1307       if (len < 0 || len >= (maxlen-5)) {
1308          pool_buf.realloc_pm(maxlen + maxlen/2);
1309          continue;
1310       }
1311       break;
1312    }
1313    return len;
1314 }
1315
1316
1317 static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
1318
1319 /*
1320  * We queue messages rather than print them directly. This
1321  *  is generally used in low level routines (msg handler, bnet)
1322  *  to prevent recursion (i.e. if you are in the middle of
1323  *  sending a message, it is a bit messy to recursively call
1324  *  yourself when the bnet packet is not reentrant).
1325  */
1326 void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1327 {
1328    va_list   arg_ptr;
1329    int len, maxlen;
1330    POOLMEM *pool_buf;
1331    MQUEUE_ITEM *item;
1332
1333    pool_buf = get_pool_memory(PM_EMSG);
1334
1335    for (;;) {
1336       maxlen = sizeof_pool_memory(pool_buf) - 1;
1337       va_start(arg_ptr, fmt);
1338       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1339       va_end(arg_ptr);
1340       if (len < 0 || len >= (maxlen-5)) {
1341          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1342          continue;
1343       }
1344       break;
1345    }
1346    item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1347    item->type = type;
1348    item->mtime = time(NULL);
1349    strcpy(item->msg, pool_buf);
1350    if (!jcr) {
1351       jcr = get_jcr_from_tsd();
1352    }
1353    /* If no jcr or dequeuing send to daemon to avoid recursion */
1354    if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
1355       /* jcr==NULL => daemon message, safe to send now */
1356       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1357       free(item);
1358    } else {
1359       /* Queue message for later sending */
1360       P(msg_queue_mutex);
1361       jcr->msg_queue->append(item);
1362       V(msg_queue_mutex);
1363    }
1364    free_memory(pool_buf);
1365 }
1366
1367 /*
1368  * Dequeue messages
1369  */
1370 void dequeue_messages(JCR *jcr)
1371 {
1372    MQUEUE_ITEM *item;
1373    P(msg_queue_mutex);
1374    if (!jcr->msg_queue) {
1375       goto bail_out;
1376    }
1377    jcr->dequeuing = true;
1378    foreach_dlist(item, jcr->msg_queue) {
1379       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1380    }
1381    jcr->msg_queue->destroy();
1382    jcr->dequeuing = false;
1383
1384 bail_out:
1385    V(msg_queue_mutex);
1386 }
1387
1388
1389 /*
1390  * If we come here, prefix the message with the file:line-number,
1391  *  then pass it on to the normal Qmsg routine.
1392  */
1393 void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1394 {
1395    va_list   arg_ptr;
1396    int i, len, maxlen;
1397    POOLMEM *pool_buf;
1398
1399    pool_buf = get_pool_memory(PM_EMSG);
1400    i = Mmsg(pool_buf, "%s:%d ", file, line);
1401
1402    for (;;) {
1403       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1404       va_start(arg_ptr, fmt);
1405       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1406       va_end(arg_ptr);
1407       if (len < 0 || len >= (maxlen-5)) {
1408          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1409          continue;
1410       }
1411       break;
1412    }
1413
1414    Qmsg(jcr, type, mtime, "%s", pool_buf);
1415    free_memory(pool_buf);
1416 }