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 bool prt_kaboom = false; /* Print kaboom output */
52 utime_t daemon_start_time = 0; /* Daemon start time */
53 const char *version = VERSION " (" BDATE ")";
54 char my_name[30]; /* daemon name is stored here */
55 char host_name[50]; /* host machine name */
56 char *exepath = (char *)NULL;
57 char *exename = (char *)NULL;
58 int console_msg_pending = false;
59 char con_fname[500]; /* Console filename */
60 FILE *con_fd = NULL; /* Console file descriptor */
61 brwlock_t con_lock; /* Console lock structure */
63 /* Forward referenced functions */
65 /* Imported functions */
66 void create_jcr_key();
70 /* Allow only one thread to tweak d->fd at a time */
71 static pthread_mutex_t fides_mutex = PTHREAD_MUTEX_INITIALIZER;
72 static MSGS *daemon_msgs; /* global messages */
73 static char *catalog_db = NULL; /* database type */
74 static void (*message_callback)(int type, char *msg) = NULL;
75 static FILE *trace_fd = NULL;
76 #if defined(HAVE_WIN32)
77 static bool trace = true;
79 static bool trace = false;
83 const char *host_os = HOST_OS;
84 const char *distname = DISTNAME;
85 const char *distver = DISTVER;
88 void register_message_callback(void msg_callback(int type, char *msg))
90 message_callback = msg_callback;
95 * Set daemon name. Also, find canonical execution
96 * path. Note, exepath has spare room for tacking on
97 * the exename so that we can reconstruct the full name.
99 * Note, this routine can get called multiple times
100 * The second time is to put the name as found in the
101 * Resource record. On the second call, generally,
102 * argv is NULL to avoid doing the path code twice.
104 void my_name_is(int argc, char *argv[], const char *name)
110 if (gethostname(host_name, sizeof(host_name)) != 0) {
111 bstrncpy(host_name, "Hostname unknown", sizeof(host_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();
189 /* Create a daemon key then set invalid jcr */
190 /* Maybe we should give the daemon a jcr??? */
192 set_jcr_in_tsd(INVALID_JCR);
195 #if !defined(HAVE_WIN32)
197 * Make sure we have fd's 0, 1, 2 open
198 * If we don't do this one of our sockets may open
199 * there and if we then use stdout, it could
200 * send total garbage to our socket.
204 fd = open("/dev/null", O_RDONLY, 0644);
208 for(i=1; fd + i <= 2; i++) {
215 * If msg is NULL, initialize global chain for STDOUT and syslog
218 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
219 memset(daemon_msgs, 0, sizeof(MSGS));
220 for (i=1; i<=M_MAX; i++) {
221 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
223 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
228 * Walk down the message resource chain duplicating it
229 * for the current Job.
231 for (d=msg->dest_chain; d; d=d->next) {
232 dnew = (DEST *)malloc(sizeof(DEST));
233 memcpy(dnew, d, sizeof(DEST));
234 dnew->next = temp_chain;
236 dnew->mail_filename = NULL;
238 dnew->mail_cmd = bstrdup(d->mail_cmd);
241 dnew->where = bstrdup(d->where);
247 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
248 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
249 jcr->jcr_msgs->dest_chain = temp_chain;
250 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
252 /* If we have default values, release them now */
254 free_msgs_res(daemon_msgs);
256 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
257 memset(daemon_msgs, 0, sizeof(MSGS));
258 daemon_msgs->dest_chain = temp_chain;
259 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
261 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
265 /* Initialize so that the console (User Agent) can
266 * receive messages -- stored in a file.
268 void init_console_msg(const char *wd)
272 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
273 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
276 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
277 con_fname, be.bstrerror());
279 if (lseek(fd, 0, SEEK_END) > 0) {
280 console_msg_pending = 1;
283 con_fd = fopen(con_fname, "a+b");
286 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
287 con_fname, be.bstrerror());
289 if (rwl_init(&con_lock) != 0) {
291 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
297 * Called only during parsing of the config file.
299 * Add a message destination. I.e. associate a message type with
300 * a destination (code).
301 * Note, where in the case of dest_code FILE is a filename,
302 * but in the case of MAIL is a space separated list of
303 * email addresses, ...
305 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
309 * First search the existing chain and see if we
310 * can simply add this msg_type to an existing entry.
312 for (d=msg->dest_chain; d; d=d->next) {
313 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
314 (strcmp(where, d->where) == 0))) {
315 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
316 d, msg_type, dest_code, NPRT(where));
317 set_bit(msg_type, d->msg_types);
318 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
322 /* Not found, create a new entry */
323 d = (DEST *)malloc(sizeof(DEST));
324 memset(d, 0, sizeof(DEST));
325 d->next = msg->dest_chain;
326 d->dest_code = dest_code;
327 set_bit(msg_type, d->msg_types); /* set type bit in structure */
328 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
330 d->where = bstrdup(where);
333 d->mail_cmd = bstrdup(mail_cmd);
335 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
336 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
341 * Called only during parsing of the config file.
343 * Remove a message destination
345 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
349 for (d=msg->dest_chain; d; d=d->next) {
350 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
351 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
352 ((where == NULL && d->where == NULL) ||
353 (strcmp(where, d->where) == 0))) {
354 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
355 d, msg_type, dest_code);
356 clear_bit(msg_type, d->msg_types);
357 Dmsg0(850, "Return rem_msg_dest\n");
365 * Create a unique filename for the mail command
367 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
370 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
371 jcr->Job, (int)(intptr_t)d);
373 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
374 my_name, (int)(intptr_t)d);
376 Dmsg1(850, "mailname=%s\n", name);
382 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
387 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
389 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
393 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
394 /* If we had to use sendmail, add subject */
396 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
400 Jmsg(jcr, M_ERROR, 0, _("open mail pipe %s failed: ERR=%s\n"),
401 cmd, be.bstrerror());
407 * Close the messages for this Messages resource, which means to close
408 * any open files, and dispatch any pending email messages.
410 void close_msg(JCR *jcr)
418 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
420 if (jcr == NULL) { /* NULL -> global chain */
423 msgs = jcr->jcr_msgs;
424 jcr->jcr_msgs = NULL;
430 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
431 cmd = get_pool_memory(PM_MESSAGE);
432 for (d=msgs->dest_chain; d; ) {
434 switch (d->dest_code) {
438 fclose(d->fd); /* close open file descriptor */
443 case MD_MAIL_ON_ERROR:
444 case MD_MAIL_ON_SUCCESS:
445 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
450 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
451 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
453 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
454 jcr->JobStatus == JS_ErrorTerminated)
459 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
460 Pmsg0(000, _("open mail pipe failed.\n"));
463 Dmsg0(850, "Opened mail pipe\n");
465 line = get_memory(len);
467 while (fgets(line, len, d->fd)) {
468 fputs(line, bpipe->wfd);
470 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
472 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
476 * Since we are closing all messages, before "recursing"
477 * make sure we are not closing the daemon messages, otherwise
480 if (msgs != daemon_msgs) {
481 /* read what mail prog returned -- should be nothing */
482 while (fgets(line, len, bpipe->rfd)) {
483 Qmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line);
487 stat = close_bpipe(bpipe);
488 if (stat != 0 && msgs != daemon_msgs) {
491 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
492 Qmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
494 "ERR=%s\n"), cmd, be.bstrerror());
498 /* Remove temp file */
501 unlink(d->mail_filename);
502 free_pool_memory(d->mail_filename);
503 d->mail_filename = NULL;
504 Dmsg0(850, "end mail or mail on error\n");
511 d = d->next; /* point to next buffer */
514 free_pool_memory(cmd);
515 Dmsg0(850, "Done walking message chain.\n");
520 Dmsg0(850, "===End close msg resource\n");
524 * Free memory associated with Messages resource
526 void free_msgs_res(MSGS *msgs)
530 /* Walk down the message chain releasing allocated buffers */
531 for (d=msgs->dest_chain; d; ) {
538 old = d; /* save pointer to release */
539 d = d->next; /* point to next buffer */
540 free(old); /* free the destination item */
542 msgs->dest_chain = NULL;
543 free(msgs); /* free the head */
548 * Terminate the message handler for good.
549 * Release the global destination chain.
551 * Also, clean up a few other items (cons, exepath). Note,
552 * these really should be done elsewhere.
556 Dmsg0(850, "Enter term_msg\n");
557 close_msg(NULL); /* close global chain */
558 free_msgs_res(daemon_msgs); /* free the resources */
581 term_last_jobs_list();
584 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
586 d->fd = fopen(d->where, mode);
590 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
598 * Handle sending the message to the appropriate place
600 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
603 char dt[MAX_TIME_LENGTH];
610 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
613 * Most messages are prefixed by a date and time. If mtime is
614 * zero, then we use the current time. If mtime is 1 (special
615 * kludge), we do not prefix the date and time. Otherwise,
616 * we assume mtime is a utime_t and use it.
624 mtime = time(NULL); /* get time for SQL log */
626 bstrftime_ny(dt, sizeof(dt), mtime);
632 /* If the program registered a callback, send it there */
633 if (message_callback) {
634 message_callback(type, msg);
638 if (type == M_ABORT || type == M_ERROR_TERM) {
640 fputs(msg, stdout); /* print this here to INSURE that it is printed */
642 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
646 /* Now figure out where to send the message */
649 jcr = get_jcr_from_tsd();
652 msgs = jcr->jcr_msgs;
657 for (d=msgs->dest_chain; d; d=d->next) {
658 if (bit_is_set(type, d->msg_types)) {
659 switch (d->dest_code) {
662 if (!jcr || !jcr->db) {
665 if (p_sql_query && p_sql_escape) {
666 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
667 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
669 int len = strlen(msg) + 1;
670 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
671 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
673 bstrutime(dt, sizeof(dt), mtime);
674 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
675 edit_int64(jcr->JobId, ed1), dt, esc_msg);
676 p_sql_query(jcr, cmd);
678 free_pool_memory(cmd);
679 free_pool_memory(esc_msg);
683 Dmsg1(850, "CONSOLE for following msg: %s", msg);
685 con_fd = fopen(con_fname, "a+b");
686 Dmsg0(850, "Console file not open.\n");
689 Pw(con_lock); /* get write lock on console message file */
692 (void)fwrite(dt, dtlen, 1, con_fd);
696 (void)fwrite(msg, len, 1, con_fd);
697 if (msg[len-1] != '\n') {
698 (void)fwrite("\n", 2, 1, con_fd);
701 (void)fwrite("\n", 2, 1, con_fd);
704 console_msg_pending = true;
709 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
711 * We really should do an openlog() here.
713 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
716 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
717 mcmd = get_pool_memory(PM_MESSAGE);
718 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
720 fputs(dt, bpipe->wfd);
721 fputs(msg, bpipe->wfd);
722 /* Messages to the operator go one at a time */
723 stat = close_bpipe(bpipe);
727 Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n"
729 "ERR=%s\n"), mcmd, be.bstrerror());
732 free_pool_memory(mcmd);
735 case MD_MAIL_ON_ERROR:
736 case MD_MAIL_ON_SUCCESS:
737 Dmsg1(850, "MAIL for following msg: %s", msg);
740 POOLMEM *name = get_pool_memory(PM_MESSAGE);
741 make_unique_mail_filename(jcr, name, d);
742 d->fd = fopen(name, "w+b");
746 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), name,
749 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 */
764 Dmsg1(850, "APPEND for following msg: %s", msg);
768 Dmsg1(850, "FILE for following msg: %s", msg);
772 if (!d->fd && !open_dest_file(jcr, d, mode)) {
778 /* On error, we close and reopen to handle log rotation */
782 if (open_dest_file(jcr, d, mode)) {
790 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
791 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
792 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
793 jcr->Job, type, mtime, msg);
795 Dmsg1(800, "no jcr for following msg: %s", msg);
799 Dmsg1(850, "STDOUT for following msg: %s", msg);
800 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
807 Dmsg1(850, "STDERR for following msg: %s", msg);
819 /*********************************************************************
821 * This subroutine returns the filename portion of a Windows
822 * path. It is used because Microsoft Visual Studio sets __FILE__
827 get_basename(const char *pathname)
829 #if defined(_MSC_VER)
830 const char *basename;
832 if ((basename = strrchr(pathname, '\\')) == NULL) {
844 /*********************************************************************
846 * This subroutine prints a debug message if the level number
847 * is less than or equal the debug_level. File and line numbers
848 * are included for more detail if desired, but not currently
851 * If the level is negative, the details of file and line number
855 d_msg(const char *file, int line, int level, const char *fmt,...)
868 if (level <= debug_level) {
871 bstrftimes(buf, sizeof(buf), mtime);
880 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
881 my_name, get_basename(file), line, get_jobid_from_tsd());
888 va_start(arg_ptr, fmt);
889 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
893 * Used the "trace on" command in the console to turn on
894 * output to the trace file. "trace off" will close the file.
899 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
900 trace_fd = fopen(fn, "a+b");
903 fputs(buf, trace_fd);
906 /* Some problem, turn off tracing */
909 } else { /* not tracing */
917 * Set trace flag on/off. If argument is negative, there is no change
919 void set_trace(int trace_flag)
921 if (trace_flag < 0) {
923 } else if (trace_flag > 0) {
928 if (!trace && trace_fd) {
929 FILE *ltrace_fd = trace_fd;
931 bmicrosleep(0, 100000); /* yield to prevent seg faults */
941 /*********************************************************************
943 * This subroutine prints a message regardless of the debug level
945 * If the level is negative, the details of file and line number
949 p_msg(const char *file, int line, int level, const char *fmt,...)
957 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
964 va_start(arg_ptr, fmt);
965 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
972 /*********************************************************************
974 * subroutine writes a debug message to the trace file if the level number
975 * is less than or equal the debug_level. File and line numbers
976 * are included for more detail if desired, but not currently
979 * If the level is negative, the details of file and line number
983 t_msg(const char *file, int line, int level, const char *fmt,...)
995 if (level <= debug_level) {
997 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
998 trace_fd = fopen(buf, "a+b");
1001 #ifdef FULL_LOCATION
1003 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1010 va_start(arg_ptr, fmt);
1011 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1013 if (trace_fd != NULL) {
1014 fputs(buf, trace_fd);
1020 /* *********************************************************
1022 * print an error message
1026 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1033 * Check if we have a message destination defined.
1034 * We always report M_ABORT and M_ERROR_TERM
1036 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1037 !bit_is_set(type, daemon_msgs->send_msg))) {
1038 return; /* no destination */
1042 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1043 my_name, get_basename(file), line);
1046 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1047 my_name, get_basename(file), line);
1050 if (level == -1) /* skip details */
1051 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1053 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1056 if (level == -1) /* skip details */
1057 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1059 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1062 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1065 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1068 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1072 va_start(arg_ptr, fmt);
1073 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1076 dispatch_message(NULL, type, 0, buf);
1078 if (type == M_ABORT) {
1080 p[0] = 0; /* generate segmentation violation */
1082 if (type == M_ERROR_TERM) {
1087 /* *********************************************************
1089 * Generate a Job message
1093 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1102 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1104 /* Special case for the console, which has a dir_bsock and JobId==0,
1105 * in that case, we send the message directly back to the
1108 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1109 BSOCK *dir = jcr->dir_bsock;
1110 va_start(arg_ptr, fmt);
1111 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1114 jcr->dir_bsock->send();
1120 jcr = get_jcr_from_tsd();
1123 msgs = jcr->jcr_msgs;
1127 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1131 * Check if we have a message destination defined.
1132 * We always report M_ABORT and M_ERROR_TERM
1134 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1135 !bit_is_set(type, msgs->send_msg)) {
1136 return; /* no destination */
1140 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1143 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1146 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1148 set_jcr_job_status(jcr, JS_FatalError);
1152 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1158 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1164 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1168 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1172 va_start(arg_ptr, fmt);
1173 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1176 dispatch_message(jcr, type, mtime, rbuf);
1178 if (type == M_ABORT){
1180 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1181 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1182 p[0] = 0; /* generate segmentation violation */
1184 if (type == M_ERROR_TERM) {
1190 * If we come here, prefix the message with the file:line-number,
1191 * then pass it on to the normal Jmsg routine.
1193 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1199 pool_buf = get_pool_memory(PM_EMSG);
1200 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1203 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1204 va_start(arg_ptr, fmt);
1205 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1207 if (len < 0 || len >= (maxlen-5)) {
1208 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1214 Jmsg(jcr, type, mtime, "%s", pool_buf);
1215 free_memory(pool_buf);
1220 * Edit a message into a Pool memory buffer, with file:lineno
1222 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1227 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1230 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1231 va_start(arg_ptr, fmt);
1232 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1234 if (len < 0 || len >= (maxlen-5)) {
1235 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1243 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1248 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1251 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1252 va_start(arg_ptr, fmt);
1253 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1255 if (len < 0 || len >= (maxlen-5)) {
1256 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1266 * Edit a message into a Pool Memory buffer NO file:lineno
1267 * Returns: string length of what was edited.
1269 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1275 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1276 va_start(arg_ptr, fmt);
1277 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1279 if (len < 0 || len >= (maxlen-5)) {
1280 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1288 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1294 maxlen = sizeof_pool_memory(pool_buf) - 1;
1295 va_start(arg_ptr, fmt);
1296 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1298 if (len < 0 || len >= (maxlen-5)) {
1299 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1307 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1313 maxlen = pool_buf.max_size() - 1;
1314 va_start(arg_ptr, fmt);
1315 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1317 if (len < 0 || len >= (maxlen-5)) {
1318 pool_buf.realloc_pm(maxlen + maxlen/2);
1328 * We queue messages rather than print them directly. This
1329 * is generally used in low level routines (msg handler, bnet)
1330 * to prevent recursion (i.e. if you are in the middle of
1331 * sending a message, it is a bit messy to recursively call
1332 * yourself when the bnet packet is not reentrant).
1334 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1341 pool_buf = get_pool_memory(PM_EMSG);
1344 maxlen = sizeof_pool_memory(pool_buf) - 1;
1345 va_start(arg_ptr, fmt);
1346 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1348 if (len < 0 || len >= (maxlen-5)) {
1349 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1354 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1356 item->mtime = time(NULL);
1357 strcpy(item->msg, pool_buf);
1359 jcr = get_jcr_from_tsd();
1361 /* If no jcr or no queue or dequeuing send to syslog */
1362 if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1363 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1366 /* Queue message for later sending */
1367 P(jcr->msg_queue_mutex);
1368 jcr->msg_queue->append(item);
1369 V(jcr->msg_queue_mutex);
1371 free_memory(pool_buf);
1377 void dequeue_messages(JCR *jcr)
1380 if (!jcr->msg_queue) {
1383 P(jcr->msg_queue_mutex);
1384 jcr->dequeuing_msgs = true;
1385 foreach_dlist(item, jcr->msg_queue) {
1386 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1388 /* Remove messages just sent */
1389 jcr->msg_queue->destroy();
1390 jcr->dequeuing_msgs = false;
1391 V(jcr->msg_queue_mutex);
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);