2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 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 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 * Kern Sibbald, April 2000
41 sql_query p_sql_query = NULL;
42 sql_escape p_sql_escape = NULL;
44 #define FULL_LOCATION 1 /* set for file:line in Debug messages */
47 * This is where we define "Globals" because all the
48 * daemons include this file.
50 const char *working_directory = NULL; /* working directory path stored here */
51 int verbose = 0; /* increase User messages */
52 int debug_level = 0; /* debug level */
53 bool dbg_timestamp = false; /* print timestamp in debug output */
54 time_t daemon_start_time = 0; /* Daemon start time */
55 const char *version = VERSION " (" BDATE ")";
56 char my_name[30]; /* daemon name is stored here */
57 char host_name[50]; /* host machine name */
58 char *exepath = (char *)NULL;
59 char *exename = (char *)NULL;
60 int console_msg_pending = false;
61 char con_fname[500]; /* Console filename */
62 FILE *con_fd = NULL; /* Console file descriptor */
63 brwlock_t con_lock; /* Console lock structure */
65 /* Forward referenced functions */
67 /* Imported functions */
72 /* Used to allow only one thread close the daemon messages at a time */
73 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
74 static MSGS *daemon_msgs; /* global messages */
75 static char *catalog_db = NULL; /* database type */
76 static void (*message_callback)(int type, char *msg) = NULL;
77 static FILE *trace_fd = NULL;
78 #if defined(HAVE_WIN32)
79 static bool trace = true;
81 static bool trace = false;
85 const char *host_os = HOST_OS;
86 const char *distname = DISTNAME;
87 const char *distver = DISTVER;
90 void register_message_callback(void msg_callback(int type, char *msg))
92 message_callback = msg_callback;
97 * Set daemon name. Also, find canonical execution
98 * path. Note, exepath has spare room for tacking on
99 * the exename so that we can reconstruct the full name.
101 * Note, this routine can get called multiple times
102 * The second time is to put the name as found in the
103 * Resource record. On the second call, generally,
104 * argv is NULL to avoid doing the path code twice.
106 void my_name_is(int argc, char *argv[], const char *name)
112 if (gethostname(host_name, sizeof(host_name)) != 0) {
113 bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
115 bstrncpy(my_name, name, sizeof(my_name));
116 if (argc>0 && argv && argv[0]) {
117 /* strip trailing filename and save exepath */
118 for (l=p=argv[0]; *p; p++) {
119 if (IsPathSeparator(*p)) {
120 l = p; /* set pos of last slash */
123 if (IsPathSeparator(*l)) {
127 #if defined(HAVE_WIN32)
128 /* On Windows allow c: junk */
138 exename = (char *)malloc(len);
144 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
145 for (p=argv[0],q=exepath; p < l; ) {
149 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
150 if (getcwd(cpath, sizeof(cpath))) {
152 exepath = (char *)malloc(strlen(cpath) + 1 + len);
153 strcpy(exepath, cpath);
156 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
163 return catalog_db != NULL ? catalog_db : "unknown";
167 set_db_type(const char *name)
169 if (catalog_db != NULL) {
172 catalog_db = bstrdup(name);
176 * Initialize message handler for a daemon or a Job
177 * We make a copy of the MSGS resource passed, so it belows
178 * to the job or daemon and thus can be modified.
180 * NULL for jcr -> initialize global messages for daemon
181 * non-NULL -> initialize jcr using Message resource
184 init_msg(JCR *jcr, MSGS *msg)
186 DEST *d, *dnew, *temp_chain = NULL;
189 if (jcr == NULL && msg == NULL) {
190 init_last_jobs_list();
193 #if !defined(HAVE_WIN32)
195 * Make sure we have fd's 0, 1, 2 open
196 * If we don't do this one of our sockets may open
197 * there and if we then use stdout, it could
198 * send total garbage to our socket.
202 fd = open("/dev/null", O_RDONLY, 0644);
206 for(i=1; fd + i <= 2; i++) {
213 * If msg is NULL, initialize global chain for STDOUT and syslog
216 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
217 memset(daemon_msgs, 0, sizeof(MSGS));
218 for (i=1; i<=M_MAX; i++) {
219 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
221 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
226 * Walk down the message resource chain duplicating it
227 * for the current Job.
229 for (d=msg->dest_chain; d; d=d->next) {
230 dnew = (DEST *)malloc(sizeof(DEST));
231 memcpy(dnew, d, sizeof(DEST));
232 dnew->next = temp_chain;
234 dnew->mail_filename = NULL;
236 dnew->mail_cmd = bstrdup(d->mail_cmd);
239 dnew->where = bstrdup(d->where);
245 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
246 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
247 jcr->jcr_msgs->dest_chain = temp_chain;
248 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
250 /* If we have default values, release them now */
252 free_msgs_res(daemon_msgs);
254 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
255 memset(daemon_msgs, 0, sizeof(MSGS));
256 daemon_msgs->dest_chain = temp_chain;
257 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
259 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
263 /* Initialize so that the console (User Agent) can
264 * receive messages -- stored in a file.
266 void init_console_msg(const char *wd)
270 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
271 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
274 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
275 con_fname, be.bstrerror());
277 if (lseek(fd, 0, SEEK_END) > 0) {
278 console_msg_pending = 1;
281 con_fd = fopen(con_fname, "a+b");
284 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
285 con_fname, be.bstrerror());
287 if (rwl_init(&con_lock) != 0) {
289 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
295 * Called only during parsing of the config file.
297 * Add a message destination. I.e. associate a message type with
298 * a destination (code).
299 * Note, where in the case of dest_code FILE is a filename,
300 * but in the case of MAIL is a space separated list of
301 * email addresses, ...
303 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
307 * First search the existing chain and see if we
308 * can simply add this msg_type to an existing entry.
310 for (d=msg->dest_chain; d; d=d->next) {
311 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
312 (strcmp(where, d->where) == 0))) {
313 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
314 d, msg_type, dest_code, NPRT(where));
315 set_bit(msg_type, d->msg_types);
316 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
320 /* Not found, create a new entry */
321 d = (DEST *)malloc(sizeof(DEST));
322 memset(d, 0, sizeof(DEST));
323 d->next = msg->dest_chain;
324 d->dest_code = dest_code;
325 set_bit(msg_type, d->msg_types); /* set type bit in structure */
326 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
328 d->where = bstrdup(where);
331 d->mail_cmd = bstrdup(mail_cmd);
333 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
334 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
339 * Called only during parsing of the config file.
341 * Remove a message destination
343 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
347 for (d=msg->dest_chain; d; d=d->next) {
348 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
349 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
350 ((where == NULL && d->where == NULL) ||
351 (strcmp(where, d->where) == 0))) {
352 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
353 d, msg_type, dest_code);
354 clear_bit(msg_type, d->msg_types);
355 Dmsg0(850, "Return rem_msg_dest\n");
363 * Create a unique filename for the mail command
365 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
368 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
369 jcr->Job, (int)(long)d);
371 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
372 my_name, (int)(long)d);
374 Dmsg1(850, "mailname=%s\n", name);
380 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
385 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
387 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
391 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
392 /* If we had to use sendmail, add subject */
394 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
398 Jmsg(jcr, M_ERROR, 0, _("open mail pipe %s failed: ERR=%s\n"),
399 cmd, be.bstrerror());
405 * Close the messages for this Messages resource, which means to close
406 * any open files, and dispatch any pending email messages.
408 void close_msg(JCR *jcr)
416 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
418 if (jcr == NULL) { /* NULL -> global chain */
420 P(mutex); /* only one thread walking the chain */
422 msgs = jcr->jcr_msgs;
423 jcr->jcr_msgs = NULL;
428 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
429 cmd = get_pool_memory(PM_MESSAGE);
430 for (d=msgs->dest_chain; d; ) {
432 switch (d->dest_code) {
436 fclose(d->fd); /* close open file descriptor */
441 case MD_MAIL_ON_ERROR:
442 case MD_MAIL_ON_SUCCESS:
443 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
448 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
449 jcr->JobStatus == JS_Terminated)
451 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
452 jcr->JobStatus == JS_ErrorTerminated)
457 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
458 Pmsg0(000, _("open mail pipe failed.\n"));
461 Dmsg0(850, "Opened mail pipe\n");
463 line = get_memory(len);
465 while (fgets(line, len, d->fd)) {
466 fputs(line, bpipe->wfd);
468 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
470 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
474 * Since we are closing all messages, before "recursing"
475 * make sure we are not closing the daemon messages, otherwise
478 if (msgs != daemon_msgs) {
479 /* read what mail prog returned -- should be nothing */
480 while (fgets(line, len, bpipe->rfd)) {
481 Jmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line);
485 stat = close_bpipe(bpipe);
486 if (stat != 0 && msgs != daemon_msgs) {
489 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
490 Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
492 "ERR=%s\n"), cmd, be.bstrerror());
496 /* Remove temp file */
499 unlink(d->mail_filename);
500 free_pool_memory(d->mail_filename);
501 d->mail_filename = NULL;
502 Dmsg0(850, "end mail or mail on error\n");
509 d = d->next; /* point to next buffer */
511 free_pool_memory(cmd);
512 Dmsg0(850, "Done walking message chain.\n");
519 Dmsg0(850, "===End close msg resource\n");
523 * Free memory associated with Messages resource
525 void free_msgs_res(MSGS *msgs)
529 /* Walk down the message chain releasing allocated buffers */
530 for (d=msgs->dest_chain; d; ) {
537 old = d; /* save pointer to release */
538 d = d->next; /* point to next buffer */
539 free(old); /* free the destination item */
541 msgs->dest_chain = NULL;
542 free(msgs); /* free the head */
547 * Terminate the message handler for good.
548 * Release the global destination chain.
550 * Also, clean up a few other items (cons, exepath). Note,
551 * these really should be done elsewhere.
555 Dmsg0(850, "Enter term_msg\n");
556 close_msg(NULL); /* close global chain */
557 free_msgs_res(daemon_msgs); /* free the resources */
580 term_last_jobs_list();
583 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
585 d->fd = fopen(d->where, mode);
589 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
597 * Handle sending the message to the appropriate place
599 void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
602 char dt[MAX_TIME_LENGTH];
609 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
612 * Most messages are prefixed by a date and time. If mtime is
613 * zero, then we use the current time. If mtime is 1 (special
614 * kludge), we do not prefix the date and time. Otherwise,
615 * we assume mtime is a time_t and use it.
624 bstrftime_ny(dt, sizeof(dt), mtime);
630 /* If the program registered a callback, send it there */
631 if (message_callback) {
632 message_callback(type, msg);
636 if (type == M_ABORT || type == M_ERROR_TERM) {
638 fputs(msg, stdout); /* print this here to INSURE that it is printed */
643 /* Now figure out where to send the message */
646 jcr = get_jcr_from_tsd();
649 msgs = jcr->jcr_msgs;
654 for (d=msgs->dest_chain; d; d=d->next) {
655 if (bit_is_set(type, d->msg_types)) {
656 switch (d->dest_code) {
659 if (!jcr || !jcr->db) {
662 if (p_sql_query && p_sql_escape) {
663 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
664 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
666 int len = strlen(msg) + 1;
667 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
668 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
670 bstrutime(dt, sizeof(dt), mtime);
671 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
672 edit_int64(jcr->JobId, ed1), dt, esc_msg);
673 p_sql_query(jcr, cmd);
675 free_pool_memory(cmd);
676 free_pool_memory(esc_msg);
680 Dmsg1(850, "CONSOLE for following msg: %s", msg);
682 con_fd = fopen(con_fname, "a+b");
683 Dmsg0(850, "Console file not open.\n");
686 Pw(con_lock); /* get write lock on console message file */
689 (void)fwrite(dt, dtlen, 1, con_fd);
693 (void)fwrite(msg, len, 1, con_fd);
694 if (msg[len-1] != '\n') {
695 (void)fwrite("\n", 2, 1, con_fd);
698 (void)fwrite("\n", 2, 1, con_fd);
701 console_msg_pending = true;
706 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
708 * We really should do an openlog() here.
710 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
713 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
714 mcmd = get_pool_memory(PM_MESSAGE);
715 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
717 fputs(dt, bpipe->wfd);
718 fputs(msg, bpipe->wfd);
719 /* Messages to the operator go one at a time */
720 stat = close_bpipe(bpipe);
724 Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n"
726 "ERR=%s\n"), mcmd, be.bstrerror());
729 free_pool_memory(mcmd);
732 case MD_MAIL_ON_ERROR:
733 case MD_MAIL_ON_SUCCESS:
734 Dmsg1(850, "MAIL for following msg: %s", msg);
736 POOLMEM *name = get_pool_memory(PM_MESSAGE);
737 make_unique_mail_filename(jcr, name, d);
738 d->fd = fopen(name, "w+b");
742 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), name,
745 free_pool_memory(name);
748 d->mail_filename = name;
751 len = strlen(msg) + dtlen;;
752 if (len > d->max_len) {
753 d->max_len = len; /* keep max line length */
758 Dmsg1(850, "APPEND for following msg: %s", msg);
762 Dmsg1(850, "FILE for following msg: %s", msg);
765 if (!d->fd && !open_dest_file(jcr, d, mode)) {
770 /* On error, we close and reopen to handle log rotation */
774 if (open_dest_file(jcr, d, mode)) {
781 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
782 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
783 bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s",
784 jcr->Job, type, mtime, msg);
788 Dmsg1(850, "STDOUT for following msg: %s", msg);
789 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
796 Dmsg1(850, "STDERR for following msg: %s", msg);
808 /*********************************************************************
810 * This subroutine returns the filename portion of a Windows
811 * path. It is used because Microsoft Visual Studio sets __FILE__
816 get_basename(const char *pathname)
818 #if defined(_MSC_VER)
819 const char *basename;
821 if ((basename = strrchr(pathname, '\\')) == NULL) {
833 /*********************************************************************
835 * This subroutine prints a debug message if the level number
836 * is less than or equal the debug_level. File and line numbers
837 * are included for more detail if desired, but not currently
840 * If the level is negative, the details of file and line number
844 d_msg(const char *file, int line, int level, const char *fmt,...)
857 if (level <= debug_level) {
860 bstrftimes(buf, sizeof(buf), mtime);
869 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
870 my_name, get_basename(file), line, get_jobid_from_tsd());
877 va_start(arg_ptr, fmt);
878 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
882 * Used the "trace on" command in the console to turn on
883 * output to the trace file. "trace off" will close the file.
888 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
889 trace_fd = fopen(fn, "a+b");
892 fputs(buf, trace_fd);
895 /* Some problem, turn off tracing */
898 } else { /* not tracing */
906 * Set trace flag on/off. If argument is negative, there is no change
908 void set_trace(int trace_flag)
910 if (trace_flag < 0) {
912 } else if (trace_flag > 0) {
917 if (!trace && trace_fd) {
918 FILE *ltrace_fd = trace_fd;
920 bmicrosleep(0, 100000); /* yield to prevent seg faults */
930 /*********************************************************************
932 * This subroutine prints a message regardless of the debug level
934 * If the level is negative, the details of file and line number
938 p_msg(const char *file, int line, int level, const char *fmt,...)
946 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
953 va_start(arg_ptr, fmt);
954 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
961 /*********************************************************************
963 * subroutine writes a debug message to the trace file if the level number
964 * is less than or equal the debug_level. File and line numbers
965 * are included for more detail if desired, but not currently
968 * If the level is negative, the details of file and line number
972 t_msg(const char *file, int line, int level, const char *fmt,...)
984 if (level <= debug_level) {
986 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
987 trace_fd = fopen(buf, "a+b");
992 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
999 va_start(arg_ptr, fmt);
1000 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1002 if (trace_fd != NULL) {
1003 fputs(buf, trace_fd);
1011 /* *********************************************************
1013 * print an error message
1017 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1024 * Check if we have a message destination defined.
1025 * We always report M_ABORT and M_ERROR_TERM
1027 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1028 !bit_is_set(type, daemon_msgs->send_msg))) {
1029 return; /* no destination */
1033 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1034 my_name, get_basename(file), line);
1037 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1038 my_name, get_basename(file), line);
1041 if (level == -1) /* skip details */
1042 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1044 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1047 if (level == -1) /* skip details */
1048 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1050 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1053 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1056 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1059 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1063 va_start(arg_ptr, fmt);
1064 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1067 dispatch_message(NULL, type, 0, buf);
1069 if (type == M_ABORT) {
1071 p[0] = 0; /* generate segmentation violation */
1073 if (type == M_ERROR_TERM) {
1078 /* *********************************************************
1080 * Generate a Job message
1084 Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1093 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1095 /* Special case for the console, which has a dir_bsock and JobId==0,
1096 * in that case, we send the message directly back to the
1099 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1100 BSOCK *dir = jcr->dir_bsock;
1101 va_start(arg_ptr, fmt);
1102 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1105 jcr->dir_bsock->send();
1111 jcr = get_jcr_from_tsd();
1114 msgs = jcr->jcr_msgs;
1118 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1122 * Check if we have a message destination defined.
1123 * We always report M_ABORT and M_ERROR_TERM
1125 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1126 !bit_is_set(type, msgs->send_msg)) {
1127 return; /* no destination */
1131 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1134 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1137 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1139 set_jcr_job_status(jcr, JS_FatalError);
1143 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1149 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1152 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1156 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1160 va_start(arg_ptr, fmt);
1161 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1164 dispatch_message(jcr, type, mtime, rbuf);
1166 if (type == M_ABORT){
1168 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1169 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1170 p[0] = 0; /* generate segmentation violation */
1172 if (type == M_ERROR_TERM) {
1178 * If we come here, prefix the message with the file:line-number,
1179 * then pass it on to the normal Jmsg routine.
1181 void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1187 pool_buf = get_pool_memory(PM_EMSG);
1188 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1191 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1192 va_start(arg_ptr, fmt);
1193 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1195 if (len < 0 || len >= (maxlen-5)) {
1196 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1202 Jmsg(jcr, type, mtime, "%s", pool_buf);
1203 free_memory(pool_buf);
1208 * Edit a message into a Pool memory buffer, with file:lineno
1210 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1215 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1218 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1219 va_start(arg_ptr, fmt);
1220 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1222 if (len < 0 || len >= (maxlen-5)) {
1223 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1231 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1236 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1239 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1240 va_start(arg_ptr, fmt);
1241 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1243 if (len < 0 || len >= (maxlen-5)) {
1244 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1254 * Edit a message into a Pool Memory buffer NO file:lineno
1255 * Returns: string length of what was edited.
1257 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1263 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1264 va_start(arg_ptr, fmt);
1265 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1267 if (len < 0 || len >= (maxlen-5)) {
1268 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1276 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1282 maxlen = sizeof_pool_memory(pool_buf) - 1;
1283 va_start(arg_ptr, fmt);
1284 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1286 if (len < 0 || len >= (maxlen-5)) {
1287 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1295 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1301 maxlen = pool_buf.max_size() - 1;
1302 va_start(arg_ptr, fmt);
1303 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1305 if (len < 0 || len >= (maxlen-5)) {
1306 pool_buf.realloc_pm(maxlen + maxlen/2);
1315 static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
1318 * We queue messages rather than print them directly. This
1319 * is generally used in low level routines (msg handler, bnet)
1320 * to prevent recursion (i.e. if you are in the middle of
1321 * sending a message, it is a bit messy to recursively call
1322 * yourself when the bnet packet is not reentrant).
1324 void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1331 pool_buf = get_pool_memory(PM_EMSG);
1334 maxlen = sizeof_pool_memory(pool_buf) - 1;
1335 va_start(arg_ptr, fmt);
1336 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1338 if (len < 0 || len >= (maxlen-5)) {
1339 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1344 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1346 item->mtime = time(NULL);
1347 strcpy(item->msg, pool_buf);
1349 jcr = get_jcr_from_tsd();
1351 /* If no jcr or dequeuing send to daemon to avoid recursion */
1352 if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
1353 /* jcr==NULL => daemon message, safe to send now */
1354 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1357 /* Queue message for later sending */
1359 jcr->msg_queue->append(item);
1362 free_memory(pool_buf);
1368 void dequeue_messages(JCR *jcr)
1372 if (!jcr->msg_queue) {
1375 jcr->dequeuing = true;
1376 foreach_dlist(item, jcr->msg_queue) {
1377 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1379 jcr->msg_queue->destroy();
1380 jcr->dequeuing = false;
1388 * If we come here, prefix the message with the file:line-number,
1389 * then pass it on to the normal Qmsg routine.
1391 void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1397 pool_buf = get_pool_memory(PM_EMSG);
1398 i = Mmsg(pool_buf, "%s:%d ", file, line);
1401 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1402 va_start(arg_ptr, fmt);
1403 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1405 if (len < 0 || len >= (maxlen-5)) {
1406 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1412 Qmsg(jcr, type, mtime, "%s", pool_buf);
1413 free_memory(pool_buf);