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