]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/message.c
- Inhibit printing of FileSet for a restore as it is misleading.
[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[400], npath[400];
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(050, "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(150, "===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(150, "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(150, "Opened mail pipe\n");
456             len = d->max_len+10;
457             line = get_memory(len);
458             rewind(d->fd);
459             while (fgets(mp_chr(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(mp_chr(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(150, "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(mp_chr(d->mail_filename));
492             free_pool_memory(d->mail_filename);
493             d->mail_filename = NULL;
494             Dmsg0(150, "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(150, "Done walking message chain.\n");
505    if (jcr) {
506       free_msgs_res(msgs);
507       msgs = NULL;
508    } else {
509       V(mutex);
510    }
511    Dmsg0(150, "===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(100, "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(mp_chr(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 /*********************************************************************
820  *
821  *  This subroutine prints a message regardless of the debug level
822  *  
823  *  If the level is negative, the details of file and line number
824  *  are not printed.
825  */
826 void 
827 p_msg(const char *file, int line, int level, const char *fmt,...)
828 {
829     char      buf[5000];
830     int       len;
831     va_list   arg_ptr;
832
833 #ifdef FULL_LOCATION
834     if (level >= 0) {
835        len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line);
836     } else {
837        len = 0;
838     }
839 #else
840     len = 0;
841 #endif
842     va_start(arg_ptr, fmt);
843     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
844     va_end(arg_ptr);
845     fputs(buf, stdout);
846 }
847
848
849 /*********************************************************************
850  *
851  *  subroutine writes a debug message to the trace file if the level number
852  *  is less than or equal the debug_level. File and line numbers
853  *  are included for more detail if desired, but not currently
854  *  printed.
855  *  
856  *  If the level is negative, the details of file and line number
857  *  are not printed.
858  */
859 void 
860 t_msg(const char *file, int line, int level, const char *fmt,...)
861 {
862     char      buf[5000];
863     int       len;
864     va_list   arg_ptr;
865     int       details = TRUE;
866
867     if (level < 0) {
868        details = FALSE;
869        level = -level;
870     }
871
872     if (level <= debug_level) {
873        if (!trace_fd) {
874           bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory);
875           trace_fd = fopen(buf, "a+");
876        }
877     
878 #ifdef FULL_LOCATION
879        if (details) {
880           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line);
881        } else {
882           len = 0;
883        }
884 #else
885        len = 0;
886 #endif
887        va_start(arg_ptr, fmt);
888        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
889        va_end(arg_ptr);
890        if (trace_fd != NULL) {
891            fputs(buf, trace_fd);
892            fflush(trace_fd);
893        }
894    }
895 }
896
897
898
899 /* *********************************************************
900  *
901  * print an error message
902  *
903  */
904 void 
905 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
906 {
907     char     buf[5000];
908     va_list   arg_ptr;
909     int len;
910
911     /* 
912      * Check if we have a message destination defined.  
913      * We always report M_ABORT and M_ERROR_TERM 
914      */
915     if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) && 
916                          !bit_is_set(type, daemon_msgs->send_msg))) {
917        return;                        /* no destination */
918     }
919     switch (type) {
920     case M_ABORT:
921        len = bsnprintf(buf, sizeof(buf), "%s: ABORTING due to ERROR in %s:%d\n", 
922                my_name, file, line);
923        break;
924     case M_ERROR_TERM:
925        len = bsnprintf(buf, sizeof(buf), "%s: ERROR TERMINATION at %s:%d\n", 
926                my_name, file, line);
927        break;
928     case M_FATAL:
929        if (level == -1)            /* skip details */
930           len = bsnprintf(buf, sizeof(buf), "%s: Fatal Error because: ", my_name);
931        else
932           len = bsnprintf(buf, sizeof(buf), "%s: Fatal Error at %s:%d because:\n", my_name, file, line);
933        break;
934     case M_ERROR:
935        if (level == -1)            /* skip details */
936           len = bsnprintf(buf, sizeof(buf), "%s: ERROR: ", my_name);
937        else
938           len = bsnprintf(buf, sizeof(buf), "%s: ERROR in %s:%d ", my_name, file, line);
939        break;
940     case M_WARNING:
941        len = bsnprintf(buf, sizeof(buf), "%s: Warning: ", my_name);
942        break;
943     case M_SECURITY:
944        len = bsnprintf(buf, sizeof(buf), "%s: Security violation: ", my_name);
945        break;
946     default:
947        len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
948        break;
949     }
950
951     va_start(arg_ptr, fmt);
952     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
953     va_end(arg_ptr);
954
955     dispatch_message(NULL, type, level, buf);
956
957     if (type == M_ABORT) {
958        char *p = 0;
959        p[0] = 0;                      /* generate segmentation violation */
960     }
961     if ((type == M_ERROR_TERM) && exit_on_error) {
962        exit(1);
963     }
964 }
965
966 /* *********************************************************
967  *
968  * Generate a Job message
969  *
970  */
971 void 
972 Jmsg(JCR *jcr, int type, int level, const char *fmt,...)
973 {
974     char     rbuf[5000];
975     va_list   arg_ptr;
976     int len;
977     MSGS *msgs;
978     const char *job;
979
980     
981     Dmsg1(800, "Enter Jmsg type=%d\n", type);
982
983     /* Special case for the console, which has a dir_bsock and JobId==0,
984      *  in that case, we send the message directly back to the
985      *  dir_bsock.  
986      */
987     if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
988        BSOCK *dir = jcr->dir_bsock;
989        va_start(arg_ptr, fmt);
990        dir->msglen = bvsnprintf(mp_chr(dir->msg), sizeof_pool_memory(dir->msg), 
991                                 fmt, arg_ptr);
992        va_end(arg_ptr);
993        bnet_send(jcr->dir_bsock);
994        return;
995     }
996
997     msgs = NULL;
998     job = NULL;
999     if (jcr) {
1000        msgs = jcr->jcr_msgs;
1001        job = jcr->Job;
1002     } 
1003     if (!msgs) {
1004        msgs = daemon_msgs;            /* if no jcr, we use daemon handler */
1005     }
1006     if (!job) {
1007        job = "";                      /* Set null job name if none */
1008     }
1009
1010     /* 
1011      * Check if we have a message destination defined.  
1012      * We always report M_ABORT and M_ERROR_TERM 
1013      */
1014     if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1015          !bit_is_set(type, msgs->send_msg)) {
1016        return;                        /* no destination */
1017     }
1018     switch (type) {
1019     case M_ABORT:
1020        len = bsnprintf(rbuf, sizeof(rbuf), "%s ABORTING due to ERROR\n", my_name);
1021        break;
1022     case M_ERROR_TERM:
1023        len = bsnprintf(rbuf, sizeof(rbuf), "%s ERROR TERMINATION\n", my_name);
1024        break;
1025     case M_FATAL:
1026        len = bsnprintf(rbuf, sizeof(rbuf), "%s: %s Fatal error: ", my_name, job);
1027        if (jcr) {
1028           set_jcr_job_status(jcr, JS_FatalError);
1029        }
1030        break;
1031     case M_ERROR:
1032        len = bsnprintf(rbuf, sizeof(rbuf), "%s: %s Error: ", my_name, job);
1033        if (jcr) {
1034           jcr->Errors++;
1035        }
1036        break;
1037     case M_WARNING:
1038        len = bsnprintf(rbuf, sizeof(rbuf), "%s: %s Warning: ", my_name, job);
1039        break;
1040     case M_SECURITY:
1041        len = bsnprintf(rbuf, sizeof(rbuf), "%s: %s Security violation: ", my_name, job);
1042        break;
1043     default:
1044        len = bsnprintf(rbuf, sizeof(rbuf), "%s: ", my_name);
1045        break;
1046     }
1047
1048     va_start(arg_ptr, fmt);
1049     bvsnprintf(rbuf+len,  sizeof(rbuf)-len, fmt, arg_ptr);
1050     va_end(arg_ptr);
1051
1052     dispatch_message(jcr, type, level, rbuf);
1053
1054     if (type == M_ABORT){
1055        char *p = 0;
1056        p[0] = 0;                      /* generate segmentation violation */
1057     }
1058     if ((type == M_ERROR_TERM) && exit_on_error) {
1059        exit(1);
1060     }
1061 }
1062
1063 /*
1064  * If we come here, prefix the message with the file:line-number,
1065  *  then pass it on to the normal Jmsg routine.
1066  */
1067 void j_msg(const char *file, int line, JCR *jcr, int type, int level, const char *fmt,...)
1068 {
1069    va_list   arg_ptr;
1070    int i, len, maxlen;
1071    POOLMEM *pool_buf;
1072
1073    pool_buf = get_pool_memory(PM_EMSG);
1074    i = Mmsg(pool_buf, "%s:%d ", file, line);
1075
1076    for (;;) {
1077       maxlen = sizeof_pool_memory(pool_buf) - i - 1; 
1078       va_start(arg_ptr, fmt);
1079       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1080       va_end(arg_ptr);
1081       if (len < 0 || len >= (maxlen-5)) {
1082          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1083          continue;
1084       }
1085       break;
1086    }
1087
1088    Jmsg(jcr, type, level, "%s", pool_buf);
1089    free_memory(pool_buf);
1090 }
1091
1092
1093 /*
1094  * Edit a message into a Pool memory buffer, with file:lineno
1095  */                                                  
1096 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1097 {
1098    va_list   arg_ptr;
1099    int i, len, maxlen;
1100
1101    i = sprintf(mp_chr(*pool_buf), "%s:%d ", file, line);
1102
1103    for (;;) {
1104       maxlen = sizeof_pool_memory(*pool_buf) - i - 1; 
1105       va_start(arg_ptr, fmt);
1106       len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1107       va_end(arg_ptr);
1108       if (len < 0 || len >= (maxlen-5)) {
1109          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1110          continue;
1111       }
1112       break;
1113    }
1114    return len;
1115 }
1116
1117 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1118 {
1119    va_list   arg_ptr;
1120    int i, len, maxlen;
1121
1122    i = sprintf(pool_buf, "%s:%d ", file, line);
1123
1124    for (;;) {
1125       maxlen = sizeof_pool_memory(pool_buf) - i - 1; 
1126       va_start(arg_ptr, fmt);
1127       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1128       va_end(arg_ptr);
1129       if (len < 0 || len >= (maxlen-5)) {
1130          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1131          continue;
1132       }
1133       break;
1134    }
1135    return len;
1136 }
1137
1138
1139 /*
1140  * Edit a message into a Pool Memory buffer NO file:lineno
1141  *  Returns: string length of what was edited.
1142  */
1143 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1144 {
1145    va_list   arg_ptr;
1146    int len, maxlen;
1147
1148    for (;;) {
1149       maxlen = sizeof_pool_memory(*pool_buf) - 1; 
1150       va_start(arg_ptr, fmt);
1151       len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1152       va_end(arg_ptr);
1153       if (len < 0 || len >= (maxlen-5)) {
1154          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1155          continue;
1156       }
1157       break;
1158    }
1159    return len;
1160 }
1161
1162 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1163 {
1164    va_list   arg_ptr;
1165    int len, maxlen;
1166
1167    for (;;) {
1168       maxlen = sizeof_pool_memory(pool_buf) - 1; 
1169       va_start(arg_ptr, fmt);
1170       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1171       va_end(arg_ptr);
1172       if (len < 0 || len >= (maxlen-5)) {
1173          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1174          continue;
1175       }
1176       break;
1177    }
1178    return len;
1179 }
1180
1181
1182 static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
1183
1184 /*
1185  * We queue messages rather than print them directly. This
1186  *  is generally used in low level routines (msg handler, bnet)
1187  *  to prevent recursion (i.e. if you are in the middle of 
1188  *  sending a message, it is a bit messy to recursively call
1189  *  yourself when the bnet packet is not reentrant).
1190  */
1191 void Qmsg(JCR *jcr, int type, int level, const char *fmt,...)
1192 {
1193    va_list   arg_ptr;
1194    int len, maxlen;
1195    POOLMEM *pool_buf;
1196    MQUEUE_ITEM *item;
1197
1198    pool_buf = get_pool_memory(PM_EMSG);
1199
1200    for (;;) {
1201       maxlen = sizeof_pool_memory(pool_buf) - 1; 
1202       va_start(arg_ptr, fmt);
1203       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1204       va_end(arg_ptr);
1205       if (len < 0 || len >= (maxlen-5)) {
1206          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1207          continue;
1208       }
1209       break;
1210    }
1211    item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1212    item->type = type;
1213    item->level = level;
1214    strcpy(item->msg, pool_buf);  
1215    P(msg_queue_mutex);
1216    /* If no jcr or dequeuing send to daemon to avoid recursion */
1217    if (!jcr || jcr->dequeuing) {
1218       /* jcr==NULL => daemon message, safe to send now */
1219       Jmsg(NULL, item->type, item->level, "%s", item->msg);
1220       free(item);
1221    } else {
1222       /* Queue message for later sending */
1223       jcr->msg_queue->append(item);
1224 //    Dmsg1(000, "queue item=%lu\n", (long unsigned)item);
1225    }
1226    V(msg_queue_mutex);
1227    free_memory(pool_buf);
1228 }
1229
1230 /*
1231  * Dequeue messages 
1232  */
1233 void dequeue_messages(JCR *jcr)
1234 {
1235    MQUEUE_ITEM *item;
1236    P(msg_queue_mutex);
1237    jcr->dequeuing = true;
1238    foreach_dlist(item, jcr->msg_queue) {
1239 //    Dmsg1(000, "dequeue item=%lu\n", (long unsigned)item);
1240       Jmsg(jcr, item->type, item->level, "%s", item->msg);
1241    }
1242    jcr->msg_queue->destroy();
1243    jcr->dequeuing = false;
1244    V(msg_queue_mutex);
1245 }                                                 
1246
1247
1248 /*
1249  * If we come here, prefix the message with the file:line-number,
1250  *  then pass it on to the normal Qmsg routine.
1251  */
1252 void q_msg(const char *file, int line, JCR *jcr, int type, int level, const char *fmt,...)
1253 {
1254    va_list   arg_ptr;
1255    int i, len, maxlen;
1256    POOLMEM *pool_buf;
1257
1258    pool_buf = get_pool_memory(PM_EMSG);
1259    i = Mmsg(pool_buf, "%s:%d ", file, line);
1260
1261    for (;;) {
1262       maxlen = sizeof_pool_memory(pool_buf) - i - 1; 
1263       va_start(arg_ptr, fmt);
1264       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1265       va_end(arg_ptr);
1266       if (len < 0 || len >= (maxlen-5)) {
1267          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1268          continue;
1269       }
1270       break;
1271    }
1272
1273    Qmsg(jcr, type, level, "%s", pool_buf);
1274    free_memory(pool_buf);
1275 }
1276
1277 /* 
1278  * Define if e_msg must exit when M_ERROR_TERM is received
1279  */
1280 void set_exit_on_error(int value) {
1281    exit_on_error = value;
1282 }