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