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