2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2011 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;
95 /* Some message class methods */
107 * Wait for not in use variable to be clear
109 void MSGS::wait_not_in_use() /* leaves fides_mutex set */
114 bmicrosleep(0, 200); /* wait */
120 * Handle message delivery errors
122 static void delivery_error(const char *fmt,...)
127 char dt[MAX_TIME_LENGTH];
130 pool_buf = get_pool_memory(PM_EMSG);
132 bstrftime_ny(dt, sizeof(dt), time(NULL));
137 i = Mmsg(pool_buf, "%s Message delivery ERROR: ", dt);
140 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
141 va_start(arg_ptr, fmt);
142 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
144 if (len < 0 || len >= (maxlen-5)) {
145 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
151 fputs(pool_buf, stdout); /* print this here to INSURE that it is printed */
153 syslog(LOG_DAEMON|LOG_ERR, "%s", pool_buf);
154 free_memory(pool_buf);
157 void register_message_callback(void msg_callback(int type, char *msg))
159 message_callback = msg_callback;
164 * Set daemon name. Also, find canonical execution
165 * path. Note, exepath has spare room for tacking on
166 * the exename so that we can reconstruct the full name.
168 * Note, this routine can get called multiple times
169 * The second time is to put the name as found in the
170 * Resource record. On the second call, generally,
171 * argv is NULL to avoid doing the path code twice.
173 void my_name_is(int argc, char *argv[], const char *name)
179 if (gethostname(host_name, sizeof(host_name)) != 0) {
180 bstrncpy(host_name, "Hostname unknown", sizeof(host_name));
182 bstrncpy(my_name, name, sizeof(my_name));
183 if (argc>0 && argv && argv[0]) {
184 /* strip trailing filename and save exepath */
185 for (l=p=argv[0]; *p; p++) {
186 if (IsPathSeparator(*p)) {
187 l = p; /* set pos of last slash */
190 if (IsPathSeparator(*l)) {
194 #if defined(HAVE_WIN32)
195 /* On Windows allow c: drive specification */
205 exename = (char *)malloc(len);
211 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
212 for (p=argv[0],q=exepath; p < l; ) {
216 if (strchr(exepath, '.') || !IsPathSeparator(exepath[0])) {
217 if (getcwd(cpath, sizeof(cpath))) {
219 exepath = (char *)malloc(strlen(cpath) + 1 + len);
220 strcpy(exepath, cpath);
223 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
228 set_db_type(const char *name)
230 if (catalog_db != NULL) {
233 catalog_db = bstrdup(name);
237 * Initialize message handler for a daemon or a Job
238 * We make a copy of the MSGS resource passed, so it belows
239 * to the job or daemon and thus can be modified.
241 * NULL for jcr -> initialize global messages for daemon
242 * non-NULL -> initialize jcr using Message resource
245 init_msg(JCR *jcr, MSGS *msg)
247 DEST *d, *dnew, *temp_chain = NULL;
250 if (jcr == NULL && msg == NULL) {
251 init_last_jobs_list();
252 /* Create a daemon key then set invalid jcr */
253 /* Maybe we should give the daemon a jcr??? */
255 set_jcr_in_tsd(INVALID_JCR);
258 #if !defined(HAVE_WIN32)
260 * Make sure we have fd's 0, 1, 2 open
261 * If we don't do this one of our sockets may open
262 * there and if we then use stdout, it could
263 * send total garbage to our socket.
267 fd = open("/dev/null", O_RDONLY, 0644);
271 for(i=1; fd + i <= 2; i++) {
278 * If msg is NULL, initialize global chain for STDOUT and syslog
281 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
282 memset(daemon_msgs, 0, sizeof(MSGS));
283 for (i=1; i<=M_MAX; i++) {
284 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
286 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
291 * Walk down the message resource chain duplicating it
292 * for the current Job.
294 for (d=msg->dest_chain; d; d=d->next) {
295 dnew = (DEST *)malloc(sizeof(DEST));
296 memcpy(dnew, d, sizeof(DEST));
297 dnew->next = temp_chain;
299 dnew->mail_filename = NULL;
301 dnew->mail_cmd = bstrdup(d->mail_cmd);
304 dnew->where = bstrdup(d->where);
310 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
311 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
312 jcr->jcr_msgs->dest_chain = temp_chain;
313 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
315 /* If we have default values, release them now */
317 free_msgs_res(daemon_msgs);
319 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
320 memset(daemon_msgs, 0, sizeof(MSGS));
321 daemon_msgs->dest_chain = temp_chain;
322 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
325 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
329 /* Initialize so that the console (User Agent) can
330 * receive messages -- stored in a file.
332 void init_console_msg(const char *wd)
336 bsnprintf(con_fname, sizeof(con_fname), "%s%c%s.conmsg", wd, PathSeparator, my_name);
337 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
340 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
341 con_fname, be.bstrerror());
343 if (lseek(fd, 0, SEEK_END) > 0) {
344 console_msg_pending = 1;
347 con_fd = fopen(con_fname, "a+b");
350 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
351 con_fname, be.bstrerror());
353 if (rwl_init(&con_lock) != 0) {
355 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
361 * Called only during parsing of the config file.
363 * Add a message destination. I.e. associate a message type with
364 * a destination (code).
365 * Note, where in the case of dest_code FILE is a filename,
366 * but in the case of MAIL is a space separated list of
367 * email addresses, ...
369 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
373 * First search the existing chain and see if we
374 * can simply add this msg_type to an existing entry.
376 for (d=msg->dest_chain; d; d=d->next) {
377 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
378 (strcmp(where, d->where) == 0))) {
379 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
380 d, msg_type, dest_code, NPRT(where));
381 set_bit(msg_type, d->msg_types);
382 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
386 /* Not found, create a new entry */
387 d = (DEST *)malloc(sizeof(DEST));
388 memset(d, 0, sizeof(DEST));
389 d->next = msg->dest_chain;
390 d->dest_code = dest_code;
391 set_bit(msg_type, d->msg_types); /* set type bit in structure */
392 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
394 d->where = bstrdup(where);
397 d->mail_cmd = bstrdup(mail_cmd);
399 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
400 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
405 * Called only during parsing of the config file.
407 * Remove a message destination
409 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
413 for (d=msg->dest_chain; d; d=d->next) {
414 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
415 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
416 ((where == NULL && d->where == NULL) ||
417 (strcmp(where, d->where) == 0))) {
418 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
419 d, msg_type, dest_code);
420 clear_bit(msg_type, d->msg_types);
421 Dmsg0(850, "Return rem_msg_dest\n");
429 * Create a unique filename for the mail command
431 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
434 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
435 jcr->Job, (int)(intptr_t)d);
437 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
438 my_name, (int)(intptr_t)d);
440 Dmsg1(850, "mailname=%s\n", name);
446 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
451 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
453 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
457 if ((bpipe = open_bpipe(cmd, 120, "rw"))) {
458 /* If we had to use sendmail, add subject */
460 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
464 delivery_error(_("open mail pipe %s failed: ERR=%s\n"),
465 cmd, be.bstrerror());
471 * Close the messages for this Messages resource, which means to close
472 * any open files, and dispatch any pending email messages.
474 void close_msg(JCR *jcr)
482 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
484 if (jcr == NULL) { /* NULL -> global chain */
487 msgs = jcr->jcr_msgs;
488 jcr->jcr_msgs = NULL;
494 /* Wait for item to be not in use, then mark closing */
495 if (msgs->is_closing()) {
498 msgs->wait_not_in_use(); /* leaves fides_mutex set */
502 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
503 cmd = get_pool_memory(PM_MESSAGE);
504 for (d=msgs->dest_chain; d; ) {
506 switch (d->dest_code) {
510 fclose(d->fd); /* close open file descriptor */
515 case MD_MAIL_ON_ERROR:
516 case MD_MAIL_ON_SUCCESS:
517 Dmsg0(850, "Got MD_MAIL, MD_MAIL_ON_ERROR or MD_MAIL_ON_SUCCESS\n");
522 (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
523 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
525 (d->dest_code == MD_MAIL_ON_SUCCESS && jcr &&
526 jcr->JobStatus == JS_ErrorTerminated)
531 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
532 Pmsg0(000, _("open mail pipe failed.\n"));
535 Dmsg0(850, "Opened mail pipe\n");
537 line = get_memory(len);
539 while (fgets(line, len, d->fd)) {
540 fputs(line, bpipe->wfd);
542 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
544 Pmsg1(000, _("close error: ERR=%s\n"), be.bstrerror());
548 * Since we are closing all messages, before "recursing"
549 * make sure we are not closing the daemon messages, otherwise
552 if (msgs != daemon_msgs) {
553 /* read what mail prog returned -- should be nothing */
554 while (fgets(line, len, bpipe->rfd)) {
555 delivery_error(_("Mail prog: %s"), line);
559 stat = close_bpipe(bpipe);
560 if (stat != 0 && msgs != daemon_msgs) {
563 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
564 delivery_error(_("Mail program terminated in error.\n"
566 "ERR=%s\n"), cmd, be.bstrerror());
570 /* Remove temp file */
573 unlink(d->mail_filename);
574 free_pool_memory(d->mail_filename);
575 d->mail_filename = NULL;
576 Dmsg0(850, "end mail or mail on error\n");
583 d = d->next; /* point to next buffer */
585 free_pool_memory(cmd);
586 Dmsg0(850, "Done walking message chain.\n");
591 msgs->clear_closing();
593 Dmsg0(850, "===End close msg resource\n");
597 * Free memory associated with Messages resource
599 void free_msgs_res(MSGS *msgs)
603 /* Walk down the message chain releasing allocated buffers */
604 for (d=msgs->dest_chain; d; ) {
611 old = d; /* save pointer to release */
612 d = d->next; /* point to next buffer */
613 free(old); /* free the destination item */
615 msgs->dest_chain = NULL;
616 free(msgs); /* free the head */
621 * Terminate the message handler for good.
622 * Release the global destination chain.
624 * Also, clean up a few other items (cons, exepath). Note,
625 * these really should be done elsewhere.
629 Dmsg0(850, "Enter term_msg\n");
630 close_msg(NULL); /* close global chain */
631 free_msgs_res(daemon_msgs); /* free the resources */
654 term_last_jobs_list();
657 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
659 d->fd = fopen(d->where, mode);
662 delivery_error(_("fopen %s failed: ERR=%s\n"), d->where, be.bstrerror());
668 /* Split the output for syslog (it converts \n to ' ' and is
669 * limited to 1024 characters per syslog message
671 static void send_to_syslog(int mode, const char *msg)
678 while (*p && ((p2 = strchr(p, '\n')) != NULL)) {
679 len = MIN((int)sizeof(buf) - 1, p2 - p + 1); /* Add 1 to keep \n */
680 strncpy(buf, p, len);
682 syslog(mode, "%s", buf);
683 p = p2+1; /* skip \n */
685 if (*p != 0) { /* no \n at the end ? */
686 syslog(mode, "%s", p);
691 * Handle sending the message to the appropriate place
693 void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
696 char dt[MAX_TIME_LENGTH];
703 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
706 * Most messages are prefixed by a date and time. If mtime is
707 * zero, then we use the current time. If mtime is 1 (special
708 * kludge), we do not prefix the date and time. Otherwise,
709 * we assume mtime is a utime_t and use it.
717 mtime = time(NULL); /* get time for SQL log */
719 bstrftime_ny(dt, sizeof(dt), mtime);
725 /* If the program registered a callback, send it there */
726 if (message_callback) {
727 message_callback(type, msg);
731 /* For serious errors make sure message is printed or logged */
732 if (type == M_ABORT || type == M_ERROR_TERM) {
736 if (type == M_ABORT) {
737 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
742 /* Now figure out where to send the message */
745 jcr = get_jcr_from_tsd();
748 msgs = jcr->jcr_msgs;
754 * If closing this message resource, print and send to syslog,
757 if (msgs->is_closing()) {
761 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
765 for (d=msgs->dest_chain; d; d=d->next) {
766 if (bit_is_set(type, d->msg_types)) {
767 switch (d->dest_code) {
770 if (!jcr || !jcr->db) {
773 if (p_sql_query && p_sql_escape) {
774 POOLMEM *cmd = get_pool_memory(PM_MESSAGE);
775 POOLMEM *esc_msg = get_pool_memory(PM_MESSAGE);
777 int len = strlen(msg) + 1;
778 esc_msg = check_pool_memory_size(esc_msg, len*2+1);
779 p_sql_escape(jcr, jcr->db, esc_msg, msg, len);
781 bstrutime(dt, sizeof(dt), mtime);
782 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
783 edit_int64(jcr->JobId, ed1), dt, esc_msg);
784 p_sql_query(jcr, cmd);
786 free_pool_memory(cmd);
787 free_pool_memory(esc_msg);
791 Dmsg1(850, "CONSOLE for following msg: %s", msg);
793 con_fd = fopen(con_fname, "a+b");
794 Dmsg0(850, "Console file not open.\n");
797 Pw(con_lock); /* get write lock on console message file */
800 (void)fwrite(dt, dtlen, 1, con_fd);
804 (void)fwrite(msg, len, 1, con_fd);
805 if (msg[len-1] != '\n') {
806 (void)fwrite("\n", 2, 1, con_fd);
809 (void)fwrite("\n", 2, 1, con_fd);
812 console_msg_pending = true;
817 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
819 * We really should do an openlog() here.
821 send_to_syslog(LOG_DAEMON|LOG_ERR, msg);
824 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
825 mcmd = get_pool_memory(PM_MESSAGE);
826 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
828 fputs(dt, bpipe->wfd);
829 fputs(msg, bpipe->wfd);
830 /* Messages to the operator go one at a time */
831 stat = close_bpipe(bpipe);
835 delivery_error(_("Msg delivery error: Operator mail program terminated in error.\n"
837 "ERR=%s\n"), mcmd, be.bstrerror());
840 free_pool_memory(mcmd);
843 case MD_MAIL_ON_ERROR:
844 case MD_MAIL_ON_SUCCESS:
845 Dmsg1(850, "MAIL for following msg: %s", msg);
846 if (msgs->is_closing()) {
851 POOLMEM *name = get_pool_memory(PM_MESSAGE);
852 make_unique_mail_filename(jcr, name, d);
853 d->fd = fopen(name, "w+b");
856 delivery_error(_("Msg delivery error: fopen %s failed: ERR=%s\n"), name,
858 free_pool_memory(name);
859 msgs->clear_in_use();
862 d->mail_filename = name;
865 len = strlen(msg) + dtlen;;
866 if (len > d->max_len) {
867 d->max_len = len; /* keep max line length */
870 msgs->clear_in_use();
873 Dmsg1(850, "APPEND for following msg: %s", msg);
877 Dmsg1(850, "FILE for following msg: %s", msg);
880 if (msgs->is_closing()) {
884 if (!d->fd && !open_dest_file(jcr, d, mode)) {
885 msgs->clear_in_use();
890 /* On error, we close and reopen to handle log rotation */
894 if (open_dest_file(jcr, d, mode)) {
899 msgs->clear_in_use();
902 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
903 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
904 jcr->dir_bsock->fsend("Jmsg Job=%s type=%d level=%lld %s",
905 jcr->Job, type, mtime, msg);
907 Dmsg1(800, "no jcr for following msg: %s", msg);
911 Dmsg1(850, "STDOUT for following msg: %s", msg);
912 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
919 Dmsg1(850, "STDERR for following msg: %s", msg);
931 /*********************************************************************
933 * This subroutine returns the filename portion of a path.
934 * It is used because some compilers set __FILE__
935 * to the full path. Try to return base + next higher path.
938 const char *get_basename(const char *pathname)
940 const char *basename, *basename2;
942 if ((basename = strrchr(pathname, PathSeparator)) == NULL) {
944 if ((basename2 = strrchr(pathname, PathSeparator)) != NULL) {
945 basename = basename2 + 1;
955 * print or write output to trace file
957 static void pt_out(char *buf)
960 * Used the "trace on" command in the console to turn on
961 * output to the trace file. "trace off" will close the file.
966 bsnprintf(fn, sizeof(fn), "%s/%s.trace", working_directory ? working_directory : "./", my_name);
967 trace_fd = fopen(fn, "a+b");
970 fputs(buf, trace_fd);
974 /* Some problem, turn off tracing */
983 /*********************************************************************
985 * This subroutine prints a debug message if the level number
986 * is less than or equal the debug_level. File and line numbers
987 * are included for more detail if desired, but not currently
990 * If the level is negative, the details of file and line number
994 d_msg(const char *file, int line, int level, const char *fmt,...)
1007 if (level <= debug_level) {
1008 if (dbg_timestamp) {
1010 bstrftimes(buf, sizeof(buf), mtime);
1017 #ifdef FULL_LOCATION
1019 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d-%u ",
1020 my_name, get_basename(file), line, get_jobid_from_tsd());
1027 va_start(arg_ptr, fmt);
1028 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1036 * Set trace flag on/off. If argument is negative, there is no change
1038 void set_trace(int trace_flag)
1040 if (trace_flag < 0) {
1042 } else if (trace_flag > 0) {
1047 if (!trace && trace_fd) {
1048 FILE *ltrace_fd = trace_fd;
1050 bmicrosleep(0, 100000); /* yield to prevent seg faults */
1055 void set_hangup(int hangup_value)
1057 if (hangup_value < 0) {
1060 hangup = hangup_value;
1064 int get_hangup(void)
1069 bool get_trace(void)
1074 /*********************************************************************
1076 * This subroutine prints a message regardless of the debug level
1078 * If the level is negative, the details of file and line number
1082 p_msg(const char *file, int line, int level, const char *fmt,...)
1088 #ifdef FULL_LOCATION
1090 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1097 va_start(arg_ptr, fmt);
1098 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1105 /*********************************************************************
1107 * subroutine writes a debug message to the trace file if the level number
1108 * is less than or equal the debug_level. File and line numbers
1109 * are included for more detail if desired, but not currently
1112 * If the level is negative, the details of file and line number
1116 t_msg(const char *file, int line, int level, const char *fmt,...)
1128 if (level <= debug_level) {
1130 bsnprintf(buf, sizeof(buf), "%s/%s.trace", working_directory ? working_directory : ".", my_name);
1131 trace_fd = fopen(buf, "a+b");
1134 #ifdef FULL_LOCATION
1136 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
1143 va_start(arg_ptr, fmt);
1144 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1146 if (trace_fd != NULL) {
1147 fputs(buf, trace_fd);
1153 /* *********************************************************
1155 * print an error message
1159 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
1166 * Check if we have a message destination defined.
1167 * We always report M_ABORT and M_ERROR_TERM
1169 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
1170 !bit_is_set(type, daemon_msgs->send_msg))) {
1171 return; /* no destination */
1175 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
1176 my_name, get_basename(file), line);
1179 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
1180 my_name, get_basename(file), line);
1183 if (level == -1) /* skip details */
1184 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
1186 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
1189 if (level == -1) /* skip details */
1190 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
1192 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
1195 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
1198 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
1201 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
1205 va_start(arg_ptr, fmt);
1206 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1209 dispatch_message(NULL, type, 0, buf);
1211 if (type == M_ABORT) {
1213 p[0] = 0; /* generate segmentation violation */
1215 if (type == M_ERROR_TERM) {
1220 /* *********************************************************
1222 * Generate a Job message
1226 Jmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1235 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1237 /* Special case for the console, which has a dir_bsock and JobId==0,
1238 * in that case, we send the message directly back to the
1241 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1242 BSOCK *dir = jcr->dir_bsock;
1243 va_start(arg_ptr, fmt);
1244 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1247 jcr->dir_bsock->send();
1251 /* The watchdog thread can't use Jmsg directly, we always queued it */
1252 if (is_watchdog()) {
1253 va_start(arg_ptr, fmt);
1254 bvsnprintf(rbuf, sizeof(rbuf), fmt, arg_ptr);
1256 Qmsg(jcr, type, mtime, "%s", rbuf);
1262 jcr = get_jcr_from_tsd();
1265 if (!jcr->dequeuing_msgs) { /* Avoid recursion */
1266 /* Dequeue messages to keep the original order */
1267 dequeue_messages(jcr);
1269 msgs = jcr->jcr_msgs;
1273 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1277 * Check if we have a message destination defined.
1278 * We always report M_ABORT and M_ERROR_TERM
1280 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1281 !bit_is_set(type, msgs->send_msg)) {
1282 return; /* no destination */
1286 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1289 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1292 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Fatal error: "), my_name, JobId);
1294 jcr->setJobStatus(JS_FatalError);
1296 if (jcr && jcr->JobErrors == 0) {
1301 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Error: "), my_name, JobId);
1307 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Warning: "), my_name, JobId);
1313 len = bsnprintf(rbuf, sizeof(rbuf), _("%s JobId %u: Security violation: "),
1317 len = bsnprintf(rbuf, sizeof(rbuf), "%s JobId %u: ", my_name, JobId);
1321 va_start(arg_ptr, fmt);
1322 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1325 dispatch_message(jcr, type, mtime, rbuf);
1327 if (type == M_ABORT){
1329 printf("Bacula forced SEG FAULT to obtain traceback.\n");
1330 syslog(LOG_DAEMON|LOG_ERR, "Bacula forced SEG FAULT to obtain traceback.\n");
1331 p[0] = 0; /* generate segmentation violation */
1333 if (type == M_ERROR_TERM) {
1339 * If we come here, prefix the message with the file:line-number,
1340 * then pass it on to the normal Jmsg routine.
1342 void j_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1348 pool_buf = get_pool_memory(PM_EMSG);
1349 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1352 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1353 va_start(arg_ptr, fmt);
1354 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1356 if (len < 0 || len >= (maxlen-5)) {
1357 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1363 Jmsg(jcr, type, mtime, "%s", pool_buf);
1364 free_memory(pool_buf);
1369 * Edit a message into a Pool memory buffer, with file:lineno
1371 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1376 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1379 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1380 va_start(arg_ptr, fmt);
1381 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1383 if (len < 0 || len >= (maxlen-5)) {
1384 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1392 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1397 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1400 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1401 va_start(arg_ptr, fmt);
1402 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1404 if (len < 0 || len >= (maxlen-5)) {
1405 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1415 * Edit a message into a Pool Memory buffer NO file:lineno
1416 * Returns: string length of what was edited.
1418 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1424 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1425 va_start(arg_ptr, fmt);
1426 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1428 if (len < 0 || len >= (maxlen-5)) {
1429 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1437 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1443 maxlen = sizeof_pool_memory(pool_buf) - 1;
1444 va_start(arg_ptr, fmt);
1445 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1447 if (len < 0 || len >= (maxlen-5)) {
1448 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1456 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1462 maxlen = pool_buf.max_size() - 1;
1463 va_start(arg_ptr, fmt);
1464 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1466 if (len < 0 || len >= (maxlen-5)) {
1467 pool_buf.realloc_pm(maxlen + maxlen/2);
1477 * We queue messages rather than print them directly. This
1478 * is generally used in low level routines (msg handler, bnet)
1479 * to prevent recursion (i.e. if you are in the middle of
1480 * sending a message, it is a bit messy to recursively call
1481 * yourself when the bnet packet is not reentrant).
1483 void Qmsg(JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1490 pool_buf = get_pool_memory(PM_EMSG);
1493 maxlen = sizeof_pool_memory(pool_buf) - 1;
1494 va_start(arg_ptr, fmt);
1495 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1497 if (len < 0 || len >= (maxlen-5)) {
1498 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1503 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1505 item->mtime = time(NULL);
1506 strcpy(item->msg, pool_buf);
1508 jcr = get_jcr_from_tsd();
1510 /* If no jcr or no queue or dequeuing send to syslog */
1511 if (!jcr || !jcr->msg_queue || jcr->dequeuing_msgs) {
1512 syslog(LOG_DAEMON|LOG_ERR, "%s", item->msg);
1515 /* Queue message for later sending */
1516 P(jcr->msg_queue_mutex);
1517 jcr->msg_queue->append(item);
1518 V(jcr->msg_queue_mutex);
1520 free_memory(pool_buf);
1526 void dequeue_messages(JCR *jcr)
1529 if (!jcr->msg_queue) {
1532 P(jcr->msg_queue_mutex);
1533 jcr->dequeuing_msgs = true;
1534 foreach_dlist(item, jcr->msg_queue) {
1535 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1537 /* Remove messages just sent */
1538 jcr->msg_queue->destroy();
1539 jcr->dequeuing_msgs = false;
1540 V(jcr->msg_queue_mutex);
1545 * If we come here, prefix the message with the file:line-number,
1546 * then pass it on to the normal Qmsg routine.
1548 void q_msg(const char *file, int line, JCR *jcr, int type, utime_t mtime, const char *fmt,...)
1554 pool_buf = get_pool_memory(PM_EMSG);
1555 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1558 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1559 va_start(arg_ptr, fmt);
1560 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1562 if (len < 0 || len >= (maxlen-5)) {
1563 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1569 Qmsg(jcr, type, mtime, "%s", pool_buf);
1570 free_memory(pool_buf);