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