/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark of John Walker.
+ Bacula® is a registered trademark of Kern Sibbald.
The licensor of Bacula is the Free Software Foundation Europe
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*
* Kern Sibbald, April 2000
*
- * Version $Id$
- *
*/
-
#include "bacula.h"
#include "jcr.h"
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 */
+bool prt_kaboom = false; /* Print kaboom output */
+utime_t daemon_start_time = 0; /* Daemon start time */
const char *version = VERSION " (" BDATE ")";
char my_name[30]; /* daemon name is stored here */
+char host_name[50]; /* host machine name */
char *exepath = (char *)NULL;
char *exename = (char *)NULL;
int console_msg_pending = false;
/* Forward referenced functions */
/* Imported functions */
-
+void create_jcr_key();
/* Static storage */
-/* Used to allow only one thread close the daemon messages at a time */
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+/* Allow only one thread to tweak d->fd at a time */
+static pthread_mutex_t fides_mutex = PTHREAD_MUTEX_INITIALIZER;
static MSGS *daemon_msgs; /* global messages */
static char *catalog_db = NULL; /* database type */
static void (*message_callback)(int type, char *msg) = NULL;
char cpath[1024];
int len;
+ if (gethostname(host_name, sizeof(host_name)) != 0) {
+ bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
+ }
bstrncpy(my_name, name, sizeof(my_name));
if (argc>0 && argv && argv[0]) {
/* strip trailing filename and save exepath */
if (jcr == NULL && msg == NULL) {
init_last_jobs_list();
+ /* Create a daemon key then set invalid jcr */
+ /* Maybe we should give the daemon a jcr??? */
+ create_jcr_key();
+ set_jcr_in_tsd(INVALID_JCR);
}
#if !defined(HAVE_WIN32)
{
if (jcr) {
Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
- jcr->Job, (int)(long)d);
+ jcr->Job, (int)(intptr_t)d);
} else {
Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
- my_name, (int)(long)d);
+ my_name, (int)(intptr_t)d);
}
Dmsg1(850, "mailname=%s\n", name);
}
}
fflush(stdout);
- if (!(bpipe = open_bpipe(cmd, 120, "rw"))) {
+ if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
+ /* If we had to use sendmail, add subject */
+ if (!d->mail_cmd) {
+ fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
+ }
+ } else {
berrno be;
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: %s\r\n\r\n", _("Bacula Message"));
- }
-
return bpipe;
}
if (jcr == NULL) { /* NULL -> global chain */
msgs = daemon_msgs;
- P(mutex); /* only one thread walking the chain */
} else {
msgs = jcr->jcr_msgs;
jcr->jcr_msgs = NULL;
if (msgs == NULL) {
return;
}
+ P(fides_mutex);
Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
cmd = get_pool_memory(PM_MESSAGE);
for (d=msgs->dest_chain; d; ) {
}
if (
(d->dest_code == MD_MAIL_ON_ERROR && jcr &&
- jcr->JobStatus == JS_Terminated)
+ (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
||
(d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
jcr->JobStatus == JS_ErrorTerminated)
- ){
+ ) {
goto rem_temp_file;
}
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);
+ Qmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line);
}
}
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"
+ Qmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
"CMD=%s\n"
"ERR=%s\n"), cmd, be.bstrerror());
}
}
d = d->next; /* point to next buffer */
}
+ V(fides_mutex);
free_pool_memory(cmd);
Dmsg0(850, "Done walking message chain.\n");
if (jcr) {
free_msgs_res(msgs);
msgs = NULL;
- } else {
- V(mutex);
}
Dmsg0(850, "===End close msg resource\n");
}
/*
* Handle sending the message to the appropriate place
*/
-void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
+void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
{
DEST *d;
char dt[MAX_TIME_LENGTH];
* 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.
+ * we assume mtime is a utime_t and use it.
*/
if (mtime == 0) {
mtime = time(NULL);
if (mtime == 1) {
*dt = 0;
dtlen = 0;
+ mtime = time(NULL); /* get time for SQL log */
} else {
bstrftime_ny(dt, sizeof(dt), mtime);
dtlen = strlen(dt);
fputs(dt, stdout);
fputs(msg, stdout); /* print this here to INSURE that it is printed */
fflush(stdout);
+ syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
}
case MD_MAIL_ON_ERROR:
case MD_MAIL_ON_SUCCESS:
Dmsg1(850, "MAIL for following msg: %s", msg);
+ P(fides_mutex);
if (!d->fd) {
POOLMEM *name = get_pool_memory(PM_MESSAGE);
make_unique_mail_filename(jcr, name, d);
be.bstrerror());
d->fd = NULL;
free_pool_memory(name);
+ V(fides_mutex);
break;
}
d->mail_filename = name;
d->max_len = len; /* keep max line length */
}
fputs(msg, d->fd);
+ V(fides_mutex);
break;
case MD_APPEND:
Dmsg1(850, "APPEND for following msg: %s", msg);
Dmsg1(850, "FILE for following msg: %s", msg);
mode = "w+b";
send_to_file:
+ P(fides_mutex);
if (!d->fd && !open_dest_file(jcr, d, mode)) {
+ V(fides_mutex);
break;
}
fputs(dt, d->fd);
fputs(msg, d->fd);
}
}
+ V(fides_mutex);
break;
case MD_DIRECTOR:
Dmsg1(850, "DIRECTOR for following msg: %s", msg);
if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
- bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s",
+ jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
jcr->Job, type, mtime, msg);
+ } else {
+ Dmsg1(800, "no jcr for following msg: %s", msg);
}
break;
case MD_STDOUT:
int len;
va_list arg_ptr;
bool details = true;
- time_t mtime;
+ utime_t mtime;
if (level < 0) {
details = false;
if (trace) {
if (!trace_fd) {
char fn[200];
- bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
+ bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
trace_fd = fopen(fn, "a+b");
}
if (trace_fd) {
}
}
-
-
/* *********************************************************
*
* print an error message
*
*/
void
-Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
+Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
{
char rbuf[5000];
va_list arg_ptr;
case M_ERROR:
len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
if (jcr) {
- jcr->Errors++;
+ jcr->JobErrors++;
}
break;
case M_WARNING:
len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
+ if (jcr) {
+ jcr->JobWarnings++;
+ }
break;
case M_SECURITY:
len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
* If we come here, prefix the message with the file:line-number,
* then pass it on to the normal Jmsg routine.
*/
-void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
+void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
{
va_list arg_ptr;
int i, len, maxlen;
}
-static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
-
/*
* We queue messages rather than print them directly. This
* is generally used in low level routines (msg handler, bnet)
* sending a message, it is a bit messy to recursively call
* yourself when the bnet packet is not reentrant).
*/
-void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
+void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
{
va_list arg_ptr;
int len, maxlen;
if (!jcr) {
jcr = get_jcr_from_tsd();
}
- /* If no jcr or dequeuing send to daemon to avoid recursion */
- if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
- /* jcr==NULL => daemon message, safe to send now */
- Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
+ /* If no jcr or no queue or dequeuing send to syslog */
+ if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
+ syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
free(item);
} else {
/* Queue message for later sending */
- P(msg_queue_mutex);
+ P(jcr->msg_queue_mutex);
jcr->msg_queue->append(item);
- V(msg_queue_mutex);
+ V(jcr->msg_queue_mutex);
}
free_memory(pool_buf);
}
void dequeue_messages(JCR *jcr)
{
MQUEUE_ITEM *item;
- P(msg_queue_mutex);
if (!jcr->msg_queue) {
- goto bail_out;
+ return;
}
- jcr->dequeuing = true;
+ P(jcr->msg_queue_mutex);
+ jcr->dequeuing_msgs = true;
foreach_dlist(item, jcr->msg_queue) {
Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
}
+ /* Remove messages just sent */
jcr->msg_queue->destroy();
- jcr->dequeuing = false;
-
-bail_out:
- V(msg_queue_mutex);
+ jcr->dequeuing_msgs = false;
+ V(jcr->msg_queue_mutex);
}
* If we come here, prefix the message with the file:line-number,
* then pass it on to the normal Qmsg routine.
*/
-void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
+void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
{
va_list arg_ptr;
int i, len, maxlen;