]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/message.c
Apply patch from Marco van Wieringen <mvw@planets.elm.net>
[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 /* *********************************************************
1016  *
1017  * print an error message
1018  *
1019  */
1020 void
1021 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1022 {
1023     char     buf[5000];
1024     va_list   arg_ptr;
1025     int len;
1026
1027     /*
1028      * Check if we have a message destination defined.
1029      * We always report M_ABORT and M_ERROR_TERM
1030      */
1031     if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1032                          !bit_is_set(type, daemon_msgs->send_msg))) {
1033        return;                        /* no destination */
1034     }
1035     switch (type) {
1036     case M_ABORT:
1037        len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1038                my_name, get_basename(file), line);
1039        break;
1040     case M_ERROR_TERM:
1041        len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1042                my_name, get_basename(file), line);
1043        break;
1044     case M_FATAL:
1045        if (level == -1)            /* skip details */
1046           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1047        else
1048           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1049        break;
1050     case M_ERROR:
1051        if (level == -1)            /* skip details */
1052           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1053        else
1054           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1055        break;
1056     case M_WARNING:
1057        len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1058        break;
1059     case M_SECURITY:
1060        len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1061        break;
1062     default:
1063        len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1064        break;
1065     }
1066
1067     va_start(arg_ptr, fmt);
1068     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1069     va_end(arg_ptr);
1070
1071     dispatch_message(NULL, type, 0, buf);
1072
1073     if (type == M_ABORT) {
1074        char *p = 0;
1075        p[0] = 0;                      /* generate segmentation violation */
1076     }
1077     if (type == M_ERROR_TERM) {
1078        exit(1);
1079     }
1080 }
1081
1082 /* *********************************************************
1083  *
1084  * Generate a Job message
1085  *
1086  */
1087 void
1088 Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1089 {
1090     char     rbuf[5000];
1091     va_list   arg_ptr;
1092     int len;
1093     MSGS *msgs;
1094     uint32_t JobId = 0;
1095
1096
1097     Dmsg1(850, "Enter Jmsg type=%d\n", type);
1098
1099     /* Special case for the console, which has a dir_bsock and JobId==0,
1100      *  in that case, we send the message directly back to the
1101      *  dir_bsock.
1102      */
1103     if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1104        BSOCK *dir = jcr->dir_bsock;
1105        va_start(arg_ptr, fmt);
1106        dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1107                                 fmt, arg_ptr);
1108        va_end(arg_ptr);
1109        jcr->dir_bsock->send();
1110        return;
1111     }
1112
1113     msgs = NULL;
1114     if (!jcr) {
1115        jcr = get_jcr_from_tsd();
1116     }
1117     if (jcr) {
1118        msgs = jcr->jcr_msgs;
1119        JobId = jcr->JobId;
1120     }
1121     if (!msgs) {
1122        msgs = daemon_msgs;            /* if no jcr, we use daemon handler */
1123     }
1124
1125     /*
1126      * Check if we have a message destination defined.
1127      * We always report M_ABORT and M_ERROR_TERM
1128      */
1129     if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1130          !bit_is_set(type, msgs->send_msg)) {
1131        return;                        /* no destination */
1132     }
1133     switch (type) {
1134     case M_ABORT:
1135        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1136        break;
1137     case M_ERROR_TERM:
1138        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1139        break;
1140     case M_FATAL:
1141        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1142        if (jcr) {
1143           set_jcr_job_status(jcr, JS_FatalError);
1144        }
1145        break;
1146     case M_ERROR:
1147        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1148        if (jcr) {
1149           jcr->Errors++;
1150        }
1151        break;
1152     case M_WARNING:
1153        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1154        break;
1155     case M_SECURITY:
1156        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "), 
1157                my_name, JobId);
1158        break;
1159     default:
1160        len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1161        break;
1162     }
1163
1164     va_start(arg_ptr, fmt);
1165     bvsnprintf(rbuf+len,  sizeof(rbuf)-len, fmt, arg_ptr);
1166     va_end(arg_ptr);
1167
1168     dispatch_message(jcr, type, mtime, rbuf);
1169
1170     if (type == M_ABORT){
1171        char *p = 0;
1172        printf("Bacula forced SEG FAULT to obtain traceback.\n");
1173        syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1174        p[0] = 0;                      /* generate segmentation violation */
1175     }
1176     if (type == M_ERROR_TERM) {
1177        exit(1);
1178     }
1179 }
1180
1181 /*
1182  * If we come here, prefix the message with the file:line-number,
1183  *  then pass it on to the normal Jmsg routine.
1184  */
1185 void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1186 {
1187    va_list   arg_ptr;
1188    int i, len, maxlen;
1189    POOLMEM *pool_buf;
1190
1191    pool_buf = get_pool_memory(PM_EMSG);
1192    i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1193
1194    for (;;) {
1195       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1196       va_start(arg_ptr, fmt);
1197       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1198       va_end(arg_ptr);
1199       if (len < 0 || len >= (maxlen-5)) {
1200          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1201          continue;
1202       }
1203       break;
1204    }
1205
1206    Jmsg(jcr, type, mtime, "%s", pool_buf);
1207    free_memory(pool_buf);
1208 }
1209
1210
1211 /*
1212  * Edit a message into a Pool memory buffer, with file:lineno
1213  */
1214 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1215 {
1216    va_list   arg_ptr;
1217    int i, len, maxlen;
1218
1219    i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1220
1221    for (;;) {
1222       maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1223       va_start(arg_ptr, fmt);
1224       len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1225       va_end(arg_ptr);
1226       if (len < 0 || len >= (maxlen-5)) {
1227          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1228          continue;
1229       }
1230       break;
1231    }
1232    return len;
1233 }
1234
1235 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1236 {
1237    va_list   arg_ptr;
1238    int i, len, maxlen;
1239
1240    i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1241
1242    for (;;) {
1243       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1244       va_start(arg_ptr, fmt);
1245       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1246       va_end(arg_ptr);
1247       if (len < 0 || len >= (maxlen-5)) {
1248          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1249          continue;
1250       }
1251       break;
1252    }
1253    return len;
1254 }
1255
1256
1257 /*
1258  * Edit a message into a Pool Memory buffer NO file:lineno
1259  *  Returns: string length of what was edited.
1260  */
1261 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1262 {
1263    va_list   arg_ptr;
1264    int len, maxlen;
1265
1266    for (;;) {
1267       maxlen = sizeof_pool_memory(*pool_buf) - 1;
1268       va_start(arg_ptr, fmt);
1269       len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1270       va_end(arg_ptr);
1271       if (len < 0 || len >= (maxlen-5)) {
1272          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1273          continue;
1274       }
1275       break;
1276    }
1277    return len;
1278 }
1279
1280 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1281 {
1282    va_list   arg_ptr;
1283    int len, maxlen;
1284
1285    for (;;) {
1286       maxlen = sizeof_pool_memory(pool_buf) - 1;
1287       va_start(arg_ptr, fmt);
1288       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1289       va_end(arg_ptr);
1290       if (len < 0 || len >= (maxlen-5)) {
1291          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1292          continue;
1293       }
1294       break;
1295    }
1296    return len;
1297 }
1298
1299 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1300 {
1301    va_list   arg_ptr;
1302    int len, maxlen;
1303
1304    for (;;) {
1305       maxlen = pool_buf.max_size() - 1;
1306       va_start(arg_ptr, fmt);
1307       len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1308       va_end(arg_ptr);
1309       if (len < 0 || len >= (maxlen-5)) {
1310          pool_buf.realloc_pm(maxlen + maxlen/2);
1311          continue;
1312       }
1313       break;
1314    }
1315    return len;
1316 }
1317
1318
1319 static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
1320
1321 /*
1322  * We queue messages rather than print them directly. This
1323  *  is generally used in low level routines (msg handler, bnet)
1324  *  to prevent recursion (i.e. if you are in the middle of
1325  *  sending a message, it is a bit messy to recursively call
1326  *  yourself when the bnet packet is not reentrant).
1327  */
1328 void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1329 {
1330    va_list   arg_ptr;
1331    int len, maxlen;
1332    POOLMEM *pool_buf;
1333    MQUEUE_ITEM *item;
1334
1335    pool_buf = get_pool_memory(PM_EMSG);
1336
1337    for (;;) {
1338       maxlen = sizeof_pool_memory(pool_buf) - 1;
1339       va_start(arg_ptr, fmt);
1340       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1341       va_end(arg_ptr);
1342       if (len < 0 || len >= (maxlen-5)) {
1343          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1344          continue;
1345       }
1346       break;
1347    }
1348    item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1349    item->type = type;
1350    item->mtime = time(NULL);
1351    strcpy(item->msg, pool_buf);
1352    if (!jcr) {
1353       jcr = get_jcr_from_tsd();
1354    }
1355    /* If no jcr or dequeuing send to daemon to avoid recursion */
1356    if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
1357       /* jcr==NULL => daemon message, safe to send now */
1358       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1359       free(item);
1360    } else {
1361       /* Queue message for later sending */
1362       P(msg_queue_mutex);
1363       jcr->msg_queue->append(item);
1364       V(msg_queue_mutex);
1365    }
1366    free_memory(pool_buf);
1367 }
1368
1369 /*
1370  * Dequeue messages
1371  */
1372 void dequeue_messages(JCR *jcr)
1373 {
1374    MQUEUE_ITEM *item;
1375    P(msg_queue_mutex);
1376    if (!jcr->msg_queue) {
1377       goto bail_out;
1378    }
1379    jcr->dequeuing = true;
1380    foreach_dlist(item, jcr->msg_queue) {
1381       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1382    }
1383    jcr->msg_queue->destroy();
1384    jcr->dequeuing = false;
1385
1386 bail_out:
1387    V(msg_queue_mutex);
1388 }
1389
1390
1391 /*
1392  * If we come here, prefix the message with the file:line-number,
1393  *  then pass it on to the normal Qmsg routine.
1394  */
1395 void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1396 {
1397    va_list   arg_ptr;
1398    int i, len, maxlen;
1399    POOLMEM *pool_buf;
1400
1401    pool_buf = get_pool_memory(PM_EMSG);
1402    i = Mmsg(pool_buf, "%s:%d ", file, line);
1403
1404    for (;;) {
1405       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1406       va_start(arg_ptr, fmt);
1407       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1408       va_end(arg_ptr);
1409       if (len < 0 || len >= (maxlen-5)) {
1410          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1411          continue;
1412       }
1413       break;
1414    }
1415
1416    Qmsg(jcr, type, mtime, "%s", pool_buf);
1417    free_memory(pool_buf);
1418 }