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