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 const char *assert_msg = (char *)NULL; /* ASSERT2 error message */
54 int verbose = 0; /* increase User messages */
55 int debug_level = 0; /* debug level */
56 bool dbg_timestamp = false; /* print timestamp in debug output */
57 bool prt_kaboom = false; /* Print kaboom output */
58 utime_t daemon_start_time = 0; /* Daemon start time */
59 const char *version = VERSION " (" BDATE ")";
60 const char *dist_name = DISTNAME " " DISTVER;
62 char my_name[30] = {0}; /* daemon name is stored here */
63 char host_name[50] = {0}; /* host machine name */
64 char *exepath = (char *)NULL;
65 char *exename = (char *)NULL;
66 int console_msg_pending = false;
67 char con_fname[500]; /* Console filename */
68 FILE *con_fd = NULL; /* Console file descriptor */
69 brwlock_t con_lock; /* Console lock structure */
71 /* Forward referenced functions */
73 /* Imported functions */
74 void create_jcr_key();
78 /* Exclude spaces but require .mail at end */
79 #define MAIL_REGEX "^[^ ]+\\.mail$"
81 /* Allow only one thread to tweak d->fd at a time */
82 static pthread_mutex_t fides_mutex = PTHREAD_MUTEX_INITIALIZER;
83 static MSGS *daemon_msgs; /* global messages */
84 static char *catalog_db = NULL; /* database type */
85 static void (*message_callback)(int type, char *msg) = NULL;
86 static FILE *trace_fd = NULL;
87 #if defined(HAVE_WIN32)
88 static bool trace = true;
90 static bool trace = false;
92 static int hangup = 0;
95 const char *host_os = HOST_OS;
96 const char *distname = DISTNAME;
97 const char *distver = DISTVER;
100 * Walk back in a string from end looking for a
102 * This routine is passed the start of the string and
103 * the end of the string, it returns either the beginning
104 * of the string or where it found a path separator.
106 static const char *bstrrpath(const char *start, const char *end)
108 while ( end > start ) {
110 if (IsPathSeparator(*end)) {
117 /* Some message class methods */
129 * Wait for not in use variable to be clear
131 void MSGS::wait_not_in_use() /* leaves fides_mutex set */
134 while (m_in_use || m_closing) {
136 bmicrosleep(0, 200); /* wait */
142 * Handle message delivery errors
144 static void delivery_error(const char *fmt,...)
149 char dt[MAX_TIME_LENGTH];
152 pool_buf = get_pool_memory(PM_EMSG);
154 bstrftime_ny(dt, sizeof(dt), time(NULL));
159 i = Mmsg(pool_buf, "%s Message delivery ERROR: ", dt);
162 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
163 va_start(arg_ptr, fmt);
164 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
166 if (len < 0 || len >= (maxlen-5)) {
167 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
173 fputs(pool_buf, stdout); /* print this here to INSURE that it is printed */
175 syslog(LOG_DAEMON|LOG_ERR, "%s", pool_buf);
176 free_memory(pool_buf);
179 void register_message_callback(void msg_callback(int type, char *msg))
181 message_callback = msg_callback;
186 * Set daemon name. Also, find canonical execution
187 * path. Note, exepath has spare room for tacking on
188 * the exename so that we can reconstruct the full name.
190 * Note, this routine can get called multiple times
191 * The second time is to put the name as found in the
192 * Resource record. On the second call, generally,
193 * argv is NULL to avoid doing the path code twice.
195 void my_name_is(int argc, char *argv[], const char *name)
201 if (gethostname(host_name, sizeof(host_name)) != 0) {
202 bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
204 bstrncpy(my_name, name, sizeof(my_name));
205 if (argc>0 && argv && argv[0]) {
206 /* strip trailing filename and save exepath */
207 for (l=p=argv[0]; *p; p++) {
208 if (IsPathSeparator(*p)) {
209 l = p; /* set pos of last slash */
212 if (IsPathSeparator(*l)) {
216 #if defined(HAVE_WIN32)
217 /* On Windows allow c: drive specification */
227 exename = (char *)malloc(len);
233 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
234 for (p=argv[0],q=exepath; p < l; ) {
238 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
239 if (getcwd(cpath, sizeof(cpath))) {
241 exepath = (char *)malloc(strlen(cpath) + 1 + len);
242 strcpy(exepath, cpath);
245 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
250 set_db_type(const char *name)
252 if (catalog_db != NULL) {
255 catalog_db = bstrdup(name);
259 * Initialize message handler for a daemon or a Job
260 * We make a copy of the MSGS resource passed, so it belows
261 * to the job or daemon and thus can be modified.
263 * NULL for jcr -> initialize global messages for daemon
264 * non-NULL -> initialize jcr using Message resource
267 init_msg(JCR *jcr, MSGS *msg)
269 DEST *d, *dnew, *temp_chain = NULL;
272 if (jcr == NULL && msg == NULL) {
273 init_last_jobs_list();
274 /* Create a daemon key then set invalid jcr */
275 /* Maybe we should give the daemon a jcr??? */
277 set_jcr_in_tsd(INVALID_JCR);
280 #if !defined(HAVE_WIN32)
282 * Make sure we have fd's 0, 1, 2 open
283 * If we don't do this one of our sockets may open
284 * there and if we then use stdout, it could
285 * send total garbage to our socket.
289 fd = open("/dev/null", O_RDONLY, 0644);
293 for(i=1; fd + i <= 2; i++) {
300 * If msg is NULL, initialize global chain for STDOUT and syslog
303 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
304 memset(daemon_msgs, 0, sizeof(MSGS));
305 for (i=1; i<=M_MAX; i++) {
306 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
308 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
313 * Walk down the message resource chain duplicating it
314 * for the current Job.
316 for (d=msg->dest_chain; d; d=d->next) {
317 dnew = (DEST *)malloc(sizeof(DEST));
318 memcpy(dnew, d, sizeof(DEST));
319 dnew->next = temp_chain;
321 dnew->mail_filename = NULL;
323 dnew->mail_cmd = bstrdup(d->mail_cmd);
326 dnew->where = bstrdup(d->where);
332 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
333 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
334 jcr->jcr_msgs->dest_chain = temp_chain;
335 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
337 /* If we have default values, release them now */
339 free_msgs_res(daemon_msgs);
341 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
342 memset(daemon_msgs, 0, sizeof(MSGS));
343 daemon_msgs->dest_chain = temp_chain;
344 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
347 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
351 /* Initialize so that the console (User Agent) can
352 * receive messages -- stored in a file.
354 void init_console_msg(const char *wd)
358 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
359 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
362 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
363 con_fname, be.bstrerror());
365 if (lseek(fd, 0, SEEK_END) > 0) {
366 console_msg_pending = 1;
369 con_fd = fopen(con_fname, "a+b");
372 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
373 con_fname, be.bstrerror());
375 if (rwl_init(&con_lock) != 0) {
377 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
383 * Called only during parsing of the config file.
385 * Add a message destination. I.e. associate a message type with
386 * a destination (code).
387 * Note, where in the case of dest_code FILE is a filename,
388 * but in the case of MAIL is a space separated list of
389 * email addresses, ...
391 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
395 * First search the existing chain and see if we
396 * can simply add this msg_type to an existing entry.
398 for (d=msg->dest_chain; d; d=d->next) {
399 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
400 (strcmp(where, d->where) == 0))) {
401 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
402 d, msg_type, dest_code, NPRT(where));
403 set_bit(msg_type, d->msg_types);
404 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
408 /* Not found, create a new entry */
409 d = (DEST *)malloc(sizeof(DEST));
410 memset(d, 0, sizeof(DEST));
411 d->next = msg->dest_chain;
412 d->dest_code = dest_code;
413 set_bit(msg_type, d->msg_types); /* set type bit in structure */
414 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
416 d->where = bstrdup(where);
419 d->mail_cmd = bstrdup(mail_cmd);
421 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
422 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
427 * Called only during parsing of the config file.
429 * Remove a message destination
431 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
435 for (d=msg->dest_chain; d; d=d->next) {
436 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
437 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
438 ((where == NULL && d->where == NULL) ||
439 (strcmp(where, d->where) == 0))) {
440 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
441 d, msg_type, dest_code);
442 clear_bit(msg_type, d->msg_types);
443 Dmsg0(850, "Return rem_msg_dest\n");
451 * Create a unique filename for the mail command
453 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
456 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
457 jcr->Job, (int)(intptr_t)d);
459 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
460 my_name, (int)(intptr_t)d);
462 Dmsg1(850, "mailname=%s\n", name);
468 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
473 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
475 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
479 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
480 /* If we had to use sendmail, add subject */
482 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
486 delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
487 cmd, be.bstrerror());
493 * Close the messages for this Messages resource, which means to close
494 * any open files, and dispatch any pending email messages.
496 void close_msg(JCR *jcr)
504 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
506 if (jcr == NULL) { /* NULL -> global chain */
509 msgs = jcr->jcr_msgs;
510 jcr->jcr_msgs = NULL;
516 /* Wait for item to be not in use, then mark closing */
517 if (msgs->is_closing()) {
520 msgs->wait_not_in_use(); /* leaves fides_mutex set */
521 /* Note get_closing() does not lock because we are already locked */
522 if (msgs->get_closing()) {
529 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
530 cmd = get_pool_memory(PM_MESSAGE);
531 for (d=msgs->dest_chain; d; ) {
533 switch (d->dest_code) {
537 fclose(d->fd); /* close open file descriptor */
542 case MD_MAIL_ON_ERROR:
543 case MD_MAIL_ON_SUCCESS:
544 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
549 switch (d->dest_code) {
550 case MD_MAIL_ON_ERROR:
552 switch (jcr->JobStatus) {
561 case MD_MAIL_ON_SUCCESS:
563 switch (jcr->JobStatus) {
576 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
577 Pmsg0(000, _("open mail pipe failed.\n"));
581 Dmsg0(850, "Opened mail pipe\n");
583 line = get_memory(len);
585 while (fgets(line, len, d->fd)) {
586 fputs(line, bpipe->wfd);
588 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
590 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
594 * Since we are closing all messages, before "recursing"
595 * make sure we are not closing the daemon messages, otherwise
598 if (msgs != daemon_msgs) {
599 /* read what mail prog returned -- should be nothing */
600 while (fgets(line, len, bpipe->rfd)) {
601 delivery_error(_("Mail prog: %s"), line);
605 stat = close_bpipe(bpipe);
606 if (stat != 0 && msgs != daemon_msgs) {
609 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
610 delivery_error(_("Mail program terminated in error.\n"
612 "ERR=%s\n"), cmd, be.bstrerror());
616 /* Remove temp file */
621 if (d->mail_filename) {
622 /* Exclude spaces in mail_filename */
623 safer_unlink(d->mail_filename, MAIL_REGEX);
624 free_pool_memory(d->mail_filename);
625 d->mail_filename = NULL;
627 Dmsg0(850, "end mail or mail on error\n");
634 d = d->next; /* point to next buffer */
636 free_pool_memory(cmd);
637 Dmsg0(850, "Done walking message chain.\n");
642 msgs->clear_closing();
644 Dmsg0(850, "===End close msg resource\n");
648 * Free memory associated with Messages resource
650 void free_msgs_res(MSGS *msgs)
654 /* Walk down the message chain releasing allocated buffers */
655 for (d=msgs->dest_chain; d; ) {
662 old = d; /* save pointer to release */
663 d = d->next; /* point to next buffer */
664 free(old); /* free the destination item */
666 msgs->dest_chain = NULL;
667 free(msgs); /* free the head */
672 * Terminate the message handler for good.
673 * Release the global destination chain.
675 * Also, clean up a few other items (cons, exepath). Note,
676 * these really should be done elsewhere.
680 Dmsg0(850, "Enter term_msg\n");
681 close_msg(NULL); /* close global chain */
682 free_msgs_res(daemon_msgs); /* free the resources */
705 term_last_jobs_list();
708 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
710 d->fd = fopen(d->where, mode);
713 delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
719 /* Split the output for syslog (it converts \n to ' ' and is
720 * limited to 1024 characters per syslog message
722 static void send_to_syslog(int mode, const char *msg)
729 while (*p && ((p2 = strchr(p, '\n')) != NULL)) {
730 len = MIN((int)sizeof(buf) - 1, p2 - p + 1); /* Add 1 to keep \n */
731 strncpy(buf, p, len);
733 syslog(mode, "%s", buf);
734 p = p2+1; /* skip \n */
736 if (*p != 0) { /* no \n at the end ? */
737 syslog(mode, "%s", p);
742 * Handle sending the message to the appropriate place
744 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
747 char dt[MAX_TIME_LENGTH];
754 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
757 * Most messages are prefixed by a date and time. If mtime is
758 * zero, then we use the current time. If mtime is 1 (special
759 * kludge), we do not prefix the date and time. Otherwise,
760 * we assume mtime is a utime_t and use it.
768 mtime = time(NULL); /* get time for SQL log */
770 bstrftime_ny(dt, sizeof(dt), mtime);
776 /* If the program registered a callback, send it there */
777 if (message_callback) {
778 message_callback(type, msg);
782 /* For serious errors make sure message is printed or logged */
783 if (type == M_ABORT || type == M_ERROR_TERM) {
787 if (type == M_ABORT) {
788 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
793 /* Now figure out where to send the message */
796 jcr = get_jcr_from_tsd();
799 msgs = jcr->jcr_msgs;
805 * If closing this message resource, print and send to syslog,
808 if (msgs->is_closing()) {
812 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
816 for (d=msgs->dest_chain; d; d=d->next) {
817 if (bit_is_set(type, d->msg_types)) {
818 switch (d->dest_code) {
821 if (!jcr || !jcr->db) {
824 if (p_sql_query && p_sql_escape) {
825 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
826 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
828 int len = strlen(msg) + 1;
829 esc_msg = check_pool_memory_size(esc_msg, len * 2 + 1);
830 if (p_sql_escape(jcr, jcr->db, esc_msg, msg, len)) {
831 bstrutime(dt, sizeof(dt), mtime);
832 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
833 edit_int64(jcr->JobId, ed1), dt, esc_msg);
834 if (!p_sql_query(jcr, cmd)) {
835 delivery_error(_("Msg delivery error: Unable to store data in database.\n"));
838 delivery_error(_("Msg delivery error: Unable to store data in database.\n"));
841 free_pool_memory(cmd);
842 free_pool_memory(esc_msg);
846 Dmsg1(850, "CONSOLE for following msg: %s", msg);
848 con_fd = fopen(con_fname, "a+b");
849 Dmsg0(850, "Console file not open.\n");
852 Pw(con_lock); /* get write lock on console message file */
855 (void)fwrite(dt, dtlen, 1, con_fd);
859 (void)fwrite(msg, len, 1, con_fd);
860 if (msg[len-1] != '\n') {
861 (void)fwrite("\n", 2, 1, con_fd);
864 (void)fwrite("\n", 2, 1, con_fd);
867 console_msg_pending = true;
872 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
874 * We really should do an openlog() here.
876 send_to_syslog(LOG_DAEMON|LOG_ERR, msg);
879 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
880 mcmd = get_pool_memory(PM_MESSAGE);
881 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
883 fputs(dt, bpipe->wfd);
884 fputs(msg, bpipe->wfd);
885 /* Messages to the operator go one at a time */
886 stat = close_bpipe(bpipe);
890 delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
892 "ERR=%s\n"), mcmd, be.bstrerror());
895 free_pool_memory(mcmd);
898 case MD_MAIL_ON_ERROR:
899 case MD_MAIL_ON_SUCCESS:
900 Dmsg1(850, "MAIL for following msg: %s", msg);
901 if (msgs->is_closing()) {
906 POOLMEM *name = get_pool_memory(PM_MESSAGE);
907 make_unique_mail_filename(jcr, name, d);
908 d->fd = fopen(name, "w+b");
911 delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
913 free_pool_memory(name);
914 msgs->clear_in_use();
917 d->mail_filename = name;
920 len = strlen(msg) + dtlen;;
921 if (len > d->max_len) {
922 d->max_len = len; /* keep max line length */
925 msgs->clear_in_use();
928 Dmsg1(850, "APPEND for following msg: %s", msg);
932 Dmsg1(850, "FILE for following msg: %s", msg);
935 if (msgs->is_closing()) {
939 if (!d->fd && !open_dest_file(jcr, d, mode)) {
940 msgs->clear_in_use();
945 /* On error, we close and reopen to handle log rotation */
949 if (open_dest_file(jcr, d, mode)) {
954 msgs->clear_in_use();
957 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
958 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
959 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
960 jcr->Job, type, mtime, msg);
962 Dmsg1(800, "no jcr for following msg: %s", msg);
966 Dmsg1(850, "STDOUT for following msg: %s", msg);
967 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
974 Dmsg1(850, "STDERR for following msg: %s", msg);
986 /*********************************************************************
988 * This subroutine returns the filename portion of a path.
989 * It is used because some compilers set __FILE__
990 * to the full path. Try to return base + next higher path.
993 const char *get_basename(const char *pathname)
995 const char *basename;
997 if ((basename = bstrrpath(pathname, pathname+strlen(pathname))) == pathname) {
999 } else if ((basename = bstrrpath(pathname, basename-1)) == pathname) {
1008 * print or write output to trace file
1010 static void pt_out(char *buf)
1013 * Used the "trace on" command in the console to turn on
1014 * output to the trace file. "trace off" will close the file.
1019 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
1020 trace_fd = fopen(fn, "a+b");
1023 fputs(buf, trace_fd);
1027 /* Some problem, turn off tracing */
1036 /*********************************************************************
1038 * This subroutine prints a debug message if the level number
1039 * is less than or equal the debug_level. File and line numbers
1040 * are included for more detail if desired, but not currently
1043 * If the level is negative, the details of file and line number
1047 d_msg(const char *file, int line, int level, const char *fmt,...)
1052 bool details = true;
1060 if (level <= debug_level) {
1061 if (dbg_timestamp) {
1063 bstrftimes(buf, sizeof(buf), mtime);
1070 #ifdef FULL_LOCATION
1072 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
1073 my_name, get_basename(file), line, get_jobid_from_tsd());
1080 va_start(arg_ptr, fmt);
1081 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1089 * Set trace flag on/off. If argument is negative, there is no change
1091 void set_trace(int trace_flag)
1093 if (trace_flag < 0) {
1095 } else if (trace_flag > 0) {
1100 if (!trace && trace_fd) {
1101 FILE *ltrace_fd = trace_fd;
1103 bmicrosleep(0, 100000); /* yield to prevent seg faults */
1108 void set_hangup(int hangup_value)
1110 if (hangup_value < 0) {
1113 hangup = hangup_value;
1117 int get_hangup(void)
1122 bool get_trace(void)
1127 /*********************************************************************
1129 * This subroutine prints a message regardless of the debug level
1131 * If the level is negative, the details of file and line number
1135 p_msg(const char *file, int line, int level, const char *fmt,...)
1141 #ifdef FULL_LOCATION
1143 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
1144 my_name, get_basename(file), line, get_jobid_from_tsd());
1152 va_start(arg_ptr, fmt);
1153 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1160 /*********************************************************************
1162 * subroutine writes a debug message to the trace file if the level number
1163 * is less than or equal the debug_level. File and line numbers
1164 * are included for more detail if desired, but not currently
1167 * If the level is negative, the details of file and line number
1171 t_msg(const char *file, int line, int level, const char *fmt,...)
1183 if (level <= debug_level) {
1185 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1186 trace_fd = fopen(buf, "a+b");
1189 #ifdef FULL_LOCATION
1191 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1198 va_start(arg_ptr, fmt);
1199 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1201 if (trace_fd != NULL) {
1202 fputs(buf, trace_fd);
1208 /* *********************************************************
1210 * print an error message
1214 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1221 * Check if we have a message destination defined.
1222 * We always report M_ABORT and M_ERROR_TERM
1224 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1225 !bit_is_set(type, daemon_msgs->send_msg))) {
1226 return; /* no destination */
1230 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1231 my_name, get_basename(file), line);
1234 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1235 my_name, get_basename(file), line);
1238 if (level == -1) /* skip details */
1239 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1241 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1244 if (level == -1) /* skip details */
1245 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1247 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1250 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1253 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1256 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1260 va_start(arg_ptr, fmt);
1261 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1264 dispatch_message(NULL, type, 0, buf);
1266 if (type == M_ABORT) {
1268 p[0] = 0; /* generate segmentation violation */
1270 if (type == M_ERROR_TERM) {
1275 /* *********************************************************
1277 * Generate a Job message
1281 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1290 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1292 /* Special case for the console, which has a dir_bsock and JobId==0,
1293 * in that case, we send the message directly back to the
1296 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1297 BSOCK *dir = jcr->dir_bsock;
1298 va_start(arg_ptr, fmt);
1299 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1302 jcr->dir_bsock->send();
1306 /* The watchdog thread can't use Jmsg directly, we always queued it */
1307 if (is_watchdog()) {
1308 va_start(arg_ptr, fmt);
1309 bvsnprintf(rbuf, sizeof(rbuf), fmt, arg_ptr);
1311 Qmsg(jcr, type, mtime, "%s", rbuf);
1317 jcr = get_jcr_from_tsd();
1320 if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1321 /* Dequeue messages to keep the original order */
1322 dequeue_messages(jcr);
1324 msgs = jcr->jcr_msgs;
1328 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1332 * Check if we have a message destination defined.
1333 * We always report M_ABORT and M_ERROR_TERM
1335 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1336 !bit_is_set(type, msgs->send_msg)) {
1337 return; /* no destination */
1341 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1344 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1347 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1349 jcr->setJobStatus(JS_FatalError);
1351 if (jcr && jcr->JobErrors == 0) {
1356 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1362 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1368 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1372 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1376 va_start(arg_ptr, fmt);
1377 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1380 dispatch_message(jcr, type, mtime, rbuf);
1382 if (type == M_ABORT){
1384 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1385 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1386 p[0] = 0; /* generate segmentation violation */
1388 if (type == M_ERROR_TERM) {
1394 * If we come here, prefix the message with the file:line-number,
1395 * then pass it on to the normal Jmsg routine.
1397 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1403 pool_buf = get_pool_memory(PM_EMSG);
1404 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1407 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1408 va_start(arg_ptr, fmt);
1409 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1411 if (len < 0 || len >= (maxlen-5)) {
1412 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1418 Jmsg(jcr, type, mtime, "%s", pool_buf);
1419 free_memory(pool_buf);
1424 * Edit a message into a Pool memory buffer, with file:lineno
1426 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1431 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1434 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1435 va_start(arg_ptr, fmt);
1436 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1438 if (len < 0 || len >= (maxlen-5)) {
1439 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1447 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1452 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1455 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1456 va_start(arg_ptr, fmt);
1457 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1459 if (len < 0 || len >= (maxlen-5)) {
1460 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1470 * Edit a message into a Pool Memory buffer NO file:lineno
1471 * Returns: string length of what was edited.
1473 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1479 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1480 va_start(arg_ptr, fmt);
1481 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1483 if (len < 0 || len >= (maxlen-5)) {
1484 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1492 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1498 maxlen = sizeof_pool_memory(pool_buf) - 1;
1499 va_start(arg_ptr, fmt);
1500 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1502 if (len < 0 || len >= (maxlen-5)) {
1503 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1511 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1517 maxlen = pool_buf.max_size() - 1;
1518 va_start(arg_ptr, fmt);
1519 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1521 if (len < 0 || len >= (maxlen-5)) {
1522 pool_buf.realloc_pm(maxlen + maxlen/2);
1532 * We queue messages rather than print them directly. This
1533 * is generally used in low level routines (msg handler, bnet)
1534 * to prevent recursion (i.e. if you are in the middle of
1535 * sending a message, it is a bit messy to recursively call
1536 * yourself when the bnet packet is not reentrant).
1538 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1545 pool_buf = get_pool_memory(PM_EMSG);
1548 maxlen = sizeof_pool_memory(pool_buf) - 1;
1549 va_start(arg_ptr, fmt);
1550 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1552 if (len < 0 || len >= (maxlen-5)) {
1553 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1558 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1560 item->mtime = time(NULL);
1561 strcpy(item->msg, pool_buf);
1563 jcr = get_jcr_from_tsd();
1565 /* If no jcr or no queue or dequeuing send to syslog */
1566 if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1567 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1570 /* Queue message for later sending */
1571 P(jcr->msg_queue_mutex);
1572 jcr->msg_queue->append(item);
1573 V(jcr->msg_queue_mutex);
1575 free_memory(pool_buf);
1581 void dequeue_messages(JCR *jcr)
1584 if (!jcr->msg_queue) {
1587 P(jcr->msg_queue_mutex);
1588 jcr->dequeuing_msgs = true;
1589 foreach_dlist(item, jcr->msg_queue) {
1590 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1592 /* Remove messages just sent */
1593 jcr->msg_queue->destroy();
1594 jcr->dequeuing_msgs = false;
1595 V(jcr->msg_queue_mutex);
1600 * If we come here, prefix the message with the file:line-number,
1601 * then pass it on to the normal Qmsg routine.
1603 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1609 pool_buf = get_pool_memory(PM_EMSG);
1610 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1613 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1614 va_start(arg_ptr, fmt);
1615 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1617 if (len < 0 || len >= (maxlen-5)) {
1618 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1624 Qmsg(jcr, type, mtime, "%s", pool_buf);
1625 free_memory(pool_buf);