2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Bacula message handling routines
31 * NOTE: don't use any Jmsg or Qmsg calls within this file,
32 * except in q_msg or j_msg (setup routines),
33 * otherwise you may get into recursive calls if there are
34 * errors, and that can lead to looping or deadlocks.
36 * Kern Sibbald, April 2000
43 sql_query_func p_sql_query = NULL;
44 sql_escape_func p_sql_escape = NULL;
46 #define FULL_LOCATION 1 /* set for file:line in Debug messages */
49 * This is where we define "Globals" because all the
50 * daemons include this file.
52 const char *working_directory = NULL; /* working directory path stored here */
53 int verbose = 0; /* increase User messages */
54 int debug_level = 0; /* debug level */
55 bool dbg_timestamp = false; /* print timestamp in debug output */
56 bool prt_kaboom = false; /* Print kaboom output */
57 utime_t daemon_start_time = 0; /* Daemon start time */
58 const char *version = VERSION " (" BDATE ")";
59 const char *dist_name = DISTNAME " " DISTVER;
60 const int beef = BEEF;
61 char my_name[30] = {0}; /* daemon name is stored here */
62 char host_name[50] = {0}; /* host machine name */
63 char *exepath = (char *)NULL;
64 char *exename = (char *)NULL;
65 int console_msg_pending = false;
66 char con_fname[500]; /* Console filename */
67 FILE *con_fd = NULL; /* Console file descriptor */
68 brwlock_t con_lock; /* Console lock structure */
70 /* Forward referenced functions */
72 /* Imported functions */
73 void create_jcr_key();
77 /* Allow only one thread to tweak d->fd at a time */
78 static pthread_mutex_t fides_mutex = PTHREAD_MUTEX_INITIALIZER;
79 static MSGS *daemon_msgs; /* global messages */
80 static void (*message_callback)(int type, char *msg) = NULL;
81 static FILE *trace_fd = NULL;
82 #if defined(HAVE_WIN32)
83 static bool trace = true;
85 static bool trace = false;
89 const char *host_os = HOST_OS;
90 const char *distname = DISTNAME;
91 const char *distver = DISTVER;
93 /* Some message class methods */
105 * Wait for not in use variable to be clear
107 void MSGS::wait_not_in_use() /* leaves fides_mutex set */
112 bmicrosleep(0, 200); /* wait */
118 * Handle message delivery errors
120 static void delivery_error(const char *fmt,...)
125 char dt[MAX_TIME_LENGTH];
128 pool_buf = get_pool_memory(PM_EMSG);
130 bstrftime_ny(dt, sizeof(dt), time(NULL));
135 i = Mmsg(pool_buf, "%s Message delivery ERROR: ", dt);
138 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
139 va_start(arg_ptr, fmt);
140 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
142 if (len < 0 || len >= (maxlen-5)) {
143 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
149 fputs(pool_buf, stdout); /* print this here to INSURE that it is printed */
151 syslog(LOG_DAEMON|LOG_ERR, "%s", pool_buf);
152 free_memory(pool_buf);
155 void register_message_callback(void msg_callback(int type, char *msg))
157 message_callback = msg_callback;
162 * Set daemon name. Also, find canonical execution
163 * path. Note, exepath has spare room for tacking on
164 * the exename so that we can reconstruct the full name.
166 * Note, this routine can get called multiple times
167 * The second time is to put the name as found in the
168 * Resource record. On the second call, generally,
169 * argv is NULL to avoid doing the path code twice.
171 void my_name_is(int argc, char *argv[], const char *name)
177 if (gethostname(host_name, sizeof(host_name)) != 0) {
178 bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
180 bstrncpy(my_name, name, sizeof(my_name));
181 if (argc>0 && argv && argv[0]) {
182 /* strip trailing filename and save exepath */
183 for (l=p=argv[0]; *p; p++) {
184 if (IsPathSeparator(*p)) {
185 l = p; /* set pos of last slash */
188 if (IsPathSeparator(*l)) {
192 #if defined(HAVE_WIN32)
193 /* On Windows allow c: junk */
203 exename = (char *)malloc(len);
209 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
210 for (p=argv[0],q=exepath; p < l; ) {
214 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
215 if (getcwd(cpath, sizeof(cpath))) {
217 exepath = (char *)malloc(strlen(cpath) + 1 + len);
218 strcpy(exepath, cpath);
221 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
226 * Initialize message handler for a daemon or a Job
227 * We make a copy of the MSGS resource passed, so it belows
228 * to the job or daemon and thus can be modified.
230 * NULL for jcr -> initialize global messages for daemon
231 * non-NULL -> initialize jcr using Message resource
234 init_msg(JCR *jcr, MSGS *msg)
236 DEST *d, *dnew, *temp_chain = NULL;
239 if (jcr == NULL && msg == NULL) {
240 init_last_jobs_list();
241 /* Create a daemon key then set invalid jcr */
242 /* Maybe we should give the daemon a jcr??? */
244 set_jcr_in_tsd(INVALID_JCR);
247 #if !defined(HAVE_WIN32)
249 * Make sure we have fd's 0, 1, 2 open
250 * If we don't do this one of our sockets may open
251 * there and if we then use stdout, it could
252 * send total garbage to our socket.
256 fd = open("/dev/null", O_RDONLY, 0644);
260 for(i=1; fd + i <= 2; i++) {
267 * If msg is NULL, initialize global chain for STDOUT and syslog
270 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
271 memset(daemon_msgs, 0, sizeof(MSGS));
272 for (i=1; i<=M_MAX; i++) {
273 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
275 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
280 * Walk down the message resource chain duplicating it
281 * for the current Job.
283 for (d=msg->dest_chain; d; d=d->next) {
284 dnew = (DEST *)malloc(sizeof(DEST));
285 memcpy(dnew, d, sizeof(DEST));
286 dnew->next = temp_chain;
288 dnew->mail_filename = NULL;
290 dnew->mail_cmd = bstrdup(d->mail_cmd);
293 dnew->where = bstrdup(d->where);
299 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
300 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
301 jcr->jcr_msgs->dest_chain = temp_chain;
302 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
304 /* If we have default values, release them now */
306 free_msgs_res(daemon_msgs);
308 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
309 memset(daemon_msgs, 0, sizeof(MSGS));
310 daemon_msgs->dest_chain = temp_chain;
311 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
314 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
318 /* Initialize so that the console (User Agent) can
319 * receive messages -- stored in a file.
321 void init_console_msg(const char *wd)
325 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
326 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
329 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
330 con_fname, be.bstrerror());
332 if (lseek(fd, 0, SEEK_END) > 0) {
333 console_msg_pending = 1;
336 con_fd = fopen(con_fname, "a+b");
339 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
340 con_fname, be.bstrerror());
342 if (rwl_init(&con_lock) != 0) {
344 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
350 * Called only during parsing of the config file.
352 * Add a message destination. I.e. associate a message type with
353 * a destination (code).
354 * Note, where in the case of dest_code FILE is a filename,
355 * but in the case of MAIL is a space separated list of
356 * email addresses, ...
358 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
362 * First search the existing chain and see if we
363 * can simply add this msg_type to an existing entry.
365 for (d=msg->dest_chain; d; d=d->next) {
366 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
367 (strcmp(where, d->where) == 0))) {
368 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
369 d, msg_type, dest_code, NPRT(where));
370 set_bit(msg_type, d->msg_types);
371 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
375 /* Not found, create a new entry */
376 d = (DEST *)malloc(sizeof(DEST));
377 memset(d, 0, sizeof(DEST));
378 d->next = msg->dest_chain;
379 d->dest_code = dest_code;
380 set_bit(msg_type, d->msg_types); /* set type bit in structure */
381 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
383 d->where = bstrdup(where);
386 d->mail_cmd = bstrdup(mail_cmd);
388 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
389 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
394 * Called only during parsing of the config file.
396 * Remove a message destination
398 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
402 for (d=msg->dest_chain; d; d=d->next) {
403 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
404 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
405 ((where == NULL && d->where == NULL) ||
406 (strcmp(where, d->where) == 0))) {
407 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
408 d, msg_type, dest_code);
409 clear_bit(msg_type, d->msg_types);
410 Dmsg0(850, "Return rem_msg_dest\n");
418 * Create a unique filename for the mail command
420 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
423 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
424 jcr->Job, (int)(intptr_t)d);
426 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
427 my_name, (int)(intptr_t)d);
429 Dmsg1(850, "mailname=%s\n", name);
435 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
440 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
442 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
446 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
447 /* If we had to use sendmail, add subject */
449 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
453 delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
454 cmd, be.bstrerror());
460 * Close the messages for this Messages resource, which means to close
461 * any open files, and dispatch any pending email messages.
463 void close_msg(JCR *jcr)
471 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
473 if (jcr == NULL) { /* NULL -> global chain */
476 msgs = jcr->jcr_msgs;
477 jcr->jcr_msgs = NULL;
483 /* Wait for item to be not in use, then mark closing */
484 if (msgs->is_closing()) {
487 msgs->wait_not_in_use(); /* leaves fides_mutex set */
491 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
492 cmd = get_pool_memory(PM_MESSAGE);
493 for (d=msgs->dest_chain; d; ) {
495 switch (d->dest_code) {
499 fclose(d->fd); /* close open file descriptor */
504 case MD_MAIL_ON_ERROR:
505 case MD_MAIL_ON_SUCCESS:
506 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
511 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
512 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
514 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
515 jcr->JobStatus == JS_ErrorTerminated)
520 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
521 Pmsg0(000, _("open mail pipe failed.\n"));
524 Dmsg0(850, "Opened mail pipe\n");
526 line = get_memory(len);
528 while (fgets(line, len, d->fd)) {
529 fputs(line, bpipe->wfd);
531 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
533 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
537 * Since we are closing all messages, before "recursing"
538 * make sure we are not closing the daemon messages, otherwise
541 if (msgs != daemon_msgs) {
542 /* read what mail prog returned -- should be nothing */
543 while (fgets(line, len, bpipe->rfd)) {
544 delivery_error(_("Mail prog: %s"), line);
548 stat = close_bpipe(bpipe);
549 if (stat != 0 && msgs != daemon_msgs) {
552 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
553 delivery_error(_("Mail program terminated in error.\n"
555 "ERR=%s\n"), cmd, be.bstrerror());
559 /* Remove temp file */
562 unlink(d->mail_filename);
563 free_pool_memory(d->mail_filename);
564 d->mail_filename = NULL;
565 Dmsg0(850, "end mail or mail on error\n");
572 d = d->next; /* point to next buffer */
574 free_pool_memory(cmd);
575 Dmsg0(850, "Done walking message chain.\n");
580 msgs->clear_closing();
582 Dmsg0(850, "===End close msg resource\n");
586 * Free memory associated with Messages resource
588 void free_msgs_res(MSGS *msgs)
592 /* Walk down the message chain releasing allocated buffers */
593 for (d=msgs->dest_chain; d; ) {
600 old = d; /* save pointer to release */
601 d = d->next; /* point to next buffer */
602 free(old); /* free the destination item */
604 msgs->dest_chain = NULL;
605 free(msgs); /* free the head */
610 * Terminate the message handler for good.
611 * Release the global destination chain.
613 * Also, clean up a few other items (cons, exepath). Note,
614 * these really should be done elsewhere.
618 Dmsg0(850, "Enter term_msg\n");
619 close_msg(NULL); /* close global chain */
620 free_msgs_res(daemon_msgs); /* free the resources */
639 term_last_jobs_list();
642 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
644 d->fd = fopen(d->where, mode);
647 delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
654 * Handle sending the message to the appropriate place
656 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
659 char dt[MAX_TIME_LENGTH];
666 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
669 * Most messages are prefixed by a date and time. If mtime is
670 * zero, then we use the current time. If mtime is 1 (special
671 * kludge), we do not prefix the date and time. Otherwise,
672 * we assume mtime is a utime_t and use it.
680 mtime = time(NULL); /* get time for SQL log */
682 bstrftime_ny(dt, sizeof(dt), mtime);
688 /* If the program registered a callback, send it there */
689 if (message_callback) {
690 message_callback(type, msg);
694 /* For serious errors make sure message is printed or logged */
695 if (type == M_ABORT || type == M_ERROR_TERM) {
699 if (type == M_ABORT) {
700 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
705 /* Now figure out where to send the message */
708 jcr = get_jcr_from_tsd();
711 msgs = jcr->jcr_msgs;
717 * If closing this message resource, print and send to syslog,
720 if (msgs->is_closing()) {
724 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
728 for (d=msgs->dest_chain; d; d=d->next) {
729 if (bit_is_set(type, d->msg_types)) {
730 switch (d->dest_code) {
733 if (!jcr || !jcr->db) {
736 if (p_sql_query && p_sql_escape) {
737 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
738 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
740 int len = strlen(msg) + 1;
741 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
742 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
744 bstrutime(dt, sizeof(dt), mtime);
745 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
746 edit_int64(jcr->JobId, ed1), dt, esc_msg);
747 p_sql_query(jcr, cmd);
749 free_pool_memory(cmd);
750 free_pool_memory(esc_msg);
754 Dmsg1(850, "CONSOLE for following msg: %s", msg);
756 con_fd = fopen(con_fname, "a+b");
757 Dmsg0(850, "Console file not open.\n");
760 Pw(con_lock); /* get write lock on console message file */
763 (void)fwrite(dt, dtlen, 1, con_fd);
767 (void)fwrite(msg, len, 1, con_fd);
768 if (msg[len-1] != '\n') {
769 (void)fwrite("\n", 2, 1, con_fd);
772 (void)fwrite("\n", 2, 1, con_fd);
775 console_msg_pending = true;
780 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
782 * We really should do an openlog() here.
784 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
787 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
788 mcmd = get_pool_memory(PM_MESSAGE);
789 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
791 fputs(dt, bpipe->wfd);
792 fputs(msg, bpipe->wfd);
793 /* Messages to the operator go one at a time */
794 stat = close_bpipe(bpipe);
798 delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
800 "ERR=%s\n"), mcmd, be.bstrerror());
803 free_pool_memory(mcmd);
806 case MD_MAIL_ON_ERROR:
807 case MD_MAIL_ON_SUCCESS:
808 Dmsg1(850, "MAIL for following msg: %s", msg);
809 if (msgs->is_closing()) {
814 POOLMEM *name = get_pool_memory(PM_MESSAGE);
815 make_unique_mail_filename(jcr, name, d);
816 d->fd = fopen(name, "w+b");
819 delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
821 free_pool_memory(name);
825 d->mail_filename = name;
828 len = strlen(msg) + dtlen;;
829 if (len > d->max_len) {
830 d->max_len = len; /* keep max line length */
833 msgs->clear_in_use();
836 Dmsg1(850, "APPEND for following msg: %s", msg);
840 Dmsg1(850, "FILE for following msg: %s", msg);
843 if (msgs->is_closing()) {
847 if (!d->fd && !open_dest_file(jcr, d, mode)) {
848 msgs->clear_in_use();
853 /* On error, we close and reopen to handle log rotation */
857 if (open_dest_file(jcr, d, mode)) {
862 msgs->clear_in_use();
865 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
866 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
867 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
868 jcr->Job, type, mtime, msg);
870 Dmsg1(800, "no jcr for following msg: %s", msg);
874 Dmsg1(850, "STDOUT for following msg: %s", msg);
875 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
882 Dmsg1(850, "STDERR for following msg: %s", msg);
894 /*********************************************************************
896 * This subroutine returns the filename portion of a Windows
897 * path. It is used because Microsoft Visual Studio sets __FILE__
902 get_basename(const char *pathname)
904 #if defined(_MSC_VER)
905 const char *basename;
907 if ((basename = strrchr(pathname, '\\')) == NULL) {
920 * print or write output to trace file
922 static void pt_out(char *buf)
925 * Used the "trace on" command in the console to turn on
926 * output to the trace file. "trace off" will close the file.
931 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
932 trace_fd = fopen(fn, "a+b");
935 fputs(buf, trace_fd);
939 /* Some problem, turn off tracing */
948 /*********************************************************************
950 * This subroutine prints a debug message if the level number
951 * is less than or equal the debug_level. File and line numbers
952 * are included for more detail if desired, but not currently
955 * If the level is negative, the details of file and line number
959 d_msg(const char *file, int line, int level, const char *fmt,...)
972 if (level <= debug_level) {
975 bstrftimes(buf, sizeof(buf), mtime);
984 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
985 my_name, get_basename(file), line, get_jobid_from_tsd());
992 va_start(arg_ptr, fmt);
993 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1001 * Set trace flag on/off. If argument is negative, there is no change
1003 void set_trace(int trace_flag)
1005 if (trace_flag < 0) {
1007 } else if (trace_flag > 0) {
1012 if (!trace && trace_fd) {
1013 FILE *ltrace_fd = trace_fd;
1015 bmicrosleep(0, 100000); /* yield to prevent seg faults */
1020 bool get_trace(void)
1025 /*********************************************************************
1027 * This subroutine prints a message regardless of the debug level
1029 * If the level is negative, the details of file and line number
1033 p_msg(const char *file, int line, int level, const char *fmt,...)
1039 #ifdef FULL_LOCATION
1041 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1048 va_start(arg_ptr, fmt);
1049 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1056 /*********************************************************************
1058 * subroutine writes a debug message to the trace file if the level number
1059 * is less than or equal the debug_level. File and line numbers
1060 * are included for more detail if desired, but not currently
1063 * If the level is negative, the details of file and line number
1067 t_msg(const char *file, int line, int level, const char *fmt,...)
1079 if (level <= debug_level) {
1081 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1082 trace_fd = fopen(buf, "a+b");
1085 #ifdef FULL_LOCATION
1087 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1094 va_start(arg_ptr, fmt);
1095 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1097 if (trace_fd != NULL) {
1098 fputs(buf, trace_fd);
1104 /* *********************************************************
1106 * print an error message
1110 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1117 * Check if we have a message destination defined.
1118 * We always report M_ABORT and M_ERROR_TERM
1120 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1121 !bit_is_set(type, daemon_msgs->send_msg))) {
1122 return; /* no destination */
1126 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1127 my_name, get_basename(file), line);
1130 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1131 my_name, get_basename(file), line);
1134 if (level == -1) /* skip details */
1135 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1137 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1140 if (level == -1) /* skip details */
1141 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1143 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1146 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1149 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1152 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1156 va_start(arg_ptr, fmt);
1157 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1160 dispatch_message(NULL, type, 0, buf);
1162 if (type == M_ABORT) {
1164 p[0] = 0; /* generate segmentation violation */
1166 if (type == M_ERROR_TERM) {
1171 /* *********************************************************
1173 * Generate a Job message
1177 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1186 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1188 /* Special case for the console, which has a dir_bsock and JobId==0,
1189 * in that case, we send the message directly back to the
1192 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1193 BSOCK *dir = jcr->dir_bsock;
1194 va_start(arg_ptr, fmt);
1195 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1198 jcr->dir_bsock->send();
1202 /* The watchdog thread can't use Jmsg directly, we always queued it */
1203 if (is_watchdog()) {
1204 va_start(arg_ptr, fmt);
1205 bvsnprintf(rbuf, sizeof(rbuf), fmt, arg_ptr);
1207 Qmsg(jcr, type, mtime, "%s", rbuf);
1213 jcr = get_jcr_from_tsd();
1216 if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1217 /* Dequeue messages to keep the original order */
1218 dequeue_messages(jcr);
1220 msgs = jcr->jcr_msgs;
1224 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1228 * Check if we have a message destination defined.
1229 * We always report M_ABORT and M_ERROR_TERM
1231 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1232 !bit_is_set(type, msgs->send_msg)) {
1233 return; /* no destination */
1237 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1240 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1243 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1245 set_jcr_job_status(jcr, JS_FatalError);
1247 if (jcr && jcr->JobErrors == 0) {
1252 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1258 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1264 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1268 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1272 va_start(arg_ptr, fmt);
1273 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1276 dispatch_message(jcr, type, mtime, rbuf);
1278 if (type == M_ABORT){
1280 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1281 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1282 p[0] = 0; /* generate segmentation violation */
1284 if (type == M_ERROR_TERM) {
1290 * If we come here, prefix the message with the file:line-number,
1291 * then pass it on to the normal Jmsg routine.
1293 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1299 pool_buf = get_pool_memory(PM_EMSG);
1300 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1303 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1304 va_start(arg_ptr, fmt);
1305 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1307 if (len < 0 || len >= (maxlen-5)) {
1308 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1314 Jmsg(jcr, type, mtime, "%s", pool_buf);
1315 free_memory(pool_buf);
1320 * Edit a message into a Pool memory buffer, with file:lineno
1322 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1327 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1330 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1331 va_start(arg_ptr, fmt);
1332 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1334 if (len < 0 || len >= (maxlen-5)) {
1335 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1343 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1348 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1351 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1352 va_start(arg_ptr, fmt);
1353 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1355 if (len < 0 || len >= (maxlen-5)) {
1356 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1366 * Edit a message into a Pool Memory buffer NO file:lineno
1367 * Returns: string length of what was edited.
1369 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1375 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1376 va_start(arg_ptr, fmt);
1377 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1379 if (len < 0 || len >= (maxlen-5)) {
1380 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1388 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1394 maxlen = sizeof_pool_memory(pool_buf) - 1;
1395 va_start(arg_ptr, fmt);
1396 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1398 if (len < 0 || len >= (maxlen-5)) {
1399 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1407 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1413 maxlen = pool_buf.max_size() - 1;
1414 va_start(arg_ptr, fmt);
1415 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1417 if (len < 0 || len >= (maxlen-5)) {
1418 pool_buf.realloc_pm(maxlen + maxlen/2);
1428 * We queue messages rather than print them directly. This
1429 * is generally used in low level routines (msg handler, bnet)
1430 * to prevent recursion (i.e. if you are in the middle of
1431 * sending a message, it is a bit messy to recursively call
1432 * yourself when the bnet packet is not reentrant).
1434 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1441 pool_buf = get_pool_memory(PM_EMSG);
1444 maxlen = sizeof_pool_memory(pool_buf) - 1;
1445 va_start(arg_ptr, fmt);
1446 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1448 if (len < 0 || len >= (maxlen-5)) {
1449 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1454 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1456 item->mtime = time(NULL);
1457 strcpy(item->msg, pool_buf);
1459 jcr = get_jcr_from_tsd();
1461 /* If no jcr or no queue or dequeuing send to syslog */
1462 if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1463 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1466 /* Queue message for later sending */
1467 P(jcr->msg_queue_mutex);
1468 jcr->msg_queue->append(item);
1469 V(jcr->msg_queue_mutex);
1471 free_memory(pool_buf);
1477 void dequeue_messages(JCR *jcr)
1480 if (!jcr->msg_queue) {
1483 P(jcr->msg_queue_mutex);
1484 jcr->dequeuing_msgs = true;
1485 foreach_dlist(item, jcr->msg_queue) {
1486 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1488 /* Remove messages just sent */
1489 jcr->msg_queue->destroy();
1490 jcr->dequeuing_msgs = false;
1491 V(jcr->msg_queue_mutex);
1496 * If we come here, prefix the message with the file:line-number,
1497 * then pass it on to the normal Qmsg routine.
1499 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1505 pool_buf = get_pool_memory(PM_EMSG);
1506 i = Mmsg(pool_buf, "%s:%d ", file, line);
1509 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1510 va_start(arg_ptr, fmt);
1511 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1513 if (len < 0 || len >= (maxlen-5)) {
1514 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1520 Qmsg(jcr, type, mtime, "%s", pool_buf);
1521 free_memory(pool_buf);