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