]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/message.c
- Put Dmsg() on inside if() to avoid calling subroutine.
[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-2005 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 ammended 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)
30 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
31 #include <windows.h>
32 #endif
33 #endif
34
35 #define FULL_LOCATION 1               /* set for file:line in Debug messages */
36
37 /*
38  *  This is where we define "Globals" because all the
39  *    daemons include this file.
40  */
41 const char *working_directory = NULL;       /* working directory path stored here */
42 int verbose = 0;                      /* increase User messages */
43 int debug_level = 0;                  /* debug level */
44 time_t daemon_start_time = 0;         /* Daemon start time */
45 const char *version = VERSION " (" BDATE ")";
46 char my_name[30];                     /* daemon name is stored here */
47 char *exepath = (char *)NULL;
48 char *exename = (char *)NULL;
49 int console_msg_pending = 0;
50 char con_fname[500];                  /* Console filename */
51 FILE *con_fd = NULL;                  /* Console file descriptor */
52 brwlock_t con_lock;                   /* Console lock structure */
53
54 #ifdef HAVE_POSTGRESQL
55 char catalog_db[] = "PostgreSQL";
56 #else
57 #ifdef HAVE_MYSQL
58 char catalog_db[] = "MySQL";
59 #else
60 #ifdef HAVE_SQLITE
61 char catalog_db[] = "SQLite";
62 #else
63 char catalog_db[] = "Internal";
64 #endif
65 #endif
66 #endif
67
68 const char *host_os = HOST_OS;
69 const char *distname = DISTNAME;
70 const char *distver = DISTVER;
71 static FILE *trace_fd = NULL;
72 #ifdef HAVE_WIN32
73 static bool trace = true;
74 #else
75 static bool trace = false;
76 #endif
77
78 /* Forward referenced functions */
79
80 /* Imported functions */
81
82
83 /* Static storage */
84
85 /* Used to allow only one thread close the daemon messages at a time */
86 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
87 static MSGS *daemon_msgs;              /* global messages */
88
89
90 /*
91  * Set daemon name. Also, find canonical execution
92  *  path.  Note, exepath has spare room for tacking on
93  *  the exename so that we can reconstruct the full name.
94  *
95  * Note, this routine can get called multiple times
96  *  The second time is to put the name as found in the
97  *  Resource record. On the second call, generally,
98  *  argv is NULL to avoid doing the path code twice.
99  */
100 #define BTRACE_EXTRA 20
101 void my_name_is(int argc, char *argv[], const char *name)
102 {
103    char *l, *p, *q;
104    char cpath[1024];
105    int len;
106
107    bstrncpy(my_name, name, sizeof(my_name));
108    if (argc>0 && argv && argv[0]) {
109       /* strip trailing filename and save exepath */
110       for (l=p=argv[0]; *p; p++) {
111          if (*p == '/') {
112             l = p;                       /* set pos of last slash */
113          }
114       }
115       if (*l == '/') {
116          l++;
117       } else {
118          l = argv[0];
119 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
120          /* On Windows allow c: junk */
121          if (l[1] == ':') {
122             l += 2;
123          }
124 #endif
125       }
126       len = strlen(l) + 1;
127       if (exename) {
128          free(exename);
129       }
130       exename = (char *)malloc(len);
131       strcpy(exename, l);
132
133       if (exepath) {
134          free(exepath);
135       }
136       exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
137       for (p=argv[0],q=exepath; p < l; ) {
138          *q++ = *p++;
139       }
140       *q = 0;
141       if (strchr(exepath, '.') || exepath[0] != '/') {
142          if (getcwd(cpath, sizeof(cpath))) {
143             free(exepath);
144             exepath = (char *)malloc(strlen(cpath) + 1 + len);
145             strcpy(exepath, cpath);
146          }
147       }
148       Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
149    }
150 }
151
152 /*
153  * Initialize message handler for a daemon or a Job
154  *   We make a copy of the MSGS resource passed, so it belows
155  *   to the job or daemon and thus can be modified.
156  *
157  *   NULL for jcr -> initialize global messages for daemon
158  *   non-NULL     -> initialize jcr using Message resource
159  */
160 void
161 init_msg(JCR *jcr, MSGS *msg)
162 {
163    DEST *d, *dnew, *temp_chain = NULL;
164    int i;
165
166    if (jcr == NULL && msg == NULL) {
167       init_last_jobs_list();
168    }
169
170 #ifndef 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    fd = open("/dev/null", O_RDONLY, 0644);
180    if (fd > 2) {
181       close(fd);
182    } else {
183       for(i=1; fd + i <= 2; i++) {
184          dup2(fd, fd+i);
185       }
186    }
187
188 #endif
189    /*
190     * If msg is NULL, initialize global chain for STDOUT and syslog
191     */
192    if (msg == NULL) {
193       daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
194       memset(daemon_msgs, 0, sizeof(MSGS));
195       for (i=1; i<=M_MAX; i++) {
196 #ifndef WIN32
197          add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
198 #endif
199          add_msg_dest(daemon_msgs, MD_SYSLOG, i, NULL, NULL);
200       }
201       Dmsg1(050, "Create daemon global message resource 0x%x\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 0x%x to 0x%x\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+");
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=%x 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=%x 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=%x 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=%x 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.mail.%s.%d", working_directory, my_name,
349                  jcr->Job, (int)(long)d);
350    } else {
351       Mmsg(name, "%s/%s.mail.%s.%d", 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: Bacula Message\r\n\r\n");
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(850, "Close_msg jcr=0x%x\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 0x%x\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 #ifndef 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_CONSOLE:
607                 Dmsg1(850, "CONSOLE for following msg: %s", msg);
608                 if (!con_fd) {
609                    con_fd = fopen(con_fname, "a+");
610                    Dmsg0(850, "Console file not open.\n");
611                 }
612                 if (con_fd) {
613                    Pw(con_lock);      /* get write lock on console message file */
614                    errno = 0;
615                    if (dtlen) {
616                       fwrite(dt, dtlen, 1, con_fd);
617                    }
618                    len = strlen(msg);
619                    if (len > 0) {
620                       fwrite(msg, len, 1, con_fd);
621                       if (msg[len-1] != '\n') {
622                          fwrite("\n", 2, 1, con_fd);
623                       }
624                    } else {
625                       fwrite("\n", 2, 1, con_fd);
626                    }
627                    fflush(con_fd);
628                    console_msg_pending = TRUE;
629                    Vw(con_lock);
630                 }
631                 break;
632              case MD_SYSLOG:
633                 Dmsg1(850, "SYSLOG for collowing msg: %s\n", msg);
634                 /*
635                  * We really should do an openlog() here.
636                  */
637                 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
638                 break;
639              case MD_OPERATOR:
640                 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
641                 mcmd = get_pool_memory(PM_MESSAGE);
642                 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
643                    int stat;
644                    fputs(dt, bpipe->wfd);
645                    fputs(msg, bpipe->wfd);
646                    /* Messages to the operator go one at a time */
647                    stat = close_bpipe(bpipe);
648                    if (stat != 0) {
649                       berrno be;
650                       be.set_errno(stat);
651                       Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n"
652                             "CMD=%s\n"
653                             "ERR=%s\n"), mcmd, be.strerror());
654                    }
655                 }
656                 free_pool_memory(mcmd);
657                 break;
658              case MD_MAIL:
659              case MD_MAIL_ON_ERROR:
660                 Dmsg1(850, "MAIL for following msg: %s", msg);
661                 if (!d->fd) {
662                    POOLMEM *name = get_pool_memory(PM_MESSAGE);
663                    make_unique_mail_filename(jcr, name, d);
664                    d->fd = fopen(name, "w+");
665                    if (!d->fd) {
666                       berrno be;
667                       d->fd = stdout;
668                       Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", name,
669                             be.strerror());
670                       d->fd = NULL;
671                       free_pool_memory(name);
672                       break;
673                    }
674                    d->mail_filename = name;
675                 }
676                 fputs(dt, d->fd);
677                 len = strlen(msg) + dtlen;;
678                 if (len > d->max_len) {
679                    d->max_len = len;      /* keep max line length */
680                 }
681                 fputs(msg, d->fd);
682                 break;
683              case MD_FILE:
684                 Dmsg1(850, "FILE for following msg: %s", msg);
685                 if (!d->fd) {
686                    d->fd = fopen(d->where, "w+");
687                    if (!d->fd) {
688                       berrno be;
689                       d->fd = stdout;
690                       Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", d->where,
691                             be.strerror());
692                       d->fd = NULL;
693                       break;
694                    }
695                 }
696                 fputs(dt, d->fd);
697                 fputs(msg, d->fd);
698                 break;
699              case MD_APPEND:
700                 Dmsg1(850, "APPEND for following msg: %s", msg);
701                 if (!d->fd) {
702                    d->fd = fopen(d->where, "a");
703                    if (!d->fd) {
704                       berrno be;
705                       d->fd = stdout;
706                       Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", d->where,
707                             be.strerror());
708                       d->fd = NULL;
709                       break;
710                    }
711                 }
712                 fputs(dt, d->fd);
713                 fputs(msg, d->fd);
714                 break;
715              case MD_DIRECTOR:
716                 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
717                 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
718                    bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s",
719                       jcr->Job, type, mtime, msg);
720                 }
721                 break;
722              case MD_STDOUT:
723                 Dmsg1(850, "STDOUT for following msg: %s", msg);
724                 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
725                    fputs(dt, stdout);
726                    fputs(msg, stdout);
727                 }
728                 break;
729              case MD_STDERR:
730                 Dmsg1(850, "STDERR for following msg: %s", msg);
731                 fputs(dt, stderr);
732                 fputs(msg, stderr);
733                 break;
734              default:
735                 break;
736           }
737        }
738     }
739 }
740
741
742 /*********************************************************************
743  *
744  *  This subroutine prints a debug message if the level number
745  *  is less than or equal the debug_level. File and line numbers
746  *  are included for more detail if desired, but not currently
747  *  printed.
748  *
749  *  If the level is negative, the details of file and line number
750  *  are not printed.
751  */
752 void
753 d_msg(const char *file, int line, int level, const char *fmt,...)
754 {
755     char      buf[5000];
756     int       len;
757     va_list   arg_ptr;
758     bool      details = true;
759
760     if (level < 0) {
761        details = false;
762        level = -level;
763     }
764
765     if (level <= debug_level) {
766 #ifdef FULL_LOCATION
767        if (details) {
768           /* visual studio passes the whole path to the file as well
769            * which makes for very long lines
770            */
771           const char *f = strrchr(file, '\\');
772           if (f) file = f + 1;
773           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line);
774        } else {
775           len = 0;
776        }
777 #else
778        len = 0;
779 #endif
780        va_start(arg_ptr, fmt);
781        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
782        va_end(arg_ptr);
783
784        /*
785         * Used the "trace on" command in the console to turn on
786         *  output to the trace file.  "trace off" will close the file.
787         */
788        if (trace) {
789           if (!trace_fd) {
790              bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory ? working_directory : ".");
791              trace_fd = fopen(buf, "a+");
792           }
793           if (trace_fd) {
794              fputs(buf, trace_fd);
795              fflush(trace_fd);
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+");
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 //    Dmsg1(000, "queue item=%lu\n", (long unsigned)item);
1254    }
1255    free_memory(pool_buf);
1256 }
1257
1258 /*
1259  * Dequeue messages
1260  */
1261 void dequeue_messages(JCR *jcr)
1262 {
1263    MQUEUE_ITEM *item;
1264    P(msg_queue_mutex);
1265    jcr->dequeuing = true;
1266    foreach_dlist(item, jcr->msg_queue) {
1267 //    Dmsg1(000, "dequeue item=%lu\n", (long unsigned)item);
1268       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1269    }
1270    jcr->msg_queue->destroy();
1271    jcr->dequeuing = false;
1272    V(msg_queue_mutex);
1273 }
1274
1275
1276 /*
1277  * If we come here, prefix the message with the file:line-number,
1278  *  then pass it on to the normal Qmsg routine.
1279  */
1280 void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1281 {
1282    va_list   arg_ptr;
1283    int i, len, maxlen;
1284    POOLMEM *pool_buf;
1285
1286    pool_buf = get_pool_memory(PM_EMSG);
1287    i = Mmsg(pool_buf, "%s:%d ", file, line);
1288
1289    for (;;) {
1290       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1291       va_start(arg_ptr, fmt);
1292       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1293       va_end(arg_ptr);
1294       if (len < 0 || len >= (maxlen-5)) {
1295          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1296          continue;
1297       }
1298       break;
1299    }
1300
1301    Qmsg(jcr, type, mtime, "%s", pool_buf);
1302    free_memory(pool_buf);
1303 }