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