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