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 two of the GNU 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 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 char my_name[30]; /* daemon name is stored here */
60 char host_name[50]; /* host machine name */
61 char *exepath = (char *)NULL;
62 char *exename = (char *)NULL;
63 int console_msg_pending = false;
64 char con_fname[500]; /* Console filename */
65 FILE *con_fd = NULL; /* Console file descriptor */
66 brwlock_t con_lock; /* Console lock structure */
68 /* Forward referenced functions */
70 /* Imported functions */
71 void create_jcr_key();
75 /* Allow only one thread to tweak d->fd at a time */
76 static pthread_mutex_t fides_mutex = PTHREAD_MUTEX_INITIALIZER;
77 static MSGS *daemon_msgs; /* global messages */
78 static char *catalog_db = NULL; /* database type */
79 static void (*message_callback)(int type, char *msg) = NULL;
80 static FILE *trace_fd = NULL;
81 #if defined(HAVE_WIN32)
82 static bool trace = true;
84 static bool trace = false;
88 const char *host_os = HOST_OS;
89 const char *distname = DISTNAME;
90 const char *distver = DISTVER;
92 /* Some message class methods */
104 * Wait for not in use variable to be clear
106 void MSGS::wait_not_in_use() /* leaves fides_mutex set */
111 bmicrosleep(0, 200); /* wait */
117 * Handle message delivery errors
119 static void delivery_error(const char *fmt,...)
124 char dt[MAX_TIME_LENGTH];
127 pool_buf = get_pool_memory(PM_EMSG);
129 bstrftime_ny(dt, sizeof(dt), time(NULL));
134 i = Mmsg(pool_buf, "%s Message delivery ERROR: ", dt);
137 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
138 va_start(arg_ptr, fmt);
139 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
141 if (len < 0 || len >= (maxlen-5)) {
142 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
148 fputs(pool_buf, stdout); /* print this here to INSURE that it is printed */
150 syslog(LOG_DAEMON|LOG_ERR, "%s", pool_buf);
151 free_memory(pool_buf);
154 void register_message_callback(void msg_callback(int type, char *msg))
156 message_callback = msg_callback;
161 * Set daemon name. Also, find canonical execution
162 * path. Note, exepath has spare room for tacking on
163 * the exename so that we can reconstruct the full name.
165 * Note, this routine can get called multiple times
166 * The second time is to put the name as found in the
167 * Resource record. On the second call, generally,
168 * argv is NULL to avoid doing the path code twice.
170 void my_name_is(int argc, char *argv[], const char *name)
176 if (gethostname(host_name, sizeof(host_name)) != 0) {
177 bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
179 bstrncpy(my_name, name, sizeof(my_name));
180 if (argc>0 && argv && argv[0]) {
181 /* strip trailing filename and save exepath */
182 for (l=p=argv[0]; *p; p++) {
183 if (IsPathSeparator(*p)) {
184 l = p; /* set pos of last slash */
187 if (IsPathSeparator(*l)) {
191 #if defined(HAVE_WIN32)
192 /* On Windows allow c: junk */
202 exename = (char *)malloc(len);
208 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
209 for (p=argv[0],q=exepath; p < l; ) {
213 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
214 if (getcwd(cpath, sizeof(cpath))) {
216 exepath = (char *)malloc(strlen(cpath) + 1 + len);
217 strcpy(exepath, cpath);
220 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
227 return catalog_db != NULL ? catalog_db : "unknown";
231 set_db_type(const char *name)
233 if (catalog_db != NULL) {
236 catalog_db = bstrdup(name);
240 * Initialize message handler for a daemon or a Job
241 * We make a copy of the MSGS resource passed, so it belows
242 * to the job or daemon and thus can be modified.
244 * NULL for jcr -> initialize global messages for daemon
245 * non-NULL -> initialize jcr using Message resource
248 init_msg(JCR *jcr, MSGS *msg)
250 DEST *d, *dnew, *temp_chain = NULL;
253 if (jcr == NULL && msg == NULL) {
254 init_last_jobs_list();
255 /* Create a daemon key then set invalid jcr */
256 /* Maybe we should give the daemon a jcr??? */
258 set_jcr_in_tsd(INVALID_JCR);
261 #if !defined(HAVE_WIN32)
263 * Make sure we have fd's 0, 1, 2 open
264 * If we don't do this one of our sockets may open
265 * there and if we then use stdout, it could
266 * send total garbage to our socket.
270 fd = open("/dev/null", O_RDONLY, 0644);
274 for(i=1; fd + i <= 2; i++) {
281 * If msg is NULL, initialize global chain for STDOUT and syslog
284 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
285 memset(daemon_msgs, 0, sizeof(MSGS));
286 for (i=1; i<=M_MAX; i++) {
287 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
289 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
294 * Walk down the message resource chain duplicating it
295 * for the current Job.
297 for (d=msg->dest_chain; d; d=d->next) {
298 dnew = (DEST *)malloc(sizeof(DEST));
299 memcpy(dnew, d, sizeof(DEST));
300 dnew->next = temp_chain;
302 dnew->mail_filename = NULL;
304 dnew->mail_cmd = bstrdup(d->mail_cmd);
307 dnew->where = bstrdup(d->where);
313 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
314 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
315 jcr->jcr_msgs->dest_chain = temp_chain;
316 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
318 /* If we have default values, release them now */
320 free_msgs_res(daemon_msgs);
322 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
323 memset(daemon_msgs, 0, sizeof(MSGS));
324 daemon_msgs->dest_chain = temp_chain;
325 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
328 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
332 /* Initialize so that the console (User Agent) can
333 * receive messages -- stored in a file.
335 void init_console_msg(const char *wd)
339 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
340 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
343 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
344 con_fname, be.bstrerror());
346 if (lseek(fd, 0, SEEK_END) > 0) {
347 console_msg_pending = 1;
350 con_fd = fopen(con_fname, "a+b");
353 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
354 con_fname, be.bstrerror());
356 if (rwl_init(&con_lock) != 0) {
358 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
364 * Called only during parsing of the config file.
366 * Add a message destination. I.e. associate a message type with
367 * a destination (code).
368 * Note, where in the case of dest_code FILE is a filename,
369 * but in the case of MAIL is a space separated list of
370 * email addresses, ...
372 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
376 * First search the existing chain and see if we
377 * can simply add this msg_type to an existing entry.
379 for (d=msg->dest_chain; d; d=d->next) {
380 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
381 (strcmp(where, d->where) == 0))) {
382 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
383 d, msg_type, dest_code, NPRT(where));
384 set_bit(msg_type, d->msg_types);
385 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
389 /* Not found, create a new entry */
390 d = (DEST *)malloc(sizeof(DEST));
391 memset(d, 0, sizeof(DEST));
392 d->next = msg->dest_chain;
393 d->dest_code = dest_code;
394 set_bit(msg_type, d->msg_types); /* set type bit in structure */
395 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
397 d->where = bstrdup(where);
400 d->mail_cmd = bstrdup(mail_cmd);
402 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
403 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
408 * Called only during parsing of the config file.
410 * Remove a message destination
412 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
416 for (d=msg->dest_chain; d; d=d->next) {
417 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
418 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
419 ((where == NULL && d->where == NULL) ||
420 (strcmp(where, d->where) == 0))) {
421 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
422 d, msg_type, dest_code);
423 clear_bit(msg_type, d->msg_types);
424 Dmsg0(850, "Return rem_msg_dest\n");
432 * Create a unique filename for the mail command
434 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
437 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
438 jcr->Job, (int)(intptr_t)d);
440 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
441 my_name, (int)(intptr_t)d);
443 Dmsg1(850, "mailname=%s\n", name);
449 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
454 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
456 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
460 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
461 /* If we had to use sendmail, add subject */
463 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
467 delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
468 cmd, be.bstrerror());
474 * Close the messages for this Messages resource, which means to close
475 * any open files, and dispatch any pending email messages.
477 void close_msg(JCR *jcr)
485 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
487 if (jcr == NULL) { /* NULL -> global chain */
490 msgs = jcr->jcr_msgs;
491 jcr->jcr_msgs = NULL;
497 /* Wait for item to be not in use, then mark closing */
498 if (msgs->is_closing()) {
501 msgs->wait_not_in_use(); /* leaves fides_mutex set */
505 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
506 cmd = get_pool_memory(PM_MESSAGE);
507 for (d=msgs->dest_chain; d; ) {
509 switch (d->dest_code) {
513 fclose(d->fd); /* close open file descriptor */
518 case MD_MAIL_ON_ERROR:
519 case MD_MAIL_ON_SUCCESS:
520 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
525 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
526 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
528 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
529 jcr->JobStatus == JS_ErrorTerminated)
534 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
535 Pmsg0(000, _("open mail pipe failed.\n"));
538 Dmsg0(850, "Opened mail pipe\n");
540 line = get_memory(len);
542 while (fgets(line, len, d->fd)) {
543 fputs(line, bpipe->wfd);
545 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
547 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
551 * Since we are closing all messages, before "recursing"
552 * make sure we are not closing the daemon messages, otherwise
555 if (msgs != daemon_msgs) {
556 /* read what mail prog returned -- should be nothing */
557 while (fgets(line, len, bpipe->rfd)) {
558 delivery_error(_("Mail prog: %s"), line);
562 stat = close_bpipe(bpipe);
563 if (stat != 0 && msgs != daemon_msgs) {
566 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
567 delivery_error(_("Mail program terminated in error.\n"
569 "ERR=%s\n"), cmd, be.bstrerror());
573 /* Remove temp file */
576 unlink(d->mail_filename);
577 free_pool_memory(d->mail_filename);
578 d->mail_filename = NULL;
579 Dmsg0(850, "end mail or mail on error\n");
586 d = d->next; /* point to next buffer */
588 free_pool_memory(cmd);
589 Dmsg0(850, "Done walking message chain.\n");
594 msgs->clear_closing();
596 Dmsg0(850, "===End close msg resource\n");
600 * Free memory associated with Messages resource
602 void free_msgs_res(MSGS *msgs)
606 /* Walk down the message chain releasing allocated buffers */
607 for (d=msgs->dest_chain; d; ) {
614 old = d; /* save pointer to release */
615 d = d->next; /* point to next buffer */
616 free(old); /* free the destination item */
618 msgs->dest_chain = NULL;
619 free(msgs); /* free the head */
624 * Terminate the message handler for good.
625 * Release the global destination chain.
627 * Also, clean up a few other items (cons, exepath). Note,
628 * these really should be done elsewhere.
632 Dmsg0(850, "Enter term_msg\n");
633 close_msg(NULL); /* close global chain */
634 free_msgs_res(daemon_msgs); /* free the resources */
657 term_last_jobs_list();
660 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
662 d->fd = fopen(d->where, mode);
665 delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
672 * Handle sending the message to the appropriate place
674 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
677 char dt[MAX_TIME_LENGTH];
684 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
687 * Most messages are prefixed by a date and time. If mtime is
688 * zero, then we use the current time. If mtime is 1 (special
689 * kludge), we do not prefix the date and time. Otherwise,
690 * we assume mtime is a utime_t and use it.
698 mtime = time(NULL); /* get time for SQL log */
700 bstrftime_ny(dt, sizeof(dt), mtime);
706 /* If the program registered a callback, send it there */
707 if (message_callback) {
708 message_callback(type, msg);
712 /* For serious errors make sure message is printed or logged */
713 if (type == M_ABORT || type == M_ERROR_TERM) {
717 if (type == M_ABORT) {
718 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
723 /* Now figure out where to send the message */
726 jcr = get_jcr_from_tsd();
729 msgs = jcr->jcr_msgs;
735 * If closing this message resource, print and send to syslog,
738 if (msgs->is_closing()) {
742 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
746 for (d=msgs->dest_chain; d; d=d->next) {
747 if (bit_is_set(type, d->msg_types)) {
748 switch (d->dest_code) {
751 if (!jcr || !jcr->db) {
754 if (p_sql_query && p_sql_escape) {
755 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
756 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
758 int len = strlen(msg) + 1;
759 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
760 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
762 bstrutime(dt, sizeof(dt), mtime);
763 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
764 edit_int64(jcr->JobId, ed1), dt, esc_msg);
765 p_sql_query(jcr, cmd);
767 free_pool_memory(cmd);
768 free_pool_memory(esc_msg);
772 Dmsg1(850, "CONSOLE for following msg: %s", msg);
774 con_fd = fopen(con_fname, "a+b");
775 Dmsg0(850, "Console file not open.\n");
778 Pw(con_lock); /* get write lock on console message file */
781 (void)fwrite(dt, dtlen, 1, con_fd);
785 (void)fwrite(msg, len, 1, con_fd);
786 if (msg[len-1] != '\n') {
787 (void)fwrite("\n", 2, 1, con_fd);
790 (void)fwrite("\n", 2, 1, con_fd);
793 console_msg_pending = true;
798 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
800 * We really should do an openlog() here.
802 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
805 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
806 mcmd = get_pool_memory(PM_MESSAGE);
807 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
809 fputs(dt, bpipe->wfd);
810 fputs(msg, bpipe->wfd);
811 /* Messages to the operator go one at a time */
812 stat = close_bpipe(bpipe);
816 delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
818 "ERR=%s\n"), mcmd, be.bstrerror());
821 free_pool_memory(mcmd);
824 case MD_MAIL_ON_ERROR:
825 case MD_MAIL_ON_SUCCESS:
826 Dmsg1(850, "MAIL for following msg: %s", msg);
827 if (msgs->is_closing()) {
832 POOLMEM *name = get_pool_memory(PM_MESSAGE);
833 make_unique_mail_filename(jcr, name, d);
834 d->fd = fopen(name, "w+b");
837 delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
839 free_pool_memory(name);
843 d->mail_filename = name;
846 len = strlen(msg) + dtlen;;
847 if (len > d->max_len) {
848 d->max_len = len; /* keep max line length */
851 msgs->clear_in_use();
854 Dmsg1(850, "APPEND for following msg: %s", msg);
858 Dmsg1(850, "FILE for following msg: %s", msg);
861 if (msgs->is_closing()) {
865 if (!d->fd && !open_dest_file(jcr, d, mode)) {
866 msgs->clear_in_use();
871 /* On error, we close and reopen to handle log rotation */
875 if (open_dest_file(jcr, d, mode)) {
880 msgs->clear_in_use();
883 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
884 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
885 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
886 jcr->Job, type, mtime, msg);
888 Dmsg1(800, "no jcr for following msg: %s", msg);
892 Dmsg1(850, "STDOUT for following msg: %s", msg);
893 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
900 Dmsg1(850, "STDERR for following msg: %s", msg);
912 /*********************************************************************
914 * This subroutine returns the filename portion of a Windows
915 * path. It is used because Microsoft Visual Studio sets __FILE__
920 get_basename(const char *pathname)
922 #if defined(_MSC_VER)
923 const char *basename;
925 if ((basename = strrchr(pathname, '\\')) == NULL) {
938 * print or write output to trace file
940 static void pt_out(char *buf)
943 * Used the "trace on" command in the console to turn on
944 * output to the trace file. "trace off" will close the file.
949 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
950 trace_fd = fopen(fn, "a+b");
953 fputs(buf, trace_fd);
956 /* Some problem, turn off tracing */
959 } else { /* not tracing */
965 /*********************************************************************
967 * This subroutine prints a debug message if the level number
968 * is less than or equal the debug_level. File and line numbers
969 * are included for more detail if desired, but not currently
972 * If the level is negative, the details of file and line number
976 d_msg(const char *file, int line, int level, const char *fmt,...)
989 if (level <= debug_level) {
992 bstrftimes(buf, sizeof(buf), mtime);
1001 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
1002 my_name, get_basename(file), line, get_jobid_from_tsd());
1009 va_start(arg_ptr, fmt);
1010 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1018 * Set trace flag on/off. If argument is negative, there is no change
1020 void set_trace(int trace_flag)
1022 if (trace_flag < 0) {
1024 } else if (trace_flag > 0) {
1029 if (!trace && trace_fd) {
1030 FILE *ltrace_fd = trace_fd;
1032 bmicrosleep(0, 100000); /* yield to prevent seg faults */
1037 bool get_trace(void)
1042 /*********************************************************************
1044 * This subroutine prints a message regardless of the debug level
1046 * If the level is negative, the details of file and line number
1050 p_msg(const char *file, int line, int level, const char *fmt,...)
1056 #ifdef FULL_LOCATION
1058 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1065 va_start(arg_ptr, fmt);
1066 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1073 /*********************************************************************
1075 * subroutine writes a debug message to the trace file if the level number
1076 * is less than or equal the debug_level. File and line numbers
1077 * are included for more detail if desired, but not currently
1080 * If the level is negative, the details of file and line number
1084 t_msg(const char *file, int line, int level, const char *fmt,...)
1096 if (level <= debug_level) {
1098 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1099 trace_fd = fopen(buf, "a+b");
1102 #ifdef FULL_LOCATION
1104 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1111 va_start(arg_ptr, fmt);
1112 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1114 if (trace_fd != NULL) {
1115 fputs(buf, trace_fd);
1121 /* *********************************************************
1123 * print an error message
1127 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1134 * Check if we have a message destination defined.
1135 * We always report M_ABORT and M_ERROR_TERM
1137 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1138 !bit_is_set(type, daemon_msgs->send_msg))) {
1139 return; /* no destination */
1143 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1144 my_name, get_basename(file), line);
1147 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1148 my_name, get_basename(file), line);
1151 if (level == -1) /* skip details */
1152 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1154 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1157 if (level == -1) /* skip details */
1158 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1160 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1163 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1166 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1169 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1173 va_start(arg_ptr, fmt);
1174 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1177 dispatch_message(NULL, type, 0, buf);
1179 if (type == M_ABORT) {
1181 p[0] = 0; /* generate segmentation violation */
1183 if (type == M_ERROR_TERM) {
1188 /* *********************************************************
1190 * Generate a Job message
1194 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1203 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1205 /* Special case for the console, which has a dir_bsock and JobId==0,
1206 * in that case, we send the message directly back to the
1209 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1210 BSOCK *dir = jcr->dir_bsock;
1211 va_start(arg_ptr, fmt);
1212 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1215 jcr->dir_bsock->send();
1219 /* The watchdog thread can't use Jmsg directly, we always queued it */
1220 if (is_watchdog()) {
1221 va_start(arg_ptr, fmt);
1222 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1224 Qmsg(jcr, type, mtime, "%s", rbuf);
1230 jcr = get_jcr_from_tsd();
1233 if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1234 /* Dequeue messages to keep the original order */
1235 dequeue_messages(jcr);
1237 msgs = jcr->jcr_msgs;
1241 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1245 * Check if we have a message destination defined.
1246 * We always report M_ABORT and M_ERROR_TERM
1248 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1249 !bit_is_set(type, msgs->send_msg)) {
1250 return; /* no destination */
1254 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1257 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1260 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1262 set_jcr_job_status(jcr, JS_FatalError);
1266 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1272 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1278 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1282 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1286 va_start(arg_ptr, fmt);
1287 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1290 dispatch_message(jcr, type, mtime, rbuf);
1292 if (type == M_ABORT){
1294 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1295 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1296 p[0] = 0; /* generate segmentation violation */
1298 if (type == M_ERROR_TERM) {
1304 * If we come here, prefix the message with the file:line-number,
1305 * then pass it on to the normal Jmsg routine.
1307 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1313 pool_buf = get_pool_memory(PM_EMSG);
1314 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1317 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1318 va_start(arg_ptr, fmt);
1319 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1321 if (len < 0 || len >= (maxlen-5)) {
1322 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1328 Jmsg(jcr, type, mtime, "%s", pool_buf);
1329 free_memory(pool_buf);
1334 * Edit a message into a Pool memory buffer, with file:lineno
1336 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1341 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1344 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1345 va_start(arg_ptr, fmt);
1346 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1348 if (len < 0 || len >= (maxlen-5)) {
1349 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1357 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1362 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1365 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1366 va_start(arg_ptr, fmt);
1367 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1369 if (len < 0 || len >= (maxlen-5)) {
1370 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1380 * Edit a message into a Pool Memory buffer NO file:lineno
1381 * Returns: string length of what was edited.
1383 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1389 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1390 va_start(arg_ptr, fmt);
1391 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1393 if (len < 0 || len >= (maxlen-5)) {
1394 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1402 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1408 maxlen = sizeof_pool_memory(pool_buf) - 1;
1409 va_start(arg_ptr, fmt);
1410 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1412 if (len < 0 || len >= (maxlen-5)) {
1413 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1421 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1427 maxlen = pool_buf.max_size() - 1;
1428 va_start(arg_ptr, fmt);
1429 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1431 if (len < 0 || len >= (maxlen-5)) {
1432 pool_buf.realloc_pm(maxlen + maxlen/2);
1442 * We queue messages rather than print them directly. This
1443 * is generally used in low level routines (msg handler, bnet)
1444 * to prevent recursion (i.e. if you are in the middle of
1445 * sending a message, it is a bit messy to recursively call
1446 * yourself when the bnet packet is not reentrant).
1448 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1455 pool_buf = get_pool_memory(PM_EMSG);
1458 maxlen = sizeof_pool_memory(pool_buf) - 1;
1459 va_start(arg_ptr, fmt);
1460 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1462 if (len < 0 || len >= (maxlen-5)) {
1463 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1468 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1470 item->mtime = time(NULL);
1471 strcpy(item->msg, pool_buf);
1473 jcr = get_jcr_from_tsd();
1475 /* If no jcr or no queue or dequeuing send to syslog */
1476 if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1477 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1480 /* Queue message for later sending */
1481 P(jcr->msg_queue_mutex);
1482 jcr->msg_queue->append(item);
1483 V(jcr->msg_queue_mutex);
1485 free_memory(pool_buf);
1491 void dequeue_messages(JCR *jcr)
1494 if (!jcr->msg_queue) {
1497 P(jcr->msg_queue_mutex);
1498 jcr->dequeuing_msgs = true;
1499 foreach_dlist(item, jcr->msg_queue) {
1500 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1502 /* Remove messages just sent */
1503 jcr->msg_queue->destroy();
1504 jcr->dequeuing_msgs = false;
1505 V(jcr->msg_queue_mutex);
1510 * If we come here, prefix the message with the file:line-number,
1511 * then pass it on to the normal Qmsg routine.
1513 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1519 pool_buf = get_pool_memory(PM_EMSG);
1520 i = Mmsg(pool_buf, "%s:%d ", file, line);
1523 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1524 va_start(arg_ptr, fmt);
1525 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1527 if (len < 0 || len >= (maxlen-5)) {
1528 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1534 Qmsg(jcr, type, mtime, "%s", pool_buf);
1535 free_memory(pool_buf);