/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2012 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.
utime_t daemon_start_time = 0; /* Daemon start time */
const char *version = VERSION " (" BDATE ")";
const char *dist_name = DISTNAME " " DISTVER;
-const int beef = BEEF;
+int beef = BEEF;
char my_name[30] = {0}; /* daemon name is stored here */
char host_name[50] = {0}; /* host machine name */
char *exepath = (char *)NULL;
/* Static storage */
+/* Exclude spaces but require .mail at end */
+#define MAIL_REGEX "^[^ ]+\\.mail$"
+
/* 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 */
const char *distname = DISTNAME;
const char *distver = DISTVER;
+/*
+ * Walk back in a string from end looking for a
+ * path separator.
+ * This routine is passed the start of the string and
+ * the end of the string, it returns either the beginning
+ * of the string or where it found a path separator.
+ */
+static const char *bstrrpath(const char *start, const char *end)
+{
+ while ( end > start ) {
+ end--;
+ if (IsPathSeparator(*end)) {
+ break;
+ }
+ }
+ return end;
+}
+
/* Some message class methods */
void MSGS::lock()
{
void MSGS::wait_not_in_use() /* leaves fides_mutex set */
{
lock();
- while (m_in_use) {
+ while (m_in_use || m_closing) {
unlock();
bmicrosleep(0, 200); /* wait */
lock();
return;
}
msgs->wait_not_in_use(); /* leaves fides_mutex set */
+ /* Note get_closing() does not lock because we are already locked */
+ if (msgs->get_closing()) {
+ msgs->unlock();
+ return;
+ }
msgs->set_closing();
msgs->unlock();
if (!d->fd) {
break;
}
- if (
- (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
- (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
- ||
- (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
- jcr->JobStatus == JS_ErrorTerminated)
- ) {
- goto rem_temp_file;
+
+ switch (d->dest_code) {
+ case MD_MAIL_ON_ERROR:
+ if (jcr) {
+ switch (jcr->JobStatus) {
+ case JS_Terminated:
+ case JS_Warnings:
+ goto rem_temp_file;
+ default:
+ break;
+ }
+ }
+ break;
+ case MD_MAIL_ON_SUCCESS:
+ if (jcr) {
+ switch (jcr->JobStatus) {
+ case JS_Terminated:
+ case JS_Warnings:
+ break;
+ default:
+ goto rem_temp_file;
+ }
+ }
+ break;
+ default:
+ break;
}
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);
free_memory(line);
rem_temp_file:
/* Remove temp file */
- fclose(d->fd);
- d->fd = NULL;
- unlink(d->mail_filename);
- free_pool_memory(d->mail_filename);
- d->mail_filename = NULL;
+ if (d->fd) {
+ fclose(d->fd);
+ d->fd = NULL;
+ }
+ if (d->mail_filename) {
+ /* Exclude spaces in mail_filename */
+ safer_unlink(d->mail_filename, MAIL_REGEX);
+ free_pool_memory(d->mail_filename);
+ d->mail_filename = NULL;
+ }
Dmsg0(850, "end mail or mail on error\n");
break;
default:
return true;
}
+/* Split the output for syslog (it converts \n to ' ' and is
+ * limited to 1024 characters per syslog message
+ */
+static void send_to_syslog(int mode, const char *msg)
+{
+ int len;
+ char buf[1024];
+ const char *p2;
+ const char *p = msg;
+
+ while (*p && ((p2 = strchr(p, '\n')) != NULL)) {
+ len = MIN((int)sizeof(buf) - 1, p2 - p + 1); /* Add 1 to keep \n */
+ strncpy(buf, p, len);
+ buf[len] = 0;
+ syslog(mode, "%s", buf);
+ p = p2+1; /* skip \n */
+ }
+ if (*p != 0) { /* no \n at the end ? */
+ syslog(mode, "%s", p);
+ }
+}
+
/*
* Handle sending the message to the appropriate place
*/
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);
+ esc_msg = check_pool_memory_size(esc_msg, len * 2 + 1);
+ if (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);
+ if (!p_sql_query(jcr, cmd)) {
+ delivery_error(_("Msg delivery error: Unable to store data in database.\n"));
+ }
+ } else {
+ delivery_error(_("Msg delivery error: Unable to store data in database.\n"));
+ }
free_pool_memory(cmd);
free_pool_memory(esc_msg);
/*
* We really should do an openlog() here.
*/
- syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
+ send_to_syslog(LOG_DAEMON|LOG_ERR, msg);
break;
case MD_OPERATOR:
Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
be.bstrerror());
free_pool_memory(name);
- V(fides_mutex);
+ msgs->clear_in_use();
break;
}
d->mail_filename = name;
* to the full path. Try to return base + next higher path.
*/
-const char *
-get_basename(const char *pathname)
+const char *get_basename(const char *pathname)
{
- const char *basename, *basename2;
+ const char *basename;
- if ((basename = strrchr(pathname, PathSeparator)) == NULL) {
- basename = pathname;
- if ((basename2 = strrchr(pathname, PathSeparator)) != NULL) {
- basename = basename2 + 1;
- }
+ if ((basename = bstrrpath(pathname, pathname+strlen(pathname))) == pathname) {
+ /* empty */
+ } else if ((basename = bstrrpath(pathname, basename-1)) == pathname) {
+ /* empty */
} else {
basename++;
}
-
return basename;
}
len = strlen(buf);
buf[len++] = ' ';
buf[len] = 0;
- fputs(buf, stdout);
+ pt_out(buf);
}
#ifdef FULL_LOCATION
#ifdef FULL_LOCATION
if (level >= 0) {
- len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
+ len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
+ my_name, get_basename(file), line, get_jobid_from_tsd());
} else {
len = 0;
}
#else
- len = 0;
+ len = 0;
#endif
+
va_start(arg_ptr, fmt);
bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
va_end(arg_ptr);
case M_FATAL:
len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
if (jcr) {
- set_jcr_job_status(jcr, JS_FatalError);
+ jcr->setJobStatus(JS_FatalError);
}
if (jcr && jcr->JobErrors == 0) {
jcr->JobErrors = 1;