2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
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 three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
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.
18 You should have received a copy of the GNU Affero 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
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.
29 * Bacula message handling routines
31 * NOTE: don't use any Jmsg or Qmsg calls within this file,
32 * except in q_msg or j_msg (setup routines),
33 * otherwise you may get into recursive calls if there are
34 * errors, and that can lead to looping or deadlocks.
36 * Kern Sibbald, April 2000
43 sql_query_func p_sql_query = NULL;
44 sql_escape_func p_sql_escape = NULL;
46 #define FULL_LOCATION 1 /* set for file:line in Debug messages */
49 * This is where we define "Globals" because all the
50 * daemons include this file.
52 const char *working_directory = NULL; /* working directory path stored here */
53 int verbose = 0; /* increase User messages */
54 int debug_level = 0; /* debug level */
55 bool dbg_timestamp = false; /* print timestamp in debug output */
56 bool prt_kaboom = false; /* Print kaboom output */
57 utime_t daemon_start_time = 0; /* Daemon start time */
58 const char *version = VERSION " (" BDATE ")";
59 const char *dist_name = DISTNAME " " DISTVER;
60 const int beef = BEEF;
61 char my_name[30] = {0}; /* daemon name is stored here */
62 char host_name[50] = {0}; /* host machine name */
63 char *exepath = (char *)NULL;
64 char *exename = (char *)NULL;
65 int console_msg_pending = false;
66 char con_fname[500]; /* Console filename */
67 FILE *con_fd = NULL; /* Console file descriptor */
68 brwlock_t con_lock; /* Console lock structure */
70 /* Forward referenced functions */
72 /* Imported functions */
73 void create_jcr_key();
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 char *catalog_db = NULL; /* database type */
81 static void (*message_callback)(int type, char *msg) = NULL;
82 static FILE *trace_fd = NULL;
83 #if defined(HAVE_WIN32)
84 static bool trace = true;
86 static bool trace = false;
90 const char *host_os = HOST_OS;
91 const char *distname = DISTNAME;
92 const char *distver = DISTVER;
94 /* Some message class methods */
106 * Wait for not in use variable to be clear
108 void MSGS::wait_not_in_use() /* leaves fides_mutex set */
113 bmicrosleep(0, 200); /* wait */
119 * Handle message delivery errors
121 static void delivery_error(const char *fmt,...)
126 char dt[MAX_TIME_LENGTH];
129 pool_buf = get_pool_memory(PM_EMSG);
131 bstrftime_ny(dt, sizeof(dt), time(NULL));
136 i = Mmsg(pool_buf, "%s Message delivery ERROR: ", dt);
139 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
140 va_start(arg_ptr, fmt);
141 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
143 if (len < 0 || len >= (maxlen-5)) {
144 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
150 fputs(pool_buf, stdout); /* print this here to INSURE that it is printed */
152 syslog(LOG_DAEMON|LOG_ERR, "%s", pool_buf);
153 free_memory(pool_buf);
156 void register_message_callback(void msg_callback(int type, char *msg))
158 message_callback = msg_callback;
163 * Set daemon name. Also, find canonical execution
164 * path. Note, exepath has spare room for tacking on
165 * the exename so that we can reconstruct the full name.
167 * Note, this routine can get called multiple times
168 * The second time is to put the name as found in the
169 * Resource record. On the second call, generally,
170 * argv is NULL to avoid doing the path code twice.
172 void my_name_is(int argc, char *argv[], const char *name)
178 if (gethostname(host_name, sizeof(host_name)) != 0) {
179 bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
181 bstrncpy(my_name, name, sizeof(my_name));
182 if (argc>0 && argv && argv[0]) {
183 /* strip trailing filename and save exepath */
184 for (l=p=argv[0]; *p; p++) {
185 if (IsPathSeparator(*p)) {
186 l = p; /* set pos of last slash */
189 if (IsPathSeparator(*l)) {
193 #if defined(HAVE_WIN32)
194 /* On Windows allow c: junk */
204 exename = (char *)malloc(len);
210 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
211 for (p=argv[0],q=exepath; p < l; ) {
215 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
216 if (getcwd(cpath, sizeof(cpath))) {
218 exepath = (char *)malloc(strlen(cpath) + 1 + len);
219 strcpy(exepath, cpath);
222 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
227 set_db_type(const char *name)
229 if (catalog_db != NULL) {
232 catalog_db = bstrdup(name);
236 * Initialize message handler for a daemon or a Job
237 * We make a copy of the MSGS resource passed, so it belows
238 * to the job or daemon and thus can be modified.
240 * NULL for jcr -> initialize global messages for daemon
241 * non-NULL -> initialize jcr using Message resource
244 init_msg(JCR *jcr, MSGS *msg)
246 DEST *d, *dnew, *temp_chain = NULL;
249 if (jcr == NULL && msg == NULL) {
250 init_last_jobs_list();
251 /* Create a daemon key then set invalid jcr */
252 /* Maybe we should give the daemon a jcr??? */
254 set_jcr_in_tsd(INVALID_JCR);
257 #if !defined(HAVE_WIN32)
259 * Make sure we have fd's 0, 1, 2 open
260 * If we don't do this one of our sockets may open
261 * there and if we then use stdout, it could
262 * send total garbage to our socket.
266 fd = open("/dev/null", O_RDONLY, 0644);
270 for(i=1; fd + i <= 2; i++) {
277 * If msg is NULL, initialize global chain for STDOUT and syslog
280 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
281 memset(daemon_msgs, 0, sizeof(MSGS));
282 for (i=1; i<=M_MAX; i++) {
283 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
285 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
290 * Walk down the message resource chain duplicating it
291 * for the current Job.
293 for (d=msg->dest_chain; d; d=d->next) {
294 dnew = (DEST *)malloc(sizeof(DEST));
295 memcpy(dnew, d, sizeof(DEST));
296 dnew->next = temp_chain;
298 dnew->mail_filename = NULL;
300 dnew->mail_cmd = bstrdup(d->mail_cmd);
303 dnew->where = bstrdup(d->where);
309 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
310 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
311 jcr->jcr_msgs->dest_chain = temp_chain;
312 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
314 /* If we have default values, release them now */
316 free_msgs_res(daemon_msgs);
318 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
319 memset(daemon_msgs, 0, sizeof(MSGS));
320 daemon_msgs->dest_chain = temp_chain;
321 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
324 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
328 /* Initialize so that the console (User Agent) can
329 * receive messages -- stored in a file.
331 void init_console_msg(const char *wd)
335 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
336 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
339 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
340 con_fname, be.bstrerror());
342 if (lseek(fd, 0, SEEK_END) > 0) {
343 console_msg_pending = 1;
346 con_fd = fopen(con_fname, "a+b");
349 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
350 con_fname, be.bstrerror());
352 if (rwl_init(&con_lock) != 0) {
354 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
360 * Called only during parsing of the config file.
362 * Add a message destination. I.e. associate a message type with
363 * a destination (code).
364 * Note, where in the case of dest_code FILE is a filename,
365 * but in the case of MAIL is a space separated list of
366 * email addresses, ...
368 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
372 * First search the existing chain and see if we
373 * can simply add this msg_type to an existing entry.
375 for (d=msg->dest_chain; d; d=d->next) {
376 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
377 (strcmp(where, d->where) == 0))) {
378 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
379 d, msg_type, dest_code, NPRT(where));
380 set_bit(msg_type, d->msg_types);
381 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
385 /* Not found, create a new entry */
386 d = (DEST *)malloc(sizeof(DEST));
387 memset(d, 0, sizeof(DEST));
388 d->next = msg->dest_chain;
389 d->dest_code = dest_code;
390 set_bit(msg_type, d->msg_types); /* set type bit in structure */
391 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
393 d->where = bstrdup(where);
396 d->mail_cmd = bstrdup(mail_cmd);
398 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
399 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
404 * Called only during parsing of the config file.
406 * Remove a message destination
408 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
412 for (d=msg->dest_chain; d; d=d->next) {
413 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
414 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
415 ((where == NULL && d->where == NULL) ||
416 (strcmp(where, d->where) == 0))) {
417 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
418 d, msg_type, dest_code);
419 clear_bit(msg_type, d->msg_types);
420 Dmsg0(850, "Return rem_msg_dest\n");
428 * Create a unique filename for the mail command
430 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
433 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
434 jcr->Job, (int)(intptr_t)d);
436 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
437 my_name, (int)(intptr_t)d);
439 Dmsg1(850, "mailname=%s\n", name);
445 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
450 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
452 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
456 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
457 /* If we had to use sendmail, add subject */
459 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
463 delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
464 cmd, be.bstrerror());
470 * Close the messages for this Messages resource, which means to close
471 * any open files, and dispatch any pending email messages.
473 void close_msg(JCR *jcr)
481 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
483 if (jcr == NULL) { /* NULL -> global chain */
486 msgs = jcr->jcr_msgs;
487 jcr->jcr_msgs = NULL;
493 /* Wait for item to be not in use, then mark closing */
494 if (msgs->is_closing()) {
497 msgs->wait_not_in_use(); /* leaves fides_mutex set */
501 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
502 cmd = get_pool_memory(PM_MESSAGE);
503 for (d=msgs->dest_chain; d; ) {
505 switch (d->dest_code) {
509 fclose(d->fd); /* close open file descriptor */
514 case MD_MAIL_ON_ERROR:
515 case MD_MAIL_ON_SUCCESS:
516 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
521 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
522 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
524 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
525 jcr->JobStatus == JS_ErrorTerminated)
530 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
531 Pmsg0(000, _("open mail pipe failed.\n"));
534 Dmsg0(850, "Opened mail pipe\n");
536 line = get_memory(len);
538 while (fgets(line, len, d->fd)) {
539 fputs(line, bpipe->wfd);
541 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
543 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
547 * Since we are closing all messages, before "recursing"
548 * make sure we are not closing the daemon messages, otherwise
551 if (msgs != daemon_msgs) {
552 /* read what mail prog returned -- should be nothing */
553 while (fgets(line, len, bpipe->rfd)) {
554 delivery_error(_("Mail prog: %s"), line);
558 stat = close_bpipe(bpipe);
559 if (stat != 0 && msgs != daemon_msgs) {
562 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
563 delivery_error(_("Mail program terminated in error.\n"
565 "ERR=%s\n"), cmd, be.bstrerror());
569 /* Remove temp file */
572 unlink(d->mail_filename);
573 free_pool_memory(d->mail_filename);
574 d->mail_filename = NULL;
575 Dmsg0(850, "end mail or mail on error\n");
582 d = d->next; /* point to next buffer */
584 free_pool_memory(cmd);
585 Dmsg0(850, "Done walking message chain.\n");
590 msgs->clear_closing();
592 Dmsg0(850, "===End close msg resource\n");
596 * Free memory associated with Messages resource
598 void free_msgs_res(MSGS *msgs)
602 /* Walk down the message chain releasing allocated buffers */
603 for (d=msgs->dest_chain; d; ) {
610 old = d; /* save pointer to release */
611 d = d->next; /* point to next buffer */
612 free(old); /* free the destination item */
614 msgs->dest_chain = NULL;
615 free(msgs); /* free the head */
620 * Terminate the message handler for good.
621 * Release the global destination chain.
623 * Also, clean up a few other items (cons, exepath). Note,
624 * these really should be done elsewhere.
628 Dmsg0(850, "Enter term_msg\n");
629 close_msg(NULL); /* close global chain */
630 free_msgs_res(daemon_msgs); /* free the resources */
653 term_last_jobs_list();
656 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
658 d->fd = fopen(d->where, mode);
661 delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
668 * Handle sending the message to the appropriate place
670 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
673 char dt[MAX_TIME_LENGTH];
680 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
683 * Most messages are prefixed by a date and time. If mtime is
684 * zero, then we use the current time. If mtime is 1 (special
685 * kludge), we do not prefix the date and time. Otherwise,
686 * we assume mtime is a utime_t and use it.
694 mtime = time(NULL); /* get time for SQL log */
696 bstrftime_ny(dt, sizeof(dt), mtime);
702 /* If the program registered a callback, send it there */
703 if (message_callback) {
704 message_callback(type, msg);
708 /* For serious errors make sure message is printed or logged */
709 if (type == M_ABORT || type == M_ERROR_TERM) {
713 if (type == M_ABORT) {
714 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
719 /* Now figure out where to send the message */
722 jcr = get_jcr_from_tsd();
725 msgs = jcr->jcr_msgs;
731 * If closing this message resource, print and send to syslog,
734 if (msgs->is_closing()) {
738 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
742 for (d=msgs->dest_chain; d; d=d->next) {
743 if (bit_is_set(type, d->msg_types)) {
744 switch (d->dest_code) {
747 if (!jcr || !jcr->db) {
750 if (p_sql_query && p_sql_escape) {
751 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
752 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
754 int len = strlen(msg) + 1;
755 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
756 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
758 bstrutime(dt, sizeof(dt), mtime);
759 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
760 edit_int64(jcr->JobId, ed1), dt, esc_msg);
761 p_sql_query(jcr, cmd);
763 free_pool_memory(cmd);
764 free_pool_memory(esc_msg);
768 Dmsg1(850, "CONSOLE for following msg: %s", msg);
770 con_fd = fopen(con_fname, "a+b");
771 Dmsg0(850, "Console file not open.\n");
774 Pw(con_lock); /* get write lock on console message file */
777 (void)fwrite(dt, dtlen, 1, con_fd);
781 (void)fwrite(msg, len, 1, con_fd);
782 if (msg[len-1] != '\n') {
783 (void)fwrite("\n", 2, 1, con_fd);
786 (void)fwrite("\n", 2, 1, con_fd);
789 console_msg_pending = true;
794 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
796 * We really should do an openlog() here.
798 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
801 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
802 mcmd = get_pool_memory(PM_MESSAGE);
803 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
805 fputs(dt, bpipe->wfd);
806 fputs(msg, bpipe->wfd);
807 /* Messages to the operator go one at a time */
808 stat = close_bpipe(bpipe);
812 delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
814 "ERR=%s\n"), mcmd, be.bstrerror());
817 free_pool_memory(mcmd);
820 case MD_MAIL_ON_ERROR:
821 case MD_MAIL_ON_SUCCESS:
822 Dmsg1(850, "MAIL for following msg: %s", msg);
823 if (msgs->is_closing()) {
828 POOLMEM *name = get_pool_memory(PM_MESSAGE);
829 make_unique_mail_filename(jcr, name, d);
830 d->fd = fopen(name, "w+b");
833 delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
835 free_pool_memory(name);
839 d->mail_filename = name;
842 len = strlen(msg) + dtlen;;
843 if (len > d->max_len) {
844 d->max_len = len; /* keep max line length */
847 msgs->clear_in_use();
850 Dmsg1(850, "APPEND for following msg: %s", msg);
854 Dmsg1(850, "FILE for following msg: %s", msg);
857 if (msgs->is_closing()) {
861 if (!d->fd && !open_dest_file(jcr, d, mode)) {
862 msgs->clear_in_use();
867 /* On error, we close and reopen to handle log rotation */
871 if (open_dest_file(jcr, d, mode)) {
876 msgs->clear_in_use();
879 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
880 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
881 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
882 jcr->Job, type, mtime, msg);
884 Dmsg1(800, "no jcr for following msg: %s", msg);
888 Dmsg1(850, "STDOUT for following msg: %s", msg);
889 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
896 Dmsg1(850, "STDERR for following msg: %s", msg);
908 /*********************************************************************
910 * This subroutine returns the filename portion of a Windows
911 * path. It is used because Microsoft Visual Studio sets __FILE__
916 get_basename(const char *pathname)
918 #if defined(_MSC_VER)
919 const char *basename;
921 if ((basename = strrchr(pathname, '\\')) == NULL) {
934 * print or write output to trace file
936 static void pt_out(char *buf)
939 * Used the "trace on" command in the console to turn on
940 * output to the trace file. "trace off" will close the file.
945 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
946 trace_fd = fopen(fn, "a+b");
949 fputs(buf, trace_fd);
953 /* Some problem, turn off tracing */
962 /*********************************************************************
964 * This subroutine prints a debug message if the level number
965 * is less than or equal the debug_level. File and line numbers
966 * are included for more detail if desired, but not currently
969 * If the level is negative, the details of file and line number
973 d_msg(const char *file, int line, int level, const char *fmt,...)
986 if (level <= debug_level) {
989 bstrftimes(buf, sizeof(buf), mtime);
998 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
999 my_name, get_basename(file), line, get_jobid_from_tsd());
1006 va_start(arg_ptr, fmt);
1007 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1015 * Set trace flag on/off. If argument is negative, there is no change
1017 void set_trace(int trace_flag)
1019 if (trace_flag < 0) {
1021 } else if (trace_flag > 0) {
1026 if (!trace && trace_fd) {
1027 FILE *ltrace_fd = trace_fd;
1029 bmicrosleep(0, 100000); /* yield to prevent seg faults */
1034 bool get_trace(void)
1039 /*********************************************************************
1041 * This subroutine prints a message regardless of the debug level
1043 * If the level is negative, the details of file and line number
1047 p_msg(const char *file, int line, int level, const char *fmt,...)
1053 #ifdef FULL_LOCATION
1055 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1062 va_start(arg_ptr, fmt);
1063 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1070 /*********************************************************************
1072 * subroutine writes a debug message to the trace file 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
1077 * If the level is negative, the details of file and line number
1081 t_msg(const char *file, int line, int level, const char *fmt,...)
1093 if (level <= debug_level) {
1095 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1096 trace_fd = fopen(buf, "a+b");
1099 #ifdef FULL_LOCATION
1101 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1108 va_start(arg_ptr, fmt);
1109 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1111 if (trace_fd != NULL) {
1112 fputs(buf, trace_fd);
1118 /* *********************************************************
1120 * print an error message
1124 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1131 * Check if we have a message destination defined.
1132 * We always report M_ABORT and M_ERROR_TERM
1134 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1135 !bit_is_set(type, daemon_msgs->send_msg))) {
1136 return; /* no destination */
1140 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1141 my_name, get_basename(file), line);
1144 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1145 my_name, get_basename(file), line);
1148 if (level == -1) /* skip details */
1149 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1151 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1154 if (level == -1) /* skip details */
1155 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1157 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1160 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1163 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1166 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1170 va_start(arg_ptr, fmt);
1171 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1174 dispatch_message(NULL, type, 0, buf);
1176 if (type == M_ABORT) {
1178 p[0] = 0; /* generate segmentation violation */
1180 if (type == M_ERROR_TERM) {
1185 /* *********************************************************
1187 * Generate a Job message
1191 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1200 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1202 /* Special case for the console, which has a dir_bsock and JobId==0,
1203 * in that case, we send the message directly back to the
1206 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1207 BSOCK *dir = jcr->dir_bsock;
1208 va_start(arg_ptr, fmt);
1209 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1212 jcr->dir_bsock->send();
1216 /* The watchdog thread can't use Jmsg directly, we always queued it */
1217 if (is_watchdog()) {
1218 va_start(arg_ptr, fmt);
1219 bvsnprintf(rbuf, sizeof(rbuf), fmt, arg_ptr);
1221 Qmsg(jcr, type, mtime, "%s", rbuf);
1227 jcr = get_jcr_from_tsd();
1230 if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1231 /* Dequeue messages to keep the original order */
1232 dequeue_messages(jcr);
1234 msgs = jcr->jcr_msgs;
1238 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1242 * Check if we have a message destination defined.
1243 * We always report M_ABORT and M_ERROR_TERM
1245 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1246 !bit_is_set(type, msgs->send_msg)) {
1247 return; /* no destination */
1251 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1254 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1257 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1259 set_jcr_job_status(jcr, JS_FatalError);
1261 if (jcr && jcr->JobErrors == 0) {
1266 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1272 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1278 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1282 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1286 va_start(arg_ptr, fmt);
1287 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1290 dispatch_message(jcr, type, mtime, rbuf);
1292 if (type == M_ABORT){
1294 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1295 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1296 p[0] = 0; /* generate segmentation violation */
1298 if (type == M_ERROR_TERM) {
1304 * If we come here, prefix the message with the file:line-number,
1305 * then pass it on to the normal Jmsg routine.
1307 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1313 pool_buf = get_pool_memory(PM_EMSG);
1314 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1317 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1318 va_start(arg_ptr, fmt);
1319 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1321 if (len < 0 || len >= (maxlen-5)) {
1322 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1328 Jmsg(jcr, type, mtime, "%s", pool_buf);
1329 free_memory(pool_buf);
1334 * Edit a message into a Pool memory buffer, with file:lineno
1336 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1341 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1344 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1345 va_start(arg_ptr, fmt);
1346 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1348 if (len < 0 || len >= (maxlen-5)) {
1349 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1357 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1362 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1365 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1366 va_start(arg_ptr, fmt);
1367 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1369 if (len < 0 || len >= (maxlen-5)) {
1370 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1380 * Edit a message into a Pool Memory buffer NO file:lineno
1381 * Returns: string length of what was edited.
1383 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1389 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1390 va_start(arg_ptr, fmt);
1391 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1393 if (len < 0 || len >= (maxlen-5)) {
1394 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1402 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1408 maxlen = sizeof_pool_memory(pool_buf) - 1;
1409 va_start(arg_ptr, fmt);
1410 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1412 if (len < 0 || len >= (maxlen-5)) {
1413 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1421 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1427 maxlen = pool_buf.max_size() - 1;
1428 va_start(arg_ptr, fmt);
1429 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1431 if (len < 0 || len >= (maxlen-5)) {
1432 pool_buf.realloc_pm(maxlen + maxlen/2);
1442 * We queue messages rather than print them directly. This
1443 * is generally used in low level routines (msg handler, bnet)
1444 * to prevent recursion (i.e. if you are in the middle of
1445 * sending a message, it is a bit messy to recursively call
1446 * yourself when the bnet packet is not reentrant).
1448 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1455 pool_buf = get_pool_memory(PM_EMSG);
1458 maxlen = sizeof_pool_memory(pool_buf) - 1;
1459 va_start(arg_ptr, fmt);
1460 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1462 if (len < 0 || len >= (maxlen-5)) {
1463 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1468 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1470 item->mtime = time(NULL);
1471 strcpy(item->msg, pool_buf);
1473 jcr = get_jcr_from_tsd();
1475 /* If no jcr or no queue or dequeuing send to syslog */
1476 if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1477 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1480 /* Queue message for later sending */
1481 P(jcr->msg_queue_mutex);
1482 jcr->msg_queue->append(item);
1483 V(jcr->msg_queue_mutex);
1485 free_memory(pool_buf);
1491 void dequeue_messages(JCR *jcr)
1494 if (!jcr->msg_queue) {
1497 P(jcr->msg_queue_mutex);
1498 jcr->dequeuing_msgs = true;
1499 foreach_dlist(item, jcr->msg_queue) {
1500 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1502 /* Remove messages just sent */
1503 jcr->msg_queue->destroy();
1504 jcr->dequeuing_msgs = false;
1505 V(jcr->msg_queue_mutex);
1510 * If we come here, prefix the message with the file:line-number,
1511 * then pass it on to the normal Qmsg routine.
1513 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1519 pool_buf = get_pool_memory(PM_EMSG);
1520 i = Mmsg(pool_buf, "%s:%d ", file, line);
1523 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1524 va_start(arg_ptr, fmt);
1525 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1527 if (len < 0 || len >= (maxlen-5)) {
1528 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1534 Qmsg(jcr, type, mtime, "%s", pool_buf);
1535 free_memory(pool_buf);