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