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 utime_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 */
68 void create_jcr_key();
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();
191 /* Create a daemon key then set invalid jcr */
192 /* Maybe we should give the daemon a jcr??? */
194 set_jcr_in_tsd(INVALID_JCR);
197 #if !defined(HAVE_WIN32)
199 * Make sure we have fd's 0, 1, 2 open
200 * If we don't do this one of our sockets may open
201 * there and if we then use stdout, it could
202 * send total garbage to our socket.
206 fd = open("/dev/null", O_RDONLY, 0644);
210 for(i=1; fd + i <= 2; i++) {
217 * If msg is NULL, initialize global chain for STDOUT and syslog
220 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
221 memset(daemon_msgs, 0, sizeof(MSGS));
222 for (i=1; i<=M_MAX; i++) {
223 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
225 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
230 * Walk down the message resource chain duplicating it
231 * for the current Job.
233 for (d=msg->dest_chain; d; d=d->next) {
234 dnew = (DEST *)malloc(sizeof(DEST));
235 memcpy(dnew, d, sizeof(DEST));
236 dnew->next = temp_chain;
238 dnew->mail_filename = NULL;
240 dnew->mail_cmd = bstrdup(d->mail_cmd);
243 dnew->where = bstrdup(d->where);
249 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
250 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
251 jcr->jcr_msgs->dest_chain = temp_chain;
252 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
254 /* If we have default values, release them now */
256 free_msgs_res(daemon_msgs);
258 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
259 memset(daemon_msgs, 0, sizeof(MSGS));
260 daemon_msgs->dest_chain = temp_chain;
261 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
263 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
267 /* Initialize so that the console (User Agent) can
268 * receive messages -- stored in a file.
270 void init_console_msg(const char *wd)
274 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
275 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
278 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
279 con_fname, be.bstrerror());
281 if (lseek(fd, 0, SEEK_END) > 0) {
282 console_msg_pending = 1;
285 con_fd = fopen(con_fname, "a+b");
288 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
289 con_fname, be.bstrerror());
291 if (rwl_init(&con_lock) != 0) {
293 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
299 * Called only during parsing of the config file.
301 * Add a message destination. I.e. associate a message type with
302 * a destination (code).
303 * Note, where in the case of dest_code FILE is a filename,
304 * but in the case of MAIL is a space separated list of
305 * email addresses, ...
307 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
311 * First search the existing chain and see if we
312 * can simply add this msg_type to an existing entry.
314 for (d=msg->dest_chain; d; d=d->next) {
315 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
316 (strcmp(where, d->where) == 0))) {
317 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
318 d, msg_type, dest_code, NPRT(where));
319 set_bit(msg_type, d->msg_types);
320 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
324 /* Not found, create a new entry */
325 d = (DEST *)malloc(sizeof(DEST));
326 memset(d, 0, sizeof(DEST));
327 d->next = msg->dest_chain;
328 d->dest_code = dest_code;
329 set_bit(msg_type, d->msg_types); /* set type bit in structure */
330 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
332 d->where = bstrdup(where);
335 d->mail_cmd = bstrdup(mail_cmd);
337 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
338 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
343 * Called only during parsing of the config file.
345 * Remove a message destination
347 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
351 for (d=msg->dest_chain; d; d=d->next) {
352 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
353 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
354 ((where == NULL && d->where == NULL) ||
355 (strcmp(where, d->where) == 0))) {
356 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
357 d, msg_type, dest_code);
358 clear_bit(msg_type, d->msg_types);
359 Dmsg0(850, "Return rem_msg_dest\n");
367 * Create a unique filename for the mail command
369 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
372 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
373 jcr->Job, (int)(intptr_t)d);
375 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
376 my_name, (int)(intptr_t)d);
378 Dmsg1(850, "mailname=%s\n", name);
384 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
389 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
391 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
395 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
396 /* If we had to use sendmail, add subject */
398 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
402 Jmsg(jcr, M_ERROR, 0, _("open mail pipe %s failed: ERR=%s\n"),
403 cmd, be.bstrerror());
409 * Close the messages for this Messages resource, which means to close
410 * any open files, and dispatch any pending email messages.
412 void close_msg(JCR *jcr)
420 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
422 if (jcr == NULL) { /* NULL -> global chain */
424 P(mutex); /* only one thread walking the chain */
426 msgs = jcr->jcr_msgs;
427 jcr->jcr_msgs = NULL;
432 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
433 cmd = get_pool_memory(PM_MESSAGE);
434 for (d=msgs->dest_chain; d; ) {
436 switch (d->dest_code) {
440 fclose(d->fd); /* close open file descriptor */
445 case MD_MAIL_ON_ERROR:
446 case MD_MAIL_ON_SUCCESS:
447 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
452 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
453 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
455 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
456 jcr->JobStatus == JS_ErrorTerminated)
461 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
462 Pmsg0(000, _("open mail pipe failed.\n"));
465 Dmsg0(850, "Opened mail pipe\n");
467 line = get_memory(len);
469 while (fgets(line, len, d->fd)) {
470 fputs(line, bpipe->wfd);
472 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
474 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
478 * Since we are closing all messages, before "recursing"
479 * make sure we are not closing the daemon messages, otherwise
482 if (msgs != daemon_msgs) {
483 /* read what mail prog returned -- should be nothing */
484 while (fgets(line, len, bpipe->rfd)) {
485 Jmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line);
489 stat = close_bpipe(bpipe);
490 if (stat != 0 && msgs != daemon_msgs) {
493 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
494 Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
496 "ERR=%s\n"), cmd, be.bstrerror());
500 /* Remove temp file */
503 unlink(d->mail_filename);
504 free_pool_memory(d->mail_filename);
505 d->mail_filename = NULL;
506 Dmsg0(850, "end mail or mail on error\n");
513 d = d->next; /* point to next buffer */
515 free_pool_memory(cmd);
516 Dmsg0(850, "Done walking message chain.\n");
523 Dmsg0(850, "===End close msg resource\n");
527 * Free memory associated with Messages resource
529 void free_msgs_res(MSGS *msgs)
533 /* Walk down the message chain releasing allocated buffers */
534 for (d=msgs->dest_chain; d; ) {
541 old = d; /* save pointer to release */
542 d = d->next; /* point to next buffer */
543 free(old); /* free the destination item */
545 msgs->dest_chain = NULL;
546 free(msgs); /* free the head */
551 * Terminate the message handler for good.
552 * Release the global destination chain.
554 * Also, clean up a few other items (cons, exepath). Note,
555 * these really should be done elsewhere.
559 Dmsg0(850, "Enter term_msg\n");
560 close_msg(NULL); /* close global chain */
561 free_msgs_res(daemon_msgs); /* free the resources */
584 term_last_jobs_list();
587 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
589 d->fd = fopen(d->where, mode);
593 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
601 * Handle sending the message to the appropriate place
603 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
606 char dt[MAX_TIME_LENGTH];
613 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
616 * Most messages are prefixed by a date and time. If mtime is
617 * zero, then we use the current time. If mtime is 1 (special
618 * kludge), we do not prefix the date and time. Otherwise,
619 * we assume mtime is a utime_t and use it.
627 mtime = time(NULL); /* get time for SQL log */
629 bstrftime_ny(dt, sizeof(dt), mtime);
635 /* If the program registered a callback, send it there */
636 if (message_callback) {
637 message_callback(type, msg);
641 if (type == M_ABORT || type == M_ERROR_TERM) {
643 fputs(msg, stdout); /* print this here to INSURE that it is printed */
648 /* Now figure out where to send the message */
651 jcr = get_jcr_from_tsd();
654 msgs = jcr->jcr_msgs;
659 for (d=msgs->dest_chain; d; d=d->next) {
660 if (bit_is_set(type, d->msg_types)) {
661 switch (d->dest_code) {
664 if (!jcr || !jcr->db) {
667 if (p_sql_query && p_sql_escape) {
668 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
669 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
671 int len = strlen(msg) + 1;
672 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
673 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
675 bstrutime(dt, sizeof(dt), mtime);
676 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
677 edit_int64(jcr->JobId, ed1), dt, esc_msg);
678 p_sql_query(jcr, cmd);
680 free_pool_memory(cmd);
681 free_pool_memory(esc_msg);
685 Dmsg1(850, "CONSOLE for following msg: %s", msg);
687 con_fd = fopen(con_fname, "a+b");
688 Dmsg0(850, "Console file not open.\n");
691 Pw(con_lock); /* get write lock on console message file */
694 (void)fwrite(dt, dtlen, 1, con_fd);
698 (void)fwrite(msg, len, 1, con_fd);
699 if (msg[len-1] != '\n') {
700 (void)fwrite("\n", 2, 1, con_fd);
703 (void)fwrite("\n", 2, 1, con_fd);
706 console_msg_pending = true;
711 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
713 * We really should do an openlog() here.
715 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
718 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
719 mcmd = get_pool_memory(PM_MESSAGE);
720 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
722 fputs(dt, bpipe->wfd);
723 fputs(msg, bpipe->wfd);
724 /* Messages to the operator go one at a time */
725 stat = close_bpipe(bpipe);
729 Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n"
731 "ERR=%s\n"), mcmd, be.bstrerror());
734 free_pool_memory(mcmd);
737 case MD_MAIL_ON_ERROR:
738 case MD_MAIL_ON_SUCCESS:
739 Dmsg1(850, "MAIL for following msg: %s", msg);
741 POOLMEM *name = get_pool_memory(PM_MESSAGE);
742 make_unique_mail_filename(jcr, name, d);
743 d->fd = fopen(name, "w+b");
747 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), name,
750 free_pool_memory(name);
753 d->mail_filename = name;
756 len = strlen(msg) + dtlen;;
757 if (len > d->max_len) {
758 d->max_len = len; /* keep max line length */
763 Dmsg1(850, "APPEND for following msg: %s", msg);
767 Dmsg1(850, "FILE for following msg: %s", msg);
770 if (!d->fd && !open_dest_file(jcr, d, mode)) {
775 /* On error, we close and reopen to handle log rotation */
779 if (open_dest_file(jcr, d, mode)) {
786 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
787 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
788 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
789 jcr->Job, type, mtime, msg);
791 Dmsg1(800, "no jcr for following msg: %s", msg);
795 Dmsg1(850, "STDOUT for following msg: %s", msg);
796 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
803 Dmsg1(850, "STDERR for following msg: %s", msg);
815 /*********************************************************************
817 * This subroutine returns the filename portion of a Windows
818 * path. It is used because Microsoft Visual Studio sets __FILE__
823 get_basename(const char *pathname)
825 #if defined(_MSC_VER)
826 const char *basename;
828 if ((basename = strrchr(pathname, '\\')) == NULL) {
840 /*********************************************************************
842 * This subroutine prints a debug message if the level number
843 * is less than or equal the debug_level. File and line numbers
844 * are included for more detail if desired, but not currently
847 * If the level is negative, the details of file and line number
851 d_msg(const char *file, int line, int level, const char *fmt,...)
864 if (level <= debug_level) {
867 bstrftimes(buf, sizeof(buf), mtime);
876 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
877 my_name, get_basename(file), line, get_jobid_from_tsd());
884 va_start(arg_ptr, fmt);
885 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
889 * Used the "trace on" command in the console to turn on
890 * output to the trace file. "trace off" will close the file.
895 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
896 trace_fd = fopen(fn, "a+b");
899 fputs(buf, trace_fd);
902 /* Some problem, turn off tracing */
905 } else { /* not tracing */
913 * Set trace flag on/off. If argument is negative, there is no change
915 void set_trace(int trace_flag)
917 if (trace_flag < 0) {
919 } else if (trace_flag > 0) {
924 if (!trace && trace_fd) {
925 FILE *ltrace_fd = trace_fd;
927 bmicrosleep(0, 100000); /* yield to prevent seg faults */
937 /*********************************************************************
939 * This subroutine prints a message regardless of the debug level
941 * If the level is negative, the details of file and line number
945 p_msg(const char *file, int line, int level, const char *fmt,...)
953 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
960 va_start(arg_ptr, fmt);
961 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
968 /*********************************************************************
970 * subroutine writes a debug message to the trace file if the level number
971 * is less than or equal the debug_level. File and line numbers
972 * are included for more detail if desired, but not currently
975 * If the level is negative, the details of file and line number
979 t_msg(const char *file, int line, int level, const char *fmt,...)
991 if (level <= debug_level) {
993 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
994 trace_fd = fopen(buf, "a+b");
999 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1006 va_start(arg_ptr, fmt);
1007 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1009 if (trace_fd != NULL) {
1010 fputs(buf, trace_fd);
1016 /* *********************************************************
1018 * print an error message
1022 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1029 * Check if we have a message destination defined.
1030 * We always report M_ABORT and M_ERROR_TERM
1032 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1033 !bit_is_set(type, daemon_msgs->send_msg))) {
1034 return; /* no destination */
1038 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1039 my_name, get_basename(file), line);
1042 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1043 my_name, get_basename(file), line);
1046 if (level == -1) /* skip details */
1047 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1049 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1052 if (level == -1) /* skip details */
1053 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1055 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1058 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1061 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1064 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1068 va_start(arg_ptr, fmt);
1069 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1072 dispatch_message(NULL, type, 0, buf);
1074 if (type == M_ABORT) {
1076 p[0] = 0; /* generate segmentation violation */
1078 if (type == M_ERROR_TERM) {
1083 /* *********************************************************
1085 * Generate a Job message
1089 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1098 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1100 /* Special case for the console, which has a dir_bsock and JobId==0,
1101 * in that case, we send the message directly back to the
1104 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1105 BSOCK *dir = jcr->dir_bsock;
1106 va_start(arg_ptr, fmt);
1107 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1110 jcr->dir_bsock->send();
1116 jcr = get_jcr_from_tsd();
1119 msgs = jcr->jcr_msgs;
1123 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1127 * Check if we have a message destination defined.
1128 * We always report M_ABORT and M_ERROR_TERM
1130 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1131 !bit_is_set(type, msgs->send_msg)) {
1132 return; /* no destination */
1136 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1139 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1142 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1144 set_jcr_job_status(jcr, JS_FatalError);
1148 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1154 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1160 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1164 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1168 va_start(arg_ptr, fmt);
1169 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1172 dispatch_message(jcr, type, mtime, rbuf);
1174 if (type == M_ABORT){
1176 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1177 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1178 p[0] = 0; /* generate segmentation violation */
1180 if (type == M_ERROR_TERM) {
1186 * If we come here, prefix the message with the file:line-number,
1187 * then pass it on to the normal Jmsg routine.
1189 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1195 pool_buf = get_pool_memory(PM_EMSG);
1196 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1199 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1200 va_start(arg_ptr, fmt);
1201 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1203 if (len < 0 || len >= (maxlen-5)) {
1204 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1210 Jmsg(jcr, type, mtime, "%s", pool_buf);
1211 free_memory(pool_buf);
1216 * Edit a message into a Pool memory buffer, with file:lineno
1218 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1223 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1226 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1227 va_start(arg_ptr, fmt);
1228 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1230 if (len < 0 || len >= (maxlen-5)) {
1231 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1239 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1244 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1247 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1248 va_start(arg_ptr, fmt);
1249 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1251 if (len < 0 || len >= (maxlen-5)) {
1252 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1262 * Edit a message into a Pool Memory buffer NO file:lineno
1263 * Returns: string length of what was edited.
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(POOLMEM *&pool_buf, const char *fmt, ...)
1290 maxlen = sizeof_pool_memory(pool_buf) - 1;
1291 va_start(arg_ptr, fmt);
1292 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1294 if (len < 0 || len >= (maxlen-5)) {
1295 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1303 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1309 maxlen = pool_buf.max_size() - 1;
1310 va_start(arg_ptr, fmt);
1311 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1313 if (len < 0 || len >= (maxlen-5)) {
1314 pool_buf.realloc_pm(maxlen + maxlen/2);
1323 static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
1326 * We queue messages rather than print them directly. This
1327 * is generally used in low level routines (msg handler, bnet)
1328 * to prevent recursion (i.e. if you are in the middle of
1329 * sending a message, it is a bit messy to recursively call
1330 * yourself when the bnet packet is not reentrant).
1332 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1339 pool_buf = get_pool_memory(PM_EMSG);
1342 maxlen = sizeof_pool_memory(pool_buf) - 1;
1343 va_start(arg_ptr, fmt);
1344 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1346 if (len < 0 || len >= (maxlen-5)) {
1347 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1352 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1354 item->mtime = time(NULL);
1355 strcpy(item->msg, pool_buf);
1357 jcr = get_jcr_from_tsd();
1359 /* If no jcr or dequeuing send to daemon to avoid recursion */
1360 if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
1361 /* jcr==NULL => daemon message, safe to send now */
1362 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1365 /* Queue message for later sending */
1367 jcr->msg_queue->append(item);
1370 free_memory(pool_buf);
1376 void dequeue_messages(JCR *jcr)
1380 if (!jcr->msg_queue) {
1383 jcr->dequeuing = true;
1384 foreach_dlist(item, jcr->msg_queue) {
1385 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1387 jcr->msg_queue->destroy();
1388 jcr->dequeuing = false;
1396 * If we come here, prefix the message with the file:line-number,
1397 * then pass it on to the normal Qmsg routine.
1399 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1405 pool_buf = get_pool_memory(PM_EMSG);
1406 i = Mmsg(pool_buf, "%s:%d ", file, line);
1409 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1410 va_start(arg_ptr, fmt);
1411 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1413 if (len < 0 || len >= (maxlen-5)) {
1414 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1420 Qmsg(jcr, type, mtime, "%s", pool_buf);
1421 free_memory(pool_buf);