X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Fmessage.c;h=2b624f823595163ccfad674c98d10a5f88d2d88f;hb=334b701e895a6ec517b26d05cf1266c25d518025;hp=d86280278cfbd0f9cdefb03eb5bea9f62fe6e23f;hpb=da8584df92d56dd3cbf3c9a7563b22d8335ba219;p=bacula%2Fbacula diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c old mode 100755 new mode 100644 index d86280278c..2b624f8235 --- a/bacula/src/lib/message.c +++ b/bacula/src/lib/message.c @@ -1,84 +1,65 @@ /* - * Bacula message handling routines - * - * Kern Sibbald, April 2000 - * - * Version $Id$ - * - */ + Bacula® - The Network Backup Solution -/* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2008 Free Software Foundation Europe e.V. - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation and included + in the file LICENSE. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * Bacula message handling routines + * + * Kern Sibbald, April 2000 + * + * Version $Id$ + * */ #include "bacula.h" #include "jcr.h" -#if !defined(HAVE_CONSOLE) -#if defined(HAVE_CYGWIN) || defined(HAVE_WIN32) -#include -#endif -#endif +sql_query p_sql_query = NULL; +sql_escape p_sql_escape = NULL; -#define FULL_LOCATION 1 /* set for file:line in Debug messages */ +#define FULL_LOCATION 1 /* set for file:line in Debug messages */ /* * This is where we define "Globals" because all the * daemons include this file. */ -const char *working_directory = NULL; /* working directory path stored here */ -int verbose = 0; /* increase User messages */ -int debug_level = 0; /* debug level */ -time_t daemon_start_time = 0; /* Daemon start time */ +const char *working_directory = NULL; /* working directory path stored here */ +int verbose = 0; /* increase User messages */ +int debug_level = 0; /* debug level */ +bool dbg_timestamp = false; /* print timestamp in debug output */ +time_t daemon_start_time = 0; /* Daemon start time */ const char *version = VERSION " (" BDATE ")"; -char my_name[30]; /* daemon name is stored here */ +char my_name[30]; /* daemon name is stored here */ char *exepath = (char *)NULL; char *exename = (char *)NULL; -int console_msg_pending = 0; -char con_fname[500]; /* Console filename */ -FILE *con_fd = NULL; /* Console file descriptor */ -brwlock_t con_lock; /* Console lock structure */ - -#ifdef HAVE_POSTGRESQL -char catalog_db[] = "PostgreSQL"; -#else -#ifdef HAVE_MYSQL -char catalog_db[] = "MySQL"; -#else -#ifdef HAVE_SQLITE -char catalog_db[] = "SQLite"; -#else -char catalog_db[] = "Internal"; -#endif -#endif -#endif - -const char *host_os = HOST_OS; -const char *distname = DISTNAME; -const char *distver = DISTVER; -static FILE *trace_fd = NULL; -#ifdef HAVE_WIN32 -static bool trace = true; -#else -static bool trace = false; -#endif +int console_msg_pending = false; +char con_fname[500]; /* Console filename */ +FILE *con_fd = NULL; /* Console file descriptor */ +brwlock_t con_lock; /* Console lock structure */ /* Forward referenced functions */ @@ -89,10 +70,27 @@ static bool trace = false; /* Used to allow only one thread close the daemon messages at a time */ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static MSGS *daemon_msgs; /* global messages */ +static MSGS *daemon_msgs; /* global messages */ +static char *catalog_db = NULL; /* database type */ +static void (*message_callback)(int type, char *msg) = NULL; +static FILE *trace_fd = NULL; +#if defined(HAVE_WIN32) +static bool trace = true; +#else +static bool trace = false; +#endif + +/* Constants */ +const char *host_os = HOST_OS; +const char *distname = DISTNAME; +const char *distver = DISTVER; + + +void register_message_callback(void msg_callback(int type, char *msg)) +{ + message_callback = msg_callback; +} -/* Define if e_msg must exit when M_ERROR_TERM is received */ -static int exit_on_error = 1; /* * Set daemon name. Also, find canonical execution @@ -104,7 +102,6 @@ static int exit_on_error = 1; * Resource record. On the second call, generally, * argv is NULL to avoid doing the path code twice. */ -#define BTRACE_EXTRA 20 void my_name_is(int argc, char *argv[], const char *name) { char *l, *p, *q; @@ -115,54 +112,69 @@ void my_name_is(int argc, char *argv[], const char *name) if (argc>0 && argv && argv[0]) { /* strip trailing filename and save exepath */ for (l=p=argv[0]; *p; p++) { - if (*p == '/') { - l = p; /* set pos of last slash */ - } + if (IsPathSeparator(*p)) { + l = p; /* set pos of last slash */ + } } - if (*l == '/') { - l++; + if (IsPathSeparator(*l)) { + l++; } else { - l = argv[0]; -#if defined(HAVE_CYGWIN) || defined(HAVE_WIN32) - /* On Windows allow c: junk */ + l = argv[0]; +#if defined(HAVE_WIN32) + /* On Windows allow c: junk */ if (l[1] == ':') { - l += 2; - } + l += 2; + } #endif } len = strlen(l) + 1; if (exename) { - free(exename); + free(exename); } exename = (char *)malloc(len); strcpy(exename, l); if (exepath) { - free(exepath); + free(exepath); } exepath = (char *)malloc(strlen(argv[0]) + 1 + len); for (p=argv[0],q=exepath; p < l; ) { - *q++ = *p++; + *q++ = *p++; } *q = 0; - if (strchr(exepath, '.') || exepath[0] != '/') { - if (getcwd(cpath, sizeof(cpath))) { - free(exepath); - exepath = (char *)malloc(strlen(cpath) + 1 + len); - strcpy(exepath, cpath); - } + if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) { + if (getcwd(cpath, sizeof(cpath))) { + free(exepath); + exepath = (char *)malloc(strlen(cpath) + 1 + len); + strcpy(exepath, cpath); + } } Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename); } } +const char * +get_db_type(void) +{ + return catalog_db != NULL ? catalog_db : "unknown"; +} + +void +set_db_type(const char *name) +{ + if (catalog_db != NULL) { + free(catalog_db); + } + catalog_db = bstrdup(name); +} + /* * Initialize message handler for a daemon or a Job * We make a copy of the MSGS resource passed, so it belows * to the job or daemon and thus can be modified. * * NULL for jcr -> initialize global messages for daemon - * non-NULL -> initialize jcr using Message resource + * non-NULL -> initialize jcr using Message resource */ void init_msg(JCR *jcr, MSGS *msg) @@ -174,7 +186,7 @@ init_msg(JCR *jcr, MSGS *msg) init_last_jobs_list(); } -#ifndef HAVE_WIN32 +#if !defined(HAVE_WIN32) /* * Make sure we have fd's 0, 1, 2 open * If we don't do this one of our sockets may open @@ -188,7 +200,7 @@ init_msg(JCR *jcr, MSGS *msg) close(fd); } else { for(i=1; fd + i <= 2; i++) { - dup2(fd, fd+i); + dup2(fd, fd+i); } } @@ -200,12 +212,9 @@ init_msg(JCR *jcr, MSGS *msg) daemon_msgs = (MSGS *)malloc(sizeof(MSGS)); memset(daemon_msgs, 0, sizeof(MSGS)); for (i=1; i<=M_MAX; i++) { -#ifndef WIN32 - add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL); -#endif - add_msg_dest(daemon_msgs, MD_SYSLOG, i, NULL, NULL); + add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL); } - Dmsg1(050, "Create daemon global message resource 0x%x\n", daemon_msgs); + Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs); return; } @@ -220,10 +229,10 @@ init_msg(JCR *jcr, MSGS *msg) dnew->fd = NULL; dnew->mail_filename = NULL; if (d->mail_cmd) { - dnew->mail_cmd = bstrdup(d->mail_cmd); + dnew->mail_cmd = bstrdup(d->mail_cmd); } if (d->where) { - dnew->where = bstrdup(d->where); + dnew->where = bstrdup(d->where); } temp_chain = dnew; } @@ -236,14 +245,14 @@ init_msg(JCR *jcr, MSGS *msg) } else { /* If we have default values, release them now */ if (daemon_msgs) { - free_msgs_res(daemon_msgs); + free_msgs_res(daemon_msgs); } daemon_msgs = (MSGS *)malloc(sizeof(MSGS)); memset(daemon_msgs, 0, sizeof(MSGS)); daemon_msgs->dest_chain = temp_chain; memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg)); } - Dmsg2(250, "Copy message resource 0x%x to 0x%x\n", msg, temp_chain); + Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain); } @@ -254,27 +263,27 @@ void init_console_msg(const char *wd) { int fd; - bsnprintf(con_fname, sizeof(con_fname), "%s/%s.conmsg", wd, my_name); + bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name); fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600); if (fd == -1) { berrno be; Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"), - con_fname, be.strerror()); + con_fname, be.bstrerror()); } if (lseek(fd, 0, SEEK_END) > 0) { console_msg_pending = 1; } close(fd); - con_fd = fopen(con_fname, "a+"); + con_fd = fopen(con_fname, "a+b"); if (!con_fd) { berrno be; Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"), - con_fname, be.strerror()); + con_fname, be.bstrerror()); } if (rwl_init(&con_lock) != 0) { berrno be; Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"), - be.strerror()); + be.bstrerror()); } } @@ -296,12 +305,12 @@ void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mai */ for (d=msg->dest_chain; d; d=d->next) { if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) || - (strcmp(where, d->where) == 0))) { - Dmsg4(850, "Add to existing d=%x msgtype=%d destcode=%d where=%s\n", - d, msg_type, dest_code, NPRT(where)); - set_bit(msg_type, d->msg_types); - set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */ - return; + (strcmp(where, d->where) == 0))) { + Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n", + d, msg_type, dest_code, NPRT(where)); + set_bit(msg_type, d->msg_types); + set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */ + return; } } /* Not found, create a new entry */ @@ -309,16 +318,16 @@ void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mai memset(d, 0, sizeof(DEST)); d->next = msg->dest_chain; d->dest_code = dest_code; - set_bit(msg_type, d->msg_types); /* set type bit in structure */ - set_bit(msg_type, msg->send_msg); /* set type bit in our local */ + set_bit(msg_type, d->msg_types); /* set type bit in structure */ + set_bit(msg_type, msg->send_msg); /* set type bit in our local */ if (where) { d->where = bstrdup(where); } if (mail_cmd) { d->mail_cmd = bstrdup(mail_cmd); } - Dmsg5(850, "add new d=%x msgtype=%d destcode=%d where=%s mailcmd=%s\n", - d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd)); + Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n", + d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd)); msg->dest_chain = d; } @@ -332,15 +341,15 @@ void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where) DEST *d; for (d=msg->dest_chain; d; d=d->next) { - Dmsg2(850, "Remove_msg_dest d=%x where=%s\n", d, NPRT(d->where)); + Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where)); if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) && - ((where == NULL && d->where == NULL) || - (strcmp(where, d->where) == 0))) { - Dmsg3(850, "Found for remove d=%x msgtype=%d destcode=%d\n", - d, msg_type, dest_code); - clear_bit(msg_type, d->msg_types); + ((where == NULL && d->where == NULL) || + (strcmp(where, d->where) == 0))) { + Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n", + d, msg_type, dest_code); + clear_bit(msg_type, d->msg_types); Dmsg0(850, "Return rem_msg_dest\n"); - return; + return; } } } @@ -352,11 +361,11 @@ void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where) static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d) { if (jcr) { - Mmsg(name, "%s/%s.mail.%s.%d", working_directory, my_name, - jcr->Job, (int)(long)d); + Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name, + jcr->Job, (int)(long)d); } else { - Mmsg(name, "%s/%s.mail.%s.%d", working_directory, my_name, - my_name, (int)(long)d); + Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name, + my_name, (int)(long)d); } Dmsg1(850, "mailname=%s\n", name); } @@ -377,13 +386,13 @@ static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d) if (!(bpipe = open_bpipe(cmd, 120, "rw"))) { berrno be; - Jmsg(jcr, M_ERROR, 0, "open mail pipe %s failed: ERR=%s\n", - cmd, be.strerror()); + Jmsg(jcr, M_ERROR, 0, _("open mail pipe %s failed: ERR=%s\n"), + cmd, be.bstrerror()); } /* If we had to use sendmail, add subject */ if (!d->mail_cmd) { - fprintf(bpipe->wfd, "Subject: Bacula Message\r\n\r\n"); + fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message")); } return bpipe; @@ -401,11 +410,11 @@ void close_msg(JCR *jcr) POOLMEM *cmd, *line; int len, stat; - Dmsg1(850, "Close_msg jcr=0x%x\n", jcr); + Dmsg1(580, "Close_msg jcr=%p\n", jcr); - if (jcr == NULL) { /* NULL -> global chain */ + if (jcr == NULL) { /* NULL -> global chain */ msgs = daemon_msgs; - P(mutex); /* only one thread walking the chain */ + P(mutex); /* only one thread walking the chain */ } else { msgs = jcr->jcr_msgs; jcr->jcr_msgs = NULL; @@ -413,80 +422,88 @@ void close_msg(JCR *jcr) if (msgs == NULL) { return; } - Dmsg1(850, "===Begin close msg resource at 0x%x\n", msgs); + Dmsg1(850, "===Begin close msg resource at %p\n", msgs); cmd = get_pool_memory(PM_MESSAGE); for (d=msgs->dest_chain; d; ) { if (d->fd) { - switch (d->dest_code) { - case MD_FILE: - case MD_APPEND: - if (d->fd) { - fclose(d->fd); /* close open file descriptor */ - } - break; - case MD_MAIL: - case MD_MAIL_ON_ERROR: - Dmsg0(850, "Got MD_MAIL or MD_MAIL_ON_ERROR\n"); - if (!d->fd) { - break; - } - if (d->dest_code == MD_MAIL_ON_ERROR && jcr && - jcr->JobStatus == JS_Terminated) { - goto rem_temp_file; - } - - if (!(bpipe=open_mail_pipe(jcr, cmd, d))) { - Pmsg0(000, "open mail pipe failed.\n"); - goto rem_temp_file; - } + switch (d->dest_code) { + case MD_FILE: + case MD_APPEND: + if (d->fd) { + fclose(d->fd); /* close open file descriptor */ + d->fd = NULL; + } + break; + case MD_MAIL: + case MD_MAIL_ON_ERROR: + case MD_MAIL_ON_SUCCESS: + Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n"); + if (!d->fd) { + break; + } + if ( + (d->dest_code == MD_MAIL_ON_ERROR && jcr && + jcr->JobStatus == JS_Terminated) + || + (d->dest_code == MD_MAIL_ON_SUCCESS && jcr && + jcr->JobStatus == JS_ErrorTerminated) + ){ + goto rem_temp_file; + } + + if (!(bpipe=open_mail_pipe(jcr, cmd, d))) { + Pmsg0(000, _("open mail pipe failed.\n")); + goto rem_temp_file; + } Dmsg0(850, "Opened mail pipe\n"); - len = d->max_len+10; - line = get_memory(len); - rewind(d->fd); - while (fgets(line, len, d->fd)) { - fputs(line, bpipe->wfd); - } - if (!close_wpipe(bpipe)) { /* close write pipe sending mail */ - berrno be; - Pmsg1(000, "close error: ERR=%s\n", be.strerror()); - } - - /* + len = d->max_len+10; + line = get_memory(len); + rewind(d->fd); + while (fgets(line, len, d->fd)) { + fputs(line, bpipe->wfd); + } + if (!close_wpipe(bpipe)) { /* close write pipe sending mail */ + berrno be; + Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror()); + } + + /* * Since we are closing all messages, before "recursing" - * make sure we are not closing the daemon messages, otherwise - * kaboom. - */ - if (msgs != daemon_msgs) { - /* read what mail prog returned -- should be nothing */ - while (fgets(line, len, bpipe->rfd)) { + * make sure we are not closing the daemon messages, otherwise + * kaboom. + */ + if (msgs != daemon_msgs) { + /* read what mail prog returned -- should be nothing */ + while (fgets(line, len, bpipe->rfd)) { Jmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line); - } - } + } + } - stat = close_bpipe(bpipe); - if (stat != 0 && msgs != daemon_msgs) { - berrno be; - be.set_errno(stat); + stat = close_bpipe(bpipe); + if (stat != 0 && msgs != daemon_msgs) { + berrno be; + be.set_errno(stat); Dmsg1(850, "Calling emsg. CMD=%s\n", cmd); Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n" "CMD=%s\n" - "ERR=%s\n"), cmd, be.strerror()); - } - free_memory(line); + "ERR=%s\n"), cmd, be.bstrerror()); + } + free_memory(line); rem_temp_file: - /* Remove temp file */ - fclose(d->fd); - unlink(d->mail_filename); - free_pool_memory(d->mail_filename); - d->mail_filename = NULL; + /* Remove temp file */ + fclose(d->fd); + d->fd = NULL; + unlink(d->mail_filename); + free_pool_memory(d->mail_filename); + d->mail_filename = NULL; Dmsg0(850, "end mail or mail on error\n"); - break; - default: - break; - } - d->fd = NULL; + break; + default: + break; + } + d->fd = NULL; } - d = d->next; /* point to next buffer */ + d = d->next; /* point to next buffer */ } free_pool_memory(cmd); Dmsg0(850, "Done walking message chain.\n"); @@ -509,17 +526,17 @@ void free_msgs_res(MSGS *msgs) /* Walk down the message chain releasing allocated buffers */ for (d=msgs->dest_chain; d; ) { if (d->where) { - free(d->where); + free(d->where); } if (d->mail_cmd) { - free(d->mail_cmd); + free(d->mail_cmd); } - old = d; /* save pointer to release */ - d = d->next; /* point to next buffer */ - free(old); /* free the destination item */ + old = d; /* save pointer to release */ + d = d->next; /* point to next buffer */ + free(old); /* free the destination item */ } msgs->dest_chain = NULL; - free(msgs); /* free the head */ + free(msgs); /* free the head */ } @@ -533,8 +550,8 @@ void free_msgs_res(MSGS *msgs) void term_msg() { Dmsg0(850, "Enter term_msg\n"); - close_msg(NULL); /* close global chain */ - free_msgs_res(daemon_msgs); /* free the resources */ + close_msg(NULL); /* close global chain */ + free_msgs_res(daemon_msgs); /* free the resources */ daemon_msgs = NULL; if (con_fd) { fflush(con_fd); @@ -553,10 +570,25 @@ void term_msg() fclose(trace_fd); trace_fd = NULL; } + if (catalog_db) { + free(catalog_db); + catalog_db = NULL; + } term_last_jobs_list(); } - +static bool open_dest_file(JCR *jcr, DEST *d, const char *mode) +{ + d->fd = fopen(d->where, mode); + if (!d->fd) { + berrno be; + d->fd = stdout; + Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror()); + d->fd = NULL; + return false; + } + return true; +} /* * Handle sending the message to the appropriate place @@ -569,14 +601,15 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) int len, dtlen; MSGS *msgs; BPIPE *bpipe; + const char *mode; - Dmsg2(850, "Enter dispatch_msg type=%d msg=%s\n", type, msg); + Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg); /* * Most messages are prefixed by a date and time. If mtime is - * zero, then we use the current time. If mtime is 1 (special - * kludge), we do not prefix the date and time. Otherwise, - * we assume mtime is a time_t and use it. + * zero, then we use the current time. If mtime is 1 (special + * kludge), we do not prefix the date and time. Otherwise, + * we assume mtime is a time_t and use it. */ if (mtime == 0) { mtime = time(NULL); @@ -591,24 +624,24 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) dt[dtlen] = 0; } + /* If the program registered a callback, send it there */ + if (message_callback) { + message_callback(type, msg); + return; + } + if (type == M_ABORT || type == M_ERROR_TERM) { -#ifndef HAVE_WIN32 fputs(dt, stdout); - fputs(msg, stdout); /* print this here to INSURE that it is printed */ + fputs(msg, stdout); /* print this here to INSURE that it is printed */ fflush(stdout); -#endif -#if !defined(HAVE_CONSOLE) -#if defined(HAVE_CYGWIN) || defined(HAVE_WIN32) - /* If we don't exit on error, error messages are parsed by UA */ - if (exit_on_error) { - MessageBox(NULL, msg, "Bacula", MB_OK); - } -#endif -#endif } + /* Now figure out where to send the message */ msgs = NULL; + if (!jcr) { + jcr = get_jcr_from_tsd(); + } if (jcr) { msgs = jcr->jcr_msgs; } @@ -617,142 +650,182 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) } for (d=msgs->dest_chain; d; d=d->next) { if (bit_is_set(type, d->msg_types)) { - switch (d->dest_code) { - case MD_CONSOLE: + switch (d->dest_code) { + case MD_CATALOG: + char ed1[50]; + if (!jcr || !jcr->db) { + break; + } + if (p_sql_query && p_sql_escape) { + POOLMEM *cmd = get_pool_memory(PM_MESSAGE); + POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE); + + int len = strlen(msg) + 1; + esc_msg = check_pool_memory_size(esc_msg, len*2+1); + p_sql_escape(jcr, jcr->db, esc_msg, msg, len); + + bstrutime(dt, sizeof(dt), mtime); + Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')", + edit_int64(jcr->JobId, ed1), dt, esc_msg); + p_sql_query(jcr, cmd); + + free_pool_memory(cmd); + free_pool_memory(esc_msg); + } + break; + case MD_CONSOLE: Dmsg1(850, "CONSOLE for following msg: %s", msg); - if (!con_fd) { - con_fd = fopen(con_fname, "a+"); + if (!con_fd) { + con_fd = fopen(con_fname, "a+b"); Dmsg0(850, "Console file not open.\n"); - } - if (con_fd) { - Pw(con_lock); /* get write lock on console message file */ - errno = 0; - if (dtlen) { - fwrite(dt, dtlen, 1, con_fd); - } - len = strlen(msg); - if (len > 0) { - fwrite(msg, len, 1, con_fd); + } + if (con_fd) { + Pw(con_lock); /* get write lock on console message file */ + errno = 0; + if (dtlen) { + (void)fwrite(dt, dtlen, 1, con_fd); + } + len = strlen(msg); + if (len > 0) { + (void)fwrite(msg, len, 1, con_fd); if (msg[len-1] != '\n') { - fwrite("\n", 2, 1, con_fd); - } - } else { - fwrite("\n", 2, 1, con_fd); - } - fflush(con_fd); - console_msg_pending = TRUE; - Vw(con_lock); - } - break; - case MD_SYSLOG: - Dmsg1(850, "SYSLOG for collowing msg: %s\n", msg); - /* - * We really should do an openlog() here. - */ + (void)fwrite("\n", 2, 1, con_fd); + } + } else { + (void)fwrite("\n", 2, 1, con_fd); + } + fflush(con_fd); + console_msg_pending = true; + Vw(con_lock); + } + break; + case MD_SYSLOG: + Dmsg1(850, "SYSLOG for following msg: %s\n", msg); + /* + * We really should do an openlog() here. + */ syslog(LOG_DAEMON|LOG_ERR, "%s", msg); - break; - case MD_OPERATOR: + break; + case MD_OPERATOR: Dmsg1(850, "OPERATOR for following msg: %s\n", msg); - mcmd = get_pool_memory(PM_MESSAGE); - if ((bpipe=open_mail_pipe(jcr, mcmd, d))) { - int stat; - fputs(dt, bpipe->wfd); - fputs(msg, bpipe->wfd); - /* Messages to the operator go one at a time */ - stat = close_bpipe(bpipe); - if (stat != 0) { - berrno be; - be.set_errno(stat); + mcmd = get_pool_memory(PM_MESSAGE); + if ((bpipe=open_mail_pipe(jcr, mcmd, d))) { + int stat; + fputs(dt, bpipe->wfd); + fputs(msg, bpipe->wfd); + /* Messages to the operator go one at a time */ + stat = close_bpipe(bpipe); + if (stat != 0) { + berrno be; + be.set_errno(stat); Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n" "CMD=%s\n" - "ERR=%s\n"), mcmd, be.strerror()); - } - } - free_pool_memory(mcmd); - break; - case MD_MAIL: - case MD_MAIL_ON_ERROR: + "ERR=%s\n"), mcmd, be.bstrerror()); + } + } + free_pool_memory(mcmd); + break; + case MD_MAIL: + case MD_MAIL_ON_ERROR: + case MD_MAIL_ON_SUCCESS: Dmsg1(850, "MAIL for following msg: %s", msg); - if (!d->fd) { - POOLMEM *name = get_pool_memory(PM_MESSAGE); - make_unique_mail_filename(jcr, name, d); - d->fd = fopen(name, "w+"); - if (!d->fd) { - berrno be; - d->fd = stdout; - Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", name, - be.strerror()); - d->fd = NULL; - free_pool_memory(name); - break; - } - d->mail_filename = name; - } - fputs(dt, d->fd); - len = strlen(msg) + dtlen;; - if (len > d->max_len) { - d->max_len = len; /* keep max line length */ - } - fputs(msg, d->fd); - break; - case MD_FILE: - Dmsg1(850, "FILE for following msg: %s", msg); - if (!d->fd) { - d->fd = fopen(d->where, "w+"); - if (!d->fd) { - berrno be; - d->fd = stdout; - Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", d->where, - be.strerror()); - d->fd = NULL; - break; - } - } - fputs(dt, d->fd); - fputs(msg, d->fd); - break; - case MD_APPEND: + if (!d->fd) { + POOLMEM *name = get_pool_memory(PM_MESSAGE); + make_unique_mail_filename(jcr, name, d); + d->fd = fopen(name, "w+b"); + if (!d->fd) { + berrno be; + d->fd = stdout; + Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), name, + be.bstrerror()); + d->fd = NULL; + free_pool_memory(name); + break; + } + d->mail_filename = name; + } + fputs(dt, d->fd); + len = strlen(msg) + dtlen;; + if (len > d->max_len) { + d->max_len = len; /* keep max line length */ + } + fputs(msg, d->fd); + break; + case MD_APPEND: Dmsg1(850, "APPEND for following msg: %s", msg); - if (!d->fd) { - d->fd = fopen(d->where, "a"); - if (!d->fd) { - berrno be; - d->fd = stdout; - Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", d->where, - be.strerror()); - d->fd = NULL; - break; - } - } - fputs(dt, d->fd); - fputs(msg, d->fd); - break; - case MD_DIRECTOR: + mode = "ab"; + goto send_to_file; + case MD_FILE: + Dmsg1(850, "FILE for following msg: %s", msg); + mode = "w+b"; +send_to_file: + if (!d->fd && !open_dest_file(jcr, d, mode)) { + break; + } + fputs(dt, d->fd); + fputs(msg, d->fd); + /* On error, we close and reopen to handle log rotation */ + if (ferror(d->fd)) { + fclose(d->fd); + d->fd = NULL; + if (open_dest_file(jcr, d, mode)) { + fputs(dt, d->fd); + fputs(msg, d->fd); + } + } + break; + case MD_DIRECTOR: Dmsg1(850, "DIRECTOR for following msg: %s", msg); - if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) { + if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) { bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s", - jcr->Job, type, mtime, msg); - } - break; - case MD_STDOUT: + jcr->Job, type, mtime, msg); + } + break; + case MD_STDOUT: Dmsg1(850, "STDOUT for following msg: %s", msg); - if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */ - fputs(dt, stdout); - fputs(msg, stdout); - } - break; - case MD_STDERR: + if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */ + fputs(dt, stdout); + fputs(msg, stdout); + fflush(stdout); + } + break; + case MD_STDERR: Dmsg1(850, "STDERR for following msg: %s", msg); - fputs(dt, stderr); - fputs(msg, stderr); - break; - default: - break; - } + fputs(dt, stderr); + fputs(msg, stderr); + fflush(stdout); + break; + default: + break; + } } } } +/********************************************************************* + * + * This subroutine returns the filename portion of a Windows + * path. It is used because Microsoft Visual Studio sets __FILE__ + * to the full path. + */ + +inline const char * +get_basename(const char *pathname) +{ +#if defined(_MSC_VER) + const char *basename; + + if ((basename = strrchr(pathname, '\\')) == NULL) { + basename = pathname; + } else { + basename++; + } + + return basename; +#else + return pathname; +#endif +} /********************************************************************* * @@ -770,24 +843,30 @@ d_msg(const char *file, int line, int level, const char *fmt,...) char buf[5000]; int len; va_list arg_ptr; - int details = TRUE; + bool details = true; + time_t mtime; if (level < 0) { - details = FALSE; + details = false; level = -level; } if (level <= debug_level) { + if (dbg_timestamp) { + mtime = time(NULL); + bstrftimes(buf, sizeof(buf), mtime); + len = strlen(buf); + buf[len++] = ' '; + buf[len] = 0; + fputs(buf, stdout); + } + #ifdef FULL_LOCATION if (details) { - /* visual studio passes the whole path to the file as well - * which makes for very long lines - */ - const char *f = strrchr(file, '\\'); - if (f) file = f + 1; - len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line); + len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ", + my_name, get_basename(file), line, get_jobid_from_tsd()); } else { - len = 0; + len = 0; } #else len = 0; @@ -799,18 +878,23 @@ d_msg(const char *file, int line, int level, const char *fmt,...) /* * Used the "trace on" command in the console to turn on * output to the trace file. "trace off" will close the file. - */ + */ if (trace) { - if (!trace_fd) { - bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory ? working_directory : "."); - trace_fd = fopen(buf, "a+"); - } - if (trace_fd) { - fputs(buf, trace_fd); - fflush(trace_fd); - } + if (!trace_fd) { + char fn[200]; + bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : ".", my_name); + trace_fd = fopen(fn, "a+b"); + } + if (trace_fd) { + fputs(buf, trace_fd); + fflush(trace_fd); + } else { + /* Some problem, turn off tracing */ + trace = false; + } } else { /* not tracing */ - fputs(buf, stdout); + fputs(buf, stdout); + fflush(stdout); } } } @@ -830,7 +914,7 @@ void set_trace(int trace_flag) if (!trace && trace_fd) { FILE *ltrace_fd = trace_fd; trace_fd = NULL; - bmicrosleep(0, 100000); /* yield to prevent seg faults */ + bmicrosleep(0, 100000); /* yield to prevent seg faults */ fclose(ltrace_fd); } } @@ -856,7 +940,7 @@ p_msg(const char *file, int line, int level, const char *fmt,...) #ifdef FULL_LOCATION if (level >= 0) { - len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line); + len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line); } else { len = 0; } @@ -867,6 +951,7 @@ p_msg(const char *file, int line, int level, const char *fmt,...) bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr); va_end(arg_ptr); fputs(buf, stdout); + fflush(stdout); } @@ -895,15 +980,15 @@ t_msg(const char *file, int line, int level, const char *fmt,...) if (level <= debug_level) { if (!trace_fd) { - bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory); - trace_fd = fopen(buf, "a+"); + bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name); + trace_fd = fopen(buf, "a+b"); } #ifdef FULL_LOCATION if (details) { - len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line); + len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line); } else { - len = 0; + len = 0; } #else len = 0; @@ -912,8 +997,8 @@ t_msg(const char *file, int line, int level, const char *fmt,...) bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr); va_end(arg_ptr); if (trace_fd != NULL) { - fputs(buf, trace_fd); - fflush(trace_fd); + fputs(buf, trace_fd); + fflush(trace_fd); } } } @@ -937,35 +1022,35 @@ e_msg(const char *file, int line, int type, int level, const char *fmt,...) * We always report M_ABORT and M_ERROR_TERM */ if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) && - !bit_is_set(type, daemon_msgs->send_msg))) { - return; /* no destination */ + !bit_is_set(type, daemon_msgs->send_msg))) { + return; /* no destination */ } switch (type) { case M_ABORT: - len = bsnprintf(buf, sizeof(buf), "%s: ABORTING due to ERROR in %s:%d\n", - my_name, file, line); + len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"), + my_name, get_basename(file), line); break; case M_ERROR_TERM: - len = bsnprintf(buf, sizeof(buf), "%s: ERROR TERMINATION at %s:%d\n", - my_name, file, line); + len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"), + my_name, get_basename(file), line); break; case M_FATAL: - if (level == -1) /* skip details */ - len = bsnprintf(buf, sizeof(buf), "%s: Fatal Error because: ", my_name); + if (level == -1) /* skip details */ + len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name); else - len = bsnprintf(buf, sizeof(buf), "%s: Fatal Error at %s:%d because:\n", my_name, file, line); + len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line); break; case M_ERROR: - if (level == -1) /* skip details */ - len = bsnprintf(buf, sizeof(buf), "%s: ERROR: ", my_name); + if (level == -1) /* skip details */ + len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name); else - len = bsnprintf(buf, sizeof(buf), "%s: ERROR in %s:%d ", my_name, file, line); + len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line); break; case M_WARNING: - len = bsnprintf(buf, sizeof(buf), "%s: Warning: ", my_name); + len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name); break; case M_SECURITY: - len = bsnprintf(buf, sizeof(buf), "%s: Security violation: ", my_name); + len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name); break; default: len = bsnprintf(buf, sizeof(buf), "%s: ", my_name); @@ -980,9 +1065,9 @@ e_msg(const char *file, int line, int type, int level, const char *fmt,...) if (type == M_ABORT) { char *p = 0; - p[0] = 0; /* generate segmentation violation */ + p[0] = 0; /* generate segmentation violation */ } - if ((type == M_ERROR_TERM) && exit_on_error) { + if (type == M_ERROR_TERM) { exit(1); } } @@ -999,36 +1084,35 @@ Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...) va_list arg_ptr; int len; MSGS *msgs; - const char *job; + uint32_t JobId = 0; Dmsg1(850, "Enter Jmsg type=%d\n", type); /* Special case for the console, which has a dir_bsock and JobId==0, - * in that case, we send the message directly back to the - * dir_bsock. + * in that case, we send the message directly back to the + * dir_bsock. */ if (jcr && jcr->JobId == 0 && jcr->dir_bsock) { BSOCK *dir = jcr->dir_bsock; va_start(arg_ptr, fmt); dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg), - fmt, arg_ptr); + fmt, arg_ptr); va_end(arg_ptr); - bnet_send(jcr->dir_bsock); + jcr->dir_bsock->send(); return; } msgs = NULL; - job = NULL; + if (!jcr) { + jcr = get_jcr_from_tsd(); + } if (jcr) { msgs = jcr->jcr_msgs; - job = jcr->Job; + JobId = jcr->JobId; } if (!msgs) { - msgs = daemon_msgs; /* if no jcr, we use daemon handler */ - } - if (!job) { - job = ""; /* Set null job name if none */ + msgs = daemon_msgs; /* if no jcr, we use daemon handler */ } /* @@ -1036,36 +1120,37 @@ Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...) * We always report M_ABORT and M_ERROR_TERM */ if (msgs && (type != M_ABORT && type != M_ERROR_TERM) && - !bit_is_set(type, msgs->send_msg)) { - return; /* no destination */ + !bit_is_set(type, msgs->send_msg)) { + return; /* no destination */ } switch (type) { case M_ABORT: - len = bsnprintf(rbuf, sizeof(rbuf), "%s ABORTING due to ERROR\n", my_name); + len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name); break; case M_ERROR_TERM: - len = bsnprintf(rbuf, sizeof(rbuf), "%s ERROR TERMINATION\n", my_name); + len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name); break; case M_FATAL: - len = bsnprintf(rbuf, sizeof(rbuf), "%s: %s Fatal error: ", my_name, job); + len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId); if (jcr) { - set_jcr_job_status(jcr, JS_FatalError); + set_jcr_job_status(jcr, JS_FatalError); } break; case M_ERROR: - len = bsnprintf(rbuf, sizeof(rbuf), "%s: %s Error: ", my_name, job); + len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId); if (jcr) { - jcr->Errors++; + jcr->Errors++; } break; case M_WARNING: - len = bsnprintf(rbuf, sizeof(rbuf), "%s: %s Warning: ", my_name, job); + len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId); break; case M_SECURITY: - len = bsnprintf(rbuf, sizeof(rbuf), "%s: %s Security violation: ", my_name, job); + len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "), + my_name, JobId); break; default: - len = bsnprintf(rbuf, sizeof(rbuf), "%s: ", my_name); + len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId); break; } @@ -1077,9 +1162,11 @@ Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...) if (type == M_ABORT){ char *p = 0; - p[0] = 0; /* generate segmentation violation */ + printf("Bacula forced SEG FAULT to obtain traceback.\n"); + syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n"); + p[0] = 0; /* generate segmentation violation */ } - if ((type == M_ERROR_TERM) && exit_on_error) { + if (type == M_ERROR_TERM) { exit(1); } } @@ -1095,7 +1182,7 @@ void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const c POOLMEM *pool_buf; pool_buf = get_pool_memory(PM_EMSG); - i = Mmsg(pool_buf, "%s:%d ", file, line); + i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line); for (;;) { maxlen = sizeof_pool_memory(pool_buf) - i - 1; @@ -1103,8 +1190,8 @@ void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const c len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr); va_end(arg_ptr); if (len < 0 || len >= (maxlen-5)) { - pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2); - continue; + pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2); + continue; } break; } @@ -1122,7 +1209,7 @@ int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...) va_list arg_ptr; int i, len, maxlen; - i = sprintf(*pool_buf, "%s:%d ", file, line); + i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line); for (;;) { maxlen = sizeof_pool_memory(*pool_buf) - i - 1; @@ -1130,8 +1217,8 @@ int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...) len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr); va_end(arg_ptr); if (len < 0 || len >= (maxlen-5)) { - *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2); - continue; + *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2); + continue; } break; } @@ -1143,7 +1230,7 @@ int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...) va_list arg_ptr; int i, len, maxlen; - i = sprintf(pool_buf, "%s:%d ", file, line); + i = sprintf(pool_buf, "%s:%d ", get_basename(file), line); for (;;) { maxlen = sizeof_pool_memory(pool_buf) - i - 1; @@ -1151,8 +1238,8 @@ int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...) len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr); va_end(arg_ptr); if (len < 0 || len >= (maxlen-5)) { - pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2); - continue; + pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2); + continue; } break; } @@ -1175,8 +1262,8 @@ int Mmsg(POOLMEM **pool_buf, const char *fmt, ...) len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr); va_end(arg_ptr); if (len < 0 || len >= (maxlen-5)) { - *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2); - continue; + *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2); + continue; } break; } @@ -1194,8 +1281,8 @@ int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...) len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr); va_end(arg_ptr); if (len < 0 || len >= (maxlen-5)) { - pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2); - continue; + pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2); + continue; } break; } @@ -1213,8 +1300,8 @@ int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...) len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr); va_end(arg_ptr); if (len < 0 || len >= (maxlen-5)) { - pool_buf.realloc_pm(maxlen + maxlen/2); - continue; + pool_buf.realloc_pm(maxlen + maxlen/2); + continue; } break; } @@ -1246,8 +1333,8 @@ void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...) len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr); va_end(arg_ptr); if (len < 0 || len >= (maxlen-5)) { - pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2); - continue; + pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2); + continue; } break; } @@ -1255,17 +1342,19 @@ void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...) item->type = type; item->mtime = time(NULL); strcpy(item->msg, pool_buf); + if (!jcr) { + jcr = get_jcr_from_tsd(); + } /* If no jcr or dequeuing send to daemon to avoid recursion */ - if (!jcr || jcr->dequeuing) { + if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) { /* jcr==NULL => daemon message, safe to send now */ - Jmsg(NULL, item->type, item->mtime, "%s", item->msg); + Jmsg(jcr, item->type, item->mtime, "%s", item->msg); free(item); } else { /* Queue message for later sending */ P(msg_queue_mutex); jcr->msg_queue->append(item); V(msg_queue_mutex); -// Dmsg1(000, "queue item=%lu\n", (long unsigned)item); } free_memory(pool_buf); } @@ -1277,13 +1366,17 @@ void dequeue_messages(JCR *jcr) { MQUEUE_ITEM *item; P(msg_queue_mutex); + if (!jcr->msg_queue) { + goto bail_out; + } jcr->dequeuing = true; foreach_dlist(item, jcr->msg_queue) { -// Dmsg1(000, "dequeue item=%lu\n", (long unsigned)item); Jmsg(jcr, item->type, item->mtime, "%s", item->msg); } jcr->msg_queue->destroy(); jcr->dequeuing = false; + +bail_out: V(msg_queue_mutex); } @@ -1307,8 +1400,8 @@ void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const c len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr); va_end(arg_ptr); if (len < 0 || len >= (maxlen-5)) { - pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2); - continue; + pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2); + continue; } break; } @@ -1316,10 +1409,3 @@ void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const c Qmsg(jcr, type, mtime, "%s", pool_buf); free_memory(pool_buf); } - -/* - * Define if e_msg must exit when M_ERROR_TERM is received - */ -void set_exit_on_error(int value) { - exit_on_error = value; -}