FILE *con_fd = NULL; /* Console file descriptor */
brwlock_t con_lock; /* Console lock structure */
-
-#if defined(HAVE_POSTGRESQL)
-char catalog_db[] = "PostgreSQL";
-#elif defined(HAVE_MYSQL)
-char catalog_db[] = "MySQL";
-#elif defined(HAVE_SQLITE)
-char catalog_db[] = "SQLite";
-#else
-char catalog_db[] = "Internal";
-#endif
+static char *catalog_db = NULL; /* database type */
const char *host_os = HOST_OS;
const char *distname = DISTNAME;
}
}
+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
init_msg(JCR *jcr, MSGS *msg)
{
DEST *d, *dnew, *temp_chain = NULL;
+ int i;
if (jcr == NULL && msg == NULL) {
init_last_jobs_list();
*
*/
int fd;
- int i;
fd = open("/dev/null", O_RDONLY, 0644);
if (fd > 2) {
close(fd);
if (msg == NULL) {
daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
memset(daemon_msgs, 0, sizeof(MSGS));
-#if !defined(HAVE_WIN32)
for (i=1; i<=M_MAX; i++) {
add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
}
-#endif
Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
return;
}
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.strerror());
+ d->fd = NULL;
+ return false;
+ }
+ return true;
+}
/*
* Handle sending the message to the appropriate place
int len, dtlen;
MSGS *msgs;
BPIPE *bpipe;
+ char *mode;
Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
}
if (type == M_ABORT || type == M_ERROR_TERM) {
-#if !defined(HAVE_WIN32)
fputs(dt, stdout);
fputs(msg, stdout); /* print this here to INSURE that it is printed */
fflush(stdout);
-#endif
}
/* Now figure out where to send the message */
}
if (p_sql_query) {
POOL_MEM cmd(PM_MESSAGE);
- Mmsg(cmd, "INSERT INTO Log (JobId, LogText) VALUES (%s, '%s')",
- edit_int64(jcr->JobId, ed1), msg);
+ bstrftimes(dt, sizeof(dt), mtime);
+ Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
+ edit_int64(jcr->JobId, ed1), dt, msg);
p_sql_query(jcr, cmd.c_str());
}
break;
}
fputs(msg, d->fd);
break;
+ case MD_APPEND:
+ Dmsg1(850, "APPEND for following msg: %s", msg);
+ mode = "ab";
+ goto send_to_file;
case MD_FILE:
Dmsg1(850, "FILE for following msg: %s", msg);
- if (!d->fd) {
- d->fd = fopen(d->where, "w+b");
- 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;
- }
+ mode = "w+b";
+send_to_file:
+ if (!d->fd && !open_dest_file(jcr, d, mode)) {
+ break;
}
fputs(dt, d->fd);
fputs(msg, d->fd);
- break;
- case MD_APPEND:
- Dmsg1(850, "APPEND for following msg: %s", msg);
- if (!d->fd) {
- d->fd = fopen(d->where, "ab");
- 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;
+ /* On error, we close and reopen to handle log rotation */
+ if (ferror(d->fd)) {
+ fclose(d->fd);
+ if (open_dest_file(jcr, d, mode)) {
+ fputs(dt, d->fd);
+ fputs(msg, d->fd);
}
}
- fputs(dt, d->fd);
- fputs(msg, d->fd);
break;
case MD_DIRECTOR:
Dmsg1(850, "DIRECTOR for following msg: %s", msg);
}
}
+/*********************************************************************
+ *
+ * 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
+}
/*********************************************************************
*
if (level <= debug_level) {
#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 ", my_name, get_basename(file), line);
} else {
len = 0;
}
if (trace) {
if (!trace_fd) {
char fn[200];
- bsnprintf(fn, sizeof(fn), "%s/bacula.trace", working_directory ? working_directory : ".");
+ bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
trace_fd = fopen(fn, "a+b");
}
if (trace_fd) {
#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;
}
if (level <= debug_level) {
if (!trace_fd) {
- bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory);
+ 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;
}
switch (type) {
case M_ABORT:
len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
- my_name, file, line);
+ 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);
+ 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);
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);
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);
if (type == M_ABORT){
char *p = 0;
+ 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) {
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;
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;
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;
{
MQUEUE_ITEM *item;
P(msg_queue_mutex);
+ if (!jcr->msg_queue) {
+ goto bail_out;
+ }
jcr->dequeuing = true;
foreach_dlist(item, jcr->msg_queue) {
Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
}
jcr->msg_queue->destroy();
jcr->dequeuing = false;
+
+bail_out:
V(msg_queue_mutex);
}