2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2012 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 three of the GNU Affero 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 Affero 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 * NOTE: don't use any Jmsg or Qmsg calls within this file,
32 * except in q_msg or j_msg (setup routines),
33 * otherwise you may get into recursive calls if there are
34 * errors, and that can lead to looping or deadlocks.
36 * Kern Sibbald, April 2000
43 sql_query_func p_sql_query = NULL;
44 sql_escape_func p_sql_escape = NULL;
46 #define FULL_LOCATION 1 /* set for file:line in Debug messages */
49 * This is where we define "Globals" because all the
50 * daemons include this file.
52 const char *working_directory = NULL; /* working directory path stored here */
53 int verbose = 0; /* increase User messages */
54 int debug_level = 0; /* debug level */
55 bool dbg_timestamp = false; /* print timestamp in debug output */
56 bool prt_kaboom = false; /* Print kaboom output */
57 utime_t daemon_start_time = 0; /* Daemon start time */
58 const char *version = VERSION " (" BDATE ")";
59 const char *dist_name = DISTNAME " " DISTVER;
61 char my_name[30] = {0}; /* daemon name is stored here */
62 char host_name[50] = {0}; /* host machine name */
63 char *exepath = (char *)NULL;
64 char *exename = (char *)NULL;
65 int console_msg_pending = false;
66 char con_fname[500]; /* Console filename */
67 FILE *con_fd = NULL; /* Console file descriptor */
68 brwlock_t con_lock; /* Console lock structure */
70 /* Forward referenced functions */
72 /* Imported functions */
73 void create_jcr_key();
77 /* Exclude spaces but require .mail at end */
78 #define MAIL_REGEX "^[^ ]+\\.mail$"
80 /* Allow only one thread to tweak d->fd at a time */
81 static pthread_mutex_t fides_mutex = PTHREAD_MUTEX_INITIALIZER;
82 static MSGS *daemon_msgs; /* global messages */
83 static char *catalog_db = NULL; /* database type */
84 static void (*message_callback)(int type, char *msg) = NULL;
85 static FILE *trace_fd = NULL;
86 #if defined(HAVE_WIN32)
87 static bool trace = true;
89 static bool trace = false;
91 static int hangup = 0;
94 const char *host_os = HOST_OS;
95 const char *distname = DISTNAME;
96 const char *distver = DISTVER;
99 * Walk back in a string from end looking for a
101 * This routine is passed the start of the string and
102 * the end of the string, it returns either the beginning
103 * of the string or where it found a path separator.
105 static const char *bstrrpath(const char *start, const char *end)
107 while ( end > start ) {
109 if (IsPathSeparator(*end)) {
116 /* Some message class methods */
128 * Wait for not in use variable to be clear
130 void MSGS::wait_not_in_use() /* leaves fides_mutex set */
133 while (m_in_use || m_closing) {
135 bmicrosleep(0, 200); /* wait */
141 * Handle message delivery errors
143 static void delivery_error(const char *fmt,...)
148 char dt[MAX_TIME_LENGTH];
151 pool_buf = get_pool_memory(PM_EMSG);
153 bstrftime_ny(dt, sizeof(dt), time(NULL));
158 i = Mmsg(pool_buf, "%s Message delivery ERROR: ", dt);
161 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
162 va_start(arg_ptr, fmt);
163 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
165 if (len < 0 || len >= (maxlen-5)) {
166 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
172 fputs(pool_buf, stdout); /* print this here to INSURE that it is printed */
174 syslog(LOG_DAEMON|LOG_ERR, "%s", pool_buf);
175 free_memory(pool_buf);
178 void register_message_callback(void msg_callback(int type, char *msg))
180 message_callback = msg_callback;
185 * Set daemon name. Also, find canonical execution
186 * path. Note, exepath has spare room for tacking on
187 * the exename so that we can reconstruct the full name.
189 * Note, this routine can get called multiple times
190 * The second time is to put the name as found in the
191 * Resource record. On the second call, generally,
192 * argv is NULL to avoid doing the path code twice.
194 void my_name_is(int argc, char *argv[], const char *name)
200 if (gethostname(host_name, sizeof(host_name)) != 0) {
201 bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
203 bstrncpy(my_name, name, sizeof(my_name));
204 if (argc>0 && argv && argv[0]) {
205 /* strip trailing filename and save exepath */
206 for (l=p=argv[0]; *p; p++) {
207 if (IsPathSeparator(*p)) {
208 l = p; /* set pos of last slash */
211 if (IsPathSeparator(*l)) {
215 #if defined(HAVE_WIN32)
216 /* On Windows allow c: drive specification */
226 exename = (char *)malloc(len);
232 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
233 for (p=argv[0],q=exepath; p < l; ) {
237 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
238 if (getcwd(cpath, sizeof(cpath))) {
240 exepath = (char *)malloc(strlen(cpath) + 1 + len);
241 strcpy(exepath, cpath);
244 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
249 set_db_type(const char *name)
251 if (catalog_db != NULL) {
254 catalog_db = bstrdup(name);
258 * Initialize message handler for a daemon or a Job
259 * We make a copy of the MSGS resource passed, so it belows
260 * to the job or daemon and thus can be modified.
262 * NULL for jcr -> initialize global messages for daemon
263 * non-NULL -> initialize jcr using Message resource
266 init_msg(JCR *jcr, MSGS *msg)
268 DEST *d, *dnew, *temp_chain = NULL;
271 if (jcr == NULL && msg == NULL) {
272 init_last_jobs_list();
273 /* Create a daemon key then set invalid jcr */
274 /* Maybe we should give the daemon a jcr??? */
276 set_jcr_in_tsd(INVALID_JCR);
279 #if !defined(HAVE_WIN32)
281 * Make sure we have fd's 0, 1, 2 open
282 * If we don't do this one of our sockets may open
283 * there and if we then use stdout, it could
284 * send total garbage to our socket.
288 fd = open("/dev/null", O_RDONLY, 0644);
292 for(i=1; fd + i <= 2; i++) {
299 * If msg is NULL, initialize global chain for STDOUT and syslog
302 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
303 memset(daemon_msgs, 0, sizeof(MSGS));
304 for (i=1; i<=M_MAX; i++) {
305 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
307 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
312 * Walk down the message resource chain duplicating it
313 * for the current Job.
315 for (d=msg->dest_chain; d; d=d->next) {
316 dnew = (DEST *)malloc(sizeof(DEST));
317 memcpy(dnew, d, sizeof(DEST));
318 dnew->next = temp_chain;
320 dnew->mail_filename = NULL;
322 dnew->mail_cmd = bstrdup(d->mail_cmd);
325 dnew->where = bstrdup(d->where);
331 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
332 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
333 jcr->jcr_msgs->dest_chain = temp_chain;
334 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
336 /* If we have default values, release them now */
338 free_msgs_res(daemon_msgs);
340 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
341 memset(daemon_msgs, 0, sizeof(MSGS));
342 daemon_msgs->dest_chain = temp_chain;
343 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
346 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
350 /* Initialize so that the console (User Agent) can
351 * receive messages -- stored in a file.
353 void init_console_msg(const char *wd)
357 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
358 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
361 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
362 con_fname, be.bstrerror());
364 if (lseek(fd, 0, SEEK_END) > 0) {
365 console_msg_pending = 1;
368 con_fd = fopen(con_fname, "a+b");
371 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
372 con_fname, be.bstrerror());
374 if (rwl_init(&con_lock) != 0) {
376 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
382 * Called only during parsing of the config file.
384 * Add a message destination. I.e. associate a message type with
385 * a destination (code).
386 * Note, where in the case of dest_code FILE is a filename,
387 * but in the case of MAIL is a space separated list of
388 * email addresses, ...
390 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
394 * First search the existing chain and see if we
395 * can simply add this msg_type to an existing entry.
397 for (d=msg->dest_chain; d; d=d->next) {
398 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
399 (strcmp(where, d->where) == 0))) {
400 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
401 d, msg_type, dest_code, NPRT(where));
402 set_bit(msg_type, d->msg_types);
403 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
407 /* Not found, create a new entry */
408 d = (DEST *)malloc(sizeof(DEST));
409 memset(d, 0, sizeof(DEST));
410 d->next = msg->dest_chain;
411 d->dest_code = dest_code;
412 set_bit(msg_type, d->msg_types); /* set type bit in structure */
413 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
415 d->where = bstrdup(where);
418 d->mail_cmd = bstrdup(mail_cmd);
420 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
421 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
426 * Called only during parsing of the config file.
428 * Remove a message destination
430 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
434 for (d=msg->dest_chain; d; d=d->next) {
435 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
436 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
437 ((where == NULL && d->where == NULL) ||
438 (strcmp(where, d->where) == 0))) {
439 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
440 d, msg_type, dest_code);
441 clear_bit(msg_type, d->msg_types);
442 Dmsg0(850, "Return rem_msg_dest\n");
450 * Create a unique filename for the mail command
452 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
455 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
456 jcr->Job, (int)(intptr_t)d);
458 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
459 my_name, (int)(intptr_t)d);
461 Dmsg1(850, "mailname=%s\n", name);
467 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
472 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
474 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
478 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
479 /* If we had to use sendmail, add subject */
481 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
485 delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
486 cmd, be.bstrerror());
492 * Close the messages for this Messages resource, which means to close
493 * any open files, and dispatch any pending email messages.
495 void close_msg(JCR *jcr)
503 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
505 if (jcr == NULL) { /* NULL -> global chain */
508 msgs = jcr->jcr_msgs;
509 jcr->jcr_msgs = NULL;
515 /* Wait for item to be not in use, then mark closing */
516 if (msgs->is_closing()) {
519 msgs->wait_not_in_use(); /* leaves fides_mutex set */
520 /* Note get_closing() does not lock because we are already locked */
521 if (msgs->get_closing()) {
528 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
529 cmd = get_pool_memory(PM_MESSAGE);
530 for (d=msgs->dest_chain; d; ) {
532 switch (d->dest_code) {
536 fclose(d->fd); /* close open file descriptor */
541 case MD_MAIL_ON_ERROR:
542 case MD_MAIL_ON_SUCCESS:
543 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
548 switch (d->dest_code) {
549 case MD_MAIL_ON_ERROR:
551 switch (jcr->JobStatus) {
560 case MD_MAIL_ON_SUCCESS:
562 switch (jcr->JobStatus) {
575 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
576 Pmsg0(000, _("open mail pipe failed.\n"));
580 Dmsg0(850, "Opened mail pipe\n");
582 line = get_memory(len);
584 while (fgets(line, len, d->fd)) {
585 fputs(line, bpipe->wfd);
587 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
589 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
593 * Since we are closing all messages, before "recursing"
594 * make sure we are not closing the daemon messages, otherwise
597 if (msgs != daemon_msgs) {
598 /* read what mail prog returned -- should be nothing */
599 while (fgets(line, len, bpipe->rfd)) {
600 delivery_error(_("Mail prog: %s"), line);
604 stat = close_bpipe(bpipe);
605 if (stat != 0 && msgs != daemon_msgs) {
608 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
609 delivery_error(_("Mail program terminated in error.\n"
611 "ERR=%s\n"), cmd, be.bstrerror());
615 /* Remove temp file */
620 if (d->mail_filename) {
621 /* Exclude spaces in mail_filename */
622 safer_unlink(d->mail_filename, MAIL_REGEX);
623 free_pool_memory(d->mail_filename);
624 d->mail_filename = NULL;
626 Dmsg0(850, "end mail or mail on error\n");
633 d = d->next; /* point to next buffer */
635 free_pool_memory(cmd);
636 Dmsg0(850, "Done walking message chain.\n");
641 msgs->clear_closing();
643 Dmsg0(850, "===End close msg resource\n");
647 * Free memory associated with Messages resource
649 void free_msgs_res(MSGS *msgs)
653 /* Walk down the message chain releasing allocated buffers */
654 for (d=msgs->dest_chain; d; ) {
661 old = d; /* save pointer to release */
662 d = d->next; /* point to next buffer */
663 free(old); /* free the destination item */
665 msgs->dest_chain = NULL;
666 free(msgs); /* free the head */
671 * Terminate the message handler for good.
672 * Release the global destination chain.
674 * Also, clean up a few other items (cons, exepath). Note,
675 * these really should be done elsewhere.
679 Dmsg0(850, "Enter term_msg\n");
680 close_msg(NULL); /* close global chain */
681 free_msgs_res(daemon_msgs); /* free the resources */
704 term_last_jobs_list();
707 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
709 d->fd = fopen(d->where, mode);
712 delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
718 /* Split the output for syslog (it converts \n to ' ' and is
719 * limited to 1024 characters per syslog message
721 static void send_to_syslog(int mode, const char *msg)
728 while (*p && ((p2 = strchr(p, '\n')) != NULL)) {
729 len = MIN((int)sizeof(buf) - 1, p2 - p + 1); /* Add 1 to keep \n */
730 strncpy(buf, p, len);
732 syslog(mode, "%s", buf);
733 p = p2+1; /* skip \n */
735 if (*p != 0) { /* no \n at the end ? */
736 syslog(mode, "%s", p);
741 * Handle sending the message to the appropriate place
743 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
746 char dt[MAX_TIME_LENGTH];
753 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
756 * Most messages are prefixed by a date and time. If mtime is
757 * zero, then we use the current time. If mtime is 1 (special
758 * kludge), we do not prefix the date and time. Otherwise,
759 * we assume mtime is a utime_t and use it.
767 mtime = time(NULL); /* get time for SQL log */
769 bstrftime_ny(dt, sizeof(dt), mtime);
775 /* If the program registered a callback, send it there */
776 if (message_callback) {
777 message_callback(type, msg);
781 /* For serious errors make sure message is printed or logged */
782 if (type == M_ABORT || type == M_ERROR_TERM) {
786 if (type == M_ABORT) {
787 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
792 /* Now figure out where to send the message */
795 jcr = get_jcr_from_tsd();
798 msgs = jcr->jcr_msgs;
804 * If closing this message resource, print and send to syslog,
807 if (msgs->is_closing()) {
811 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
815 for (d=msgs->dest_chain; d; d=d->next) {
816 if (bit_is_set(type, d->msg_types)) {
817 switch (d->dest_code) {
820 if (!jcr || !jcr->db) {
823 if (p_sql_query && p_sql_escape) {
824 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
825 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
827 int len = strlen(msg) + 1;
828 esc_msg = check_pool_memory_size(esc_msg, len * 2 + 1);
829 if (p_sql_escape(jcr, jcr->db, esc_msg, msg, len)) {
830 bstrutime(dt, sizeof(dt), mtime);
831 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
832 edit_int64(jcr->JobId, ed1), dt, esc_msg);
833 if (!p_sql_query(jcr, cmd)) {
834 delivery_error(_("Msg delivery error: Unable to store data in database.\n"));
837 delivery_error(_("Msg delivery error: Unable to store data in database.\n"));
840 free_pool_memory(cmd);
841 free_pool_memory(esc_msg);
845 Dmsg1(850, "CONSOLE for following msg: %s", msg);
847 con_fd = fopen(con_fname, "a+b");
848 Dmsg0(850, "Console file not open.\n");
851 Pw(con_lock); /* get write lock on console message file */
854 (void)fwrite(dt, dtlen, 1, con_fd);
858 (void)fwrite(msg, len, 1, con_fd);
859 if (msg[len-1] != '\n') {
860 (void)fwrite("\n", 2, 1, con_fd);
863 (void)fwrite("\n", 2, 1, con_fd);
866 console_msg_pending = true;
871 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
873 * We really should do an openlog() here.
875 send_to_syslog(LOG_DAEMON|LOG_ERR, msg);
878 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
879 mcmd = get_pool_memory(PM_MESSAGE);
880 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
882 fputs(dt, bpipe->wfd);
883 fputs(msg, bpipe->wfd);
884 /* Messages to the operator go one at a time */
885 stat = close_bpipe(bpipe);
889 delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
891 "ERR=%s\n"), mcmd, be.bstrerror());
894 free_pool_memory(mcmd);
897 case MD_MAIL_ON_ERROR:
898 case MD_MAIL_ON_SUCCESS:
899 Dmsg1(850, "MAIL for following msg: %s", msg);
900 if (msgs->is_closing()) {
905 POOLMEM *name = get_pool_memory(PM_MESSAGE);
906 make_unique_mail_filename(jcr, name, d);
907 d->fd = fopen(name, "w+b");
910 delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
912 free_pool_memory(name);
913 msgs->clear_in_use();
916 d->mail_filename = name;
919 len = strlen(msg) + dtlen;;
920 if (len > d->max_len) {
921 d->max_len = len; /* keep max line length */
924 msgs->clear_in_use();
927 Dmsg1(850, "APPEND for following msg: %s", msg);
931 Dmsg1(850, "FILE for following msg: %s", msg);
934 if (msgs->is_closing()) {
938 if (!d->fd && !open_dest_file(jcr, d, mode)) {
939 msgs->clear_in_use();
944 /* On error, we close and reopen to handle log rotation */
948 if (open_dest_file(jcr, d, mode)) {
953 msgs->clear_in_use();
956 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
957 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
958 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
959 jcr->Job, type, mtime, msg);
961 Dmsg1(800, "no jcr for following msg: %s", msg);
965 Dmsg1(850, "STDOUT for following msg: %s", msg);
966 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
973 Dmsg1(850, "STDERR for following msg: %s", msg);
985 /*********************************************************************
987 * This subroutine returns the filename portion of a path.
988 * It is used because some compilers set __FILE__
989 * to the full path. Try to return base + next higher path.
992 const char *get_basename(const char *pathname)
994 const char *basename;
996 if ((basename = bstrrpath(pathname, pathname+strlen(pathname))) == pathname) {
998 } else if ((basename = bstrrpath(pathname, basename-1)) == pathname) {
1007 * print or write output to trace file
1009 static void pt_out(char *buf)
1012 * Used the "trace on" command in the console to turn on
1013 * output to the trace file. "trace off" will close the file.
1018 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
1019 trace_fd = fopen(fn, "a+b");
1022 fputs(buf, trace_fd);
1026 /* Some problem, turn off tracing */
1035 /*********************************************************************
1037 * This subroutine prints a debug message if the level number
1038 * is less than or equal the debug_level. File and line numbers
1039 * are included for more detail if desired, but not currently
1042 * If the level is negative, the details of file and line number
1046 d_msg(const char *file, int line, int level, const char *fmt,...)
1051 bool details = true;
1059 if (level <= debug_level) {
1060 if (dbg_timestamp) {
1062 bstrftimes(buf, sizeof(buf), mtime);
1069 #ifdef FULL_LOCATION
1071 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
1072 my_name, get_basename(file), line, get_jobid_from_tsd());
1079 va_start(arg_ptr, fmt);
1080 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1088 * Set trace flag on/off. If argument is negative, there is no change
1090 void set_trace(int trace_flag)
1092 if (trace_flag < 0) {
1094 } else if (trace_flag > 0) {
1099 if (!trace && trace_fd) {
1100 FILE *ltrace_fd = trace_fd;
1102 bmicrosleep(0, 100000); /* yield to prevent seg faults */
1107 void set_hangup(int hangup_value)
1109 if (hangup_value < 0) {
1112 hangup = hangup_value;
1116 int get_hangup(void)
1121 bool get_trace(void)
1126 /*********************************************************************
1128 * This subroutine prints a message regardless of the debug level
1130 * If the level is negative, the details of file and line number
1134 p_msg(const char *file, int line, int level, const char *fmt,...)
1140 #ifdef FULL_LOCATION
1142 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1149 va_start(arg_ptr, fmt);
1150 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1157 /*********************************************************************
1159 * subroutine writes a debug message to the trace file if the level number
1160 * is less than or equal the debug_level. File and line numbers
1161 * are included for more detail if desired, but not currently
1164 * If the level is negative, the details of file and line number
1168 t_msg(const char *file, int line, int level, const char *fmt,...)
1180 if (level <= debug_level) {
1182 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1183 trace_fd = fopen(buf, "a+b");
1186 #ifdef FULL_LOCATION
1188 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1195 va_start(arg_ptr, fmt);
1196 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1198 if (trace_fd != NULL) {
1199 fputs(buf, trace_fd);
1205 /* *********************************************************
1207 * print an error message
1211 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1218 * Check if we have a message destination defined.
1219 * We always report M_ABORT and M_ERROR_TERM
1221 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1222 !bit_is_set(type, daemon_msgs->send_msg))) {
1223 return; /* no destination */
1227 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1228 my_name, get_basename(file), line);
1231 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1232 my_name, get_basename(file), line);
1235 if (level == -1) /* skip details */
1236 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1238 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1241 if (level == -1) /* skip details */
1242 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1244 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1247 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1250 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1253 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1257 va_start(arg_ptr, fmt);
1258 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1261 dispatch_message(NULL, type, 0, buf);
1263 if (type == M_ABORT) {
1265 p[0] = 0; /* generate segmentation violation */
1267 if (type == M_ERROR_TERM) {
1272 /* *********************************************************
1274 * Generate a Job message
1278 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1287 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1289 /* Special case for the console, which has a dir_bsock and JobId==0,
1290 * in that case, we send the message directly back to the
1293 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1294 BSOCK *dir = jcr->dir_bsock;
1295 va_start(arg_ptr, fmt);
1296 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1299 jcr->dir_bsock->send();
1303 /* The watchdog thread can't use Jmsg directly, we always queued it */
1304 if (is_watchdog()) {
1305 va_start(arg_ptr, fmt);
1306 bvsnprintf(rbuf, sizeof(rbuf), fmt, arg_ptr);
1308 Qmsg(jcr, type, mtime, "%s", rbuf);
1314 jcr = get_jcr_from_tsd();
1317 if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1318 /* Dequeue messages to keep the original order */
1319 dequeue_messages(jcr);
1321 msgs = jcr->jcr_msgs;
1325 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1329 * Check if we have a message destination defined.
1330 * We always report M_ABORT and M_ERROR_TERM
1332 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1333 !bit_is_set(type, msgs->send_msg)) {
1334 return; /* no destination */
1338 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1341 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1344 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1346 jcr->setJobStatus(JS_FatalError);
1348 if (jcr && jcr->JobErrors == 0) {
1353 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1359 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1365 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1369 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1373 va_start(arg_ptr, fmt);
1374 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1377 dispatch_message(jcr, type, mtime, rbuf);
1379 if (type == M_ABORT){
1381 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1382 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1383 p[0] = 0; /* generate segmentation violation */
1385 if (type == M_ERROR_TERM) {
1391 * If we come here, prefix the message with the file:line-number,
1392 * then pass it on to the normal Jmsg routine.
1394 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1400 pool_buf = get_pool_memory(PM_EMSG);
1401 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1404 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1405 va_start(arg_ptr, fmt);
1406 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1408 if (len < 0 || len >= (maxlen-5)) {
1409 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1415 Jmsg(jcr, type, mtime, "%s", pool_buf);
1416 free_memory(pool_buf);
1421 * Edit a message into a Pool memory buffer, with file:lineno
1423 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1428 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1431 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1432 va_start(arg_ptr, fmt);
1433 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1435 if (len < 0 || len >= (maxlen-5)) {
1436 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1444 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1449 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1452 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1453 va_start(arg_ptr, fmt);
1454 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1456 if (len < 0 || len >= (maxlen-5)) {
1457 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1467 * Edit a message into a Pool Memory buffer NO file:lineno
1468 * Returns: string length of what was edited.
1470 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1476 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1477 va_start(arg_ptr, fmt);
1478 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1480 if (len < 0 || len >= (maxlen-5)) {
1481 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1489 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1495 maxlen = sizeof_pool_memory(pool_buf) - 1;
1496 va_start(arg_ptr, fmt);
1497 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1499 if (len < 0 || len >= (maxlen-5)) {
1500 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1508 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1514 maxlen = pool_buf.max_size() - 1;
1515 va_start(arg_ptr, fmt);
1516 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1518 if (len < 0 || len >= (maxlen-5)) {
1519 pool_buf.realloc_pm(maxlen + maxlen/2);
1529 * We queue messages rather than print them directly. This
1530 * is generally used in low level routines (msg handler, bnet)
1531 * to prevent recursion (i.e. if you are in the middle of
1532 * sending a message, it is a bit messy to recursively call
1533 * yourself when the bnet packet is not reentrant).
1535 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1542 pool_buf = get_pool_memory(PM_EMSG);
1545 maxlen = sizeof_pool_memory(pool_buf) - 1;
1546 va_start(arg_ptr, fmt);
1547 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1549 if (len < 0 || len >= (maxlen-5)) {
1550 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1555 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1557 item->mtime = time(NULL);
1558 strcpy(item->msg, pool_buf);
1560 jcr = get_jcr_from_tsd();
1562 /* If no jcr or no queue or dequeuing send to syslog */
1563 if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1564 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1567 /* Queue message for later sending */
1568 P(jcr->msg_queue_mutex);
1569 jcr->msg_queue->append(item);
1570 V(jcr->msg_queue_mutex);
1572 free_memory(pool_buf);
1578 void dequeue_messages(JCR *jcr)
1581 if (!jcr->msg_queue) {
1584 P(jcr->msg_queue_mutex);
1585 jcr->dequeuing_msgs = true;
1586 foreach_dlist(item, jcr->msg_queue) {
1587 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1589 /* Remove messages just sent */
1590 jcr->msg_queue->destroy();
1591 jcr->dequeuing_msgs = false;
1592 V(jcr->msg_queue_mutex);
1597 * If we come here, prefix the message with the file:line-number,
1598 * then pass it on to the normal Qmsg routine.
1600 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1606 pool_buf = get_pool_memory(PM_EMSG);
1607 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1610 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1611 va_start(arg_ptr, fmt);
1612 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1614 if (len < 0 || len >= (maxlen-5)) {
1615 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1621 Qmsg(jcr, type, mtime, "%s", pool_buf);
1622 free_memory(pool_buf);