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