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