2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Bacula message handling routines
31 * NOTE: don't use any Jmsg or Qmsg calls within this file,
32 * except in q_msg or j_msg (setup routines),
33 * otherwise you may get into recursive calls if there are
34 * errors, and that can lead to looping or deadlocks.
36 * Kern Sibbald, April 2000
43 sql_query_func p_sql_query = NULL;
44 sql_escape_func p_sql_escape = NULL;
46 #define FULL_LOCATION 1 /* set for file:line in Debug messages */
49 * This is where we define "Globals" because all the
50 * daemons include this file.
52 const char *working_directory = NULL; /* working directory path stored here */
53 int verbose = 0; /* increase User messages */
54 int debug_level = 0; /* debug level */
55 bool dbg_timestamp = false; /* print timestamp in debug output */
56 bool prt_kaboom = false; /* Print kaboom output */
57 utime_t daemon_start_time = 0; /* Daemon start time */
58 const char *version = VERSION " (" BDATE ")";
59 const char *dist_name = DISTNAME " " DISTVER;
61 char my_name[30] = {0}; /* daemon name is stored here */
62 char host_name[50] = {0}; /* host machine name */
63 char *exepath = (char *)NULL;
64 char *exename = (char *)NULL;
65 int console_msg_pending = false;
66 char con_fname[500]; /* Console filename */
67 FILE *con_fd = NULL; /* Console file descriptor */
68 brwlock_t con_lock; /* Console lock structure */
70 /* Forward referenced functions */
72 /* Imported functions */
73 void create_jcr_key();
77 /* 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;
88 static int hangup = 0;
91 const char *host_os = HOST_OS;
92 const char *distname = DISTNAME;
93 const char *distver = DISTVER;
96 * Walk back in a string from end looking for a
98 * This routine is passed the start of the string and
99 * the end of the string, it returns either the beginning
100 * of the string or where it found a path separator.
102 static const char *bstrrpath(const char *start, const char *end)
104 while ( end > start ) {
106 if (IsPathSeparator(*end)) {
113 /* Some message class methods */
125 * Wait for not in use variable to be clear
127 void MSGS::wait_not_in_use() /* leaves fides_mutex set */
132 bmicrosleep(0, 200); /* wait */
138 * Handle message delivery errors
140 static void delivery_error(const char *fmt,...)
145 char dt[MAX_TIME_LENGTH];
148 pool_buf = get_pool_memory(PM_EMSG);
150 bstrftime_ny(dt, sizeof(dt), time(NULL));
155 i = Mmsg(pool_buf, "%s Message delivery ERROR: ", dt);
158 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
159 va_start(arg_ptr, fmt);
160 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
162 if (len < 0 || len >= (maxlen-5)) {
163 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
169 fputs(pool_buf, stdout); /* print this here to INSURE that it is printed */
171 syslog(LOG_DAEMON|LOG_ERR, "%s", pool_buf);
172 free_memory(pool_buf);
175 void register_message_callback(void msg_callback(int type, char *msg))
177 message_callback = msg_callback;
182 * Set daemon name. Also, find canonical execution
183 * path. Note, exepath has spare room for tacking on
184 * the exename so that we can reconstruct the full name.
186 * Note, this routine can get called multiple times
187 * The second time is to put the name as found in the
188 * Resource record. On the second call, generally,
189 * argv is NULL to avoid doing the path code twice.
191 void my_name_is(int argc, char *argv[], const char *name)
197 if (gethostname(host_name, sizeof(host_name)) != 0) {
198 bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
200 bstrncpy(my_name, name, sizeof(my_name));
201 if (argc>0 && argv && argv[0]) {
202 /* strip trailing filename and save exepath */
203 for (l=p=argv[0]; *p; p++) {
204 if (IsPathSeparator(*p)) {
205 l = p; /* set pos of last slash */
208 if (IsPathSeparator(*l)) {
212 #if defined(HAVE_WIN32)
213 /* On Windows allow c: drive specification */
223 exename = (char *)malloc(len);
229 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
230 for (p=argv[0],q=exepath; p < l; ) {
234 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
235 if (getcwd(cpath, sizeof(cpath))) {
237 exepath = (char *)malloc(strlen(cpath) + 1 + len);
238 strcpy(exepath, cpath);
241 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
246 set_db_type(const char *name)
248 if (catalog_db != NULL) {
251 catalog_db = bstrdup(name);
255 * Initialize message handler for a daemon or a Job
256 * We make a copy of the MSGS resource passed, so it belows
257 * to the job or daemon and thus can be modified.
259 * NULL for jcr -> initialize global messages for daemon
260 * non-NULL -> initialize jcr using Message resource
263 init_msg(JCR *jcr, MSGS *msg)
265 DEST *d, *dnew, *temp_chain = NULL;
268 if (jcr == NULL && msg == NULL) {
269 init_last_jobs_list();
270 /* Create a daemon key then set invalid jcr */
271 /* Maybe we should give the daemon a jcr??? */
273 set_jcr_in_tsd(INVALID_JCR);
276 #if !defined(HAVE_WIN32)
278 * Make sure we have fd's 0, 1, 2 open
279 * If we don't do this one of our sockets may open
280 * there and if we then use stdout, it could
281 * send total garbage to our socket.
285 fd = open("/dev/null", O_RDONLY, 0644);
289 for(i=1; fd + i <= 2; i++) {
296 * If msg is NULL, initialize global chain for STDOUT and syslog
299 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
300 memset(daemon_msgs, 0, sizeof(MSGS));
301 for (i=1; i<=M_MAX; i++) {
302 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
304 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
309 * Walk down the message resource chain duplicating it
310 * for the current Job.
312 for (d=msg->dest_chain; d; d=d->next) {
313 dnew = (DEST *)malloc(sizeof(DEST));
314 memcpy(dnew, d, sizeof(DEST));
315 dnew->next = temp_chain;
317 dnew->mail_filename = NULL;
319 dnew->mail_cmd = bstrdup(d->mail_cmd);
322 dnew->where = bstrdup(d->where);
328 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
329 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
330 jcr->jcr_msgs->dest_chain = temp_chain;
331 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
333 /* If we have default values, release them now */
335 free_msgs_res(daemon_msgs);
337 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
338 memset(daemon_msgs, 0, sizeof(MSGS));
339 daemon_msgs->dest_chain = temp_chain;
340 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
343 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
347 /* Initialize so that the console (User Agent) can
348 * receive messages -- stored in a file.
350 void init_console_msg(const char *wd)
354 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
355 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
358 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
359 con_fname, be.bstrerror());
361 if (lseek(fd, 0, SEEK_END) > 0) {
362 console_msg_pending = 1;
365 con_fd = fopen(con_fname, "a+b");
368 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
369 con_fname, be.bstrerror());
371 if (rwl_init(&con_lock) != 0) {
373 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
379 * Called only during parsing of the config file.
381 * Add a message destination. I.e. associate a message type with
382 * a destination (code).
383 * Note, where in the case of dest_code FILE is a filename,
384 * but in the case of MAIL is a space separated list of
385 * email addresses, ...
387 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
391 * First search the existing chain and see if we
392 * can simply add this msg_type to an existing entry.
394 for (d=msg->dest_chain; d; d=d->next) {
395 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
396 (strcmp(where, d->where) == 0))) {
397 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
398 d, msg_type, dest_code, NPRT(where));
399 set_bit(msg_type, d->msg_types);
400 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
404 /* Not found, create a new entry */
405 d = (DEST *)malloc(sizeof(DEST));
406 memset(d, 0, sizeof(DEST));
407 d->next = msg->dest_chain;
408 d->dest_code = dest_code;
409 set_bit(msg_type, d->msg_types); /* set type bit in structure */
410 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
412 d->where = bstrdup(where);
415 d->mail_cmd = bstrdup(mail_cmd);
417 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
418 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
423 * Called only during parsing of the config file.
425 * Remove a message destination
427 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
431 for (d=msg->dest_chain; d; d=d->next) {
432 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
433 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
434 ((where == NULL && d->where == NULL) ||
435 (strcmp(where, d->where) == 0))) {
436 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
437 d, msg_type, dest_code);
438 clear_bit(msg_type, d->msg_types);
439 Dmsg0(850, "Return rem_msg_dest\n");
447 * Create a unique filename for the mail command
449 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
452 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
453 jcr->Job, (int)(intptr_t)d);
455 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
456 my_name, (int)(intptr_t)d);
458 Dmsg1(850, "mailname=%s\n", name);
464 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
469 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
471 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
475 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
476 /* If we had to use sendmail, add subject */
478 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
482 delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
483 cmd, be.bstrerror());
489 * Close the messages for this Messages resource, which means to close
490 * any open files, and dispatch any pending email messages.
492 void close_msg(JCR *jcr)
500 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
502 if (jcr == NULL) { /* NULL -> global chain */
505 msgs = jcr->jcr_msgs;
506 jcr->jcr_msgs = NULL;
512 /* Wait for item to be not in use, then mark closing */
513 if (msgs->is_closing()) {
516 msgs->wait_not_in_use(); /* leaves fides_mutex set */
520 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
521 cmd = get_pool_memory(PM_MESSAGE);
522 for (d=msgs->dest_chain; d; ) {
524 switch (d->dest_code) {
528 fclose(d->fd); /* close open file descriptor */
533 case MD_MAIL_ON_ERROR:
534 case MD_MAIL_ON_SUCCESS:
535 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
540 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
541 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
543 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
544 jcr->JobStatus == JS_ErrorTerminated)
549 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
550 Pmsg0(000, _("open mail pipe failed.\n"));
553 Dmsg0(850, "Opened mail pipe\n");
555 line = get_memory(len);
557 while (fgets(line, len, d->fd)) {
558 fputs(line, bpipe->wfd);
560 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
562 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
566 * Since we are closing all messages, before "recursing"
567 * make sure we are not closing the daemon messages, otherwise
570 if (msgs != daemon_msgs) {
571 /* read what mail prog returned -- should be nothing */
572 while (fgets(line, len, bpipe->rfd)) {
573 delivery_error(_("Mail prog: %s"), line);
577 stat = close_bpipe(bpipe);
578 if (stat != 0 && msgs != daemon_msgs) {
581 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
582 delivery_error(_("Mail program terminated in error.\n"
584 "ERR=%s\n"), cmd, be.bstrerror());
588 /* Remove temp file */
591 unlink(d->mail_filename);
592 free_pool_memory(d->mail_filename);
593 d->mail_filename = NULL;
594 Dmsg0(850, "end mail or mail on error\n");
601 d = d->next; /* point to next buffer */
603 free_pool_memory(cmd);
604 Dmsg0(850, "Done walking message chain.\n");
609 msgs->clear_closing();
611 Dmsg0(850, "===End close msg resource\n");
615 * Free memory associated with Messages resource
617 void free_msgs_res(MSGS *msgs)
621 /* Walk down the message chain releasing allocated buffers */
622 for (d=msgs->dest_chain; d; ) {
629 old = d; /* save pointer to release */
630 d = d->next; /* point to next buffer */
631 free(old); /* free the destination item */
633 msgs->dest_chain = NULL;
634 free(msgs); /* free the head */
639 * Terminate the message handler for good.
640 * Release the global destination chain.
642 * Also, clean up a few other items (cons, exepath). Note,
643 * these really should be done elsewhere.
647 Dmsg0(850, "Enter term_msg\n");
648 close_msg(NULL); /* close global chain */
649 free_msgs_res(daemon_msgs); /* free the resources */
672 term_last_jobs_list();
675 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
677 d->fd = fopen(d->where, mode);
680 delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
686 /* Split the output for syslog (it converts \n to ' ' and is
687 * limited to 1024 characters per syslog message
689 static void send_to_syslog(int mode, const char *msg)
696 while (*p && ((p2 = strchr(p, '\n')) != NULL)) {
697 len = MIN((int)sizeof(buf) - 1, p2 - p + 1); /* Add 1 to keep \n */
698 strncpy(buf, p, len);
700 syslog(mode, "%s", buf);
701 p = p2+1; /* skip \n */
703 if (*p != 0) { /* no \n at the end ? */
704 syslog(mode, "%s", p);
709 * Handle sending the message to the appropriate place
711 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
714 char dt[MAX_TIME_LENGTH];
721 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
724 * Most messages are prefixed by a date and time. If mtime is
725 * zero, then we use the current time. If mtime is 1 (special
726 * kludge), we do not prefix the date and time. Otherwise,
727 * we assume mtime is a utime_t and use it.
735 mtime = time(NULL); /* get time for SQL log */
737 bstrftime_ny(dt, sizeof(dt), mtime);
743 /* If the program registered a callback, send it there */
744 if (message_callback) {
745 message_callback(type, msg);
749 /* For serious errors make sure message is printed or logged */
750 if (type == M_ABORT || type == M_ERROR_TERM) {
754 if (type == M_ABORT) {
755 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
760 /* Now figure out where to send the message */
763 jcr = get_jcr_from_tsd();
766 msgs = jcr->jcr_msgs;
772 * If closing this message resource, print and send to syslog,
775 if (msgs->is_closing()) {
779 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
783 for (d=msgs->dest_chain; d; d=d->next) {
784 if (bit_is_set(type, d->msg_types)) {
785 switch (d->dest_code) {
788 if (!jcr || !jcr->db) {
791 if (p_sql_query && p_sql_escape) {
792 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
793 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
795 int len = strlen(msg) + 1;
796 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
797 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
799 bstrutime(dt, sizeof(dt), mtime);
800 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
801 edit_int64(jcr->JobId, ed1), dt, esc_msg);
802 p_sql_query(jcr, cmd);
804 free_pool_memory(cmd);
805 free_pool_memory(esc_msg);
809 Dmsg1(850, "CONSOLE for following msg: %s", msg);
811 con_fd = fopen(con_fname, "a+b");
812 Dmsg0(850, "Console file not open.\n");
815 Pw(con_lock); /* get write lock on console message file */
818 (void)fwrite(dt, dtlen, 1, con_fd);
822 (void)fwrite(msg, len, 1, con_fd);
823 if (msg[len-1] != '\n') {
824 (void)fwrite("\n", 2, 1, con_fd);
827 (void)fwrite("\n", 2, 1, con_fd);
830 console_msg_pending = true;
835 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
837 * We really should do an openlog() here.
839 send_to_syslog(LOG_DAEMON|LOG_ERR, msg);
842 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
843 mcmd = get_pool_memory(PM_MESSAGE);
844 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
846 fputs(dt, bpipe->wfd);
847 fputs(msg, bpipe->wfd);
848 /* Messages to the operator go one at a time */
849 stat = close_bpipe(bpipe);
853 delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
855 "ERR=%s\n"), mcmd, be.bstrerror());
858 free_pool_memory(mcmd);
861 case MD_MAIL_ON_ERROR:
862 case MD_MAIL_ON_SUCCESS:
863 Dmsg1(850, "MAIL for following msg: %s", msg);
864 if (msgs->is_closing()) {
869 POOLMEM *name = get_pool_memory(PM_MESSAGE);
870 make_unique_mail_filename(jcr, name, d);
871 d->fd = fopen(name, "w+b");
874 delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
876 free_pool_memory(name);
877 msgs->clear_in_use();
880 d->mail_filename = name;
883 len = strlen(msg) + dtlen;;
884 if (len > d->max_len) {
885 d->max_len = len; /* keep max line length */
888 msgs->clear_in_use();
891 Dmsg1(850, "APPEND for following msg: %s", msg);
895 Dmsg1(850, "FILE for following msg: %s", msg);
898 if (msgs->is_closing()) {
902 if (!d->fd && !open_dest_file(jcr, d, mode)) {
903 msgs->clear_in_use();
908 /* On error, we close and reopen to handle log rotation */
912 if (open_dest_file(jcr, d, mode)) {
917 msgs->clear_in_use();
920 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
921 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
922 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
923 jcr->Job, type, mtime, msg);
925 Dmsg1(800, "no jcr for following msg: %s", msg);
929 Dmsg1(850, "STDOUT for following msg: %s", msg);
930 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
937 Dmsg1(850, "STDERR for following msg: %s", msg);
949 /*********************************************************************
951 * This subroutine returns the filename portion of a path.
952 * It is used because some compilers set __FILE__
953 * to the full path. Try to return base + next higher path.
956 const char *get_basename(const char *pathname)
958 const char *basename;
960 if ((basename = bstrrpath(pathname, pathname+strlen(pathname))) == pathname) {
962 } else if ((basename = bstrrpath(pathname, basename-1)) == pathname) {
971 * print or write output to trace file
973 static void pt_out(char *buf)
976 * Used the "trace on" command in the console to turn on
977 * output to the trace file. "trace off" will close the file.
982 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
983 trace_fd = fopen(fn, "a+b");
986 fputs(buf, trace_fd);
990 /* Some problem, turn off tracing */
999 /*********************************************************************
1001 * This subroutine prints a debug message if the level number
1002 * is less than or equal the debug_level. File and line numbers
1003 * are included for more detail if desired, but not currently
1006 * If the level is negative, the details of file and line number
1010 d_msg(const char *file, int line, int level, const char *fmt,...)
1015 bool details = true;
1023 if (level <= debug_level) {
1024 if (dbg_timestamp) {
1026 bstrftimes(buf, sizeof(buf), mtime);
1033 #ifdef FULL_LOCATION
1035 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
1036 my_name, get_basename(file), line, get_jobid_from_tsd());
1043 va_start(arg_ptr, fmt);
1044 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1052 * Set trace flag on/off. If argument is negative, there is no change
1054 void set_trace(int trace_flag)
1056 if (trace_flag < 0) {
1058 } else if (trace_flag > 0) {
1063 if (!trace && trace_fd) {
1064 FILE *ltrace_fd = trace_fd;
1066 bmicrosleep(0, 100000); /* yield to prevent seg faults */
1071 void set_hangup(int hangup_value)
1073 if (hangup_value < 0) {
1076 hangup = hangup_value;
1080 int get_hangup(void)
1085 bool get_trace(void)
1090 /*********************************************************************
1092 * This subroutine prints a message regardless of the debug level
1094 * If the level is negative, the details of file and line number
1098 p_msg(const char *file, int line, int level, const char *fmt,...)
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);
1121 /*********************************************************************
1123 * subroutine writes a debug message to the trace file if the level number
1124 * is less than or equal the debug_level. File and line numbers
1125 * are included for more detail if desired, but not currently
1128 * If the level is negative, the details of file and line number
1132 t_msg(const char *file, int line, int level, const char *fmt,...)
1144 if (level <= debug_level) {
1146 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1147 trace_fd = fopen(buf, "a+b");
1150 #ifdef FULL_LOCATION
1152 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1159 va_start(arg_ptr, fmt);
1160 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1162 if (trace_fd != NULL) {
1163 fputs(buf, trace_fd);
1169 /* *********************************************************
1171 * print an error message
1175 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1182 * Check if we have a message destination defined.
1183 * We always report M_ABORT and M_ERROR_TERM
1185 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1186 !bit_is_set(type, daemon_msgs->send_msg))) {
1187 return; /* no destination */
1191 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1192 my_name, get_basename(file), line);
1195 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1196 my_name, get_basename(file), line);
1199 if (level == -1) /* skip details */
1200 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1202 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1205 if (level == -1) /* skip details */
1206 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1208 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1211 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1214 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1217 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1221 va_start(arg_ptr, fmt);
1222 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1225 dispatch_message(NULL, type, 0, buf);
1227 if (type == M_ABORT) {
1229 p[0] = 0; /* generate segmentation violation */
1231 if (type == M_ERROR_TERM) {
1236 /* *********************************************************
1238 * Generate a Job message
1242 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1251 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1253 /* Special case for the console, which has a dir_bsock and JobId==0,
1254 * in that case, we send the message directly back to the
1257 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1258 BSOCK *dir = jcr->dir_bsock;
1259 va_start(arg_ptr, fmt);
1260 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1263 jcr->dir_bsock->send();
1267 /* The watchdog thread can't use Jmsg directly, we always queued it */
1268 if (is_watchdog()) {
1269 va_start(arg_ptr, fmt);
1270 bvsnprintf(rbuf, sizeof(rbuf), fmt, arg_ptr);
1272 Qmsg(jcr, type, mtime, "%s", rbuf);
1278 jcr = get_jcr_from_tsd();
1281 if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1282 /* Dequeue messages to keep the original order */
1283 dequeue_messages(jcr);
1285 msgs = jcr->jcr_msgs;
1289 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1293 * Check if we have a message destination defined.
1294 * We always report M_ABORT and M_ERROR_TERM
1296 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1297 !bit_is_set(type, msgs->send_msg)) {
1298 return; /* no destination */
1302 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1305 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1308 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1310 jcr->setJobStatus(JS_FatalError);
1312 if (jcr && jcr->JobErrors == 0) {
1317 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1323 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1329 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1333 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1337 va_start(arg_ptr, fmt);
1338 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1341 dispatch_message(jcr, type, mtime, rbuf);
1343 if (type == M_ABORT){
1345 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1346 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1347 p[0] = 0; /* generate segmentation violation */
1349 if (type == M_ERROR_TERM) {
1355 * If we come here, prefix the message with the file:line-number,
1356 * then pass it on to the normal Jmsg routine.
1358 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1364 pool_buf = get_pool_memory(PM_EMSG);
1365 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1368 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1369 va_start(arg_ptr, fmt);
1370 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1372 if (len < 0 || len >= (maxlen-5)) {
1373 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1379 Jmsg(jcr, type, mtime, "%s", pool_buf);
1380 free_memory(pool_buf);
1385 * Edit a message into a Pool memory buffer, with file:lineno
1387 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1392 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1395 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1396 va_start(arg_ptr, fmt);
1397 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1399 if (len < 0 || len >= (maxlen-5)) {
1400 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1408 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1413 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1416 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1417 va_start(arg_ptr, fmt);
1418 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1420 if (len < 0 || len >= (maxlen-5)) {
1421 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1431 * Edit a message into a Pool Memory buffer NO file:lineno
1432 * Returns: string length of what was edited.
1434 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1440 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1441 va_start(arg_ptr, fmt);
1442 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1444 if (len < 0 || len >= (maxlen-5)) {
1445 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1453 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1459 maxlen = sizeof_pool_memory(pool_buf) - 1;
1460 va_start(arg_ptr, fmt);
1461 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1463 if (len < 0 || len >= (maxlen-5)) {
1464 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1472 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1478 maxlen = pool_buf.max_size() - 1;
1479 va_start(arg_ptr, fmt);
1480 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1482 if (len < 0 || len >= (maxlen-5)) {
1483 pool_buf.realloc_pm(maxlen + maxlen/2);
1493 * We queue messages rather than print them directly. This
1494 * is generally used in low level routines (msg handler, bnet)
1495 * to prevent recursion (i.e. if you are in the middle of
1496 * sending a message, it is a bit messy to recursively call
1497 * yourself when the bnet packet is not reentrant).
1499 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1506 pool_buf = get_pool_memory(PM_EMSG);
1509 maxlen = sizeof_pool_memory(pool_buf) - 1;
1510 va_start(arg_ptr, fmt);
1511 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1513 if (len < 0 || len >= (maxlen-5)) {
1514 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1519 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1521 item->mtime = time(NULL);
1522 strcpy(item->msg, pool_buf);
1524 jcr = get_jcr_from_tsd();
1526 /* If no jcr or no queue or dequeuing send to syslog */
1527 if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1528 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1531 /* Queue message for later sending */
1532 P(jcr->msg_queue_mutex);
1533 jcr->msg_queue->append(item);
1534 V(jcr->msg_queue_mutex);
1536 free_memory(pool_buf);
1542 void dequeue_messages(JCR *jcr)
1545 if (!jcr->msg_queue) {
1548 P(jcr->msg_queue_mutex);
1549 jcr->dequeuing_msgs = true;
1550 foreach_dlist(item, jcr->msg_queue) {
1551 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1553 /* Remove messages just sent */
1554 jcr->msg_queue->destroy();
1555 jcr->dequeuing_msgs = false;
1556 V(jcr->msg_queue_mutex);
1561 * If we come here, prefix the message with the file:line-number,
1562 * then pass it on to the normal Qmsg routine.
1564 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1570 pool_buf = get_pool_memory(PM_EMSG);
1571 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1574 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1575 va_start(arg_ptr, fmt);
1576 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1578 if (len < 0 || len >= (maxlen-5)) {
1579 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1585 Qmsg(jcr, type, mtime, "%s", pool_buf);
1586 free_memory(pool_buf);