2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 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 two of the GNU 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 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 John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Bacula message handling routines
31 * Kern Sibbald, April 2000
41 #define get_jcr_from_tsd() NULL
42 #define get_jobid_from_tsd() 0
44 sql_query p_sql_query = NULL;
45 sql_escape p_sql_escape = NULL;
47 #define FULL_LOCATION 1 /* set for file:line in Debug messages */
50 * This is where we define "Globals" because all the
51 * daemons include this file.
53 const char *working_directory = NULL; /* working directory path stored here */
54 int verbose = 0; /* increase User messages */
55 int debug_level = 1; /* debug level */
56 time_t daemon_start_time = 0; /* Daemon start time */
57 const char *version = VERSION " (" BDATE ")";
58 char my_name[30]; /* daemon name is stored here */
59 char *exepath = (char *)NULL;
60 char *exename = (char *)NULL;
61 int console_msg_pending = false;
62 char con_fname[500]; /* Console filename */
63 FILE *con_fd = NULL; /* Console file descriptor */
64 brwlock_t con_lock; /* Console lock structure */
66 /* Forward referenced functions */
68 /* Imported functions */
73 /* Used to allow only one thread close the daemon messages at a time */
74 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
75 static MSGS *daemon_msgs; /* global messages */
76 static char *catalog_db = NULL; /* database type */
77 static void (*message_callback)(int type, char *msg) = NULL;
78 static FILE *trace_fd = NULL;
79 #if defined(HAVE_WIN32)
80 static bool trace = true;
82 static bool trace = false;
86 const char *host_os = HOST_OS;
87 const char *distname = DISTNAME;
88 const char *distver = DISTVER;
91 void register_message_callback(void msg_callback(int type, char *msg))
93 message_callback = msg_callback;
98 * Set daemon name. Also, find canonical execution
99 * path. Note, exepath has spare room for tacking on
100 * the exename so that we can reconstruct the full name.
102 * Note, this routine can get called multiple times
103 * The second time is to put the name as found in the
104 * Resource record. On the second call, generally,
105 * argv is NULL to avoid doing the path code twice.
107 void my_name_is(int argc, char *argv[], const char *name)
113 bstrncpy(my_name, name, sizeof(my_name));
114 if (argc>0 && argv && argv[0]) {
115 /* strip trailing filename and save exepath */
116 for (l=p=argv[0]; *p; p++) {
117 if (IsPathSeparator(*p)) {
118 l = p; /* set pos of last slash */
121 if (IsPathSeparator(*l)) {
125 #if defined(HAVE_WIN32)
126 /* On Windows allow c: junk */
136 exename = (char *)malloc(len);
142 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
143 for (p=argv[0],q=exepath; p < l; ) {
147 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
148 if (getcwd(cpath, sizeof(cpath))) {
150 exepath = (char *)malloc(strlen(cpath) + 1 + len);
151 strcpy(exepath, cpath);
154 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
161 return catalog_db != NULL ? catalog_db : "unknown";
165 set_db_type(const char *name)
167 if (catalog_db != NULL) {
170 catalog_db = bstrdup(name);
174 * Initialize message handler for a daemon or a Job
175 * We make a copy of the MSGS resource passed, so it belows
176 * to the job or daemon and thus can be modified.
178 * NULL for jcr -> initialize global messages for daemon
179 * non-NULL -> initialize jcr using Message resource
182 init_msg(JCR *jcr, MSGS *msg)
184 DEST *d, *dnew, *temp_chain = NULL;
187 if (jcr == NULL && msg == NULL) {
188 init_last_jobs_list();
191 #if !defined(HAVE_WIN32)
193 * Make sure we have fd's 0, 1, 2 open
194 * If we don't do this one of our sockets may open
195 * there and if we then use stdout, it could
196 * send total garbage to our socket.
200 fd = open("/dev/null", O_RDONLY, 0644);
204 for(i=1; fd + i <= 2; i++) {
211 * If msg is NULL, initialize global chain for STDOUT and syslog
214 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
215 memset(daemon_msgs, 0, sizeof(MSGS));
216 for (i=1; i<=M_MAX; i++) {
217 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
219 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
224 * Walk down the message resource chain duplicating it
225 * for the current Job.
227 for (d=msg->dest_chain; d; d=d->next) {
228 dnew = (DEST *)malloc(sizeof(DEST));
229 memcpy(dnew, d, sizeof(DEST));
230 dnew->next = temp_chain;
232 dnew->mail_filename = NULL;
234 dnew->mail_cmd = bstrdup(d->mail_cmd);
237 dnew->where = bstrdup(d->where);
243 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
244 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
245 jcr->jcr_msgs->dest_chain = temp_chain;
246 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
248 /* If we have default values, release them now */
250 free_msgs_res(daemon_msgs);
252 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
253 memset(daemon_msgs, 0, sizeof(MSGS));
254 daemon_msgs->dest_chain = temp_chain;
255 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
257 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
261 /* Initialize so that the console (User Agent) can
262 * receive messages -- stored in a file.
264 void init_console_msg(const char *wd)
268 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
269 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
272 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
273 con_fname, be.bstrerror());
275 if (lseek(fd, 0, SEEK_END) > 0) {
276 console_msg_pending = 1;
279 con_fd = fopen(con_fname, "a+b");
282 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
283 con_fname, be.bstrerror());
285 if (rwl_init(&con_lock) != 0) {
287 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
293 * Called only during parsing of the config file.
295 * Add a message destination. I.e. associate a message type with
296 * a destination (code).
297 * Note, where in the case of dest_code FILE is a filename,
298 * but in the case of MAIL is a space separated list of
299 * email addresses, ...
301 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
305 * First search the existing chain and see if we
306 * can simply add this msg_type to an existing entry.
308 for (d=msg->dest_chain; d; d=d->next) {
309 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
310 (strcmp(where, d->where) == 0))) {
311 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
312 d, msg_type, dest_code, NPRT(where));
313 set_bit(msg_type, d->msg_types);
314 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
318 /* Not found, create a new entry */
319 d = (DEST *)malloc(sizeof(DEST));
320 memset(d, 0, sizeof(DEST));
321 d->next = msg->dest_chain;
322 d->dest_code = dest_code;
323 set_bit(msg_type, d->msg_types); /* set type bit in structure */
324 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
326 d->where = bstrdup(where);
329 d->mail_cmd = bstrdup(mail_cmd);
331 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
332 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
337 * Called only during parsing of the config file.
339 * Remove a message destination
341 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
345 for (d=msg->dest_chain; d; d=d->next) {
346 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
347 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
348 ((where == NULL && d->where == NULL) ||
349 (strcmp(where, d->where) == 0))) {
350 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
351 d, msg_type, dest_code);
352 clear_bit(msg_type, d->msg_types);
353 Dmsg0(850, "Return rem_msg_dest\n");
361 * Create a unique filename for the mail command
363 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
366 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
367 jcr->Job, (int)(long)d);
369 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
370 my_name, (int)(long)d);
372 Dmsg1(850, "mailname=%s\n", name);
378 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
383 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
385 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
389 if (!(bpipe = open_bpipe(cmd, 120, "rw"))) {
391 Jmsg(jcr, M_ERROR, 0, _("open mail pipe %s failed: ERR=%s\n"),
392 cmd, be.bstrerror());
395 /* If we had to use sendmail, add subject */
397 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
404 * Close the messages for this Messages resource, which means to close
405 * any open files, and dispatch any pending email messages.
407 void close_msg(JCR *jcr)
415 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
417 if (jcr == NULL) { /* NULL -> global chain */
419 P(mutex); /* only one thread walking the chain */
421 msgs = jcr->jcr_msgs;
422 jcr->jcr_msgs = NULL;
427 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
428 cmd = get_pool_memory(PM_MESSAGE);
429 for (d=msgs->dest_chain; d; ) {
431 switch (d->dest_code) {
435 fclose(d->fd); /* close open file descriptor */
440 case MD_MAIL_ON_ERROR:
441 case MD_MAIL_ON_SUCCESS:
442 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
447 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
448 jcr->JobStatus == JS_Terminated)
450 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
451 jcr->JobStatus == JS_ErrorTerminated)
456 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
457 Pmsg0(000, _("open mail pipe failed.\n"));
460 Dmsg0(850, "Opened mail pipe\n");
462 line = get_memory(len);
464 while (fgets(line, len, d->fd)) {
465 fputs(line, bpipe->wfd);
467 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
469 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
473 * Since we are closing all messages, before "recursing"
474 * make sure we are not closing the daemon messages, otherwise
477 if (msgs != daemon_msgs) {
478 /* read what mail prog returned -- should be nothing */
479 while (fgets(line, len, bpipe->rfd)) {
480 Jmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line);
484 stat = close_bpipe(bpipe);
485 if (stat != 0 && msgs != daemon_msgs) {
488 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
489 Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
491 "ERR=%s\n"), cmd, be.bstrerror());
495 /* Remove temp file */
498 unlink(d->mail_filename);
499 free_pool_memory(d->mail_filename);
500 d->mail_filename = NULL;
501 Dmsg0(850, "end mail or mail on error\n");
508 d = d->next; /* point to next buffer */
510 free_pool_memory(cmd);
511 Dmsg0(850, "Done walking message chain.\n");
518 Dmsg0(850, "===End close msg resource\n");
522 * Free memory associated with Messages resource
524 void free_msgs_res(MSGS *msgs)
528 /* Walk down the message chain releasing allocated buffers */
529 for (d=msgs->dest_chain; d; ) {
536 old = d; /* save pointer to release */
537 d = d->next; /* point to next buffer */
538 free(old); /* free the destination item */
540 msgs->dest_chain = NULL;
541 free(msgs); /* free the head */
546 * Terminate the message handler for good.
547 * Release the global destination chain.
549 * Also, clean up a few other items (cons, exepath). Note,
550 * these really should be done elsewhere.
554 Dmsg0(850, "Enter term_msg\n");
555 close_msg(NULL); /* close global chain */
556 free_msgs_res(daemon_msgs); /* free the resources */
579 term_last_jobs_list();
582 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
584 d->fd = fopen(d->where, mode);
588 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
596 * Handle sending the message to the appropriate place
598 void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
601 char dt[MAX_TIME_LENGTH];
608 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
611 * Most messages are prefixed by a date and time. If mtime is
612 * zero, then we use the current time. If mtime is 1 (special
613 * kludge), we do not prefix the date and time. Otherwise,
614 * we assume mtime is a time_t and use it.
623 bstrftime_ny(dt, sizeof(dt), mtime);
629 /* If the program registered a callback, send it there */
630 if (message_callback) {
631 message_callback(type, msg);
635 if (type == M_ABORT || type == M_ERROR_TERM) {
637 fputs(msg, stdout); /* print this here to INSURE that it is printed */
642 /* Now figure out where to send the message */
645 jcr = get_jcr_from_tsd();
648 msgs = jcr->jcr_msgs;
653 for (d=msgs->dest_chain; d; d=d->next) {
654 if (bit_is_set(type, d->msg_types)) {
655 switch (d->dest_code) {
658 if (!jcr || !jcr->db) {
661 if (p_sql_query && p_sql_escape) {
662 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
663 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
665 int len = strlen(msg) + 1;
666 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
667 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
669 bstrutime(dt, sizeof(dt), mtime);
670 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
671 edit_int64(jcr->JobId, ed1), dt, esc_msg);
672 p_sql_query(jcr, cmd);
674 free_pool_memory(cmd);
675 free_pool_memory(esc_msg);
679 Dmsg1(850, "CONSOLE for following msg: %s", msg);
681 con_fd = fopen(con_fname, "a+b");
682 Dmsg0(850, "Console file not open.\n");
685 Pw(con_lock); /* get write lock on console message file */
688 (void)fwrite(dt, dtlen, 1, con_fd);
692 (void)fwrite(msg, len, 1, con_fd);
693 if (msg[len-1] != '\n') {
694 (void)fwrite("\n", 2, 1, con_fd);
697 (void)fwrite("\n", 2, 1, con_fd);
700 console_msg_pending = true;
705 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
707 * We really should do an openlog() here.
709 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
712 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
713 mcmd = get_pool_memory(PM_MESSAGE);
714 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
716 fputs(dt, bpipe->wfd);
717 fputs(msg, bpipe->wfd);
718 /* Messages to the operator go one at a time */
719 stat = close_bpipe(bpipe);
723 Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n"
725 "ERR=%s\n"), mcmd, be.bstrerror());
728 free_pool_memory(mcmd);
731 case MD_MAIL_ON_ERROR:
732 case MD_MAIL_ON_SUCCESS:
733 Dmsg1(850, "MAIL for following msg: %s", msg);
735 POOLMEM *name = get_pool_memory(PM_MESSAGE);
736 make_unique_mail_filename(jcr, name, d);
737 d->fd = fopen(name, "w+b");
741 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), name,
744 free_pool_memory(name);
747 d->mail_filename = name;
750 len = strlen(msg) + dtlen;;
751 if (len > d->max_len) {
752 d->max_len = len; /* keep max line length */
757 Dmsg1(850, "APPEND for following msg: %s", msg);
761 Dmsg1(850, "FILE for following msg: %s", msg);
764 if (!d->fd && !open_dest_file(jcr, d, mode)) {
769 /* On error, we close and reopen to handle log rotation */
773 if (open_dest_file(jcr, d, mode)) {
780 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
781 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
782 bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s",
783 jcr->Job, type, mtime, msg);
787 Dmsg1(850, "STDOUT for following msg: %s", msg);
788 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
795 Dmsg1(850, "STDERR for following msg: %s", msg);
807 /*********************************************************************
809 * This subroutine returns the filename portion of a Windows
810 * path. It is used because Microsoft Visual Studio sets __FILE__
815 get_basename(const char *pathname)
817 #if defined(_MSC_VER)
818 const char *basename;
820 if ((basename = strrchr(pathname, '\\')) == NULL) {
832 /*********************************************************************
834 * This subroutine prints a debug message if the level number
835 * is less than or equal the debug_level. File and line numbers
836 * are included for more detail if desired, but not currently
839 * If the level is negative, the details of file and line number
843 d_msg(const char *file, int line, int level, const char *fmt,...)
855 if (level <= debug_level) {
858 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
859 my_name, get_basename(file), line, get_jobid_from_tsd());
866 va_start(arg_ptr, fmt);
867 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
871 * Used the "trace on" command in the console to turn on
872 * output to the trace file. "trace off" will close the file.
877 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
878 trace_fd = fopen(fn, "a+b");
881 fputs(buf, trace_fd);
884 /* Some problem, turn off tracing */
887 } else { /* not tracing */
895 * Set trace flag on/off. If argument is negative, there is no change
897 void set_trace(int trace_flag)
899 if (trace_flag < 0) {
901 } else if (trace_flag > 0) {
906 if (!trace && trace_fd) {
907 FILE *ltrace_fd = trace_fd;
909 bmicrosleep(0, 100000); /* yield to prevent seg faults */
919 /*********************************************************************
921 * This subroutine prints a message regardless of the debug level
923 * If the level is negative, the details of file and line number
927 p_msg(const char *file, int line, int level, const char *fmt,...)
935 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
942 va_start(arg_ptr, fmt);
943 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
950 /*********************************************************************
952 * subroutine writes a debug message to the trace file if the level number
953 * is less than or equal the debug_level. File and line numbers
954 * are included for more detail if desired, but not currently
957 * If the level is negative, the details of file and line number
961 t_msg(const char *file, int line, int level, const char *fmt,...)
973 if (level <= debug_level) {
975 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
976 trace_fd = fopen(buf, "a+b");
981 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
988 va_start(arg_ptr, fmt);
989 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
991 if (trace_fd != NULL) {
992 fputs(buf, trace_fd);
1000 /* *********************************************************
1002 * print an error message
1006 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1013 * Check if we have a message destination defined.
1014 * We always report M_ABORT and M_ERROR_TERM
1016 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1017 !bit_is_set(type, daemon_msgs->send_msg))) {
1018 return; /* no destination */
1022 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1023 my_name, get_basename(file), line);
1026 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1027 my_name, get_basename(file), line);
1030 if (level == -1) /* skip details */
1031 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1033 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1036 if (level == -1) /* skip details */
1037 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1039 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1042 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1045 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1048 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1052 va_start(arg_ptr, fmt);
1053 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1056 dispatch_message(NULL, type, 0, buf);
1058 if (type == M_ABORT) {
1060 p[0] = 0; /* generate segmentation violation */
1062 if (type == M_ERROR_TERM) {
1067 /* *********************************************************
1069 * Generate a Job message
1073 Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1082 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1084 /* Special case for the console, which has a dir_bsock and JobId==0,
1085 * in that case, we send the message directly back to the
1088 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1089 BSOCK *dir = jcr->dir_bsock;
1090 va_start(arg_ptr, fmt);
1091 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1094 jcr->dir_bsock->send();
1100 jcr = get_jcr_from_tsd();
1103 msgs = jcr->jcr_msgs;
1107 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1111 * Check if we have a message destination defined.
1112 * We always report M_ABORT and M_ERROR_TERM
1114 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1115 !bit_is_set(type, msgs->send_msg)) {
1116 return; /* no destination */
1120 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1123 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1126 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1128 set_jcr_job_status(jcr, JS_FatalError);
1132 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1138 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1141 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1145 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1149 va_start(arg_ptr, fmt);
1150 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1153 dispatch_message(jcr, type, mtime, rbuf);
1155 if (type == M_ABORT){
1157 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1158 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1159 p[0] = 0; /* generate segmentation violation */
1161 if (type == M_ERROR_TERM) {
1167 * If we come here, prefix the message with the file:line-number,
1168 * then pass it on to the normal Jmsg routine.
1170 void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1176 pool_buf = get_pool_memory(PM_EMSG);
1177 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1180 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1181 va_start(arg_ptr, fmt);
1182 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1184 if (len < 0 || len >= (maxlen-5)) {
1185 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1191 Jmsg(jcr, type, mtime, "%s", pool_buf);
1192 free_memory(pool_buf);
1197 * Edit a message into a Pool memory buffer, with file:lineno
1199 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1204 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1207 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1208 va_start(arg_ptr, fmt);
1209 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1211 if (len < 0 || len >= (maxlen-5)) {
1212 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1220 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1225 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1228 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1229 va_start(arg_ptr, fmt);
1230 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1232 if (len < 0 || len >= (maxlen-5)) {
1233 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1243 * Edit a message into a Pool Memory buffer NO file:lineno
1244 * Returns: string length of what was edited.
1246 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1252 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1253 va_start(arg_ptr, fmt);
1254 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1256 if (len < 0 || len >= (maxlen-5)) {
1257 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1265 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1271 maxlen = sizeof_pool_memory(pool_buf) - 1;
1272 va_start(arg_ptr, fmt);
1273 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1275 if (len < 0 || len >= (maxlen-5)) {
1276 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1284 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1290 maxlen = pool_buf.max_size() - 1;
1291 va_start(arg_ptr, fmt);
1292 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1294 if (len < 0 || len >= (maxlen-5)) {
1295 pool_buf.realloc_pm(maxlen + maxlen/2);
1304 static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
1307 * We queue messages rather than print them directly. This
1308 * is generally used in low level routines (msg handler, bnet)
1309 * to prevent recursion (i.e. if you are in the middle of
1310 * sending a message, it is a bit messy to recursively call
1311 * yourself when the bnet packet is not reentrant).
1313 void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1320 pool_buf = get_pool_memory(PM_EMSG);
1323 maxlen = sizeof_pool_memory(pool_buf) - 1;
1324 va_start(arg_ptr, fmt);
1325 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1327 if (len < 0 || len >= (maxlen-5)) {
1328 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1333 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1335 item->mtime = time(NULL);
1336 strcpy(item->msg, pool_buf);
1338 jcr = get_jcr_from_tsd();
1340 /* If no jcr or dequeuing send to daemon to avoid recursion */
1341 if (!jcr || jcr->dequeuing) {
1342 /* jcr==NULL => daemon message, safe to send now */
1343 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1346 /* Queue message for later sending */
1348 jcr->msg_queue->append(item);
1351 free_memory(pool_buf);
1357 void dequeue_messages(JCR *jcr)
1361 if (!jcr->msg_queue) {
1364 jcr->dequeuing = true;
1365 foreach_dlist(item, jcr->msg_queue) {
1366 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1368 jcr->msg_queue->destroy();
1369 jcr->dequeuing = false;
1377 * If we come here, prefix the message with the file:line-number,
1378 * then pass it on to the normal Qmsg routine.
1380 void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1386 pool_buf = get_pool_memory(PM_EMSG);
1387 i = Mmsg(pool_buf, "%s:%d ", file, line);
1390 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1391 va_start(arg_ptr, fmt);
1392 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1394 if (len < 0 || len >= (maxlen-5)) {
1395 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1401 Qmsg(jcr, type, mtime, "%s", pool_buf);
1402 free_memory(pool_buf);