2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2010 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 p_sql_query = NULL;
44 sql_escape 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]; /* daemon name is stored here */
62 char host_name[50]; /* 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: junk */
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);
229 return catalog_db != NULL ? catalog_db : "unknown";
233 set_db_type(const char *name)
235 if (catalog_db != NULL) {
238 catalog_db = bstrdup(name);
242 * Initialize message handler for a daemon or a Job
243 * We make a copy of the MSGS resource passed, so it belows
244 * to the job or daemon and thus can be modified.
246 * NULL for jcr -> initialize global messages for daemon
247 * non-NULL -> initialize jcr using Message resource
250 init_msg(JCR *jcr, MSGS *msg)
252 DEST *d, *dnew, *temp_chain = NULL;
255 if (jcr == NULL && msg == NULL) {
256 init_last_jobs_list();
257 /* Create a daemon key then set invalid jcr */
258 /* Maybe we should give the daemon a jcr??? */
260 set_jcr_in_tsd(INVALID_JCR);
263 #if !defined(HAVE_WIN32)
265 * Make sure we have fd's 0, 1, 2 open
266 * If we don't do this one of our sockets may open
267 * there and if we then use stdout, it could
268 * send total garbage to our socket.
272 fd = open("/dev/null", O_RDONLY, 0644);
276 for(i=1; fd + i <= 2; i++) {
283 * If msg is NULL, initialize global chain for STDOUT and syslog
286 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
287 memset(daemon_msgs, 0, sizeof(MSGS));
288 for (i=1; i<=M_MAX; i++) {
289 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
291 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
296 * Walk down the message resource chain duplicating it
297 * for the current Job.
299 for (d=msg->dest_chain; d; d=d->next) {
300 dnew = (DEST *)malloc(sizeof(DEST));
301 memcpy(dnew, d, sizeof(DEST));
302 dnew->next = temp_chain;
304 dnew->mail_filename = NULL;
306 dnew->mail_cmd = bstrdup(d->mail_cmd);
309 dnew->where = bstrdup(d->where);
315 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
316 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
317 jcr->jcr_msgs->dest_chain = temp_chain;
318 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
320 /* If we have default values, release them now */
322 free_msgs_res(daemon_msgs);
324 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
325 memset(daemon_msgs, 0, sizeof(MSGS));
326 daemon_msgs->dest_chain = temp_chain;
327 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
330 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
334 /* Initialize so that the console (User Agent) can
335 * receive messages -- stored in a file.
337 void init_console_msg(const char *wd)
341 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
342 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
345 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
346 con_fname, be.bstrerror());
348 if (lseek(fd, 0, SEEK_END) > 0) {
349 console_msg_pending = 1;
352 con_fd = fopen(con_fname, "a+b");
355 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
356 con_fname, be.bstrerror());
358 if (rwl_init(&con_lock) != 0) {
360 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
366 * Called only during parsing of the config file.
368 * Add a message destination. I.e. associate a message type with
369 * a destination (code).
370 * Note, where in the case of dest_code FILE is a filename,
371 * but in the case of MAIL is a space separated list of
372 * email addresses, ...
374 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
378 * First search the existing chain and see if we
379 * can simply add this msg_type to an existing entry.
381 for (d=msg->dest_chain; d; d=d->next) {
382 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
383 (strcmp(where, d->where) == 0))) {
384 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
385 d, msg_type, dest_code, NPRT(where));
386 set_bit(msg_type, d->msg_types);
387 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
391 /* Not found, create a new entry */
392 d = (DEST *)malloc(sizeof(DEST));
393 memset(d, 0, sizeof(DEST));
394 d->next = msg->dest_chain;
395 d->dest_code = dest_code;
396 set_bit(msg_type, d->msg_types); /* set type bit in structure */
397 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
399 d->where = bstrdup(where);
402 d->mail_cmd = bstrdup(mail_cmd);
404 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
405 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
410 * Called only during parsing of the config file.
412 * Remove a message destination
414 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
418 for (d=msg->dest_chain; d; d=d->next) {
419 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
420 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
421 ((where == NULL && d->where == NULL) ||
422 (strcmp(where, d->where) == 0))) {
423 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
424 d, msg_type, dest_code);
425 clear_bit(msg_type, d->msg_types);
426 Dmsg0(850, "Return rem_msg_dest\n");
434 * Create a unique filename for the mail command
436 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
439 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
440 jcr->Job, (int)(intptr_t)d);
442 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
443 my_name, (int)(intptr_t)d);
445 Dmsg1(850, "mailname=%s\n", name);
451 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
456 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
458 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
462 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
463 /* If we had to use sendmail, add subject */
465 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
469 delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
470 cmd, be.bstrerror());
476 * Close the messages for this Messages resource, which means to close
477 * any open files, and dispatch any pending email messages.
479 void close_msg(JCR *jcr)
487 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
489 if (jcr == NULL) { /* NULL -> global chain */
492 msgs = jcr->jcr_msgs;
493 jcr->jcr_msgs = NULL;
499 /* Wait for item to be not in use, then mark closing */
500 if (msgs->is_closing()) {
503 msgs->wait_not_in_use(); /* leaves fides_mutex set */
507 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
508 cmd = get_pool_memory(PM_MESSAGE);
509 for (d=msgs->dest_chain; d; ) {
511 switch (d->dest_code) {
515 fclose(d->fd); /* close open file descriptor */
520 case MD_MAIL_ON_ERROR:
521 case MD_MAIL_ON_SUCCESS:
522 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
527 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
528 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
530 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
531 jcr->JobStatus == JS_ErrorTerminated)
536 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
537 Pmsg0(000, _("open mail pipe failed.\n"));
540 Dmsg0(850, "Opened mail pipe\n");
542 line = get_memory(len);
544 while (fgets(line, len, d->fd)) {
545 fputs(line, bpipe->wfd);
547 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
549 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
553 * Since we are closing all messages, before "recursing"
554 * make sure we are not closing the daemon messages, otherwise
557 if (msgs != daemon_msgs) {
558 /* read what mail prog returned -- should be nothing */
559 while (fgets(line, len, bpipe->rfd)) {
560 delivery_error(_("Mail prog: %s"), line);
564 stat = close_bpipe(bpipe);
565 if (stat != 0 && msgs != daemon_msgs) {
568 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
569 delivery_error(_("Mail program terminated in error.\n"
571 "ERR=%s\n"), cmd, be.bstrerror());
575 /* Remove temp file */
578 unlink(d->mail_filename);
579 free_pool_memory(d->mail_filename);
580 d->mail_filename = NULL;
581 Dmsg0(850, "end mail or mail on error\n");
588 d = d->next; /* point to next buffer */
590 free_pool_memory(cmd);
591 Dmsg0(850, "Done walking message chain.\n");
596 msgs->clear_closing();
598 Dmsg0(850, "===End close msg resource\n");
602 * Free memory associated with Messages resource
604 void free_msgs_res(MSGS *msgs)
608 /* Walk down the message chain releasing allocated buffers */
609 for (d=msgs->dest_chain; d; ) {
616 old = d; /* save pointer to release */
617 d = d->next; /* point to next buffer */
618 free(old); /* free the destination item */
620 msgs->dest_chain = NULL;
621 free(msgs); /* free the head */
626 * Terminate the message handler for good.
627 * Release the global destination chain.
629 * Also, clean up a few other items (cons, exepath). Note,
630 * these really should be done elsewhere.
634 Dmsg0(850, "Enter term_msg\n");
635 close_msg(NULL); /* close global chain */
636 free_msgs_res(daemon_msgs); /* free the resources */
659 term_last_jobs_list();
662 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
664 d->fd = fopen(d->where, mode);
667 delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
674 * Handle sending the message to the appropriate place
676 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
679 char dt[MAX_TIME_LENGTH];
686 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
689 * Most messages are prefixed by a date and time. If mtime is
690 * zero, then we use the current time. If mtime is 1 (special
691 * kludge), we do not prefix the date and time. Otherwise,
692 * we assume mtime is a utime_t and use it.
700 mtime = time(NULL); /* get time for SQL log */
702 bstrftime_ny(dt, sizeof(dt), mtime);
708 /* If the program registered a callback, send it there */
709 if (message_callback) {
710 message_callback(type, msg);
714 /* For serious errors make sure message is printed or logged */
715 if (type == M_ABORT || type == M_ERROR_TERM) {
719 if (type == M_ABORT) {
720 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
725 /* Now figure out where to send the message */
728 jcr = get_jcr_from_tsd();
731 msgs = jcr->jcr_msgs;
737 * If closing this message resource, print and send to syslog,
740 if (msgs->is_closing()) {
744 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
748 for (d=msgs->dest_chain; d; d=d->next) {
749 if (bit_is_set(type, d->msg_types)) {
750 switch (d->dest_code) {
753 if (!jcr || !jcr->db) {
756 if (p_sql_query && p_sql_escape) {
757 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
758 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
760 int len = strlen(msg) + 1;
761 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
762 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
764 bstrutime(dt, sizeof(dt), mtime);
765 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
766 edit_int64(jcr->JobId, ed1), dt, esc_msg);
767 p_sql_query(jcr, cmd);
769 free_pool_memory(cmd);
770 free_pool_memory(esc_msg);
774 Dmsg1(850, "CONSOLE for following msg: %s", msg);
776 con_fd = fopen(con_fname, "a+b");
777 Dmsg0(850, "Console file not open.\n");
780 Pw(con_lock); /* get write lock on console message file */
783 (void)fwrite(dt, dtlen, 1, con_fd);
787 (void)fwrite(msg, len, 1, con_fd);
788 if (msg[len-1] != '\n') {
789 (void)fwrite("\n", 2, 1, con_fd);
792 (void)fwrite("\n", 2, 1, con_fd);
795 console_msg_pending = true;
800 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
802 * We really should do an openlog() here.
804 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
807 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
808 mcmd = get_pool_memory(PM_MESSAGE);
809 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
811 fputs(dt, bpipe->wfd);
812 fputs(msg, bpipe->wfd);
813 /* Messages to the operator go one at a time */
814 stat = close_bpipe(bpipe);
818 delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
820 "ERR=%s\n"), mcmd, be.bstrerror());
823 free_pool_memory(mcmd);
826 case MD_MAIL_ON_ERROR:
827 case MD_MAIL_ON_SUCCESS:
828 Dmsg1(850, "MAIL for following msg: %s", msg);
829 if (msgs->is_closing()) {
834 POOLMEM *name = get_pool_memory(PM_MESSAGE);
835 make_unique_mail_filename(jcr, name, d);
836 d->fd = fopen(name, "w+b");
839 delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
841 free_pool_memory(name);
845 d->mail_filename = name;
848 len = strlen(msg) + dtlen;;
849 if (len > d->max_len) {
850 d->max_len = len; /* keep max line length */
853 msgs->clear_in_use();
856 Dmsg1(850, "APPEND for following msg: %s", msg);
860 Dmsg1(850, "FILE for following msg: %s", msg);
863 if (msgs->is_closing()) {
867 if (!d->fd && !open_dest_file(jcr, d, mode)) {
868 msgs->clear_in_use();
873 /* On error, we close and reopen to handle log rotation */
877 if (open_dest_file(jcr, d, mode)) {
882 msgs->clear_in_use();
885 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
886 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
887 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
888 jcr->Job, type, mtime, msg);
890 Dmsg1(800, "no jcr for following msg: %s", msg);
894 Dmsg1(850, "STDOUT for following msg: %s", msg);
895 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
902 Dmsg1(850, "STDERR for following msg: %s", msg);
914 /*********************************************************************
916 * This subroutine returns the filename portion of a Windows
917 * path. It is used because Microsoft Visual Studio sets __FILE__
922 get_basename(const char *pathname)
924 #if defined(_MSC_VER)
925 const char *basename;
927 if ((basename = strrchr(pathname, '\\')) == NULL) {
940 * print or write output to trace file
942 static void pt_out(char *buf)
945 * Used the "trace on" command in the console to turn on
946 * output to the trace file. "trace off" will close the file.
951 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
952 trace_fd = fopen(fn, "a+b");
955 fputs(buf, trace_fd);
958 /* Some problem, turn off tracing */
961 } else { /* not tracing */
967 /*********************************************************************
969 * This subroutine prints a debug message if the level number
970 * is less than or equal the debug_level. File and line numbers
971 * are included for more detail if desired, but not currently
974 * If the level is negative, the details of file and line number
978 d_msg(const char *file, int line, int level, const char *fmt,...)
991 if (level <= debug_level) {
994 bstrftimes(buf, sizeof(buf), mtime);
1001 #ifdef FULL_LOCATION
1003 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
1004 my_name, get_basename(file), line, get_jobid_from_tsd());
1011 va_start(arg_ptr, fmt);
1012 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1020 * Set trace flag on/off. If argument is negative, there is no change
1022 void set_trace(int trace_flag)
1024 if (trace_flag < 0) {
1026 } else if (trace_flag > 0) {
1031 if (!trace && trace_fd) {
1032 FILE *ltrace_fd = trace_fd;
1034 bmicrosleep(0, 100000); /* yield to prevent seg faults */
1039 bool get_trace(void)
1044 /*********************************************************************
1046 * This subroutine prints a message regardless of the debug level
1048 * If the level is negative, the details of file and line number
1052 p_msg(const char *file, int line, int level, const char *fmt,...)
1058 #ifdef FULL_LOCATION
1060 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1067 va_start(arg_ptr, fmt);
1068 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1075 /*********************************************************************
1077 * subroutine writes a debug message to the trace file if the level number
1078 * is less than or equal the debug_level. File and line numbers
1079 * are included for more detail if desired, but not currently
1082 * If the level is negative, the details of file and line number
1086 t_msg(const char *file, int line, int level, const char *fmt,...)
1098 if (level <= debug_level) {
1100 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1101 trace_fd = fopen(buf, "a+b");
1104 #ifdef FULL_LOCATION
1106 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1113 va_start(arg_ptr, fmt);
1114 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1116 if (trace_fd != NULL) {
1117 fputs(buf, trace_fd);
1123 /* *********************************************************
1125 * print an error message
1129 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1136 * Check if we have a message destination defined.
1137 * We always report M_ABORT and M_ERROR_TERM
1139 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1140 !bit_is_set(type, daemon_msgs->send_msg))) {
1141 return; /* no destination */
1145 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1146 my_name, get_basename(file), line);
1149 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1150 my_name, get_basename(file), line);
1153 if (level == -1) /* skip details */
1154 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1156 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1159 if (level == -1) /* skip details */
1160 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1162 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1165 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1168 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1171 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1175 va_start(arg_ptr, fmt);
1176 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1179 dispatch_message(NULL, type, 0, buf);
1181 if (type == M_ABORT) {
1183 p[0] = 0; /* generate segmentation violation */
1185 if (type == M_ERROR_TERM) {
1190 /* *********************************************************
1192 * Generate a Job message
1196 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1205 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1207 /* Special case for the console, which has a dir_bsock and JobId==0,
1208 * in that case, we send the message directly back to the
1211 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1212 BSOCK *dir = jcr->dir_bsock;
1213 va_start(arg_ptr, fmt);
1214 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1217 jcr->dir_bsock->send();
1221 /* The watchdog thread can't use Jmsg directly, we always queued it */
1222 if (is_watchdog()) {
1223 va_start(arg_ptr, fmt);
1224 bvsnprintf(rbuf, sizeof(rbuf), fmt, arg_ptr);
1226 Qmsg(jcr, type, mtime, "%s", rbuf);
1232 jcr = get_jcr_from_tsd();
1235 if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1236 /* Dequeue messages to keep the original order */
1237 dequeue_messages(jcr);
1239 msgs = jcr->jcr_msgs;
1243 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1247 * Check if we have a message destination defined.
1248 * We always report M_ABORT and M_ERROR_TERM
1250 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1251 !bit_is_set(type, msgs->send_msg)) {
1252 return; /* no destination */
1256 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1259 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1262 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1264 set_jcr_job_status(jcr, JS_FatalError);
1268 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1274 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1280 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1284 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1288 va_start(arg_ptr, fmt);
1289 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1292 dispatch_message(jcr, type, mtime, rbuf);
1294 if (type == M_ABORT){
1296 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1297 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1298 p[0] = 0; /* generate segmentation violation */
1300 if (type == M_ERROR_TERM) {
1306 * If we come here, prefix the message with the file:line-number,
1307 * then pass it on to the normal Jmsg routine.
1309 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1315 pool_buf = get_pool_memory(PM_EMSG);
1316 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1319 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1320 va_start(arg_ptr, fmt);
1321 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1323 if (len < 0 || len >= (maxlen-5)) {
1324 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1330 Jmsg(jcr, type, mtime, "%s", pool_buf);
1331 free_memory(pool_buf);
1336 * Edit a message into a Pool memory buffer, with file:lineno
1338 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1343 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1346 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1347 va_start(arg_ptr, fmt);
1348 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1350 if (len < 0 || len >= (maxlen-5)) {
1351 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1359 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1364 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1367 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1368 va_start(arg_ptr, fmt);
1369 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1371 if (len < 0 || len >= (maxlen-5)) {
1372 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1382 * Edit a message into a Pool Memory buffer NO file:lineno
1383 * Returns: string length of what was edited.
1385 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1391 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1392 va_start(arg_ptr, fmt);
1393 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1395 if (len < 0 || len >= (maxlen-5)) {
1396 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1404 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1410 maxlen = sizeof_pool_memory(pool_buf) - 1;
1411 va_start(arg_ptr, fmt);
1412 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1414 if (len < 0 || len >= (maxlen-5)) {
1415 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1423 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1429 maxlen = pool_buf.max_size() - 1;
1430 va_start(arg_ptr, fmt);
1431 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1433 if (len < 0 || len >= (maxlen-5)) {
1434 pool_buf.realloc_pm(maxlen + maxlen/2);
1444 * We queue messages rather than print them directly. This
1445 * is generally used in low level routines (msg handler, bnet)
1446 * to prevent recursion (i.e. if you are in the middle of
1447 * sending a message, it is a bit messy to recursively call
1448 * yourself when the bnet packet is not reentrant).
1450 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1457 pool_buf = get_pool_memory(PM_EMSG);
1460 maxlen = sizeof_pool_memory(pool_buf) - 1;
1461 va_start(arg_ptr, fmt);
1462 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1464 if (len < 0 || len >= (maxlen-5)) {
1465 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1470 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1472 item->mtime = time(NULL);
1473 strcpy(item->msg, pool_buf);
1475 jcr = get_jcr_from_tsd();
1477 /* If no jcr or no queue or dequeuing send to syslog */
1478 if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1479 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1482 /* Queue message for later sending */
1483 P(jcr->msg_queue_mutex);
1484 jcr->msg_queue->append(item);
1485 V(jcr->msg_queue_mutex);
1487 free_memory(pool_buf);
1493 void dequeue_messages(JCR *jcr)
1496 if (!jcr->msg_queue) {
1499 P(jcr->msg_queue_mutex);
1500 jcr->dequeuing_msgs = true;
1501 foreach_dlist(item, jcr->msg_queue) {
1502 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1504 /* Remove messages just sent */
1505 jcr->msg_queue->destroy();
1506 jcr->dequeuing_msgs = false;
1507 V(jcr->msg_queue_mutex);
1512 * If we come here, prefix the message with the file:line-number,
1513 * then pass it on to the normal Qmsg routine.
1515 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1521 pool_buf = get_pool_memory(PM_EMSG);
1522 i = Mmsg(pool_buf, "%s:%d ", file, line);
1525 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1526 va_start(arg_ptr, fmt);
1527 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1529 if (len < 0 || len >= (maxlen-5)) {
1530 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1536 Qmsg(jcr, type, mtime, "%s", pool_buf);
1537 free_memory(pool_buf);