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