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