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