2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2009 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
38 sql_query p_sql_query = NULL;
39 sql_escape p_sql_escape = NULL;
41 #define FULL_LOCATION 1 /* set for file:line in Debug messages */
44 * This is where we define "Globals" because all the
45 * daemons include this file.
47 const char *working_directory = NULL; /* working directory path stored here */
48 int verbose = 0; /* increase User messages */
49 int debug_level = 0; /* debug level */
50 bool dbg_timestamp = false; /* print timestamp in debug output */
51 utime_t daemon_start_time = 0; /* Daemon start time */
52 const char *version = VERSION " (" BDATE ")";
53 char my_name[30]; /* daemon name is stored here */
54 char host_name[50]; /* host machine name */
55 char *exepath = (char *)NULL;
56 char *exename = (char *)NULL;
57 int console_msg_pending = false;
58 char con_fname[500]; /* Console filename */
59 FILE *con_fd = NULL; /* Console file descriptor */
60 brwlock_t con_lock; /* Console lock structure */
62 /* Forward referenced functions */
64 /* Imported functions */
65 void create_jcr_key();
69 /* Allow only one thread to tweak d->fd at a time */
70 static pthread_mutex_t fides_mutex = PTHREAD_MUTEX_INITIALIZER;
71 static MSGS *daemon_msgs; /* global messages */
72 static char *catalog_db = NULL; /* database type */
73 static void (*message_callback)(int type, char *msg) = NULL;
74 static FILE *trace_fd = NULL;
75 #if defined(HAVE_WIN32)
76 static bool trace = true;
78 static bool trace = false;
82 const char *host_os = HOST_OS;
83 const char *distname = DISTNAME;
84 const char *distver = DISTVER;
87 void register_message_callback(void msg_callback(int type, char *msg))
89 message_callback = msg_callback;
94 * Set daemon name. Also, find canonical execution
95 * path. Note, exepath has spare room for tacking on
96 * the exename so that we can reconstruct the full name.
98 * Note, this routine can get called multiple times
99 * The second time is to put the name as found in the
100 * Resource record. On the second call, generally,
101 * argv is NULL to avoid doing the path code twice.
103 void my_name_is(int argc, char *argv[], const char *name)
109 if (gethostname(host_name, sizeof(host_name)) != 0) {
110 bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
112 bstrncpy(my_name, name, sizeof(my_name));
113 if (argc>0 && argv && argv[0]) {
114 /* strip trailing filename and save exepath */
115 for (l=p=argv[0]; *p; p++) {
116 if (IsPathSeparator(*p)) {
117 l = p; /* set pos of last slash */
120 if (IsPathSeparator(*l)) {
124 #if defined(HAVE_WIN32)
125 /* On Windows allow c: junk */
135 exename = (char *)malloc(len);
141 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
142 for (p=argv[0],q=exepath; p < l; ) {
146 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
147 if (getcwd(cpath, sizeof(cpath))) {
149 exepath = (char *)malloc(strlen(cpath) + 1 + len);
150 strcpy(exepath, cpath);
153 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
160 return catalog_db != NULL ? catalog_db : "unknown";
164 set_db_type(const char *name)
166 if (catalog_db != NULL) {
169 catalog_db = bstrdup(name);
173 * Initialize message handler for a daemon or a Job
174 * We make a copy of the MSGS resource passed, so it belows
175 * to the job or daemon and thus can be modified.
177 * NULL for jcr -> initialize global messages for daemon
178 * non-NULL -> initialize jcr using Message resource
181 init_msg(JCR *jcr, MSGS *msg)
183 DEST *d, *dnew, *temp_chain = NULL;
186 if (jcr == NULL && msg == NULL) {
187 init_last_jobs_list();
188 /* Create a daemon key then set invalid jcr */
189 /* Maybe we should give the daemon a jcr??? */
191 set_jcr_in_tsd(INVALID_JCR);
194 #if !defined(HAVE_WIN32)
196 * Make sure we have fd's 0, 1, 2 open
197 * If we don't do this one of our sockets may open
198 * there and if we then use stdout, it could
199 * send total garbage to our socket.
203 fd = open("/dev/null", O_RDONLY, 0644);
207 for(i=1; fd + i <= 2; i++) {
214 * If msg is NULL, initialize global chain for STDOUT and syslog
217 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
218 memset(daemon_msgs, 0, sizeof(MSGS));
219 for (i=1; i<=M_MAX; i++) {
220 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
222 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
227 * Walk down the message resource chain duplicating it
228 * for the current Job.
230 for (d=msg->dest_chain; d; d=d->next) {
231 dnew = (DEST *)malloc(sizeof(DEST));
232 memcpy(dnew, d, sizeof(DEST));
233 dnew->next = temp_chain;
235 dnew->mail_filename = NULL;
237 dnew->mail_cmd = bstrdup(d->mail_cmd);
240 dnew->where = bstrdup(d->where);
246 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
247 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
248 jcr->jcr_msgs->dest_chain = temp_chain;
249 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
251 /* If we have default values, release them now */
253 free_msgs_res(daemon_msgs);
255 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
256 memset(daemon_msgs, 0, sizeof(MSGS));
257 daemon_msgs->dest_chain = temp_chain;
258 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
260 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
264 /* Initialize so that the console (User Agent) can
265 * receive messages -- stored in a file.
267 void init_console_msg(const char *wd)
271 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
272 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
275 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
276 con_fname, be.bstrerror());
278 if (lseek(fd, 0, SEEK_END) > 0) {
279 console_msg_pending = 1;
282 con_fd = fopen(con_fname, "a+b");
285 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
286 con_fname, be.bstrerror());
288 if (rwl_init(&con_lock) != 0) {
290 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
296 * Called only during parsing of the config file.
298 * Add a message destination. I.e. associate a message type with
299 * a destination (code).
300 * Note, where in the case of dest_code FILE is a filename,
301 * but in the case of MAIL is a space separated list of
302 * email addresses, ...
304 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
308 * First search the existing chain and see if we
309 * can simply add this msg_type to an existing entry.
311 for (d=msg->dest_chain; d; d=d->next) {
312 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
313 (strcmp(where, d->where) == 0))) {
314 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
315 d, msg_type, dest_code, NPRT(where));
316 set_bit(msg_type, d->msg_types);
317 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
321 /* Not found, create a new entry */
322 d = (DEST *)malloc(sizeof(DEST));
323 memset(d, 0, sizeof(DEST));
324 d->next = msg->dest_chain;
325 d->dest_code = dest_code;
326 set_bit(msg_type, d->msg_types); /* set type bit in structure */
327 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
329 d->where = bstrdup(where);
332 d->mail_cmd = bstrdup(mail_cmd);
334 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
335 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
340 * Called only during parsing of the config file.
342 * Remove a message destination
344 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
348 for (d=msg->dest_chain; d; d=d->next) {
349 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
350 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
351 ((where == NULL && d->where == NULL) ||
352 (strcmp(where, d->where) == 0))) {
353 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
354 d, msg_type, dest_code);
355 clear_bit(msg_type, d->msg_types);
356 Dmsg0(850, "Return rem_msg_dest\n");
364 * Create a unique filename for the mail command
366 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
369 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
370 jcr->Job, (int)(intptr_t)d);
372 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
373 my_name, (int)(intptr_t)d);
375 Dmsg1(850, "mailname=%s\n", name);
381 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
386 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
388 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
392 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
393 /* If we had to use sendmail, add subject */
395 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
399 Jmsg(jcr, M_ERROR, 0, _("open mail pipe %s failed: ERR=%s\n"),
400 cmd, be.bstrerror());
406 * Close the messages for this Messages resource, which means to close
407 * any open files, and dispatch any pending email messages.
409 void close_msg(JCR *jcr)
417 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
419 if (jcr == NULL) { /* NULL -> global chain */
422 msgs = jcr->jcr_msgs;
423 jcr->jcr_msgs = NULL;
429 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
430 cmd = get_pool_memory(PM_MESSAGE);
431 for (d=msgs->dest_chain; d; ) {
433 switch (d->dest_code) {
437 fclose(d->fd); /* close open file descriptor */
442 case MD_MAIL_ON_ERROR:
443 case MD_MAIL_ON_SUCCESS:
444 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
449 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
450 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
452 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
453 jcr->JobStatus == JS_ErrorTerminated)
458 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
459 Pmsg0(000, _("open mail pipe failed.\n"));
462 Dmsg0(850, "Opened mail pipe\n");
464 line = get_memory(len);
466 while (fgets(line, len, d->fd)) {
467 fputs(line, bpipe->wfd);
469 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
471 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
475 * Since we are closing all messages, before "recursing"
476 * make sure we are not closing the daemon messages, otherwise
479 if (msgs != daemon_msgs) {
480 /* read what mail prog returned -- should be nothing */
481 while (fgets(line, len, bpipe->rfd)) {
482 Jmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line);
486 stat = close_bpipe(bpipe);
487 if (stat != 0 && msgs != daemon_msgs) {
490 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
491 Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
493 "ERR=%s\n"), cmd, be.bstrerror());
497 /* Remove temp file */
500 unlink(d->mail_filename);
501 free_pool_memory(d->mail_filename);
502 d->mail_filename = NULL;
503 Dmsg0(850, "end mail or mail on error\n");
510 d = d->next; /* point to next buffer */
513 free_pool_memory(cmd);
514 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, utime_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 utime_t and use it.
623 mtime = time(NULL); /* get time for SQL log */
625 bstrftime_ny(dt, sizeof(dt), mtime);
631 /* If the program registered a callback, send it there */
632 if (message_callback) {
633 message_callback(type, msg);
637 if (type == M_ABORT || type == M_ERROR_TERM) {
639 fputs(msg, stdout); /* print this here to INSURE that it is printed */
644 /* Now figure out where to send the message */
647 jcr = get_jcr_from_tsd();
650 msgs = jcr->jcr_msgs;
655 for (d=msgs->dest_chain; d; d=d->next) {
656 if (bit_is_set(type, d->msg_types)) {
657 switch (d->dest_code) {
660 if (!jcr || !jcr->db) {
663 if (p_sql_query && p_sql_escape) {
664 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
665 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
667 int len = strlen(msg) + 1;
668 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
669 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
671 bstrutime(dt, sizeof(dt), mtime);
672 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
673 edit_int64(jcr->JobId, ed1), dt, esc_msg);
674 p_sql_query(jcr, cmd);
676 free_pool_memory(cmd);
677 free_pool_memory(esc_msg);
681 Dmsg1(850, "CONSOLE for following msg: %s", msg);
683 con_fd = fopen(con_fname, "a+b");
684 Dmsg0(850, "Console file not open.\n");
687 Pw(con_lock); /* get write lock on console message file */
690 (void)fwrite(dt, dtlen, 1, con_fd);
694 (void)fwrite(msg, len, 1, con_fd);
695 if (msg[len-1] != '\n') {
696 (void)fwrite("\n", 2, 1, con_fd);
699 (void)fwrite("\n", 2, 1, con_fd);
702 console_msg_pending = true;
707 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
709 * We really should do an openlog() here.
711 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
714 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
715 mcmd = get_pool_memory(PM_MESSAGE);
716 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
718 fputs(dt, bpipe->wfd);
719 fputs(msg, bpipe->wfd);
720 /* Messages to the operator go one at a time */
721 stat = close_bpipe(bpipe);
725 Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n"
727 "ERR=%s\n"), mcmd, be.bstrerror());
730 free_pool_memory(mcmd);
733 case MD_MAIL_ON_ERROR:
734 case MD_MAIL_ON_SUCCESS:
735 Dmsg1(850, "MAIL for following msg: %s", msg);
738 POOLMEM *name = get_pool_memory(PM_MESSAGE);
739 make_unique_mail_filename(jcr, name, d);
740 d->fd = fopen(name, "w+b");
744 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), name,
747 free_pool_memory(name);
751 d->mail_filename = name;
754 len = strlen(msg) + dtlen;;
755 if (len > d->max_len) {
756 d->max_len = len; /* keep max line length */
762 Dmsg1(850, "APPEND for following msg: %s", msg);
766 Dmsg1(850, "FILE for following msg: %s", msg);
770 if (!d->fd && !open_dest_file(jcr, d, mode)) {
776 /* On error, we close and reopen to handle log rotation */
780 if (open_dest_file(jcr, d, mode)) {
788 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
789 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
790 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
791 jcr->Job, type, mtime, msg);
793 Dmsg1(800, "no jcr for following msg: %s", msg);
797 Dmsg1(850, "STDOUT for following msg: %s", msg);
798 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
805 Dmsg1(850, "STDERR for following msg: %s", msg);
817 /*********************************************************************
819 * This subroutine returns the filename portion of a Windows
820 * path. It is used because Microsoft Visual Studio sets __FILE__
825 get_basename(const char *pathname)
827 #if defined(_MSC_VER)
828 const char *basename;
830 if ((basename = strrchr(pathname, '\\')) == NULL) {
842 /*********************************************************************
844 * This subroutine prints a debug message if the level number
845 * is less than or equal the debug_level. File and line numbers
846 * are included for more detail if desired, but not currently
849 * If the level is negative, the details of file and line number
853 d_msg(const char *file, int line, int level, const char *fmt,...)
866 if (level <= debug_level) {
869 bstrftimes(buf, sizeof(buf), mtime);
878 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
879 my_name, get_basename(file), line, get_jobid_from_tsd());
886 va_start(arg_ptr, fmt);
887 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
891 * Used the "trace on" command in the console to turn on
892 * output to the trace file. "trace off" will close the file.
897 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
898 trace_fd = fopen(fn, "a+b");
901 fputs(buf, trace_fd);
904 /* Some problem, turn off tracing */
907 } else { /* not tracing */
915 * Set trace flag on/off. If argument is negative, there is no change
917 void set_trace(int trace_flag)
919 if (trace_flag < 0) {
921 } else if (trace_flag > 0) {
926 if (!trace && trace_fd) {
927 FILE *ltrace_fd = trace_fd;
929 bmicrosleep(0, 100000); /* yield to prevent seg faults */
939 /*********************************************************************
941 * This subroutine prints a message regardless of the debug level
943 * If the level is negative, the details of file and line number
947 p_msg(const char *file, int line, int level, const char *fmt,...)
955 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
962 va_start(arg_ptr, fmt);
963 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
970 /*********************************************************************
972 * subroutine writes a debug message to the trace file if the level number
973 * is less than or equal the debug_level. File and line numbers
974 * are included for more detail if desired, but not currently
977 * If the level is negative, the details of file and line number
981 t_msg(const char *file, int line, int level, const char *fmt,...)
993 if (level <= debug_level) {
995 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
996 trace_fd = fopen(buf, "a+b");
1001 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1008 va_start(arg_ptr, fmt);
1009 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1011 if (trace_fd != NULL) {
1012 fputs(buf, trace_fd);
1018 /* *********************************************************
1020 * print an error message
1024 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1031 * Check if we have a message destination defined.
1032 * We always report M_ABORT and M_ERROR_TERM
1034 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1035 !bit_is_set(type, daemon_msgs->send_msg))) {
1036 return; /* no destination */
1040 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1041 my_name, get_basename(file), line);
1044 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1045 my_name, get_basename(file), line);
1048 if (level == -1) /* skip details */
1049 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1051 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1054 if (level == -1) /* skip details */
1055 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1057 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1060 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1063 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1066 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1070 va_start(arg_ptr, fmt);
1071 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1074 dispatch_message(NULL, type, 0, buf);
1076 if (type == M_ABORT) {
1078 p[0] = 0; /* generate segmentation violation */
1080 if (type == M_ERROR_TERM) {
1085 /* *********************************************************
1087 * Generate a Job message
1091 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1100 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1102 /* Special case for the console, which has a dir_bsock and JobId==0,
1103 * in that case, we send the message directly back to the
1106 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1107 BSOCK *dir = jcr->dir_bsock;
1108 va_start(arg_ptr, fmt);
1109 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1112 jcr->dir_bsock->send();
1118 jcr = get_jcr_from_tsd();
1121 msgs = jcr->jcr_msgs;
1125 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1129 * Check if we have a message destination defined.
1130 * We always report M_ABORT and M_ERROR_TERM
1132 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1133 !bit_is_set(type, msgs->send_msg)) {
1134 return; /* no destination */
1138 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1141 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1144 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1146 set_jcr_job_status(jcr, JS_FatalError);
1150 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1156 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1162 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1166 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1170 va_start(arg_ptr, fmt);
1171 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1174 dispatch_message(jcr, type, mtime, rbuf);
1176 if (type == M_ABORT){
1178 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1179 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1180 p[0] = 0; /* generate segmentation violation */
1182 if (type == M_ERROR_TERM) {
1188 * If we come here, prefix the message with the file:line-number,
1189 * then pass it on to the normal Jmsg routine.
1191 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1197 pool_buf = get_pool_memory(PM_EMSG);
1198 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1201 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1202 va_start(arg_ptr, fmt);
1203 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1205 if (len < 0 || len >= (maxlen-5)) {
1206 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1212 Jmsg(jcr, type, mtime, "%s", pool_buf);
1213 free_memory(pool_buf);
1218 * Edit a message into a Pool memory buffer, with file:lineno
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);
1241 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1246 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1249 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1250 va_start(arg_ptr, fmt);
1251 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1253 if (len < 0 || len >= (maxlen-5)) {
1254 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1264 * Edit a message into a Pool Memory buffer NO file:lineno
1265 * Returns: string length of what was edited.
1267 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1273 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1274 va_start(arg_ptr, fmt);
1275 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1277 if (len < 0 || len >= (maxlen-5)) {
1278 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1286 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1292 maxlen = sizeof_pool_memory(pool_buf) - 1;
1293 va_start(arg_ptr, fmt);
1294 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1296 if (len < 0 || len >= (maxlen-5)) {
1297 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1305 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1311 maxlen = pool_buf.max_size() - 1;
1312 va_start(arg_ptr, fmt);
1313 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1315 if (len < 0 || len >= (maxlen-5)) {
1316 pool_buf.realloc_pm(maxlen + maxlen/2);
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 no queue send to daemon */
1360 if ((jcr && !jcr->msg_queue) || !jcr) {
1361 /* jcr==NULL => daemon message, safe to send now */
1362 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1365 * If we are dequeuing, we cannot queue another item,
1366 * so as a last resort send it to the syslog
1368 } else if (jcr->dequeuing_msgs) {
1369 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1372 /* Queue message for later sending */
1373 P(jcr->msg_queue_mutex);
1374 jcr->msg_queue->append(item);
1375 V(jcr->msg_queue_mutex);
1377 free_memory(pool_buf);
1383 void dequeue_messages(JCR *jcr)
1386 if (!jcr->msg_queue) {
1389 P(jcr->msg_queue_mutex);
1390 jcr->dequeuing_msgs = true;
1391 foreach_dlist(item, jcr->msg_queue) {
1392 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1394 /* Remove messages just sent */
1395 jcr->msg_queue->destroy();
1396 jcr->dequeuing_msgs = false;
1397 V(jcr->msg_queue_mutex);
1402 * If we come here, prefix the message with the file:line-number,
1403 * then pass it on to the normal Qmsg routine.
1405 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1411 pool_buf = get_pool_memory(PM_EMSG);
1412 i = Mmsg(pool_buf, "%s:%d ", file, line);
1415 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1416 va_start(arg_ptr, fmt);
1417 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1419 if (len < 0 || len >= (maxlen-5)) {
1420 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1426 Qmsg(jcr, type, mtime, "%s", pool_buf);
1427 free_memory(pool_buf);