]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/message.c
Split messages line by line before sending it to syslog() fix #3325
[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 1024c
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    {
680       len = MIN(sizeof(buf) - 1, p2 - p + 1); /* Add 1 to keep \n */
681       strncpy(buf, p, len);
682       buf[len] = 0;
683       syslog(mode, "%s", buf);
684       p = p2+1;                 /* skip \n */
685    }
686    if (*p != 0) {               /* no \n at the end ? */
687       syslog(mode, "%s", p);
688    }
689 }
690
691 /*
692  * Handle sending the message to the appropriate place
693  */
694 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
695 {
696     DEST *d;
697     char dt[MAX_TIME_LENGTH];
698     POOLMEM *mcmd;
699     int len, dtlen;
700     MSGS *msgs;
701     BPIPE *bpipe;
702     const char *mode;
703
704     Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
705
706     /*
707      * Most messages are prefixed by a date and time. If mtime is
708      *  zero, then we use the current time.  If mtime is 1 (special
709      *  kludge), we do not prefix the date and time. Otherwise,
710      *  we assume mtime is a utime_t and use it.
711      */
712     if (mtime == 0) {
713        mtime = time(NULL);
714     }
715     if (mtime == 1) {
716        *dt = 0;
717        dtlen = 0;
718        mtime = time(NULL);      /* get time for SQL log */
719     } else {
720        bstrftime_ny(dt, sizeof(dt), mtime);
721        dtlen = strlen(dt);
722        dt[dtlen++] = ' ';
723        dt[dtlen] = 0;
724     }
725
726     /* If the program registered a callback, send it there */
727     if (message_callback) {
728        message_callback(type, msg);
729        return;
730     }
731
732     /* For serious errors make sure message is printed or logged */
733     if (type == M_ABORT || type == M_ERROR_TERM) {
734        fputs(dt, stdout);
735        fputs(msg, stdout);
736        fflush(stdout);
737        if (type == M_ABORT) {
738           syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
739        }
740     }
741
742
743     /* Now figure out where to send the message */
744     msgs = NULL;
745     if (!jcr) {
746        jcr = get_jcr_from_tsd();
747     }
748     if (jcr) {
749        msgs = jcr->jcr_msgs;
750     }
751     if (msgs == NULL) {
752        msgs = daemon_msgs;
753     }
754     /*
755      * If closing this message resource, print and send to syslog,
756      *   then get out.
757      */
758     if (msgs->is_closing()) {
759        fputs(dt, stdout);
760        fputs(msg, stdout);
761        fflush(stdout);
762        syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
763        return;
764     }
765
766     for (d=msgs->dest_chain; d; d=d->next) {
767        if (bit_is_set(type, d->msg_types)) {
768           switch (d->dest_code) {
769              case MD_CATALOG:
770                 char ed1[50];
771                 if (!jcr || !jcr->db) {
772                    break;
773                 }
774                 if (p_sql_query && p_sql_escape) {
775                    POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
776                    POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
777                    
778                    int len = strlen(msg) + 1;
779                    esc_msg = check_pool_memory_size(esc_msg, len*2+1);
780                    p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
781
782                    bstrutime(dt, sizeof(dt), mtime);
783                    Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
784                          edit_int64(jcr->JobId, ed1), dt, esc_msg);
785                    p_sql_query(jcr, cmd);
786                    
787                    free_pool_memory(cmd);
788                    free_pool_memory(esc_msg);
789                 }
790                 break;
791              case MD_CONSOLE:
792                 Dmsg1(850, "CONSOLE for following msg: %s", msg);
793                 if (!con_fd) {
794                    con_fd = fopen(con_fname, "a+b");
795                    Dmsg0(850, "Console file not open.\n");
796                 }
797                 if (con_fd) {
798                    Pw(con_lock);      /* get write lock on console message file */
799                    errno = 0;
800                    if (dtlen) {
801                       (void)fwrite(dt, dtlen, 1, con_fd);
802                    }
803                    len = strlen(msg);
804                    if (len > 0) {
805                       (void)fwrite(msg, len, 1, con_fd);
806                       if (msg[len-1] != '\n') {
807                          (void)fwrite("\n", 2, 1, con_fd);
808                       }
809                    } else {
810                       (void)fwrite("\n", 2, 1, con_fd);
811                    }
812                    fflush(con_fd);
813                    console_msg_pending = true;
814                    Vw(con_lock);
815                 }
816                 break;
817              case MD_SYSLOG:
818                 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
819                 /*
820                  * We really should do an openlog() here.
821                  */
822                 send_to_syslog(LOG_DAEMON|LOG_ERR, msg);
823                 break;
824              case MD_OPERATOR:
825                 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
826                 mcmd = get_pool_memory(PM_MESSAGE);
827                 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
828                    int stat;
829                    fputs(dt, bpipe->wfd);
830                    fputs(msg, bpipe->wfd);
831                    /* Messages to the operator go one at a time */
832                    stat = close_bpipe(bpipe);
833                    if (stat != 0) {
834                       berrno be;
835                       be.set_errno(stat);
836                       delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
837                             "CMD=%s\n"
838                             "ERR=%s\n"), mcmd, be.bstrerror());
839                    }
840                 }
841                 free_pool_memory(mcmd);
842                 break;
843              case MD_MAIL:
844              case MD_MAIL_ON_ERROR:
845              case MD_MAIL_ON_SUCCESS:
846                 Dmsg1(850, "MAIL for following msg: %s", msg);
847                 if (msgs->is_closing()) {
848                    break;
849                 }
850                 msgs->set_in_use();
851                 if (!d->fd) {
852                    POOLMEM *name = get_pool_memory(PM_MESSAGE);
853                    make_unique_mail_filename(jcr, name, d);
854                    d->fd = fopen(name, "w+b");
855                    if (!d->fd) {
856                       berrno be;
857                       delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
858                             be.bstrerror());
859                       free_pool_memory(name);
860                       msgs->clear_in_use();
861                       break;
862                    }
863                    d->mail_filename = name;
864                 }
865                 fputs(dt, d->fd);
866                 len = strlen(msg) + dtlen;;
867                 if (len > d->max_len) {
868                    d->max_len = len;      /* keep max line length */
869                 }
870                 fputs(msg, d->fd);
871                 msgs->clear_in_use();
872                 break;
873              case MD_APPEND:
874                 Dmsg1(850, "APPEND for following msg: %s", msg);
875                 mode = "ab";
876                 goto send_to_file;
877              case MD_FILE:
878                 Dmsg1(850, "FILE for following msg: %s", msg);
879                 mode = "w+b";
880 send_to_file:
881                 if (msgs->is_closing()) {
882                    break;
883                 }
884                 msgs->set_in_use();
885                 if (!d->fd && !open_dest_file(jcr, d, mode)) {
886                    msgs->clear_in_use();
887                    break;
888                 }
889                 fputs(dt, d->fd);
890                 fputs(msg, d->fd);
891                 /* On error, we close and reopen to handle log rotation */
892                 if (ferror(d->fd)) {
893                    fclose(d->fd);
894                    d->fd = NULL;
895                    if (open_dest_file(jcr, d, mode)) {
896                       fputs(dt, d->fd);
897                       fputs(msg, d->fd);
898                    }
899                 }
900                 msgs->clear_in_use();
901                 break;
902              case MD_DIRECTOR:
903                 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
904                 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
905                    jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
906                       jcr->Job, type, mtime, msg);
907                 } else {
908                    Dmsg1(800, "no jcr for following msg: %s", msg);
909                 }
910                 break;
911              case MD_STDOUT:
912                 Dmsg1(850, "STDOUT for following msg: %s", msg);
913                 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
914                    fputs(dt, stdout);
915                    fputs(msg, stdout);
916                    fflush(stdout);
917                 }
918                 break;
919              case MD_STDERR:
920                 Dmsg1(850, "STDERR for following msg: %s", msg);
921                 fputs(dt, stderr);
922                 fputs(msg, stderr);
923                 fflush(stdout);
924                 break;
925              default:
926                 break;
927           }
928        }
929     }
930 }
931
932 /*********************************************************************
933  *
934  *  This subroutine returns the filename portion of a path.  
935  *  It is used because some compilers set __FILE__ 
936  *  to the full path.  Try to return base + next higher path.
937  */
938
939 const char *get_basename(const char *pathname)
940 {
941    const char *basename, *basename2;
942    
943    if ((basename = strrchr(pathname, PathSeparator)) == NULL) {
944       basename = pathname;
945       if ((basename2 = strrchr(pathname, PathSeparator)) != NULL) {
946          basename = basename2 + 1;
947       }
948    } else {
949       basename++;
950    }
951
952    return basename;
953 }
954
955 /*
956  * print or write output to trace file 
957  */
958 static void pt_out(char *buf)
959 {
960     /*
961      * Used the "trace on" command in the console to turn on
962      *  output to the trace file.  "trace off" will close the file.
963      */
964     if (trace) {
965        if (!trace_fd) {
966           char fn[200];
967           bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
968           trace_fd = fopen(fn, "a+b");
969        }
970        if (trace_fd) {
971           fputs(buf, trace_fd);
972           fflush(trace_fd);
973           return;
974        } else {
975           /* Some problem, turn off tracing */
976           trace = false;
977        }
978     }
979     /* not tracing */
980     fputs(buf, stdout);
981     fflush(stdout);
982 }
983
984 /*********************************************************************
985  *
986  *  This subroutine prints a debug message if the level number
987  *  is less than or equal the debug_level. File and line numbers
988  *  are included for more detail if desired, but not currently
989  *  printed.
990  *
991  *  If the level is negative, the details of file and line number
992  *  are not printed.
993  */
994 void
995 d_msg(const char *file, int line, int level, const char *fmt,...)
996 {
997     char      buf[5000];
998     int       len;
999     va_list   arg_ptr;
1000     bool      details = true;
1001     utime_t   mtime;
1002
1003     if (level < 0) {
1004        details = false;
1005        level = -level;
1006     }
1007
1008     if (level <= debug_level) {
1009        if (dbg_timestamp) {
1010           mtime = time(NULL);
1011           bstrftimes(buf, sizeof(buf), mtime);
1012           len = strlen(buf);
1013           buf[len++] = ' ';
1014           buf[len] = 0;
1015           pt_out(buf);
1016        }
1017     
1018 #ifdef FULL_LOCATION
1019        if (details) {
1020           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ", 
1021                 my_name, get_basename(file), line, get_jobid_from_tsd());
1022        } else {
1023           len = 0;
1024        }
1025 #else
1026        len = 0;
1027 #endif
1028        va_start(arg_ptr, fmt);
1029        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1030        va_end(arg_ptr);
1031
1032        pt_out(buf);
1033     }
1034 }
1035
1036 /*
1037  * Set trace flag on/off. If argument is negative, there is no change
1038  */
1039 void set_trace(int trace_flag)
1040 {
1041    if (trace_flag < 0) {
1042       return;
1043    } else if (trace_flag > 0) {
1044       trace = true;
1045    } else {
1046       trace = false;
1047    }
1048    if (!trace && trace_fd) {
1049       FILE *ltrace_fd = trace_fd;
1050       trace_fd = NULL;
1051       bmicrosleep(0, 100000);         /* yield to prevent seg faults */
1052       fclose(ltrace_fd);
1053    }
1054 }
1055
1056 void set_hangup(int hangup_value)
1057 {
1058    if (hangup_value < 0) {
1059       return;
1060    } else {
1061       hangup = hangup_value;
1062    }
1063 }
1064
1065 int get_hangup(void)
1066 {
1067    return hangup;
1068 }
1069
1070 bool get_trace(void)
1071 {
1072    return trace;
1073 }
1074
1075 /*********************************************************************
1076  *
1077  *  This subroutine prints a message regardless of the debug level
1078  *
1079  *  If the level is negative, the details of file and line number
1080  *  are not printed.
1081  */
1082 void
1083 p_msg(const char *file, int line, int level, const char *fmt,...)
1084 {
1085     char      buf[5000];
1086     int       len;
1087     va_list   arg_ptr;
1088
1089 #ifdef FULL_LOCATION
1090     if (level >= 0) {
1091        len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1092     } else {
1093        len = 0;
1094     }
1095 #else
1096     len = 0;
1097 #endif
1098     va_start(arg_ptr, fmt);
1099     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1100     va_end(arg_ptr);
1101
1102     pt_out(buf);     
1103 }
1104
1105
1106 /*********************************************************************
1107  *
1108  *  subroutine writes a debug message to the trace file if the level number
1109  *  is less than or equal the debug_level. File and line numbers
1110  *  are included for more detail if desired, but not currently
1111  *  printed.
1112  *
1113  *  If the level is negative, the details of file and line number
1114  *  are not printed.
1115  */
1116 void
1117 t_msg(const char *file, int line, int level, const char *fmt,...)
1118 {
1119     char      buf[5000];
1120     int       len;
1121     va_list   arg_ptr;
1122     int       details = TRUE;
1123
1124     if (level < 0) {
1125        details = FALSE;
1126        level = -level;
1127     }
1128
1129     if (level <= debug_level) {
1130        if (!trace_fd) {
1131           bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1132           trace_fd = fopen(buf, "a+b");
1133        }
1134
1135 #ifdef FULL_LOCATION
1136        if (details) {
1137           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1138        } else {
1139           len = 0;
1140        }
1141 #else
1142        len = 0;
1143 #endif
1144        va_start(arg_ptr, fmt);
1145        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1146        va_end(arg_ptr);
1147        if (trace_fd != NULL) {
1148            fputs(buf, trace_fd);
1149            fflush(trace_fd);
1150        }
1151    }
1152 }
1153
1154 /* *********************************************************
1155  *
1156  * print an error message
1157  *
1158  */
1159 void
1160 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1161 {
1162     char     buf[5000];
1163     va_list   arg_ptr;
1164     int len;
1165
1166     /*
1167      * Check if we have a message destination defined.
1168      * We always report M_ABORT and M_ERROR_TERM
1169      */
1170     if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1171                          !bit_is_set(type, daemon_msgs->send_msg))) {
1172        return;                        /* no destination */
1173     }
1174     switch (type) {
1175     case M_ABORT:
1176        len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1177                my_name, get_basename(file), line);
1178        break;
1179     case M_ERROR_TERM:
1180        len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1181                my_name, get_basename(file), line);
1182        break;
1183     case M_FATAL:
1184        if (level == -1)            /* skip details */
1185           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1186        else
1187           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1188        break;
1189     case M_ERROR:
1190        if (level == -1)            /* skip details */
1191           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1192        else
1193           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1194        break;
1195     case M_WARNING:
1196        len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1197        break;
1198     case M_SECURITY:
1199        len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1200        break;
1201     default:
1202        len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1203        break;
1204     }
1205
1206     va_start(arg_ptr, fmt);
1207     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1208     va_end(arg_ptr);
1209
1210     dispatch_message(NULL, type, 0, buf);
1211
1212     if (type == M_ABORT) {
1213        char *p = 0;
1214        p[0] = 0;                      /* generate segmentation violation */
1215     }
1216     if (type == M_ERROR_TERM) {
1217        exit(1);
1218     }
1219 }
1220
1221 /* *********************************************************
1222  *
1223  * Generate a Job message
1224  *
1225  */
1226 void
1227 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1228 {
1229     char     rbuf[5000];
1230     va_list   arg_ptr;
1231     int len;
1232     MSGS *msgs;
1233     uint32_t JobId = 0;
1234
1235
1236     Dmsg1(850, "Enter Jmsg type=%d\n", type);
1237
1238     /* Special case for the console, which has a dir_bsock and JobId==0,
1239      *  in that case, we send the message directly back to the
1240      *  dir_bsock.
1241      */
1242     if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1243        BSOCK *dir = jcr->dir_bsock;
1244        va_start(arg_ptr, fmt);
1245        dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1246                                 fmt, arg_ptr);
1247        va_end(arg_ptr);
1248        jcr->dir_bsock->send();
1249        return;
1250     }
1251
1252     /* The watchdog thread can't use Jmsg directly, we always queued it */
1253     if (is_watchdog()) {
1254        va_start(arg_ptr, fmt);
1255        bvsnprintf(rbuf,  sizeof(rbuf), fmt, arg_ptr);
1256        va_end(arg_ptr);
1257        Qmsg(jcr, type, mtime, "%s", rbuf);
1258        return;
1259     }
1260
1261     msgs = NULL;
1262     if (!jcr) {
1263        jcr = get_jcr_from_tsd();
1264     }
1265     if (jcr) {
1266        if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1267           /* Dequeue messages to keep the original order  */
1268           dequeue_messages(jcr); 
1269        }
1270        msgs = jcr->jcr_msgs;
1271        JobId = jcr->JobId;
1272     }
1273     if (!msgs) {
1274        msgs = daemon_msgs;            /* if no jcr, we use daemon handler */
1275     }
1276
1277     /*
1278      * Check if we have a message destination defined.
1279      * We always report M_ABORT and M_ERROR_TERM
1280      */
1281     if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1282          !bit_is_set(type, msgs->send_msg)) {
1283        return;                        /* no destination */
1284     }
1285     switch (type) {
1286     case M_ABORT:
1287        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1288        break;
1289     case M_ERROR_TERM:
1290        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1291        break;
1292     case M_FATAL:
1293        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1294        if (jcr) {
1295           jcr->setJobStatus(JS_FatalError);
1296        }
1297        if (jcr && jcr->JobErrors == 0) {
1298           jcr->JobErrors = 1;
1299        }
1300        break;
1301     case M_ERROR:
1302        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1303        if (jcr) {
1304           jcr->JobErrors++;
1305        }
1306        break;
1307     case M_WARNING:
1308        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1309        if (jcr) {
1310           jcr->JobWarnings++;
1311        }
1312        break;
1313     case M_SECURITY:
1314        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "), 
1315                my_name, JobId);
1316        break;
1317     default:
1318        len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1319        break;
1320     }
1321
1322     va_start(arg_ptr, fmt);
1323     bvsnprintf(rbuf+len,  sizeof(rbuf)-len, fmt, arg_ptr);
1324     va_end(arg_ptr);
1325
1326     dispatch_message(jcr, type, mtime, rbuf);
1327
1328     if (type == M_ABORT){
1329        char *p = 0;
1330        printf("Bacula forced SEG FAULT to obtain traceback.\n");
1331        syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1332        p[0] = 0;                      /* generate segmentation violation */
1333     }
1334     if (type == M_ERROR_TERM) {
1335        exit(1);
1336     }
1337 }
1338
1339 /*
1340  * If we come here, prefix the message with the file:line-number,
1341  *  then pass it on to the normal Jmsg routine.
1342  */
1343 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1344 {
1345    va_list   arg_ptr;
1346    int i, len, maxlen;
1347    POOLMEM *pool_buf;
1348
1349    pool_buf = get_pool_memory(PM_EMSG);
1350    i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1351
1352    for (;;) {
1353       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1354       va_start(arg_ptr, fmt);
1355       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1356       va_end(arg_ptr);
1357       if (len < 0 || len >= (maxlen-5)) {
1358          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1359          continue;
1360       }
1361       break;
1362    }
1363
1364    Jmsg(jcr, type, mtime, "%s", pool_buf);
1365    free_memory(pool_buf);
1366 }
1367
1368
1369 /*
1370  * Edit a message into a Pool memory buffer, with file:lineno
1371  */
1372 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1373 {
1374    va_list   arg_ptr;
1375    int i, len, maxlen;
1376
1377    i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1378
1379    for (;;) {
1380       maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1381       va_start(arg_ptr, fmt);
1382       len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1383       va_end(arg_ptr);
1384       if (len < 0 || len >= (maxlen-5)) {
1385          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1386          continue;
1387       }
1388       break;
1389    }
1390    return len;
1391 }
1392
1393 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1394 {
1395    va_list   arg_ptr;
1396    int i, len, maxlen;
1397
1398    i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1399
1400    for (;;) {
1401       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1402       va_start(arg_ptr, fmt);
1403       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1404       va_end(arg_ptr);
1405       if (len < 0 || len >= (maxlen-5)) {
1406          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1407          continue;
1408       }
1409       break;
1410    }
1411    return len;
1412 }
1413
1414
1415 /*
1416  * Edit a message into a Pool Memory buffer NO file:lineno
1417  *  Returns: string length of what was edited.
1418  */
1419 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1420 {
1421    va_list   arg_ptr;
1422    int len, maxlen;
1423
1424    for (;;) {
1425       maxlen = sizeof_pool_memory(*pool_buf) - 1;
1426       va_start(arg_ptr, fmt);
1427       len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1428       va_end(arg_ptr);
1429       if (len < 0 || len >= (maxlen-5)) {
1430          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1431          continue;
1432       }
1433       break;
1434    }
1435    return len;
1436 }
1437
1438 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1439 {
1440    va_list   arg_ptr;
1441    int len, maxlen;
1442
1443    for (;;) {
1444       maxlen = sizeof_pool_memory(pool_buf) - 1;
1445       va_start(arg_ptr, fmt);
1446       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1447       va_end(arg_ptr);
1448       if (len < 0 || len >= (maxlen-5)) {
1449          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1450          continue;
1451       }
1452       break;
1453    }
1454    return len;
1455 }
1456
1457 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1458 {
1459    va_list   arg_ptr;
1460    int len, maxlen;
1461
1462    for (;;) {
1463       maxlen = pool_buf.max_size() - 1;
1464       va_start(arg_ptr, fmt);
1465       len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1466       va_end(arg_ptr);
1467       if (len < 0 || len >= (maxlen-5)) {
1468          pool_buf.realloc_pm(maxlen + maxlen/2);
1469          continue;
1470       }
1471       break;
1472    }
1473    return len;
1474 }
1475
1476
1477 /*
1478  * We queue messages rather than print them directly. This
1479  *  is generally used in low level routines (msg handler, bnet)
1480  *  to prevent recursion (i.e. if you are in the middle of
1481  *  sending a message, it is a bit messy to recursively call
1482  *  yourself when the bnet packet is not reentrant).
1483  */
1484 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1485 {
1486    va_list   arg_ptr;
1487    int len, maxlen;
1488    POOLMEM *pool_buf;
1489    MQUEUE_ITEM *item;
1490
1491    pool_buf = get_pool_memory(PM_EMSG);
1492
1493    for (;;) {
1494       maxlen = sizeof_pool_memory(pool_buf) - 1;
1495       va_start(arg_ptr, fmt);
1496       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1497       va_end(arg_ptr);
1498       if (len < 0 || len >= (maxlen-5)) {
1499          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1500          continue;
1501       }
1502       break;
1503    }
1504    item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1505    item->type = type;
1506    item->mtime = time(NULL);
1507    strcpy(item->msg, pool_buf);
1508    if (!jcr) {
1509       jcr = get_jcr_from_tsd();
1510    }
1511    /* If no jcr or no queue or dequeuing send to syslog */
1512    if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1513       syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1514       free(item);
1515    } else {
1516       /* Queue message for later sending */
1517       P(jcr->msg_queue_mutex);
1518       jcr->msg_queue->append(item);
1519       V(jcr->msg_queue_mutex);
1520    }
1521    free_memory(pool_buf);
1522 }
1523
1524 /*
1525  * Dequeue messages
1526  */
1527 void dequeue_messages(JCR *jcr)
1528 {
1529    MQUEUE_ITEM *item;
1530    if (!jcr->msg_queue) {
1531       return;
1532    }
1533    P(jcr->msg_queue_mutex);
1534    jcr->dequeuing_msgs = true;
1535    foreach_dlist(item, jcr->msg_queue) {
1536       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1537    }
1538    /* Remove messages just sent */
1539    jcr->msg_queue->destroy();
1540    jcr->dequeuing_msgs = false;
1541    V(jcr->msg_queue_mutex);
1542 }
1543
1544
1545 /*
1546  * If we come here, prefix the message with the file:line-number,
1547  *  then pass it on to the normal Qmsg routine.
1548  */
1549 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1550 {
1551    va_list   arg_ptr;
1552    int i, len, maxlen;
1553    POOLMEM *pool_buf;
1554
1555    pool_buf = get_pool_memory(PM_EMSG);
1556    i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1557
1558    for (;;) {
1559       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1560       va_start(arg_ptr, fmt);
1561       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1562       va_end(arg_ptr);
1563       if (len < 0 || len >= (maxlen-5)) {
1564          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1565          continue;
1566       }
1567       break;
1568    }
1569
1570    Qmsg(jcr, type, mtime, "%s", pool_buf);
1571    free_memory(pool_buf);
1572 }