]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/message.c
kes Prepare to add JS_Warnings termination status.
[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 utime_t daemon_start_time = 0;        /* Daemon start time */
55 const char *version = VERSION " (" BDATE ")";
56 char my_name[30];                     /* daemon name is stored here */
57 char host_name[50];                   /* host machine name */
58 char *exepath = (char *)NULL;
59 char *exename = (char *)NULL;
60 int console_msg_pending = false;
61 char con_fname[500];                  /* Console filename */
62 FILE *con_fd = NULL;                  /* Console file descriptor */
63 brwlock_t con_lock;                   /* Console lock structure */
64
65 /* Forward referenced functions */
66
67 /* Imported functions */
68 void create_jcr_key();
69
70 /* Static storage */
71
72 /* 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)(intptr_t)d);
374    } else {
375       Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
376                  my_name, (int)(intptr_t)d);
377    }
378    Dmsg1(850, "mailname=%s\n", name);
379 }
380
381 /*
382  * Open a mail pipe
383  */
384 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
385 {
386    BPIPE *bpipe;
387
388    if (d->mail_cmd) {
389       cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
390    } else {
391       Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
392    }
393    fflush(stdout);
394
395    if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
396       /* If we had to use sendmail, add subject */
397       if (!d->mail_cmd) {
398          fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
399       }
400    } else {
401       berrno be;
402       Jmsg(jcr, M_ERROR, 0, _("open mail pipe %s failed: ERR=%s\n"),
403          cmd, be.bstrerror());
404    }
405    return bpipe;
406 }
407
408 /*
409  * Close the messages for this Messages resource, which means to close
410  *  any open files, and dispatch any pending email messages.
411  */
412 void close_msg(JCR *jcr)
413 {
414    MSGS *msgs;
415    DEST *d;
416    BPIPE *bpipe;
417    POOLMEM *cmd, *line;
418    int len, stat;
419
420    Dmsg1(580, "Close_msg jcr=%p\n", jcr);
421
422    if (jcr == NULL) {                /* NULL -> global chain */
423       msgs = daemon_msgs;
424       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 || jcr->JobStatus == JS_Warnings)) 
454                 ||
455                 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
456                  jcr->JobStatus == JS_ErrorTerminated)
457                 ) {
458                goto rem_temp_file;
459             }
460
461             if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
462                Pmsg0(000, _("open mail pipe failed.\n"));
463                goto rem_temp_file;
464             }
465             Dmsg0(850, "Opened mail pipe\n");
466             len = d->max_len+10;
467             line = get_memory(len);
468             rewind(d->fd);
469             while (fgets(line, len, d->fd)) {
470                fputs(line, bpipe->wfd);
471             }
472             if (!close_wpipe(bpipe)) {       /* close write pipe sending mail */
473                berrno be;
474                Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
475             }
476
477             /*
478              * Since we are closing all messages, before "recursing"
479              * make sure we are not closing the daemon messages, otherwise
480              * kaboom.
481              */
482             if (msgs != daemon_msgs) {
483                /* read what mail prog returned -- should be nothing */
484                while (fgets(line, len, bpipe->rfd)) {
485                   Jmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line);
486                }
487             }
488
489             stat = close_bpipe(bpipe);
490             if (stat != 0 && msgs != daemon_msgs) {
491                berrno be;
492                be.set_errno(stat);
493                Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
494                Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
495                                         "CMD=%s\n"
496                                         "ERR=%s\n"), cmd, be.bstrerror());
497             }
498             free_memory(line);
499 rem_temp_file:
500             /* Remove temp file */
501             fclose(d->fd);
502             d->fd = NULL;
503             unlink(d->mail_filename);
504             free_pool_memory(d->mail_filename);
505             d->mail_filename = NULL;
506             Dmsg0(850, "end mail or mail on error\n");
507             break;
508          default:
509             break;
510          }
511          d->fd = NULL;
512       }
513       d = d->next;                    /* point to next buffer */
514    }
515    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, utime_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 utime_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=%lld %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     utime_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, utime_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->JobErrors++;
1148        }
1149        break;
1150     case M_WARNING:
1151        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1152        if (jcr) {
1153           jcr->JobWarnings++;
1154        }
1155        break;
1156     case M_SECURITY:
1157        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "), 
1158                my_name, JobId);
1159        break;
1160     default:
1161        len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1162        break;
1163     }
1164
1165     va_start(arg_ptr, fmt);
1166     bvsnprintf(rbuf+len,  sizeof(rbuf)-len, fmt, arg_ptr);
1167     va_end(arg_ptr);
1168
1169     dispatch_message(jcr, type, mtime, rbuf);
1170
1171     if (type == M_ABORT){
1172        char *p = 0;
1173        printf("Bacula forced SEG FAULT to obtain traceback.\n");
1174        syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1175        p[0] = 0;                      /* generate segmentation violation */
1176     }
1177     if (type == M_ERROR_TERM) {
1178        exit(1);
1179     }
1180 }
1181
1182 /*
1183  * If we come here, prefix the message with the file:line-number,
1184  *  then pass it on to the normal Jmsg routine.
1185  */
1186 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1187 {
1188    va_list   arg_ptr;
1189    int i, len, maxlen;
1190    POOLMEM *pool_buf;
1191
1192    pool_buf = get_pool_memory(PM_EMSG);
1193    i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1194
1195    for (;;) {
1196       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1197       va_start(arg_ptr, fmt);
1198       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1199       va_end(arg_ptr);
1200       if (len < 0 || len >= (maxlen-5)) {
1201          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1202          continue;
1203       }
1204       break;
1205    }
1206
1207    Jmsg(jcr, type, mtime, "%s", pool_buf);
1208    free_memory(pool_buf);
1209 }
1210
1211
1212 /*
1213  * Edit a message into a Pool memory buffer, with file:lineno
1214  */
1215 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1216 {
1217    va_list   arg_ptr;
1218    int i, len, maxlen;
1219
1220    i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1221
1222    for (;;) {
1223       maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1224       va_start(arg_ptr, fmt);
1225       len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1226       va_end(arg_ptr);
1227       if (len < 0 || len >= (maxlen-5)) {
1228          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1229          continue;
1230       }
1231       break;
1232    }
1233    return len;
1234 }
1235
1236 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1237 {
1238    va_list   arg_ptr;
1239    int i, len, maxlen;
1240
1241    i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1242
1243    for (;;) {
1244       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1245       va_start(arg_ptr, fmt);
1246       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1247       va_end(arg_ptr);
1248       if (len < 0 || len >= (maxlen-5)) {
1249          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1250          continue;
1251       }
1252       break;
1253    }
1254    return len;
1255 }
1256
1257
1258 /*
1259  * Edit a message into a Pool Memory buffer NO file:lineno
1260  *  Returns: string length of what was edited.
1261  */
1262 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1263 {
1264    va_list   arg_ptr;
1265    int len, maxlen;
1266
1267    for (;;) {
1268       maxlen = sizeof_pool_memory(*pool_buf) - 1;
1269       va_start(arg_ptr, fmt);
1270       len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1271       va_end(arg_ptr);
1272       if (len < 0 || len >= (maxlen-5)) {
1273          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1274          continue;
1275       }
1276       break;
1277    }
1278    return len;
1279 }
1280
1281 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1282 {
1283    va_list   arg_ptr;
1284    int len, maxlen;
1285
1286    for (;;) {
1287       maxlen = sizeof_pool_memory(pool_buf) - 1;
1288       va_start(arg_ptr, fmt);
1289       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1290       va_end(arg_ptr);
1291       if (len < 0 || len >= (maxlen-5)) {
1292          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1293          continue;
1294       }
1295       break;
1296    }
1297    return len;
1298 }
1299
1300 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1301 {
1302    va_list   arg_ptr;
1303    int len, maxlen;
1304
1305    for (;;) {
1306       maxlen = pool_buf.max_size() - 1;
1307       va_start(arg_ptr, fmt);
1308       len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1309       va_end(arg_ptr);
1310       if (len < 0 || len >= (maxlen-5)) {
1311          pool_buf.realloc_pm(maxlen + maxlen/2);
1312          continue;
1313       }
1314       break;
1315    }
1316    return len;
1317 }
1318
1319
1320 static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
1321
1322 /*
1323  * We queue messages rather than print them directly. This
1324  *  is generally used in low level routines (msg handler, bnet)
1325  *  to prevent recursion (i.e. if you are in the middle of
1326  *  sending a message, it is a bit messy to recursively call
1327  *  yourself when the bnet packet is not reentrant).
1328  */
1329 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1330 {
1331    va_list   arg_ptr;
1332    int len, maxlen;
1333    POOLMEM *pool_buf;
1334    MQUEUE_ITEM *item;
1335
1336    pool_buf = get_pool_memory(PM_EMSG);
1337
1338    for (;;) {
1339       maxlen = sizeof_pool_memory(pool_buf) - 1;
1340       va_start(arg_ptr, fmt);
1341       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1342       va_end(arg_ptr);
1343       if (len < 0 || len >= (maxlen-5)) {
1344          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1345          continue;
1346       }
1347       break;
1348    }
1349    item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1350    item->type = type;
1351    item->mtime = time(NULL);
1352    strcpy(item->msg, pool_buf);
1353    if (!jcr) {
1354       jcr = get_jcr_from_tsd();
1355    }
1356    /* If no jcr or dequeuing send to daemon to avoid recursion */
1357    if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
1358       /* jcr==NULL => daemon message, safe to send now */
1359       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1360       free(item);
1361    } else {
1362       /* Queue message for later sending */
1363       P(msg_queue_mutex);
1364       jcr->msg_queue->append(item);
1365       V(msg_queue_mutex);
1366    }
1367    free_memory(pool_buf);
1368 }
1369
1370 /*
1371  * Dequeue messages
1372  */
1373 void dequeue_messages(JCR *jcr)
1374 {
1375    MQUEUE_ITEM *item;
1376    P(msg_queue_mutex);
1377    if (!jcr->msg_queue) {
1378       goto bail_out;
1379    }
1380    jcr->dequeuing = true;
1381    foreach_dlist(item, jcr->msg_queue) {
1382       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1383    }
1384    jcr->msg_queue->destroy();
1385    jcr->dequeuing = false;
1386
1387 bail_out:
1388    V(msg_queue_mutex);
1389 }
1390
1391
1392 /*
1393  * If we come here, prefix the message with the file:line-number,
1394  *  then pass it on to the normal Qmsg routine.
1395  */
1396 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1397 {
1398    va_list   arg_ptr;
1399    int i, len, maxlen;
1400    POOLMEM *pool_buf;
1401
1402    pool_buf = get_pool_memory(PM_EMSG);
1403    i = Mmsg(pool_buf, "%s:%d ", file, line);
1404
1405    for (;;) {
1406       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1407       va_start(arg_ptr, fmt);
1408       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1409       va_end(arg_ptr);
1410       if (len < 0 || len >= (maxlen-5)) {
1411          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1412          continue;
1413       }
1414       break;
1415    }
1416
1417    Qmsg(jcr, type, mtime, "%s", pool_buf);
1418    free_memory(pool_buf);
1419 }