]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/message.c
Strip pathname portion off all message routines that print filename:line.
[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                    bstrftimes(dt, sizeof(dt), mtime);
606                    Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
607                          edit_int64(jcr->JobId, ed1), dt, msg);
608                    p_sql_query(jcr, cmd.c_str());
609                 }
610                 break;
611              case MD_CONSOLE:
612                 Dmsg1(850, "CONSOLE for following msg: %s", msg);
613                 if (!con_fd) {
614                    con_fd = fopen(con_fname, "a+b");
615                    Dmsg0(850, "Console file not open.\n");
616                 }
617                 if (con_fd) {
618                    Pw(con_lock);      /* get write lock on console message file */
619                    errno = 0;
620                    if (dtlen) {
621                       (void)fwrite(dt, dtlen, 1, con_fd);
622                    }
623                    len = strlen(msg);
624                    if (len > 0) {
625                       (void)fwrite(msg, len, 1, con_fd);
626                       if (msg[len-1] != '\n') {
627                          (void)fwrite("\n", 2, 1, con_fd);
628                       }
629                    } else {
630                       (void)fwrite("\n", 2, 1, con_fd);
631                    }
632                    fflush(con_fd);
633                    console_msg_pending = TRUE;
634                    Vw(con_lock);
635                 }
636                 break;
637              case MD_SYSLOG:
638                 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
639                 /*
640                  * We really should do an openlog() here.
641                  */
642                 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
643                 break;
644              case MD_OPERATOR:
645                 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
646                 mcmd = get_pool_memory(PM_MESSAGE);
647                 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
648                    int stat;
649                    fputs(dt, bpipe->wfd);
650                    fputs(msg, bpipe->wfd);
651                    /* Messages to the operator go one at a time */
652                    stat = close_bpipe(bpipe);
653                    if (stat != 0) {
654                       berrno be;
655                       be.set_errno(stat);
656                       Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n"
657                             "CMD=%s\n"
658                             "ERR=%s\n"), mcmd, be.strerror());
659                    }
660                 }
661                 free_pool_memory(mcmd);
662                 break;
663              case MD_MAIL:
664              case MD_MAIL_ON_ERROR:
665                 Dmsg1(850, "MAIL for following msg: %s", msg);
666                 if (!d->fd) {
667                    POOLMEM *name = get_pool_memory(PM_MESSAGE);
668                    make_unique_mail_filename(jcr, name, d);
669                    d->fd = fopen(name, "w+b");
670                    if (!d->fd) {
671                       berrno be;
672                       d->fd = stdout;
673                       Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), name,
674                             be.strerror());
675                       d->fd = NULL;
676                       free_pool_memory(name);
677                       break;
678                    }
679                    d->mail_filename = name;
680                 }
681                 fputs(dt, d->fd);
682                 len = strlen(msg) + dtlen;;
683                 if (len > d->max_len) {
684                    d->max_len = len;      /* keep max line length */
685                 }
686                 fputs(msg, d->fd);
687                 break;
688              case MD_FILE:
689                 Dmsg1(850, "FILE for following msg: %s", msg);
690                 if (!d->fd) {
691                    d->fd = fopen(d->where, "w+b");
692                    if (!d->fd) {
693                       berrno be;
694                       d->fd = stdout;
695                       Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where,
696                             be.strerror());
697                       d->fd = NULL;
698                       break;
699                    }
700                 }
701                 fputs(dt, d->fd);
702                 fputs(msg, d->fd);
703                 break;
704              case MD_APPEND:
705                 Dmsg1(850, "APPEND for following msg: %s", msg);
706                 if (!d->fd) {
707                    d->fd = fopen(d->where, "ab");
708                    if (!d->fd) {
709                       berrno be;
710                       d->fd = stdout;
711                       Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where,
712                             be.strerror());
713                       d->fd = NULL;
714                       break;
715                    }
716                 }
717                 fputs(dt, d->fd);
718                 fputs(msg, d->fd);
719                 break;
720              case MD_DIRECTOR:
721                 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
722                 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
723                    bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s",
724                       jcr->Job, type, mtime, msg);
725                 }
726                 break;
727              case MD_STDOUT:
728                 Dmsg1(850, "STDOUT for following msg: %s", msg);
729                 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
730                    fputs(dt, stdout);
731                    fputs(msg, stdout);
732                 }
733                 break;
734              case MD_STDERR:
735                 Dmsg1(850, "STDERR for following msg: %s", msg);
736                 fputs(dt, stderr);
737                 fputs(msg, stderr);
738                 break;
739              default:
740                 break;
741           }
742        }
743     }
744 }
745
746
747 /*********************************************************************
748  *
749  *  This subroutine prints a debug message if the level number
750  *  is less than or equal the debug_level. File and line numbers
751  *  are included for more detail if desired, but not currently
752  *  printed.
753  *
754  *  If the level is negative, the details of file and line number
755  *  are not printed.
756  */
757 void
758 d_msg(const char *file, int line, int level, const char *fmt,...)
759 {
760     char      buf[5000];
761     int       len;
762     va_list   arg_ptr;
763     bool      details = true;
764
765     if (level < 0) {
766        details = false;
767        level = -level;
768     }
769
770     if (level <= debug_level) {
771 #ifdef FULL_LOCATION
772        if (details) {
773           /* visual studio passes the whole path to the file as well
774            * which makes for very long lines
775            */
776           const char *basename;
777
778           if ((basename = strrchr(file, '\\')) == NULL) {
779              basename = file;
780           } else {
781              basename++;
782           }
783           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, basename, line);
784        } else {
785           len = 0;
786        }
787 #else
788        len = 0;
789 #endif
790        va_start(arg_ptr, fmt);
791        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
792        va_end(arg_ptr);
793
794        /*
795         * Used the "trace on" command in the console to turn on
796         *  output to the trace file.  "trace off" will close the file.
797         */
798        if (trace) {
799           if (!trace_fd) {
800              char fn[200];
801              bsnprintf(fn, sizeof(fn), "%s/bacula.trace", working_directory ? working_directory : ".");
802              trace_fd = fopen(fn, "a+b");
803           }
804           if (trace_fd) {
805              fputs(buf, trace_fd);
806              fflush(trace_fd);
807           } else {
808              /* Some problem, turn off tracing */
809              trace = false;
810           }
811        } else {   /* not tracing */
812           fputs(buf, stdout);
813        }
814     }
815 }
816
817 /*
818  * Set trace flag on/off. If argument is negative, there is no change
819  */
820 void set_trace(int trace_flag)
821 {
822    if (trace_flag < 0) {
823       return;
824    } else if (trace_flag > 0) {
825       trace = true;
826    } else {
827       trace = false;
828    }
829    if (!trace && trace_fd) {
830       FILE *ltrace_fd = trace_fd;
831       trace_fd = NULL;
832       bmicrosleep(0, 100000);         /* yield to prevent seg faults */
833       fclose(ltrace_fd);
834    }
835 }
836
837 bool get_trace(void)
838 {
839    return trace;
840 }
841
842 /*********************************************************************
843  *
844  *  This subroutine prints a message regardless of the debug level
845  *
846  *  If the level is negative, the details of file and line number
847  *  are not printed.
848  */
849 void
850 p_msg(const char *file, int line, int level, const char *fmt,...)
851 {
852     char      buf[5000];
853     int       len;
854     va_list   arg_ptr;
855
856 #ifdef FULL_LOCATION
857     if (level >= 0) {
858        const char *basename;
859
860        if ((basename = strrchr(file, '\\')) == NULL) {
861           basename = file;
862        } else {
863           basename++;
864        }
865        len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, basename, line);
866     } else {
867        len = 0;
868     }
869 #else
870     len = 0;
871 #endif
872     va_start(arg_ptr, fmt);
873     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
874     va_end(arg_ptr);
875     fputs(buf, stdout);
876 }
877
878
879 /*********************************************************************
880  *
881  *  subroutine writes a debug message to the trace file if the level number
882  *  is less than or equal the debug_level. File and line numbers
883  *  are included for more detail if desired, but not currently
884  *  printed.
885  *
886  *  If the level is negative, the details of file and line number
887  *  are not printed.
888  */
889 void
890 t_msg(const char *file, int line, int level, const char *fmt,...)
891 {
892     char      buf[5000];
893     int       len;
894     va_list   arg_ptr;
895     int       details = TRUE;
896
897     if (level < 0) {
898        details = FALSE;
899        level = -level;
900     }
901
902     if (level <= debug_level) {
903        if (!trace_fd) {
904           bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory);
905           trace_fd = fopen(buf, "a+b");
906        }
907
908 #ifdef FULL_LOCATION
909        if (details) {
910           const char *basename;
911
912           if ((basename = strrchr(file, '\\')) == NULL) {
913              basename = file;
914           } else {
915              basename++;
916           }
917           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, basename, line);
918        } else {
919           len = 0;
920        }
921 #else
922        len = 0;
923 #endif
924        va_start(arg_ptr, fmt);
925        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
926        va_end(arg_ptr);
927        if (trace_fd != NULL) {
928            fputs(buf, trace_fd);
929            fflush(trace_fd);
930        }
931    }
932 }
933
934
935
936 /* *********************************************************
937  *
938  * print an error message
939  *
940  */
941 void
942 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
943 {
944     char     buf[5000];
945     va_list   arg_ptr;
946     int len;
947
948     const char *basename;
949
950     if ((basename = strrchr(file, '\\')) == NULL) {
951        basename = file;
952     } else {
953        basename++;
954     }
955
956     /*
957      * Check if we have a message destination defined.
958      * We always report M_ABORT and M_ERROR_TERM
959      */
960     if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
961                          !bit_is_set(type, daemon_msgs->send_msg))) {
962        return;                        /* no destination */
963     }
964     switch (type) {
965     case M_ABORT:
966        len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
967                my_name, basename, line);
968        break;
969     case M_ERROR_TERM:
970        len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
971                my_name, basename, line);
972        break;
973     case M_FATAL:
974        if (level == -1)            /* skip details */
975           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
976        else
977           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, basename, line);
978        break;
979     case M_ERROR:
980        if (level == -1)            /* skip details */
981           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
982        else
983           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, basename, line);
984        break;
985     case M_WARNING:
986        len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
987        break;
988     case M_SECURITY:
989        len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
990        break;
991     default:
992        len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
993        break;
994     }
995
996     va_start(arg_ptr, fmt);
997     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
998     va_end(arg_ptr);
999
1000     dispatch_message(NULL, type, 0, buf);
1001
1002     if (type == M_ABORT) {
1003        char *p = 0;
1004        p[0] = 0;                      /* generate segmentation violation */
1005     }
1006     if (type == M_ERROR_TERM) {
1007        exit(1);
1008     }
1009 }
1010
1011 /* *********************************************************
1012  *
1013  * Generate a Job message
1014  *
1015  */
1016 void
1017 Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1018 {
1019     char     rbuf[5000];
1020     va_list   arg_ptr;
1021     int len;
1022     MSGS *msgs;
1023     const char *job;
1024
1025
1026     Dmsg1(850, "Enter Jmsg type=%d\n", type);
1027
1028     /* Special case for the console, which has a dir_bsock and JobId==0,
1029      *  in that case, we send the message directly back to the
1030      *  dir_bsock.
1031      */
1032     if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1033        BSOCK *dir = jcr->dir_bsock;
1034        va_start(arg_ptr, fmt);
1035        dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1036                                 fmt, arg_ptr);
1037        va_end(arg_ptr);
1038        bnet_send(jcr->dir_bsock);
1039        return;
1040     }
1041
1042     msgs = NULL;
1043     job = NULL;
1044     if (jcr) {
1045        msgs = jcr->jcr_msgs;
1046        job = jcr->Job;
1047     }
1048     if (!msgs) {
1049        msgs = daemon_msgs;            /* if no jcr, we use daemon handler */
1050     }
1051     if (!job) {
1052        job = "";                      /* Set null job name if none */
1053     }
1054
1055     /*
1056      * Check if we have a message destination defined.
1057      * We always report M_ABORT and M_ERROR_TERM
1058      */
1059     if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1060          !bit_is_set(type, msgs->send_msg)) {
1061        return;                        /* no destination */
1062     }
1063     switch (type) {
1064     case M_ABORT:
1065        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1066        break;
1067     case M_ERROR_TERM:
1068        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1069        break;
1070     case M_FATAL:
1071        len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Fatal error: "), my_name, job);
1072        if (jcr) {
1073           set_jcr_job_status(jcr, JS_FatalError);
1074        }
1075        break;
1076     case M_ERROR:
1077        len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Error: "), my_name, job);
1078        if (jcr) {
1079           jcr->Errors++;
1080        }
1081        break;
1082     case M_WARNING:
1083        len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Warning: "), my_name, job);
1084        break;
1085     case M_SECURITY:
1086        len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Security violation: "), my_name, job);
1087        break;
1088     default:
1089        len = bsnprintf(rbuf, sizeof(rbuf), "%s: ", my_name);
1090        break;
1091     }
1092
1093     va_start(arg_ptr, fmt);
1094     bvsnprintf(rbuf+len,  sizeof(rbuf)-len, fmt, arg_ptr);
1095     va_end(arg_ptr);
1096
1097     dispatch_message(jcr, type, mtime, rbuf);
1098
1099     if (type == M_ABORT){
1100        char *p = 0;
1101        p[0] = 0;                      /* generate segmentation violation */
1102     }
1103     if (type == M_ERROR_TERM) {
1104        exit(1);
1105     }
1106 }
1107
1108 /*
1109  * If we come here, prefix the message with the file:line-number,
1110  *  then pass it on to the normal Jmsg routine.
1111  */
1112 void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1113 {
1114    va_list   arg_ptr;
1115    int i, len, maxlen;
1116    POOLMEM *pool_buf;
1117    const char *basename;
1118
1119    if ((basename = strrchr(file, '\\')) == NULL) {
1120       basename = file;
1121    } else {
1122       basename++;
1123    }
1124
1125    pool_buf = get_pool_memory(PM_EMSG);
1126    i = Mmsg(pool_buf, "%s:%d ", basename, line);
1127
1128    for (;;) {
1129       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1130       va_start(arg_ptr, fmt);
1131       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1132       va_end(arg_ptr);
1133       if (len < 0 || len >= (maxlen-5)) {
1134          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1135          continue;
1136       }
1137       break;
1138    }
1139
1140    Jmsg(jcr, type, mtime, "%s", pool_buf);
1141    free_memory(pool_buf);
1142 }
1143
1144
1145 /*
1146  * Edit a message into a Pool memory buffer, with file:lineno
1147  */
1148 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1149 {
1150    va_list   arg_ptr;
1151    int i, len, maxlen;
1152
1153    const char *basename;
1154
1155    if ((basename = strrchr(file, '\\')) == NULL) {
1156       basename = file;
1157    } else {
1158       basename++;
1159    }
1160
1161    i = sprintf(*pool_buf, "%s:%d ", basename, line);
1162
1163    for (;;) {
1164       maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1165       va_start(arg_ptr, fmt);
1166       len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1167       va_end(arg_ptr);
1168       if (len < 0 || len >= (maxlen-5)) {
1169          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1170          continue;
1171       }
1172       break;
1173    }
1174    return len;
1175 }
1176
1177 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1178 {
1179    va_list   arg_ptr;
1180    int i, len, maxlen;
1181
1182    const char *basename;
1183
1184    if ((basename = strrchr(file, '\\')) == NULL) {
1185       basename = file;
1186    } else {
1187       basename++;
1188    }
1189
1190    i = sprintf(pool_buf, "%s:%d ", basename, line);
1191
1192    for (;;) {
1193       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1194       va_start(arg_ptr, fmt);
1195       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1196       va_end(arg_ptr);
1197       if (len < 0 || len >= (maxlen-5)) {
1198          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1199          continue;
1200       }
1201       break;
1202    }
1203    return len;
1204 }
1205
1206
1207 /*
1208  * Edit a message into a Pool Memory buffer NO file:lineno
1209  *  Returns: string length of what was edited.
1210  */
1211 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1212 {
1213    va_list   arg_ptr;
1214    int len, maxlen;
1215
1216    for (;;) {
1217       maxlen = sizeof_pool_memory(*pool_buf) - 1;
1218       va_start(arg_ptr, fmt);
1219       len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1220       va_end(arg_ptr);
1221       if (len < 0 || len >= (maxlen-5)) {
1222          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1223          continue;
1224       }
1225       break;
1226    }
1227    return len;
1228 }
1229
1230 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1231 {
1232    va_list   arg_ptr;
1233    int len, maxlen;
1234
1235    for (;;) {
1236       maxlen = sizeof_pool_memory(pool_buf) - 1;
1237       va_start(arg_ptr, fmt);
1238       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1239       va_end(arg_ptr);
1240       if (len < 0 || len >= (maxlen-5)) {
1241          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1242          continue;
1243       }
1244       break;
1245    }
1246    return len;
1247 }
1248
1249 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1250 {
1251    va_list   arg_ptr;
1252    int len, maxlen;
1253
1254    for (;;) {
1255       maxlen = pool_buf.max_size() - 1;
1256       va_start(arg_ptr, fmt);
1257       len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1258       va_end(arg_ptr);
1259       if (len < 0 || len >= (maxlen-5)) {
1260          pool_buf.realloc_pm(maxlen + maxlen/2);
1261          continue;
1262       }
1263       break;
1264    }
1265    return len;
1266 }
1267
1268
1269 static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
1270
1271 /*
1272  * We queue messages rather than print them directly. This
1273  *  is generally used in low level routines (msg handler, bnet)
1274  *  to prevent recursion (i.e. if you are in the middle of
1275  *  sending a message, it is a bit messy to recursively call
1276  *  yourself when the bnet packet is not reentrant).
1277  */
1278 void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1279 {
1280    va_list   arg_ptr;
1281    int len, maxlen;
1282    POOLMEM *pool_buf;
1283    MQUEUE_ITEM *item;
1284
1285    pool_buf = get_pool_memory(PM_EMSG);
1286
1287    for (;;) {
1288       maxlen = sizeof_pool_memory(pool_buf) - 1;
1289       va_start(arg_ptr, fmt);
1290       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1291       va_end(arg_ptr);
1292       if (len < 0 || len >= (maxlen-5)) {
1293          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1294          continue;
1295       }
1296       break;
1297    }
1298    item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1299    item->type = type;
1300    item->mtime = time(NULL);
1301    strcpy(item->msg, pool_buf);
1302    /* If no jcr or dequeuing send to daemon to avoid recursion */
1303    if (!jcr || jcr->dequeuing) {
1304       /* jcr==NULL => daemon message, safe to send now */
1305       Jmsg(NULL, item->type, item->mtime, "%s", item->msg);
1306       free(item);
1307    } else {
1308       /* Queue message for later sending */
1309       P(msg_queue_mutex);
1310       jcr->msg_queue->append(item);
1311       V(msg_queue_mutex);
1312    }
1313    free_memory(pool_buf);
1314 }
1315
1316 /*
1317  * Dequeue messages
1318  */
1319 void dequeue_messages(JCR *jcr)
1320 {
1321    MQUEUE_ITEM *item;
1322    P(msg_queue_mutex);
1323    jcr->dequeuing = true;
1324    foreach_dlist(item, jcr->msg_queue) {
1325       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1326    }
1327    jcr->msg_queue->destroy();
1328    jcr->dequeuing = false;
1329    V(msg_queue_mutex);
1330 }
1331
1332
1333 /*
1334  * If we come here, prefix the message with the file:line-number,
1335  *  then pass it on to the normal Qmsg routine.
1336  */
1337 void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1338 {
1339    va_list   arg_ptr;
1340    int i, len, maxlen;
1341    POOLMEM *pool_buf;
1342
1343    pool_buf = get_pool_memory(PM_EMSG);
1344    i = Mmsg(pool_buf, "%s:%d ", file, line);
1345
1346    for (;;) {
1347       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1348       va_start(arg_ptr, fmt);
1349       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1350       va_end(arg_ptr);
1351       if (len < 0 || len >= (maxlen-5)) {
1352          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1353          continue;
1354       }
1355       break;
1356    }
1357
1358    Qmsg(jcr, type, mtime, "%s", pool_buf);
1359    free_memory(pool_buf);
1360 }