]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/message.c
ead4ca0fd9b216c9dd646ff6bcf36323aae2740a
[bacula/bacula] / bacula / src / lib / message.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2016 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is 
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  * Bacula message handling routines
21  *
22  * NOTE: don't use any Jmsg or Qmsg calls within this file,
23  *   except in q_msg or j_msg (setup routines),
24  *   otherwise you may get into recursive calls if there are
25  *   errors, and that can lead to looping or deadlocks.
26  *
27  *   Kern Sibbald, April 2000
28  *
29  */
30
31 #include "bacula.h"
32 #include "jcr.h"
33
34 sql_query_call  p_sql_query = NULL;
35 sql_escape_call p_sql_escape = NULL;
36
37 #define FULL_LOCATION 1               /* set for file:line in Debug messages */
38
39 /*
40  *  This is where we define "Globals" because all the
41  *    daemons include this file.
42  */
43 const char *working_directory = NULL; /* working directory path stored here */
44 const char *assert_msg = NULL;        /* ASSERT2 error message */
45 const char *version = VERSION " (" BDATE ")";
46 const char *dist_name = DISTNAME " " DISTVER;
47 char *exepath = (char *)NULL;
48 char *exename = (char *)NULL;
49 char db_engine_name[50] = {0};        /* Database engine name or type */
50 char con_fname[500];                  /* Console filename */
51 char my_name[MAX_NAME_LENGTH] = {0};  /* daemon name is stored here */
52 char host_name[50] = {0};             /* host machine name */
53 char fail_time[30] = {0};             /* Time of failure */
54 int verbose = 0;                      /* increase User messages */
55 int64_t debug_level = 0;              /* debug level */
56 int64_t debug_level_tags = 0;         /* debug tags */
57 int32_t debug_flags = 0;              /* debug flags */
58 int console_msg_pending = false;
59 utime_t daemon_start_time = 0;        /* Daemon start time */
60 FILE *con_fd = NULL;                  /* Console file descriptor */
61 brwlock_t con_lock;                   /* Console lock structure */
62 bool dbg_timestamp = false;           /* print timestamp in debug output */
63 bool dbg_thread = false;              /* add thread_id to details */
64 bool prt_kaboom = false;              /* Print kaboom output */
65 job_code_callback_t message_job_code_callback = NULL;   /* Job code callback. Only used by director. */
66
67 /* Forward referenced functions */
68
69 /* Imported functions */
70 void create_jcr_key();
71
72 /* Static storage */
73
74 /* Exclude spaces but require .mail at end */
75 #define MAIL_REGEX "^[^ ]+\\.mail$"
76
77 /* Allow only one thread to tweak d->fd at a time */
78 static pthread_mutex_t fides_mutex = PTHREAD_MUTEX_INITIALIZER;
79 static MSGS *daemon_msgs;              /* global messages */
80 static void (*message_callback)(int type, char *msg) = NULL;
81 static FILE *trace_fd = NULL;
82 #if defined(HAVE_WIN32)
83 static bool trace = true;
84 #else
85 static bool trace = false;
86 #endif
87 static int hangup = 0;
88 static int blowup = 0;
89
90 /* Constants */
91 const char *host_os = HOST_OS;
92 const char *distname = DISTNAME;
93 const char *distver = DISTVER;
94
95 /*
96  * Walk back in a string from end looking for a
97  *  path separator.
98  *  This routine is passed the start of the string and
99  *  the end of the string, it returns either the beginning
100  *  of the string or where it found a path separator.
101  */
102 static const char *bstrrpath(const char *start, const char *end)
103 {
104    while ( end > start ) {
105       end--;
106       if (IsPathSeparator(*end)) {
107          break;
108       }
109    }
110    return end;
111 }
112
113 /* Some message class methods */
114 void MSGS::lock()
115 {
116    P(fides_mutex);
117 }
118
119 void MSGS::unlock()
120 {
121    V(fides_mutex);
122 }
123
124 /*
125  * Wait for not in use variable to be clear
126  */
127 void MSGS::wait_not_in_use()     /* leaves fides_mutex set */
128 {
129    lock();
130    while (m_in_use || m_closing) {
131       unlock();
132       bmicrosleep(0, 200);         /* wait */
133       lock();
134    }
135 }
136
137 /*
138  * Handle message delivery errors
139  */
140 static void delivery_error(const char *fmt,...)
141 {
142    va_list   arg_ptr;
143    int i, len, maxlen;
144    POOLMEM *pool_buf;
145    char dt[MAX_TIME_LENGTH];
146    int dtlen;
147
148    pool_buf = get_pool_memory(PM_EMSG);
149
150    bstrftime_ny(dt, sizeof(dt), time(NULL));
151    dtlen = strlen(dt);
152    dt[dtlen++] = ' ';
153    dt[dtlen] = 0;
154
155    i = Mmsg(pool_buf, "%s Message delivery ERROR: ", dt);
156
157    for (;;) {
158       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
159       va_start(arg_ptr, fmt);
160       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
161       va_end(arg_ptr);
162       if (len < 0 || len >= (maxlen-5)) {
163          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
164          continue;
165       }
166       break;
167    }
168
169    fputs(pool_buf, stdout);  /* print this here to INSURE that it is printed */
170    fflush(stdout);
171    syslog(LOG_DAEMON|LOG_ERR, "%s", pool_buf);
172    free_memory(pool_buf);
173 }
174
175 void set_debug_flags(char *options)
176 {
177    for (char *p = options; *p ; p++) {
178       switch(*p) {
179       case '0':                 /* clear flags */
180          debug_flags = 0;
181          break;
182
183       case 'i':                 /* used by FD */
184       case 'd':                 /* used by FD */
185          break;
186
187       case 't':
188          dbg_timestamp = true;
189          break;
190
191       case 'T':
192          dbg_timestamp = false;
193          break;
194
195       case 'h':
196          dbg_thread = true;
197          break;
198
199       case 'H':
200          dbg_thread = false;
201          break;
202
203       case 'c':
204          /* truncate the trace file */
205          if (trace && trace_fd) {
206             ftruncate(fileno(trace_fd), 0);
207          }
208          break;
209
210       case 'l':
211          /* Turn on/off add_events for P()/V() */
212          debug_flags |= DEBUG_MUTEX_EVENT;
213          break;
214
215       case 'p':
216          /* Display event stack during lockdump */
217          debug_flags |= DEBUG_PRINT_EVENT;
218          break;
219
220       default:
221          Dmsg1(000, "Unknown debug flag %c\n", *p);
222       }
223    }
224 }
225
226 void register_message_callback(void msg_callback(int type, char *msg))
227 {
228    message_callback = msg_callback;
229 }
230
231
232 /*
233  * Set daemon name. Also, find canonical execution
234  *  path.  Note, exepath has spare room for tacking on
235  *  the exename so that we can reconstruct the full name.
236  *
237  * Note, this routine can get called multiple times
238  *  The second time is to put the name as found in the
239  *  Resource record. On the second call, generally,
240  *  argv is NULL to avoid doing the path code twice.
241  */
242 void my_name_is(int argc, char *argv[], const char *name)
243 {
244    char *l, *p, *q;
245    char cpath[1024];
246    int len;
247
248    if (gethostname(host_name, sizeof(host_name)) != 0) {
249       bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
250    }
251    bstrncpy(my_name, name, sizeof(my_name));
252    if (argc>0 && argv && argv[0]) {
253       /* strip trailing filename and save exepath */
254       for (l=p=argv[0]; *p; p++) {
255          if (IsPathSeparator(*p)) {
256             l = p;                       /* set pos of last slash */
257          }
258       }
259       if (IsPathSeparator(*l)) {
260          l++;
261       } else {
262          l = argv[0];
263 #if defined(HAVE_WIN32)
264          /* On Windows allow c: drive specification */
265          if (l[1] == ':') {
266             l += 2;
267          }
268 #endif
269       }
270       len = strlen(l) + 1;
271       if (exename) {
272          free(exename);
273       }
274       exename = (char *)malloc(len);
275       strcpy(exename, l);
276
277       if (exepath) {
278          free(exepath);
279       }
280       exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
281       for (p=argv[0],q=exepath; p < l; ) {
282          *q++ = *p++;
283       }
284       *q = 0;
285       if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
286          if (getcwd(cpath, sizeof(cpath))) {
287             free(exepath);
288             exepath = (char *)malloc(strlen(cpath) + 1 + len);
289             strcpy(exepath, cpath);
290          }
291       }
292       Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
293    }
294 }
295
296 /* Set special ASSERT2 message where debugger can find it */
297 void
298 set_assert_msg(const char *file, int line, const char *msg)
299 {
300    char buf[2000];
301    bsnprintf(buf, sizeof(buf), "ASSERT at %s:%d-%u ERR=%s",
302       get_basename(file), line, get_jobid_from_tsd(), msg);
303    assert_msg = bstrdup(buf);
304 }
305
306 void set_db_engine_name(const char *name)
307
308    bstrncpy(db_engine_name, name, sizeof(db_engine_name)-1);
309
310  
311 /*
312  * Initialize message handler for a daemon or a Job
313  *   We make a copy of the MSGS resource passed, so it belows
314  *   to the job or daemon and thus can be modified.
315  *
316  *   NULL for jcr -> initialize global messages for daemon
317  *   non-NULL     -> initialize jcr using Message resource
318  */
319 void
320 init_msg(JCR *jcr, MSGS *msg, job_code_callback_t job_code_callback)
321 {
322    DEST *d, *dnew, *temp_chain = NULL;
323    int i;
324
325    if (jcr == NULL && msg == NULL) {
326       init_last_jobs_list();
327       /* Create a daemon key then set invalid jcr */
328       /* Maybe we should give the daemon a jcr??? */
329       create_jcr_key();
330       set_jcr_in_tsd(INVALID_JCR);
331    }
332
333    message_job_code_callback = job_code_callback;
334
335 #if !defined(HAVE_WIN32)
336    /*
337     * Make sure we have fd's 0, 1, 2 open
338     *  If we don't do this one of our sockets may open
339     *  there and if we then use stdout, it could
340     *  send total garbage to our socket.
341     *
342     */
343    int fd;
344    fd = open("/dev/null", O_RDONLY, 0644);
345    if (fd > 2) {
346       close(fd);
347    } else {
348       for(i=1; fd + i <= 2; i++) {
349          dup2(fd, fd+i);
350       }
351    }
352
353 #endif
354    /*
355     * If msg is NULL, initialize global chain for STDOUT and syslog
356     */
357    if (msg == NULL) {
358       daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
359       memset(daemon_msgs, 0, sizeof(MSGS));
360       for (i=1; i<=M_MAX; i++) {
361          add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
362       }
363       Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
364       return;
365    }
366
367    /*
368     * Walk down the message resource chain duplicating it
369     * for the current Job.
370     */
371    for (d=msg->dest_chain; d; d=d->next) {
372       dnew = (DEST *)malloc(sizeof(DEST));
373       memcpy(dnew, d, sizeof(DEST));
374       dnew->next = temp_chain;
375       dnew->fd = NULL;
376       dnew->mail_filename = NULL;
377       if (d->mail_cmd) {
378          dnew->mail_cmd = bstrdup(d->mail_cmd);
379       }
380       if (d->where) {
381          dnew->where = bstrdup(d->where);
382       }
383       temp_chain = dnew;
384    }
385
386    if (jcr) {
387       jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
388       memset(jcr->jcr_msgs, 0, sizeof(MSGS));
389       jcr->jcr_msgs->dest_chain = temp_chain;
390       memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
391    } else {
392       /* If we have default values, release them now */
393       if (daemon_msgs) {
394          free_msgs_res(daemon_msgs);
395       }
396       daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
397       memset(daemon_msgs, 0, sizeof(MSGS));
398       daemon_msgs->dest_chain = temp_chain;
399       memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
400    }
401
402    Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
403 }
404
405 /* Initialize so that the console (User Agent) can
406  * receive messages -- stored in a file.
407  */
408 void init_console_msg(const char *wd)
409 {
410    int fd;
411
412    bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
413    fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
414    if (fd == -1) {
415       berrno be;
416       Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
417           con_fname, be.bstrerror());
418    }
419    if (lseek(fd, 0, SEEK_END) > 0) {
420       console_msg_pending = 1;
421    }
422    close(fd);
423    con_fd = fopen(con_fname, "a+b");
424    if (!con_fd) {
425       berrno be;
426       Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
427           con_fname, be.bstrerror());
428    }
429    if (rwl_init(&con_lock) != 0) {
430       berrno be;
431       Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
432          be.bstrerror());
433    }
434 }
435
436 /*
437  * Called only during parsing of the config file.
438  *
439  * Add a message destination. I.e. associate a message type with
440  *  a destination (code).
441  * Note, where in the case of dest_code FILE is a filename,
442  *  but in the case of MAIL is a space separated list of
443  *  email addresses, ...
444  */
445 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
446 {
447    DEST *d;
448    /*
449     * First search the existing chain and see if we
450     * can simply add this msg_type to an existing entry.
451     */
452    for (d=msg->dest_chain; d; d=d->next) {
453       if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
454                      (strcmp(where, d->where) == 0))) {
455          Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
456              d, msg_type, dest_code, NPRT(where));
457          set_bit(msg_type, d->msg_types);
458          set_bit(msg_type, msg->send_msg);  /* set msg_type bit in our local */
459          return;
460       }
461    }
462    /* Not found, create a new entry */
463    d = (DEST *)malloc(sizeof(DEST));
464    memset(d, 0, sizeof(DEST));
465    d->next = msg->dest_chain;
466    d->dest_code = dest_code;
467    set_bit(msg_type, d->msg_types);      /* set type bit in structure */
468    set_bit(msg_type, msg->send_msg);     /* set type bit in our local */
469    if (where) {
470       d->where = bstrdup(where);
471    }
472    if (mail_cmd) {
473       d->mail_cmd = bstrdup(mail_cmd);
474    }
475    Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
476           d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
477    msg->dest_chain = d;
478 }
479
480 /*
481  * Called only during parsing of the config file.
482  *
483  * Remove a message destination
484  */
485 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
486 {
487    DEST *d;
488
489    for (d=msg->dest_chain; d; d=d->next) {
490       Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
491       if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
492           ((where == NULL && d->where == NULL) ||
493                      (strcmp(where, d->where) == 0))) {
494          Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
495                d, msg_type, dest_code);
496          clear_bit(msg_type, d->msg_types);
497          Dmsg0(850, "Return rem_msg_dest\n");
498          return;
499       }
500    }
501 }
502
503
504 /*
505  * Create a unique filename for the mail command
506  */
507 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
508 {
509    if (jcr) {
510       Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
511                  jcr->Job, (int)(intptr_t)d);
512    } else {
513       Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
514                  my_name, (int)(intptr_t)d);
515    }
516    Dmsg1(850, "mailname=%s\n", name);
517 }
518
519 /*
520  * Open a mail pipe
521  */
522 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
523 {
524    BPIPE *bpipe;
525
526    if (d->mail_cmd) {
527       cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where, message_job_code_callback);
528    } else {
529       Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
530    }
531    fflush(stdout);
532
533    if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
534       /* If we had to use sendmail, add subject */
535       if (!d->mail_cmd) {
536          fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
537       }
538    } else {
539       berrno be;
540       delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
541          cmd, be.bstrerror());
542    }
543    return bpipe;
544 }
545
546 /*
547  * Close the messages for this Messages resource, which means to close
548  *  any open files, and dispatch any pending email messages.
549  */
550 void close_msg(JCR *jcr)
551 {
552    MSGS *msgs;
553    DEST *d;
554    BPIPE *bpipe;
555    POOLMEM *cmd, *line;
556    int len, stat;
557
558    Dmsg1(580, "Close_msg jcr=%p\n", jcr);
559
560    if (jcr == NULL) {                /* NULL -> global chain */
561       msgs = daemon_msgs;
562    } else {
563       msgs = jcr->jcr_msgs;
564       jcr->jcr_msgs = NULL;
565    }
566    if (msgs == NULL) {
567       return;
568    }
569
570    /* Wait for item to be not in use, then mark closing */
571    if (msgs->is_closing()) {
572       return;
573    }
574    msgs->wait_not_in_use();          /* leaves fides_mutex set */
575    /* Note get_closing() does not lock because we are already locked */
576    if (msgs->get_closing()) {
577       msgs->unlock();
578       return;
579    }
580    msgs->set_closing();
581    msgs->unlock();
582
583    Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
584    cmd = get_pool_memory(PM_MESSAGE);
585    for (d=msgs->dest_chain; d; ) {
586       bool success;
587       if (d->fd) {
588          switch (d->dest_code) {
589          case MD_FILE:
590          case MD_APPEND:
591             if (d->fd) {
592                fclose(d->fd);            /* close open file descriptor */
593                d->fd = NULL;
594             }
595             break;
596          case MD_MAIL:
597          case MD_MAIL_ON_ERROR:
598          case MD_MAIL_ON_SUCCESS:
599             Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
600             if (!d->fd) {
601                break;
602             }
603             success = jcr && (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings);
604             if (d->dest_code == MD_MAIL_ON_ERROR && success) {
605                goto rem_temp_file;       /* no mail */
606             } else if (d->dest_code == MD_MAIL_ON_SUCCESS && !success) {
607                goto rem_temp_file;       /* no mail */
608             }
609
610             if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
611                Pmsg0(000, _("open mail pipe failed.\n"));
612                goto rem_temp_file;       /* error get out */
613             }
614             Dmsg0(850, "Opened mail pipe\n");
615             len = d->max_len+10;
616             line = get_memory(len);
617             rewind(d->fd);
618             while (fgets(line, len, d->fd)) {
619                fputs(line, bpipe->wfd);
620             }
621             if (!close_wpipe(bpipe)) {       /* close write pipe sending mail */
622                berrno be;
623                Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
624             }
625
626             /*
627              * Since we are closing all messages, before "recursing"
628              * make sure we are not closing the daemon messages, otherwise
629              * kaboom.
630              */
631             if (msgs != daemon_msgs) {
632                /* read what mail prog returned -- should be nothing */
633                while (fgets(line, len, bpipe->rfd)) {
634                   delivery_error(_("Mail prog: %s"), line);
635                }
636             }
637
638             stat = close_bpipe(bpipe);
639             if (stat != 0 && msgs != daemon_msgs) {
640                berrno be;
641                be.set_errno(stat);
642                Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
643                delivery_error(_("Mail program terminated in error.\n"
644                                  "CMD=%s\n"
645                                  "ERR=%s\n"), cmd, be.bstrerror());
646             }
647             free_memory(line);
648
649 rem_temp_file:
650             /* Remove temp mail file */
651             if (d->fd) {
652               fclose(d->fd);
653               d->fd = NULL;
654             }
655             /* Exclude spaces in mail_filename */
656             if (d->mail_filename) {
657                safer_unlink(d->mail_filename, MAIL_REGEX);
658                free_pool_memory(d->mail_filename);
659                d->mail_filename = NULL;
660             }
661             Dmsg0(850, "end mail or mail on error\n");
662             break;
663          default:
664             break;
665          }
666          d->fd = NULL;
667       }
668       d = d->next;                    /* point to next buffer */
669    }
670    free_pool_memory(cmd);
671    Dmsg0(850, "Done walking message chain.\n");
672    if (jcr) {
673       free_msgs_res(msgs);
674       msgs = NULL;
675    } else {
676       msgs->clear_closing();
677    }
678    Dmsg0(850, "===End close msg resource\n");
679 }
680
681 /*
682  * Free memory associated with Messages resource
683  */
684 void free_msgs_res(MSGS *msgs)
685 {
686    DEST *d, *old;
687
688    /* Walk down the message chain releasing allocated buffers */
689    for (d=msgs->dest_chain; d; ) {
690       if (d->where) {
691          free(d->where);
692          d->where = NULL;
693       }
694       if (d->mail_cmd) {
695          free(d->mail_cmd);
696          d->mail_cmd = NULL;
697       }
698       old = d;                        /* save pointer to release */
699       d = d->next;                    /* point to next buffer */
700       free(old);                      /* free the destination item */
701    }
702    msgs->dest_chain = NULL;
703    free(msgs);                        /* free the head */
704 }
705
706
707 /*
708  * Terminate the message handler for good.
709  * Release the global destination chain.
710  *
711  * Also, clean up a few other items (cons, exepath). Note,
712  *   these really should be done elsewhere.
713  */
714 void term_msg()
715 {
716    Dmsg0(850, "Enter term_msg\n");
717    close_msg(NULL);                   /* close global chain */
718    free_msgs_res(daemon_msgs);        /* free the resources */
719    daemon_msgs = NULL;
720    if (con_fd) {
721       fflush(con_fd);
722       fclose(con_fd);
723       con_fd = NULL;
724    }
725    if (exepath) {
726       free(exepath);
727       exepath = NULL;
728    }
729    if (exename) {
730       free(exename);
731       exename = NULL;
732    }
733    if (trace_fd) {
734       fclose(trace_fd);
735       trace_fd = NULL;
736       trace = false;
737    }
738    working_directory = NULL;
739    term_last_jobs_list();
740 }
741
742 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
743 {
744    d->fd = fopen(d->where, mode);
745    if (!d->fd) {
746       berrno be;
747       delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
748       return false;
749    }
750    return true;
751 }
752
753 /* Split the output for syslog (it converts \n to ' ' and is
754  *   limited to 1024 characters per syslog message
755  */
756 static void send_to_syslog(int mode, const char *msg)
757 {
758    int len;
759    char buf[1024];
760    const char *p2;
761    const char *p = msg;
762
763    while (*p && ((p2 = strchr(p, '\n')) != NULL)) {
764       len = MIN((int)sizeof(buf) - 1, p2 - p + 1); /* Add 1 to keep \n */
765       strncpy(buf, p, len);
766       buf[len] = 0;
767       syslog(mode, "%s", buf);
768       p = p2+1;                 /* skip \n */
769    }
770    if (*p != 0) {               /* no \n at the end ? */
771       syslog(mode, "%s", p);
772    }
773 }
774
775 /*
776  * Handle sending the message to the appropriate place
777  */
778 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
779 {
780     DEST *d;
781     char dt[MAX_TIME_LENGTH];
782     POOLMEM *mcmd;
783     int len, dtlen;
784     MSGS *msgs;
785     BPIPE *bpipe;
786     const char *mode;
787
788     Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
789
790     /*
791      * Most messages are prefixed by a date and time. If mtime is
792      *  zero, then we use the current time.  If mtime is 1 (special
793      *  kludge), we do not prefix the date and time. Otherwise,
794      *  we assume mtime is a utime_t and use it.
795      */
796     if (mtime == 0) {
797        mtime = time(NULL);
798     }
799     if (mtime == 1) {
800        *dt = 0;
801        dtlen = 0;
802        mtime = time(NULL);      /* get time for SQL log */
803     } else {
804        bstrftime_ny(dt, sizeof(dt), mtime);
805        dtlen = strlen(dt);
806        dt[dtlen++] = ' ';
807        dt[dtlen] = 0;
808     }
809
810     /* If the program registered a callback, send it there */
811     if (message_callback) {
812        message_callback(type, msg);
813        return;
814     }
815
816     /* For serious errors make sure message is printed or logged */
817     if (type == M_ABORT || type == M_ERROR_TERM) {
818        fputs(dt, stdout);
819        fputs(msg, stdout);
820        fflush(stdout);
821        if (type == M_ABORT) {
822           syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
823        }
824     }
825
826
827     /* Now figure out where to send the message */
828     msgs = NULL;
829     if (!jcr) {
830        jcr = get_jcr_from_tsd();
831     }
832     if (jcr) {
833        msgs = jcr->jcr_msgs;
834     }
835     if (msgs == NULL) {
836        msgs = daemon_msgs;
837     }
838     /*
839      * If closing this message resource, print and send to syslog,
840      *   then get out.
841      */
842     if (msgs->is_closing()) {
843        fputs(dt, stdout);
844        fputs(msg, stdout);
845        fflush(stdout);
846        syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
847        return;
848     }
849
850     for (d=msgs->dest_chain; d; d=d->next) {
851        if (bit_is_set(type, d->msg_types)) {
852           bool ok;
853           switch (d->dest_code) {
854              case MD_CATALOG:
855                 char ed1[50];
856                 if (!jcr || !jcr->db) { 
857                    break;
858                 }
859                 if (p_sql_query && p_sql_escape) {
860                    POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
861                    POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
862
863                    int len = strlen(msg) + 1;
864                    esc_msg = check_pool_memory_size(esc_msg, len*2+1);
865                    ok = p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
866                    if (ok) {
867                       bstrutime(dt, sizeof(dt), mtime); 
868                       Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')", 
869                            edit_int64(jcr->JobId, ed1), dt, esc_msg);
870                       ok = p_sql_query(jcr, cmd);
871                    } 
872                    if (!ok) {
873                       delivery_error(_("Message delivery error: Unable to store data in database.\n"));
874                    } 
875                    free_pool_memory(cmd);
876                    free_pool_memory(esc_msg);
877                 }
878                 break;
879              case MD_CONSOLE:
880                 Dmsg1(850, "CONSOLE for following msg: %s", msg);
881                 if (!con_fd) {
882                    con_fd = fopen(con_fname, "a+b");
883                    Dmsg0(850, "Console file not open.\n");
884                 }
885                 if (con_fd) {
886                    Pw(con_lock);      /* get write lock on console message file */
887                    errno = 0;
888                    if (dtlen) {
889                       (void)fwrite(dt, dtlen, 1, con_fd);
890                    }
891                    len = strlen(msg);
892                    if (len > 0) {
893                       (void)fwrite(msg, len, 1, con_fd);
894                       if (msg[len-1] != '\n') {
895                          (void)fwrite("\n", 2, 1, con_fd);
896                       }
897                    } else {
898                       (void)fwrite("\n", 2, 1, con_fd);
899                    }
900                    fflush(con_fd);
901                    console_msg_pending = true;
902                    Vw(con_lock);
903                 }
904                 break;
905              case MD_SYSLOG:
906                 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
907                 /*
908                  * We really should do an openlog() here.
909                  */
910                 send_to_syslog(LOG_DAEMON|LOG_ERR, msg);
911                 break;
912              case MD_OPERATOR:
913                 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
914                 mcmd = get_pool_memory(PM_MESSAGE);
915                 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
916                    int stat;
917                    fputs(dt, bpipe->wfd);
918                    fputs(msg, bpipe->wfd);
919                    /* Messages to the operator go one at a time */
920                    stat = close_bpipe(bpipe);
921                    if (stat != 0) {
922                       berrno be;
923                       be.set_errno(stat);
924                       delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
925                             "CMD=%s\n"
926                             "ERR=%s\n"), mcmd, be.bstrerror());
927                    }
928                 }
929                 free_pool_memory(mcmd);
930                 break;
931              case MD_MAIL:
932              case MD_MAIL_ON_ERROR:
933              case MD_MAIL_ON_SUCCESS:
934                 Dmsg1(850, "MAIL for following msg: %s", msg);
935                 if (msgs->is_closing()) {
936                    break;
937                 }
938                 msgs->set_in_use();
939                 if (!d->fd) {
940                    POOLMEM *name = get_pool_memory(PM_MESSAGE);
941                    make_unique_mail_filename(jcr, name, d);
942                    d->fd = fopen(name, "w+b");
943                    if (!d->fd) {
944                       berrno be;
945                       delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
946                             be.bstrerror());
947                       free_pool_memory(name);
948                       msgs->clear_in_use();
949                       break;
950                    }
951                    d->mail_filename = name;
952                 }
953                 fputs(dt, d->fd);
954                 len = strlen(msg) + dtlen;;
955                 if (len > d->max_len) {
956                    d->max_len = len;      /* keep max line length */
957                 }
958                 fputs(msg, d->fd);
959                 msgs->clear_in_use();
960                 break;
961              case MD_APPEND:
962                 Dmsg1(850, "APPEND for following msg: %s", msg);
963                 mode = "ab";
964                 goto send_to_file;
965              case MD_FILE:
966                 Dmsg1(850, "FILE for following msg: %s", msg);
967                 mode = "w+b";
968 send_to_file:
969                 if (msgs->is_closing()) {
970                    break;
971                 }
972                 msgs->set_in_use();
973                 if (!d->fd && !open_dest_file(jcr, d, mode)) {
974                    msgs->clear_in_use();
975                    break;
976                 }
977                 fputs(dt, d->fd);
978                 fputs(msg, d->fd);
979                 /* On error, we close and reopen to handle log rotation */
980                 if (ferror(d->fd)) {
981                    fclose(d->fd);
982                    d->fd = NULL;
983                    if (open_dest_file(jcr, d, mode)) {
984                       fputs(dt, d->fd);
985                       fputs(msg, d->fd);
986                    }
987                 }
988                 msgs->clear_in_use();
989                 break;
990              case MD_DIRECTOR:
991                 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
992                 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
993                    jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
994                       jcr->Job, type, mtime, msg);
995                 } else {
996                    Dmsg1(800, "no jcr for following msg: %s", msg);
997                 }
998                 break;
999              case MD_STDOUT:
1000                 Dmsg1(850, "STDOUT for following msg: %s", msg);
1001                 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
1002                    fputs(dt, stdout);
1003                    fputs(msg, stdout);
1004                    fflush(stdout);
1005                 }
1006                 break;
1007              case MD_STDERR:
1008                 Dmsg1(850, "STDERR for following msg: %s", msg);
1009                 fputs(dt, stderr);
1010                 fputs(msg, stderr);
1011                 fflush(stdout);
1012                 break;
1013              default:
1014                 break;
1015           }
1016        }
1017     }
1018 }
1019
1020 /*********************************************************************
1021  *
1022  *  This subroutine returns the filename portion of a path.
1023  *  It is used because some compilers set __FILE__
1024  *  to the full path.  Try to return base + next higher path.
1025  */
1026
1027 const char *get_basename(const char *pathname)
1028 {
1029    const char *basename;
1030
1031    if ((basename = bstrrpath(pathname, pathname+strlen(pathname))) == pathname) {
1032       /* empty */
1033    } else if ((basename = bstrrpath(pathname, basename-1)) == pathname) {
1034       /* empty */
1035    } else {
1036       basename++;
1037    }
1038    return basename;
1039 }
1040
1041 /*
1042  * print or write output to trace file
1043  */
1044 static void pt_out(char *buf)
1045 {
1046     /*
1047      * Used the "trace on" command in the console to turn on
1048      *  output to the trace file.  "trace off" will close the file.
1049      */
1050     if (trace) {
1051        if (!trace_fd) {
1052           char fn[200];
1053           bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
1054           trace_fd = fopen(fn, "a+b");
1055        }
1056        if (trace_fd) {
1057           fputs(buf, trace_fd);
1058           fflush(trace_fd);
1059           return;
1060        } else {
1061           /* Some problem, turn off tracing */
1062           trace = false;
1063        }
1064     }
1065     /* not tracing */
1066     fputs(buf, stdout);
1067     fflush(stdout);
1068 }
1069
1070 /*********************************************************************
1071  *
1072  *  This subroutine prints a debug message if the level number
1073  *  is less than or equal the debug_level. File and line numbers
1074  *  are included for more detail if desired, but not currently
1075  *  printed.
1076  *
1077  *  If the level is negative, the details of file and line number
1078  *  are not printed.
1079  *
1080  */
1081 void
1082 vd_msg(const char *file, int line, int64_t level, const char *fmt, va_list arg_ptr)
1083 {
1084     char      buf[5000];
1085     int       len = 0; /* space used in buf */
1086     bool      details = true;
1087     utime_t   mtime;
1088
1089     if (level < 0) {
1090        details = false;
1091        level = -level;
1092     }
1093
1094     if (chk_dbglvl(level)) {
1095        if (dbg_timestamp) {
1096           mtime = time(NULL);
1097           bstrftimes(buf+len, sizeof(buf)-len, mtime);
1098           len = strlen(buf);
1099           buf[len++] = ' ';
1100        }
1101
1102 #ifdef FULL_LOCATION
1103        if (details) {
1104           if (dbg_thread) {
1105              len += bsnprintf(buf+len, sizeof(buf)-len, "%s[%lld]: %s:%d-%u ",
1106                              my_name, bthread_get_thread_id(),
1107                              get_basename(file), line, get_jobid_from_tsd());
1108           } else {
1109              len += bsnprintf(buf+len, sizeof(buf)-len, "%s: %s:%d-%u ",
1110                    my_name, get_basename(file), line, get_jobid_from_tsd());
1111           }
1112        }
1113 #endif
1114        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1115
1116        pt_out(buf);
1117     }
1118 }
1119
1120 void
1121 d_msg(const char *file, int line, int64_t level, const char *fmt,...)
1122 {
1123    va_list arg_ptr;
1124    va_start(arg_ptr, fmt);
1125    vd_msg(file, line, level, fmt, arg_ptr); /* without tags */
1126    va_end(arg_ptr);
1127 }
1128
1129
1130 /*
1131  * Set trace flag on/off. If argument is negative, there is no change
1132  */
1133 void set_trace(int trace_flag)
1134 {
1135    if (trace_flag < 0) {
1136       return;
1137    } else if (trace_flag > 0) {
1138       trace = true;
1139    } else {
1140       trace = false;
1141    }
1142    if (!trace && trace_fd) {
1143       FILE *ltrace_fd = trace_fd;
1144       trace_fd = NULL;
1145       bmicrosleep(0, 100000);         /* yield to prevent seg faults */
1146       fclose(ltrace_fd);
1147    }
1148 }
1149
1150 void set_hangup(int hangup_value)
1151 {
1152    if (hangup_value < 0) {
1153       return;
1154    } else {
1155       hangup = hangup_value;
1156    }
1157 }
1158
1159 int get_hangup(void)
1160 {
1161    return hangup;
1162 }
1163
1164 void set_blowup(int blowup_value)
1165 {
1166    if (blowup_value < 0) {
1167       return;
1168    } else {
1169       blowup = blowup_value;
1170    }
1171 }
1172
1173 int get_blowup(void)
1174 {
1175    return blowup;
1176 }
1177
1178
1179 bool get_trace(void)
1180 {
1181    return trace;
1182 }
1183
1184 /*********************************************************************
1185  *
1186  *  This subroutine prints a message regardless of the debug level
1187  *
1188  *  If the level is negative, the details of file and line number
1189  *  are not printed.
1190  */
1191 void
1192 p_msg(const char *file, int line, int level, const char *fmt,...)
1193 {
1194     char      buf[5000];
1195     int       len = 0; /* space used in buf */
1196     va_list   arg_ptr;
1197
1198     if (dbg_timestamp) {
1199        utime_t mtime = time(NULL);
1200        bstrftimes(buf+len, sizeof(buf)-len, mtime);
1201        len = strlen(buf);
1202        buf[len++] = ' ';
1203     }
1204
1205 #ifdef FULL_LOCATION
1206     if (level >= 0) {
1207        len += bsnprintf(buf+len, sizeof(buf)-len, "%s: %s:%d-%u ",
1208              my_name, get_basename(file), line, get_jobid_from_tsd());
1209     }
1210 #endif
1211
1212     va_start(arg_ptr, fmt);
1213     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1214     va_end(arg_ptr);
1215
1216     pt_out(buf);
1217 }
1218
1219
1220 /*********************************************************************
1221  *
1222  *  subroutine writes a debug message to the trace file if the level number
1223  *  is less than or equal the debug_level. File and line numbers
1224  *  are included for more detail if desired, but not currently
1225  *  printed.
1226  *
1227  *  If the level is negative, the details of file and line number
1228  *  are not printed.
1229  */
1230 void
1231 t_msg(const char *file, int line, int64_t level, const char *fmt,...)
1232 {
1233     char      buf[5000];
1234     int       len;
1235     va_list   arg_ptr;
1236     int       details = TRUE;
1237
1238     level = level & ~DT_ALL;    /* level should be tag free */
1239
1240     if (level < 0) {
1241        details = FALSE;
1242        level = -level;
1243     }
1244
1245     if (level <= debug_level) {
1246        if (!trace_fd) {
1247           bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1248           trace_fd = fopen(buf, "a+b");
1249        }
1250
1251 #ifdef FULL_LOCATION
1252        if (details) {
1253           len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1254        } else {
1255           len = 0;
1256        }
1257 #else
1258        len = 0;
1259 #endif
1260        va_start(arg_ptr, fmt);
1261        bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1262        va_end(arg_ptr);
1263        if (trace_fd != NULL) {
1264            fputs(buf, trace_fd);
1265            fflush(trace_fd);
1266        }
1267    }
1268 }
1269
1270 /* *********************************************************
1271  *
1272  * print an error message
1273  *
1274  */
1275 void
1276 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1277 {
1278     char     buf[5000];
1279     va_list   arg_ptr;
1280     int len;
1281
1282     /*
1283      * Check if we have a message destination defined.
1284      * We always report M_ABORT and M_ERROR_TERM
1285      */
1286     if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1287                          !bit_is_set(type, daemon_msgs->send_msg))) {
1288        return;                        /* no destination */
1289     }
1290     switch (type) {
1291     case M_ABORT:
1292        len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1293                my_name, get_basename(file), line);
1294        break;
1295     case M_ERROR_TERM:
1296        len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1297                my_name, get_basename(file), line);
1298        break;
1299     case M_FATAL:
1300        if (level == -1)            /* skip details */
1301           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1302        else
1303           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1304        break;
1305     case M_ERROR:
1306        if (level == -1)            /* skip details */
1307           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1308        else
1309           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1310        break;
1311     case M_WARNING:
1312        len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1313        break;
1314     case M_SECURITY:
1315        len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1316        break;
1317     default:
1318        len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1319        break;
1320     }
1321
1322     va_start(arg_ptr, fmt);
1323     bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1324     va_end(arg_ptr);
1325
1326     pt_out(buf);
1327     dispatch_message(NULL, type, 0, buf);
1328
1329     if (type == M_ABORT) {
1330        assert_msg = bstrdup(buf);
1331        char *p = 0;
1332        p[0] = 0;                      /* generate segmentation violation */
1333     }
1334     if (type == M_ERROR_TERM) {
1335        exit(1);
1336     }
1337 }
1338
1339 /* *********************************************************
1340  *
1341  * Generate a Job message
1342  *
1343  */
1344 void
1345 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1346 {
1347     char     rbuf[5000];
1348     va_list   arg_ptr;
1349     int len;
1350     MSGS *msgs;
1351     uint32_t JobId = 0;
1352
1353
1354     Dmsg1(850, "Enter Jmsg type=%d\n", type);
1355
1356     /* Special case for the console, which has a dir_bsock and JobId==0,
1357      *  in that case, we send the message directly back to the
1358      *  dir_bsock.
1359      */
1360     if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1361        BSOCK *dir = jcr->dir_bsock;
1362        va_start(arg_ptr, fmt);
1363        dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1364                                 fmt, arg_ptr);
1365        va_end(arg_ptr);
1366        jcr->dir_bsock->send();
1367        return;
1368     }
1369
1370     /* The watchdog thread can't use Jmsg directly, we always queued it */
1371     if (is_watchdog()) {
1372        va_start(arg_ptr, fmt);
1373        bvsnprintf(rbuf,  sizeof(rbuf), fmt, arg_ptr);
1374        va_end(arg_ptr);
1375        Qmsg(jcr, type, mtime, "%s", rbuf);
1376        return;
1377     }
1378
1379     msgs = NULL;
1380     if (!jcr) {
1381        jcr = get_jcr_from_tsd();
1382     }
1383     if (jcr) {
1384        if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1385           /* Dequeue messages to keep the original order  */
1386           dequeue_messages(jcr);
1387        }
1388        msgs = jcr->jcr_msgs;
1389        JobId = jcr->JobId;
1390     }
1391     if (!msgs) {
1392        msgs = daemon_msgs;            /* if no jcr, we use daemon handler */
1393     }
1394
1395     /*
1396      * Check if we have a message destination defined.
1397      * We always report M_ABORT and M_ERROR_TERM
1398      */
1399     if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1400          !bit_is_set(type, msgs->send_msg)) {
1401        return;                        /* no destination */
1402     }
1403     switch (type) {
1404     case M_ABORT:
1405        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1406        break;
1407     case M_ERROR_TERM:
1408        len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1409        break;
1410     case M_FATAL:
1411        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1412        if (jcr) {
1413           jcr->setJobStatus(JS_FatalError);
1414        }
1415        if (jcr && jcr->JobErrors == 0) {
1416           jcr->JobErrors = 1;
1417        }
1418        break;
1419     case M_ERROR:
1420        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1421        if (jcr) {
1422           jcr->JobErrors++;
1423        }
1424        break;
1425     case M_WARNING:
1426        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1427        if (jcr) {
1428           jcr->JobWarnings++;
1429        }
1430        break;
1431     case M_SECURITY:
1432        len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1433                my_name, JobId);
1434        break;
1435     default:
1436        len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1437        break;
1438     }
1439
1440     va_start(arg_ptr, fmt);
1441     bvsnprintf(rbuf+len,  sizeof(rbuf)-len, fmt, arg_ptr);
1442     va_end(arg_ptr);
1443
1444     dispatch_message(jcr, type, mtime, rbuf);
1445
1446     if (type == M_ABORT){
1447        char *p = 0;
1448        printf("Bacula forced SEG FAULT to obtain traceback.\n");
1449        syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1450        assert_msg = bstrdup(rbuf);
1451        p[0] = 0;                      /* generate segmentation violation */
1452     }
1453     if (type == M_ERROR_TERM) {
1454        exit(1);
1455     }
1456 }
1457
1458 /*
1459  * If we come here, prefix the message with the file:line-number,
1460  *  then pass it on to the normal Jmsg routine.
1461  */
1462 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1463 {
1464    va_list   arg_ptr;
1465    int i, len, maxlen;
1466    POOLMEM *pool_buf;
1467
1468    va_start(arg_ptr, fmt);
1469    vd_msg(file, line, 0, fmt, arg_ptr);
1470    va_end(arg_ptr);
1471
1472    pool_buf = get_pool_memory(PM_EMSG);
1473    i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1474
1475    for (;;) {
1476       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1477       va_start(arg_ptr, fmt);
1478       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1479       va_end(arg_ptr);
1480       if (len < 0 || len >= (maxlen-5)) {
1481          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1482          continue;
1483       }
1484       break;
1485    }
1486
1487    Jmsg(jcr, type, mtime, "%s", pool_buf);
1488    free_memory(pool_buf);
1489 }
1490
1491
1492 /*
1493  * Edit a message into a Pool memory buffer, with file:lineno
1494  */
1495 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1496 {
1497    va_list   arg_ptr;
1498    int i, len, maxlen;
1499
1500    i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1501
1502    for (;;) {
1503       maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1504       va_start(arg_ptr, fmt);
1505       len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1506       va_end(arg_ptr);
1507       if (len < 0 || len >= (maxlen-5)) {
1508          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1509          continue;
1510       }
1511       break;
1512    }
1513    return len;
1514 }
1515
1516 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1517 {
1518    va_list   arg_ptr;
1519    int i, len, maxlen;
1520
1521    i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1522
1523    for (;;) {
1524       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1525       va_start(arg_ptr, fmt);
1526       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1527       va_end(arg_ptr);
1528       if (len < 0 || len >= (maxlen-5)) {
1529          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1530          continue;
1531       }
1532       break;
1533    }
1534    return len;
1535 }
1536
1537
1538 /*
1539  * Edit a message into a Pool Memory buffer NO file:lineno
1540  *  Returns: string length of what was edited.
1541  */
1542 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1543 {
1544    va_list   arg_ptr;
1545    int len, maxlen;
1546
1547    for (;;) {
1548       maxlen = sizeof_pool_memory(*pool_buf) - 1;
1549       va_start(arg_ptr, fmt);
1550       len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1551       va_end(arg_ptr);
1552       if (len < 0 || len >= (maxlen-5)) {
1553          *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1554          continue;
1555       }
1556       break;
1557    }
1558    return len;
1559 }
1560
1561 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1562 {
1563    va_list   arg_ptr;
1564    int len, maxlen;
1565
1566    for (;;) {
1567       maxlen = sizeof_pool_memory(pool_buf) - 1;
1568       va_start(arg_ptr, fmt);
1569       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1570       va_end(arg_ptr);
1571       if (len < 0 || len >= (maxlen-5)) {
1572          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1573          continue;
1574       }
1575       break;
1576    }
1577    return len;
1578 }
1579
1580 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1581 {
1582    va_list   arg_ptr;
1583    int len, maxlen;
1584
1585    for (;;) {
1586       maxlen = pool_buf.max_size() - 1;
1587       va_start(arg_ptr, fmt);
1588       len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1589       va_end(arg_ptr);
1590       if (len < 0 || len >= (maxlen-5)) {
1591          pool_buf.realloc_pm(maxlen + maxlen/2);
1592          continue;
1593       }
1594       break;
1595    }
1596    return len;
1597 }
1598
1599
1600 /*
1601  * We queue messages rather than print them directly. This
1602  *  is generally used in low level routines (msg handler, bnet)
1603  *  to prevent recursion (i.e. if you are in the middle of
1604  *  sending a message, it is a bit messy to recursively call
1605  *  yourself when the bnet packet is not reentrant).
1606  */
1607 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1608 {
1609    va_list   arg_ptr;
1610    int len, maxlen;
1611    POOLMEM *pool_buf;
1612    MQUEUE_ITEM *item;
1613
1614    pool_buf = get_pool_memory(PM_EMSG);
1615
1616    for (;;) {
1617       maxlen = sizeof_pool_memory(pool_buf) - 1;
1618       va_start(arg_ptr, fmt);
1619       len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1620       va_end(arg_ptr);
1621       if (len < 0 || len >= (maxlen-5)) {
1622          pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1623          continue;
1624       }
1625       break;
1626    }
1627    item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1628    item->type = type;
1629    item->mtime = time(NULL);
1630    strcpy(item->msg, pool_buf);
1631    if (!jcr) {
1632       jcr = get_jcr_from_tsd();
1633    }
1634
1635    if (jcr && type==M_FATAL) {
1636       // TODO ASX MUST use a lock to protect access jcr->JobStatus from another thread
1637       jcr->setJobStatus(JS_FatalError);
1638     }
1639
1640    /* If no jcr or no queue or dequeuing send to syslog */
1641    if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1642       syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1643       free(item);
1644    } else {
1645       /* Queue message for later sending */
1646       P(jcr->msg_queue_mutex);
1647       jcr->msg_queue->append(item);
1648       V(jcr->msg_queue_mutex);
1649    }
1650    free_memory(pool_buf);
1651 }
1652
1653 /*
1654  * Dequeue messages
1655  */
1656 void dequeue_messages(JCR *jcr)
1657 {
1658    MQUEUE_ITEM *item;
1659    if (!jcr->msg_queue) {
1660       return;
1661    }
1662    P(jcr->msg_queue_mutex);
1663    jcr->dequeuing_msgs = true;
1664    foreach_dlist(item, jcr->msg_queue) {
1665       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1666    }
1667    /* Remove messages just sent */
1668    jcr->msg_queue->destroy();
1669    jcr->dequeuing_msgs = false;
1670    V(jcr->msg_queue_mutex);
1671 }
1672
1673
1674 /*
1675  * If we come here, prefix the message with the file:line-number,
1676  *  then pass it on to the normal Qmsg routine.
1677  */
1678 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1679 {
1680    va_list   arg_ptr;
1681    int i, len, maxlen;
1682    POOLMEM *pool_buf;
1683
1684    pool_buf = get_pool_memory(PM_EMSG);
1685    i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1686
1687    for (;;) {
1688       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1689       va_start(arg_ptr, fmt);
1690       len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1691       va_end(arg_ptr);
1692       if (len < 0 || len >= (maxlen-5)) {
1693          pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1694          continue;
1695       }
1696       break;
1697    }
1698
1699    Qmsg(jcr, type, mtime, "%s", pool_buf);
1700    free_memory(pool_buf);
1701 }
1702
1703
1704 /* not all in alphabetical order.  New commands are added after existing commands with similar letters
1705    to prevent breakage of existing user scripts.  */
1706 struct debugtags {
1707    const char *tag;             /* command */
1708    int64_t     bit;             /* bit to set */
1709    const char *help;            /* main purpose */
1710 };
1711
1712 /* setdebug tag=all,-plugin */
1713 static struct debugtags debug_tags[] = {
1714  { NT_("lock"),        DT_LOCK,     _("Debug lock information")},
1715  { NT_("network"),     DT_NETWORK,  _("Debug network information")},
1716  { NT_("plugin"),      DT_PLUGIN,   _("Debug plugin information")},
1717  { NT_("volume"),      DT_VOLUME,   _("Debug volume information")},
1718  { NT_("sql"),         DT_SQL,      _("Debug SQL queries")},
1719  { NT_("bvfs"),        DT_BVFS,     _("Debug BVFS queries")},
1720  { NT_("memory"),      DT_MEMORY,   _("Debug memory allocation")},
1721  { NT_("scheduler"),   DT_SCHEDULER,_("Debug scheduler information")},
1722  { NT_("protocol"),    DT_PROTOCOL, _("Debug protocol information")},
1723  { NT_("snapshot"),    DT_SNAPSHOT, _("Debug snapshots")},
1724  { NT_("asx"),         DT_ASX,      _("ASX personal's debugging")},
1725  { NT_("all"),         DT_ALL,      _("Debug all information")},
1726  { NULL,               0,   NULL}
1727 };
1728
1729 #define MAX_TAG (sizeof(debug_tags) / sizeof(struct debugtags))
1730
1731 const char *debug_get_tag(uint32_t pos, const char **desc)
1732 {
1733    if (pos < MAX_TAG) {
1734       if (desc) {
1735          *desc = debug_tags[pos].help;
1736       }
1737       return debug_tags[pos].tag;
1738    }
1739    return NULL;
1740 }
1741
1742 /* Allow +-, */
1743 bool debug_find_tag(const char *tagname, bool add, int64_t *current_level)
1744 {
1745    Dmsg3(010, "add=%d tag=%s level=%lld\n", add, tagname, *current_level);
1746    if (!*tagname) {
1747       /* Nothing in the buffer */
1748       return true;
1749    }
1750    for (int i=0; debug_tags[i].tag ; i++) {
1751       if (strcasecmp(debug_tags[i].tag, tagname) == 0) {
1752          if (add) {
1753             *current_level |= debug_tags[i].bit;
1754          } else {
1755             *current_level &= ~(debug_tags[i].bit);
1756          }
1757          return true;
1758       }
1759    }
1760    return false;
1761 }
1762
1763 bool debug_parse_tags(const char *options, int64_t *current_level)
1764 {
1765    bool operation;              /* + => true, - false */
1766    char *p, *t, tag[256];
1767    int max = sizeof(tag) - 1;
1768    bool ret=true;
1769    int64_t level= *current_level;
1770
1771    t = tag;
1772    *tag = 0;
1773    operation = true;            /* add by default */
1774
1775    if (!options) {
1776       Dmsg0(100, "No options for tags\n");
1777       return false;
1778    }
1779
1780    for (p = (char *)options; *p ; p++) {
1781       if (*p == ',' || *p == '+' || *p == '-' || *p == '!') {
1782          /* finish tag keyword */
1783          *t = 0;
1784          /* handle tag */
1785          ret &= debug_find_tag(tag, operation, &level);
1786
1787          if (*p == ',') {
1788             /* reset tag */
1789             t = tag;
1790             *tag = 0;
1791             operation = true;
1792
1793          } else {
1794             /* reset tag */
1795             t = tag;
1796             *tag = 0;
1797             operation = (*p == '+');
1798          }
1799
1800       } else if (isalpha(*p) && (t - tag) < max) {
1801          *t++ = *p;
1802
1803       } else {                  /* not isalpha or too long */
1804          Dmsg1(010, "invalid %c\n", *p);
1805          return false;
1806       }
1807    }
1808
1809    /* At the end, finish the string and look it */
1810    *t = 0;
1811    if (t > tag) {               /* something found */
1812       /* handle tag */
1813       ret &= debug_find_tag(tag, operation, &level);
1814    }
1815
1816    *current_level = level;
1817    return ret;
1818 }
1819
1820 int generate_daemon_event(JCR *jcr, const char *event) { return 0; }