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