2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2011 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;
60 const int beef = BEEF;
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 /* Allow only one thread to tweak d->fd at a time */
78 static pthread_mutex_t fides_mutex = PTHREAD_MUTEX_INITIALIZER;
79 static MSGS *daemon_msgs; /* global messages */
80 static char *catalog_db = NULL; /* database type */
81 static void (*message_callback)(int type, char *msg) = NULL;
82 static FILE *trace_fd = NULL;
83 #if defined(HAVE_WIN32)
84 static bool trace = true;
86 static bool trace = false;
90 const char *host_os = HOST_OS;
91 const char *distname = DISTNAME;
92 const char *distver = DISTVER;
94 /* Some message class methods */
106 * Wait for not in use variable to be clear
108 void MSGS::wait_not_in_use() /* leaves fides_mutex set */
113 bmicrosleep(0, 200); /* wait */
119 * Handle message delivery errors
121 static void delivery_error(const char *fmt,...)
126 char dt[MAX_TIME_LENGTH];
129 pool_buf = get_pool_memory(PM_EMSG);
131 bstrftime_ny(dt, sizeof(dt), time(NULL));
136 i = Mmsg(pool_buf, "%s Message delivery ERROR: ", dt);
139 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
140 va_start(arg_ptr, fmt);
141 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
143 if (len < 0 || len >= (maxlen-5)) {
144 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
150 fputs(pool_buf, stdout); /* print this here to INSURE that it is printed */
152 syslog(LOG_DAEMON|LOG_ERR, "%s", pool_buf);
153 free_memory(pool_buf);
156 void register_message_callback(void msg_callback(int type, char *msg))
158 message_callback = msg_callback;
163 * Set daemon name. Also, find canonical execution
164 * path. Note, exepath has spare room for tacking on
165 * the exename so that we can reconstruct the full name.
167 * Note, this routine can get called multiple times
168 * The second time is to put the name as found in the
169 * Resource record. On the second call, generally,
170 * argv is NULL to avoid doing the path code twice.
172 void my_name_is(int argc, char *argv[], const char *name)
178 if (gethostname(host_name, sizeof(host_name)) != 0) {
179 bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
181 bstrncpy(my_name, name, sizeof(my_name));
182 if (argc>0 && argv && argv[0]) {
183 /* strip trailing filename and save exepath */
184 for (l=p=argv[0]; *p; p++) {
185 if (IsPathSeparator(*p)) {
186 l = p; /* set pos of last slash */
189 if (IsPathSeparator(*l)) {
193 #if defined(HAVE_WIN32)
194 /* On Windows allow c: drive specification */
204 exename = (char *)malloc(len);
210 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
211 for (p=argv[0],q=exepath; p < l; ) {
215 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
216 if (getcwd(cpath, sizeof(cpath))) {
218 exepath = (char *)malloc(strlen(cpath) + 1 + len);
219 strcpy(exepath, cpath);
222 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
227 set_db_type(const char *name)
229 if (catalog_db != NULL) {
232 catalog_db = bstrdup(name);
236 * Initialize message handler for a daemon or a Job
237 * We make a copy of the MSGS resource passed, so it belows
238 * to the job or daemon and thus can be modified.
240 * NULL for jcr -> initialize global messages for daemon
241 * non-NULL -> initialize jcr using Message resource
244 init_msg(JCR *jcr, MSGS *msg)
246 DEST *d, *dnew, *temp_chain = NULL;
249 if (jcr == NULL && msg == NULL) {
250 init_last_jobs_list();
251 /* Create a daemon key then set invalid jcr */
252 /* Maybe we should give the daemon a jcr??? */
254 set_jcr_in_tsd(INVALID_JCR);
257 #if !defined(HAVE_WIN32)
259 * Make sure we have fd's 0, 1, 2 open
260 * If we don't do this one of our sockets may open
261 * there and if we then use stdout, it could
262 * send total garbage to our socket.
266 fd = open("/dev/null", O_RDONLY, 0644);
270 for(i=1; fd + i <= 2; i++) {
277 * If msg is NULL, initialize global chain for STDOUT and syslog
280 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
281 memset(daemon_msgs, 0, sizeof(MSGS));
282 for (i=1; i<=M_MAX; i++) {
283 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
285 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
290 * Walk down the message resource chain duplicating it
291 * for the current Job.
293 for (d=msg->dest_chain; d; d=d->next) {
294 dnew = (DEST *)malloc(sizeof(DEST));
295 memcpy(dnew, d, sizeof(DEST));
296 dnew->next = temp_chain;
298 dnew->mail_filename = NULL;
300 dnew->mail_cmd = bstrdup(d->mail_cmd);
303 dnew->where = bstrdup(d->where);
309 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
310 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
311 jcr->jcr_msgs->dest_chain = temp_chain;
312 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
314 /* If we have default values, release them now */
316 free_msgs_res(daemon_msgs);
318 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
319 memset(daemon_msgs, 0, sizeof(MSGS));
320 daemon_msgs->dest_chain = temp_chain;
321 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
324 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
328 /* Initialize so that the console (User Agent) can
329 * receive messages -- stored in a file.
331 void init_console_msg(const char *wd)
335 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
336 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
339 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
340 con_fname, be.bstrerror());
342 if (lseek(fd, 0, SEEK_END) > 0) {
343 console_msg_pending = 1;
346 con_fd = fopen(con_fname, "a+b");
349 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
350 con_fname, be.bstrerror());
352 if (rwl_init(&con_lock) != 0) {
354 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
360 * Called only during parsing of the config file.
362 * Add a message destination. I.e. associate a message type with
363 * a destination (code).
364 * Note, where in the case of dest_code FILE is a filename,
365 * but in the case of MAIL is a space separated list of
366 * email addresses, ...
368 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
372 * First search the existing chain and see if we
373 * can simply add this msg_type to an existing entry.
375 for (d=msg->dest_chain; d; d=d->next) {
376 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
377 (strcmp(where, d->where) == 0))) {
378 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
379 d, msg_type, dest_code, NPRT(where));
380 set_bit(msg_type, d->msg_types);
381 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
385 /* Not found, create a new entry */
386 d = (DEST *)malloc(sizeof(DEST));
387 memset(d, 0, sizeof(DEST));
388 d->next = msg->dest_chain;
389 d->dest_code = dest_code;
390 set_bit(msg_type, d->msg_types); /* set type bit in structure */
391 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
393 d->where = bstrdup(where);
396 d->mail_cmd = bstrdup(mail_cmd);
398 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
399 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
404 * Called only during parsing of the config file.
406 * Remove a message destination
408 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
412 for (d=msg->dest_chain; d; d=d->next) {
413 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
414 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
415 ((where == NULL && d->where == NULL) ||
416 (strcmp(where, d->where) == 0))) {
417 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
418 d, msg_type, dest_code);
419 clear_bit(msg_type, d->msg_types);
420 Dmsg0(850, "Return rem_msg_dest\n");
428 * Create a unique filename for the mail command
430 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
433 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
434 jcr->Job, (int)(intptr_t)d);
436 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
437 my_name, (int)(intptr_t)d);
439 Dmsg1(850, "mailname=%s\n", name);
445 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
450 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
452 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
456 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
457 /* If we had to use sendmail, add subject */
459 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
463 delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
464 cmd, be.bstrerror());
470 * Close the messages for this Messages resource, which means to close
471 * any open files, and dispatch any pending email messages.
473 void close_msg(JCR *jcr)
481 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
483 if (jcr == NULL) { /* NULL -> global chain */
486 msgs = jcr->jcr_msgs;
487 jcr->jcr_msgs = NULL;
493 /* Wait for item to be not in use, then mark closing */
494 if (msgs->is_closing()) {
497 msgs->wait_not_in_use(); /* leaves fides_mutex set */
501 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
502 cmd = get_pool_memory(PM_MESSAGE);
503 for (d=msgs->dest_chain; d; ) {
505 switch (d->dest_code) {
509 fclose(d->fd); /* close open file descriptor */
514 case MD_MAIL_ON_ERROR:
515 case MD_MAIL_ON_SUCCESS:
516 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
521 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
522 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
524 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
525 jcr->JobStatus == JS_ErrorTerminated)
530 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
531 Pmsg0(000, _("open mail pipe failed.\n"));
534 Dmsg0(850, "Opened mail pipe\n");
536 line = get_memory(len);
538 while (fgets(line, len, d->fd)) {
539 fputs(line, bpipe->wfd);
541 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
543 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
547 * Since we are closing all messages, before "recursing"
548 * make sure we are not closing the daemon messages, otherwise
551 if (msgs != daemon_msgs) {
552 /* read what mail prog returned -- should be nothing */
553 while (fgets(line, len, bpipe->rfd)) {
554 delivery_error(_("Mail prog: %s"), line);
558 stat = close_bpipe(bpipe);
559 if (stat != 0 && msgs != daemon_msgs) {
562 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
563 delivery_error(_("Mail program terminated in error.\n"
565 "ERR=%s\n"), cmd, be.bstrerror());
569 /* Remove temp file */
572 unlink(d->mail_filename);
573 free_pool_memory(d->mail_filename);
574 d->mail_filename = NULL;
575 Dmsg0(850, "end mail or mail on error\n");
582 d = d->next; /* point to next buffer */
584 free_pool_memory(cmd);
585 Dmsg0(850, "Done walking message chain.\n");
590 msgs->clear_closing();
592 Dmsg0(850, "===End close msg resource\n");
596 * Free memory associated with Messages resource
598 void free_msgs_res(MSGS *msgs)
602 /* Walk down the message chain releasing allocated buffers */
603 for (d=msgs->dest_chain; d; ) {
610 old = d; /* save pointer to release */
611 d = d->next; /* point to next buffer */
612 free(old); /* free the destination item */
614 msgs->dest_chain = NULL;
615 free(msgs); /* free the head */
620 * Terminate the message handler for good.
621 * Release the global destination chain.
623 * Also, clean up a few other items (cons, exepath). Note,
624 * these really should be done elsewhere.
628 Dmsg0(850, "Enter term_msg\n");
629 close_msg(NULL); /* close global chain */
630 free_msgs_res(daemon_msgs); /* free the resources */
653 term_last_jobs_list();
656 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
658 d->fd = fopen(d->where, mode);
661 delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
668 * Handle sending the message to the appropriate place
670 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
673 char dt[MAX_TIME_LENGTH];
680 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
683 * Most messages are prefixed by a date and time. If mtime is
684 * zero, then we use the current time. If mtime is 1 (special
685 * kludge), we do not prefix the date and time. Otherwise,
686 * we assume mtime is a utime_t and use it.
694 mtime = time(NULL); /* get time for SQL log */
696 bstrftime_ny(dt, sizeof(dt), mtime);
702 /* If the program registered a callback, send it there */
703 if (message_callback) {
704 message_callback(type, msg);
708 /* For serious errors make sure message is printed or logged */
709 if (type == M_ABORT || type == M_ERROR_TERM) {
713 if (type == M_ABORT) {
714 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
719 /* Now figure out where to send the message */
722 jcr = get_jcr_from_tsd();
725 msgs = jcr->jcr_msgs;
731 * If closing this message resource, print and send to syslog,
734 if (msgs->is_closing()) {
738 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
742 for (d=msgs->dest_chain; d; d=d->next) {
743 if (bit_is_set(type, d->msg_types)) {
744 switch (d->dest_code) {
747 if (!jcr || !jcr->db) {
750 if (p_sql_query && p_sql_escape) {
751 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
752 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
754 int len = strlen(msg) + 1;
755 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
756 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
758 bstrutime(dt, sizeof(dt), mtime);
759 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
760 edit_int64(jcr->JobId, ed1), dt, esc_msg);
761 p_sql_query(jcr, cmd);
763 free_pool_memory(cmd);
764 free_pool_memory(esc_msg);
768 Dmsg1(850, "CONSOLE for following msg: %s", msg);
770 con_fd = fopen(con_fname, "a+b");
771 Dmsg0(850, "Console file not open.\n");
774 Pw(con_lock); /* get write lock on console message file */
777 (void)fwrite(dt, dtlen, 1, con_fd);
781 (void)fwrite(msg, len, 1, con_fd);
782 if (msg[len-1] != '\n') {
783 (void)fwrite("\n", 2, 1, con_fd);
786 (void)fwrite("\n", 2, 1, con_fd);
789 console_msg_pending = true;
794 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
796 * We really should do an openlog() here.
798 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
801 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
802 mcmd = get_pool_memory(PM_MESSAGE);
803 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
805 fputs(dt, bpipe->wfd);
806 fputs(msg, bpipe->wfd);
807 /* Messages to the operator go one at a time */
808 stat = close_bpipe(bpipe);
812 delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
814 "ERR=%s\n"), mcmd, be.bstrerror());
817 free_pool_memory(mcmd);
820 case MD_MAIL_ON_ERROR:
821 case MD_MAIL_ON_SUCCESS:
822 Dmsg1(850, "MAIL for following msg: %s", msg);
823 if (msgs->is_closing()) {
828 POOLMEM *name = get_pool_memory(PM_MESSAGE);
829 make_unique_mail_filename(jcr, name, d);
830 d->fd = fopen(name, "w+b");
833 delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
835 free_pool_memory(name);
839 d->mail_filename = name;
842 len = strlen(msg) + dtlen;;
843 if (len > d->max_len) {
844 d->max_len = len; /* keep max line length */
847 msgs->clear_in_use();
850 Dmsg1(850, "APPEND for following msg: %s", msg);
854 Dmsg1(850, "FILE for following msg: %s", msg);
857 if (msgs->is_closing()) {
861 if (!d->fd && !open_dest_file(jcr, d, mode)) {
862 msgs->clear_in_use();
867 /* On error, we close and reopen to handle log rotation */
871 if (open_dest_file(jcr, d, mode)) {
876 msgs->clear_in_use();
879 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
880 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
881 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
882 jcr->Job, type, mtime, msg);
884 Dmsg1(800, "no jcr for following msg: %s", msg);
888 Dmsg1(850, "STDOUT for following msg: %s", msg);
889 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
896 Dmsg1(850, "STDERR for following msg: %s", msg);
908 /*********************************************************************
910 * This subroutine returns the filename portion of a path.
911 * It is used because some compilers set __FILE__
912 * to the full path. Try to return base + next higher path.
916 get_basename(const char *pathname)
918 const char *basename, *basename2;
920 if ((basename = strrchr(pathname, PathSeparator)) == NULL) {
922 if ((basename2 = strrchr(pathname, PathSeparator)) != NULL) {
923 basename = basename2 + 1;
933 * print or write output to trace file
935 static void pt_out(char *buf)
938 * Used the "trace on" command in the console to turn on
939 * output to the trace file. "trace off" will close the file.
944 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
945 trace_fd = fopen(fn, "a+b");
948 fputs(buf, trace_fd);
952 /* Some problem, turn off tracing */
961 /*********************************************************************
963 * This subroutine prints a debug message if the level number
964 * is less than or equal the debug_level. File and line numbers
965 * are included for more detail if desired, but not currently
968 * If the level is negative, the details of file and line number
972 d_msg(const char *file, int line, int level, const char *fmt,...)
985 if (level <= debug_level) {
988 bstrftimes(buf, sizeof(buf), mtime);
997 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
998 my_name, get_basename(file), line, get_jobid_from_tsd());
1005 va_start(arg_ptr, fmt);
1006 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1014 * Set trace flag on/off. If argument is negative, there is no change
1016 void set_trace(int trace_flag)
1018 if (trace_flag < 0) {
1020 } else if (trace_flag > 0) {
1025 if (!trace && trace_fd) {
1026 FILE *ltrace_fd = trace_fd;
1028 bmicrosleep(0, 100000); /* yield to prevent seg faults */
1033 bool get_trace(void)
1038 /*********************************************************************
1040 * This subroutine prints a message regardless of the debug level
1042 * If the level is negative, the details of file and line number
1046 p_msg(const char *file, int line, int level, const char *fmt,...)
1052 #ifdef FULL_LOCATION
1054 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1061 va_start(arg_ptr, fmt);
1062 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1069 /*********************************************************************
1071 * subroutine writes a debug message to the trace file if the level number
1072 * is less than or equal the debug_level. File and line numbers
1073 * are included for more detail if desired, but not currently
1076 * If the level is negative, the details of file and line number
1080 t_msg(const char *file, int line, int level, const char *fmt,...)
1092 if (level <= debug_level) {
1094 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1095 trace_fd = fopen(buf, "a+b");
1098 #ifdef FULL_LOCATION
1100 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1107 va_start(arg_ptr, fmt);
1108 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1110 if (trace_fd != NULL) {
1111 fputs(buf, trace_fd);
1117 /* *********************************************************
1119 * print an error message
1123 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1130 * Check if we have a message destination defined.
1131 * We always report M_ABORT and M_ERROR_TERM
1133 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1134 !bit_is_set(type, daemon_msgs->send_msg))) {
1135 return; /* no destination */
1139 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1140 my_name, get_basename(file), line);
1143 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1144 my_name, get_basename(file), line);
1147 if (level == -1) /* skip details */
1148 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1150 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1153 if (level == -1) /* skip details */
1154 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1156 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1159 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1162 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1165 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1169 va_start(arg_ptr, fmt);
1170 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1173 dispatch_message(NULL, type, 0, buf);
1175 if (type == M_ABORT) {
1177 p[0] = 0; /* generate segmentation violation */
1179 if (type == M_ERROR_TERM) {
1184 /* *********************************************************
1186 * Generate a Job message
1190 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1199 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1201 /* Special case for the console, which has a dir_bsock and JobId==0,
1202 * in that case, we send the message directly back to the
1205 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1206 BSOCK *dir = jcr->dir_bsock;
1207 va_start(arg_ptr, fmt);
1208 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1211 jcr->dir_bsock->send();
1215 /* The watchdog thread can't use Jmsg directly, we always queued it */
1216 if (is_watchdog()) {
1217 va_start(arg_ptr, fmt);
1218 bvsnprintf(rbuf, sizeof(rbuf), fmt, arg_ptr);
1220 Qmsg(jcr, type, mtime, "%s", rbuf);
1226 jcr = get_jcr_from_tsd();
1229 if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1230 /* Dequeue messages to keep the original order */
1231 dequeue_messages(jcr);
1233 msgs = jcr->jcr_msgs;
1237 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1241 * Check if we have a message destination defined.
1242 * We always report M_ABORT and M_ERROR_TERM
1244 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1245 !bit_is_set(type, msgs->send_msg)) {
1246 return; /* no destination */
1250 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1253 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1256 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1258 set_jcr_job_status(jcr, JS_FatalError);
1260 if (jcr && jcr->JobErrors == 0) {
1265 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1271 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1277 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1281 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1285 va_start(arg_ptr, fmt);
1286 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1289 dispatch_message(jcr, type, mtime, rbuf);
1291 if (type == M_ABORT){
1293 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1294 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1295 p[0] = 0; /* generate segmentation violation */
1297 if (type == M_ERROR_TERM) {
1303 * If we come here, prefix the message with the file:line-number,
1304 * then pass it on to the normal Jmsg routine.
1306 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1312 pool_buf = get_pool_memory(PM_EMSG);
1313 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1316 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1317 va_start(arg_ptr, fmt);
1318 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1320 if (len < 0 || len >= (maxlen-5)) {
1321 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1327 Jmsg(jcr, type, mtime, "%s", pool_buf);
1328 free_memory(pool_buf);
1333 * Edit a message into a Pool memory buffer, with file:lineno
1335 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1340 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1343 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1344 va_start(arg_ptr, fmt);
1345 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1347 if (len < 0 || len >= (maxlen-5)) {
1348 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1356 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1361 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1364 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1365 va_start(arg_ptr, fmt);
1366 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1368 if (len < 0 || len >= (maxlen-5)) {
1369 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1379 * Edit a message into a Pool Memory buffer NO file:lineno
1380 * Returns: string length of what was edited.
1382 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1388 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1389 va_start(arg_ptr, fmt);
1390 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1392 if (len < 0 || len >= (maxlen-5)) {
1393 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1401 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1407 maxlen = sizeof_pool_memory(pool_buf) - 1;
1408 va_start(arg_ptr, fmt);
1409 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1411 if (len < 0 || len >= (maxlen-5)) {
1412 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1420 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1426 maxlen = pool_buf.max_size() - 1;
1427 va_start(arg_ptr, fmt);
1428 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1430 if (len < 0 || len >= (maxlen-5)) {
1431 pool_buf.realloc_pm(maxlen + maxlen/2);
1441 * We queue messages rather than print them directly. This
1442 * is generally used in low level routines (msg handler, bnet)
1443 * to prevent recursion (i.e. if you are in the middle of
1444 * sending a message, it is a bit messy to recursively call
1445 * yourself when the bnet packet is not reentrant).
1447 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1454 pool_buf = get_pool_memory(PM_EMSG);
1457 maxlen = sizeof_pool_memory(pool_buf) - 1;
1458 va_start(arg_ptr, fmt);
1459 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1461 if (len < 0 || len >= (maxlen-5)) {
1462 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1467 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1469 item->mtime = time(NULL);
1470 strcpy(item->msg, pool_buf);
1472 jcr = get_jcr_from_tsd();
1474 /* If no jcr or no queue or dequeuing send to syslog */
1475 if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1476 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1479 /* Queue message for later sending */
1480 P(jcr->msg_queue_mutex);
1481 jcr->msg_queue->append(item);
1482 V(jcr->msg_queue_mutex);
1484 free_memory(pool_buf);
1490 void dequeue_messages(JCR *jcr)
1493 if (!jcr->msg_queue) {
1496 P(jcr->msg_queue_mutex);
1497 jcr->dequeuing_msgs = true;
1498 foreach_dlist(item, jcr->msg_queue) {
1499 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1501 /* Remove messages just sent */
1502 jcr->msg_queue->destroy();
1503 jcr->dequeuing_msgs = false;
1504 V(jcr->msg_queue_mutex);
1509 * If we come here, prefix the message with the file:line-number,
1510 * then pass it on to the normal Qmsg routine.
1512 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1518 pool_buf = get_pool_memory(PM_EMSG);
1519 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1522 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1523 va_start(arg_ptr, fmt);
1524 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1526 if (len < 0 || len >= (maxlen-5)) {
1527 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1533 Qmsg(jcr, type, mtime, "%s", pool_buf);
1534 free_memory(pool_buf);