2 * Bacula message handling routines
4 * Kern Sibbald, April 2000
10 Copyright (C) 2000-2006 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
29 sql_query p_sql_query = NULL;
31 #define FULL_LOCATION 1 /* set for file:line in Debug messages */
34 * This is where we define "Globals" because all the
35 * daemons include this file.
37 const char *working_directory = NULL; /* working directory path stored here */
38 int verbose = 0; /* increase User messages */
39 int debug_level = 0; /* debug level */
40 time_t daemon_start_time = 0; /* Daemon start time */
41 const char *version = VERSION " (" BDATE ")";
42 char my_name[30]; /* daemon name is stored here */
43 char *exepath = (char *)NULL;
44 char *exename = (char *)NULL;
45 int console_msg_pending = 0;
46 char con_fname[500]; /* Console filename */
47 FILE *con_fd = NULL; /* Console file descriptor */
48 brwlock_t con_lock; /* Console lock structure */
50 static char *catalog_db = NULL; /* database type */
52 const char *host_os = HOST_OS;
53 const char *distname = DISTNAME;
54 const char *distver = DISTVER;
55 static FILE *trace_fd = NULL;
56 #if defined(HAVE_WIN32)
57 static bool trace = true;
59 static bool trace = false;
62 /* Forward referenced functions */
64 /* Imported functions */
69 /* Used to allow only one thread close the daemon messages at a time */
70 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
71 static MSGS *daemon_msgs; /* global messages */
75 * Set daemon name. Also, find canonical execution
76 * path. Note, exepath has spare room for tacking on
77 * the exename so that we can reconstruct the full name.
79 * Note, this routine can get called multiple times
80 * The second time is to put the name as found in the
81 * Resource record. On the second call, generally,
82 * argv is NULL to avoid doing the path code twice.
84 #define BTRACE_EXTRA 20
85 void my_name_is(int argc, char *argv[], const char *name)
91 bstrncpy(my_name, name, sizeof(my_name));
92 if (argc>0 && argv && argv[0]) {
93 /* strip trailing filename and save exepath */
94 for (l=p=argv[0]; *p; p++) {
96 l = p; /* set pos of last slash */
103 #if defined(HAVE_WIN32)
104 /* On Windows allow c: junk */
114 exename = (char *)malloc(len);
120 exepath = (char *)malloc(strlen(argv[0]) + 1 + len);
121 for (p=argv[0],q=exepath; p < l; ) {
125 if (strchr(exepath, '.') || exepath[0] != '/') {
126 if (getcwd(cpath, sizeof(cpath))) {
128 exepath = (char *)malloc(strlen(cpath) + 1 + len);
129 strcpy(exepath, cpath);
132 Dmsg2(500, "exepath=%s\nexename=%s\n", exepath, exename);
139 return catalog_db != NULL ? catalog_db : "unknown";
143 set_db_type(const char *name)
145 if (catalog_db != NULL)
150 catalog_db = bstrdup(name);
154 * Initialize message handler for a daemon or a Job
155 * We make a copy of the MSGS resource passed, so it belows
156 * to the job or daemon and thus can be modified.
158 * NULL for jcr -> initialize global messages for daemon
159 * non-NULL -> initialize jcr using Message resource
162 init_msg(JCR *jcr, MSGS *msg)
164 DEST *d, *dnew, *temp_chain = NULL;
166 if (jcr == NULL && msg == NULL) {
167 init_last_jobs_list();
170 #if !defined(HAVE_WIN32)
172 * Make sure we have fd's 0, 1, 2 open
173 * If we don't do this one of our sockets may open
174 * there and if we then use stdout, it could
175 * send total garbage to our socket.
180 fd = open("/dev/null", O_RDONLY, 0644);
184 for(i=1; fd + i <= 2; i++) {
191 * If msg is NULL, initialize global chain for STDOUT and syslog
194 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
195 memset(daemon_msgs, 0, sizeof(MSGS));
196 #if !defined(HAVE_WIN32)
197 for (i=1; i<=M_MAX; i++) {
198 add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
201 Dmsg1(050, "Create daemon global message resource %p\n", daemon_msgs);
206 * Walk down the message resource chain duplicating it
207 * for the current Job.
209 for (d=msg->dest_chain; d; d=d->next) {
210 dnew = (DEST *)malloc(sizeof(DEST));
211 memcpy(dnew, d, sizeof(DEST));
212 dnew->next = temp_chain;
214 dnew->mail_filename = NULL;
216 dnew->mail_cmd = bstrdup(d->mail_cmd);
219 dnew->where = bstrdup(d->where);
225 jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
226 memset(jcr->jcr_msgs, 0, sizeof(MSGS));
227 jcr->jcr_msgs->dest_chain = temp_chain;
228 memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
230 /* If we have default values, release them now */
232 free_msgs_res(daemon_msgs);
234 daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
235 memset(daemon_msgs, 0, sizeof(MSGS));
236 daemon_msgs->dest_chain = temp_chain;
237 memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
239 Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
243 /* Initialize so that the console (User Agent) can
244 * receive messages -- stored in a file.
246 void init_console_msg(const char *wd)
250 bsnprintf(con_fname, sizeof(con_fname), "%s/%s.conmsg", wd, my_name);
251 fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
254 Emsg2(M_ERROR_TERM, 0, _("Could not open console message file %s: ERR=%s\n"),
255 con_fname, be.strerror());
257 if (lseek(fd, 0, SEEK_END) > 0) {
258 console_msg_pending = 1;
261 con_fd = fopen(con_fname, "a+b");
264 Emsg2(M_ERROR, 0, _("Could not open console message file %s: ERR=%s\n"),
265 con_fname, be.strerror());
267 if (rwl_init(&con_lock) != 0) {
269 Emsg1(M_ERROR_TERM, 0, _("Could not get con mutex: ERR=%s\n"),
275 * Called only during parsing of the config file.
277 * Add a message destination. I.e. associate a message type with
278 * a destination (code).
279 * Note, where in the case of dest_code FILE is a filename,
280 * but in the case of MAIL is a space separated list of
281 * email addresses, ...
283 void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
287 * First search the existing chain and see if we
288 * can simply add this msg_type to an existing entry.
290 for (d=msg->dest_chain; d; d=d->next) {
291 if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
292 (strcmp(where, d->where) == 0))) {
293 Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n",
294 d, msg_type, dest_code, NPRT(where));
295 set_bit(msg_type, d->msg_types);
296 set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
300 /* Not found, create a new entry */
301 d = (DEST *)malloc(sizeof(DEST));
302 memset(d, 0, sizeof(DEST));
303 d->next = msg->dest_chain;
304 d->dest_code = dest_code;
305 set_bit(msg_type, d->msg_types); /* set type bit in structure */
306 set_bit(msg_type, msg->send_msg); /* set type bit in our local */
308 d->where = bstrdup(where);
311 d->mail_cmd = bstrdup(mail_cmd);
313 Dmsg5(850, "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s\n",
314 d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd));
319 * Called only during parsing of the config file.
321 * Remove a message destination
323 void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
327 for (d=msg->dest_chain; d; d=d->next) {
328 Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NPRT(d->where));
329 if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
330 ((where == NULL && d->where == NULL) ||
331 (strcmp(where, d->where) == 0))) {
332 Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n",
333 d, msg_type, dest_code);
334 clear_bit(msg_type, d->msg_types);
335 Dmsg0(850, "Return rem_msg_dest\n");
343 * Create a unique filename for the mail command
345 static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d)
348 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
349 jcr->Job, (int)(long)d);
351 Mmsg(name, "%s/%s.%s.%d.mail", working_directory, my_name,
352 my_name, (int)(long)d);
354 Dmsg1(850, "mailname=%s\n", name);
360 static BPIPE *open_mail_pipe(JCR *jcr, POOLMEM *&cmd, DEST *d)
365 cmd = edit_job_codes(jcr, cmd, d->mail_cmd, d->where);
367 Mmsg(cmd, "/usr/lib/sendmail -F Bacula %s", d->where);
371 if (!(bpipe = open_bpipe(cmd, 120, "rw"))) {
373 Jmsg(jcr, M_ERROR, 0, _("open mail pipe %s failed: ERR=%s\n"),
377 /* If we had to use sendmail, add subject */
379 fprintf(bpipe->wfd, "Subject: %s\r\n\r\n", _("Bacula Message"));
386 * Close the messages for this Messages resource, which means to close
387 * any open files, and dispatch any pending email messages.
389 void close_msg(JCR *jcr)
397 Dmsg1(580, "Close_msg jcr=%p\n", jcr);
399 if (jcr == NULL) { /* NULL -> global chain */
401 P(mutex); /* only one thread walking the chain */
403 msgs = jcr->jcr_msgs;
404 jcr->jcr_msgs = NULL;
409 Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
410 cmd = get_pool_memory(PM_MESSAGE);
411 for (d=msgs->dest_chain; d; ) {
413 switch (d->dest_code) {
417 fclose(d->fd); /* close open file descriptor */
421 case MD_MAIL_ON_ERROR:
422 Dmsg0(850, "Got MD_MAIL or MD_MAIL_ON_ERROR\n");
426 if (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
427 jcr->JobStatus == JS_Terminated) {
431 if (!(bpipe=open_mail_pipe(jcr, cmd, d))) {
432 Pmsg0(000, _("open mail pipe failed.\n"));
435 Dmsg0(850, "Opened mail pipe\n");
437 line = get_memory(len);
439 while (fgets(line, len, d->fd)) {
440 fputs(line, bpipe->wfd);
442 if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
444 Pmsg1(000, _("close error: ERR=%s\n"), be.strerror());
448 * Since we are closing all messages, before "recursing"
449 * make sure we are not closing the daemon messages, otherwise
452 if (msgs != daemon_msgs) {
453 /* read what mail prog returned -- should be nothing */
454 while (fgets(line, len, bpipe->rfd)) {
455 Jmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line);
459 stat = close_bpipe(bpipe);
460 if (stat != 0 && msgs != daemon_msgs) {
463 Dmsg1(850, "Calling emsg. CMD=%s\n", cmd);
464 Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n"
466 "ERR=%s\n"), cmd, be.strerror());
470 /* Remove temp file */
472 unlink(d->mail_filename);
473 free_pool_memory(d->mail_filename);
474 d->mail_filename = NULL;
475 Dmsg0(850, "end mail or mail on error\n");
482 d = d->next; /* point to next buffer */
484 free_pool_memory(cmd);
485 Dmsg0(850, "Done walking message chain.\n");
492 Dmsg0(850, "===End close msg resource\n");
496 * Free memory associated with Messages resource
498 void free_msgs_res(MSGS *msgs)
502 /* Walk down the message chain releasing allocated buffers */
503 for (d=msgs->dest_chain; d; ) {
510 old = d; /* save pointer to release */
511 d = d->next; /* point to next buffer */
512 free(old); /* free the destination item */
514 msgs->dest_chain = NULL;
515 free(msgs); /* free the head */
520 * Terminate the message handler for good.
521 * Release the global destination chain.
523 * Also, clean up a few other items (cons, exepath). Note,
524 * these really should be done elsewhere.
528 Dmsg0(850, "Enter term_msg\n");
529 close_msg(NULL); /* close global chain */
530 free_msgs_res(daemon_msgs); /* free the resources */
549 term_last_jobs_list();
552 static bool open_dest_file(JCR *jcr, DEST *d, const char *mode)
554 d->fd = fopen(d->where, mode);
558 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), d->where,
567 * Handle sending the message to the appropriate place
569 void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg)
572 char dt[MAX_TIME_LENGTH];
579 Dmsg2(850, "Enter dispatch_msg type=%d msg=%s", type, msg);
582 * Most messages are prefixed by a date and time. If mtime is
583 * zero, then we use the current time. If mtime is 1 (special
584 * kludge), we do not prefix the date and time. Otherwise,
585 * we assume mtime is a time_t and use it.
594 bstrftime_ny(dt, sizeof(dt), mtime);
600 if (type == M_ABORT || type == M_ERROR_TERM) {
601 #if !defined(HAVE_WIN32)
603 fputs(msg, stdout); /* print this here to INSURE that it is printed */
608 /* Now figure out where to send the message */
611 msgs = jcr->jcr_msgs;
616 for (d=msgs->dest_chain; d; d=d->next) {
617 if (bit_is_set(type, d->msg_types)) {
618 switch (d->dest_code) {
621 if (!jcr || !jcr->db) {
625 POOL_MEM cmd(PM_MESSAGE);
626 bstrftimes(dt, sizeof(dt), mtime);
627 Mmsg(cmd, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')",
628 edit_int64(jcr->JobId, ed1), dt, msg);
629 p_sql_query(jcr, cmd.c_str());
633 Dmsg1(850, "CONSOLE for following msg: %s", msg);
635 con_fd = fopen(con_fname, "a+b");
636 Dmsg0(850, "Console file not open.\n");
639 Pw(con_lock); /* get write lock on console message file */
642 (void)fwrite(dt, dtlen, 1, con_fd);
646 (void)fwrite(msg, len, 1, con_fd);
647 if (msg[len-1] != '\n') {
648 (void)fwrite("\n", 2, 1, con_fd);
651 (void)fwrite("\n", 2, 1, con_fd);
654 console_msg_pending = TRUE;
659 Dmsg1(850, "SYSLOG for following msg: %s\n", msg);
661 * We really should do an openlog() here.
663 syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
666 Dmsg1(850, "OPERATOR for following msg: %s\n", msg);
667 mcmd = get_pool_memory(PM_MESSAGE);
668 if ((bpipe=open_mail_pipe(jcr, mcmd, d))) {
670 fputs(dt, bpipe->wfd);
671 fputs(msg, bpipe->wfd);
672 /* Messages to the operator go one at a time */
673 stat = close_bpipe(bpipe);
677 Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n"
679 "ERR=%s\n"), mcmd, be.strerror());
682 free_pool_memory(mcmd);
685 case MD_MAIL_ON_ERROR:
686 Dmsg1(850, "MAIL for following msg: %s", msg);
688 POOLMEM *name = get_pool_memory(PM_MESSAGE);
689 make_unique_mail_filename(jcr, name, d);
690 d->fd = fopen(name, "w+b");
694 Qmsg2(jcr, M_ERROR, 0, _("fopen %s failed: ERR=%s\n"), name,
697 free_pool_memory(name);
700 d->mail_filename = name;
703 len = strlen(msg) + dtlen;;
704 if (len > d->max_len) {
705 d->max_len = len; /* keep max line length */
710 Dmsg1(850, "APPEND for following msg: %s", msg);
714 Dmsg1(850, "FILE for following msg: %s", msg);
717 if (!d->fd && !open_dest_file(jcr, d, mode)) {
722 /* On error, we close and reopen to handle log rotation */
725 if (open_dest_file(jcr, d, mode)) {
732 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
733 if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
734 bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s",
735 jcr->Job, type, mtime, msg);
739 Dmsg1(850, "STDOUT for following msg: %s", msg);
740 if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */
746 Dmsg1(850, "STDERR for following msg: %s", msg);
757 /*********************************************************************
759 * This subroutine returns the filename portion of a Windows
760 * path. It is used because Microsoft Visual Studio sets __FILE__
765 get_basename(const char *pathname)
767 #if defined(_MSC_VER)
768 const char *basename;
770 if ((basename = strrchr(pathname, '\\')) == NULL) {
782 /*********************************************************************
784 * This subroutine prints a debug message if the level number
785 * is less than or equal the debug_level. File and line numbers
786 * are included for more detail if desired, but not currently
789 * If the level is negative, the details of file and line number
793 d_msg(const char *file, int line, int level, const char *fmt,...)
805 if (level <= debug_level) {
808 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
815 va_start(arg_ptr, fmt);
816 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
820 * Used the "trace on" command in the console to turn on
821 * output to the trace file. "trace off" will close the file.
826 bsnprintf(fn, sizeof(fn), "%s/bacula.trace", working_directory ? working_directory : ".");
827 trace_fd = fopen(fn, "a+b");
830 fputs(buf, trace_fd);
833 /* Some problem, turn off tracing */
836 } else { /* not tracing */
843 * Set trace flag on/off. If argument is negative, there is no change
845 void set_trace(int trace_flag)
847 if (trace_flag < 0) {
849 } else if (trace_flag > 0) {
854 if (!trace && trace_fd) {
855 FILE *ltrace_fd = trace_fd;
857 bmicrosleep(0, 100000); /* yield to prevent seg faults */
867 /*********************************************************************
869 * This subroutine prints a message regardless of the debug level
871 * If the level is negative, the details of file and line number
875 p_msg(const char *file, int line, int level, const char *fmt,...)
883 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
890 va_start(arg_ptr, fmt);
891 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
897 /*********************************************************************
899 * subroutine writes a debug message to the trace file if the level number
900 * is less than or equal the debug_level. File and line numbers
901 * are included for more detail if desired, but not currently
904 * If the level is negative, the details of file and line number
908 t_msg(const char *file, int line, int level, const char *fmt,...)
920 if (level <= debug_level) {
922 bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory);
923 trace_fd = fopen(buf, "a+b");
928 len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, get_basename(file), line);
935 va_start(arg_ptr, fmt);
936 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
938 if (trace_fd != NULL) {
939 fputs(buf, trace_fd);
947 /* *********************************************************
949 * print an error message
953 e_msg(const char *file, int line, int type, int level, const char *fmt,...)
960 * Check if we have a message destination defined.
961 * We always report M_ABORT and M_ERROR_TERM
963 if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
964 !bit_is_set(type, daemon_msgs->send_msg))) {
965 return; /* no destination */
969 len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
970 my_name, get_basename(file), line);
973 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
974 my_name, get_basename(file), line);
977 if (level == -1) /* skip details */
978 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
980 len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, get_basename(file), line);
983 if (level == -1) /* skip details */
984 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
986 len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, get_basename(file), line);
989 len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
992 len = bsnprintf(buf, sizeof(buf), _("%s: Security violation: "), my_name);
995 len = bsnprintf(buf, sizeof(buf), "%s: ", my_name);
999 va_start(arg_ptr, fmt);
1000 bvsnprintf(buf+len, sizeof(buf)-len, (char *)fmt, arg_ptr);
1003 dispatch_message(NULL, type, 0, buf);
1005 if (type == M_ABORT) {
1007 p[0] = 0; /* generate segmentation violation */
1009 if (type == M_ERROR_TERM) {
1014 /* *********************************************************
1016 * Generate a Job message
1020 Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1029 Dmsg1(850, "Enter Jmsg type=%d\n", type);
1031 /* Special case for the console, which has a dir_bsock and JobId==0,
1032 * in that case, we send the message directly back to the
1035 if (jcr && jcr->JobId == 0 && jcr->dir_bsock) {
1036 BSOCK *dir = jcr->dir_bsock;
1037 va_start(arg_ptr, fmt);
1038 dir->msglen = bvsnprintf(dir->msg, sizeof_pool_memory(dir->msg),
1041 bnet_send(jcr->dir_bsock);
1048 msgs = jcr->jcr_msgs;
1052 msgs = daemon_msgs; /* if no jcr, we use daemon handler */
1055 job = ""; /* Set null job name if none */
1059 * Check if we have a message destination defined.
1060 * We always report M_ABORT and M_ERROR_TERM
1062 if (msgs && (type != M_ABORT && type != M_ERROR_TERM) &&
1063 !bit_is_set(type, msgs->send_msg)) {
1064 return; /* no destination */
1068 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ABORTING due to ERROR\n"), my_name);
1071 len = bsnprintf(rbuf, sizeof(rbuf), _("%s ERROR TERMINATION\n"), my_name);
1074 len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Fatal error: "), my_name, job);
1076 set_jcr_job_status(jcr, JS_FatalError);
1080 len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Error: "), my_name, job);
1086 len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Warning: "), my_name, job);
1089 len = bsnprintf(rbuf, sizeof(rbuf), _("%s: %s Security violation: "), my_name, job);
1092 len = bsnprintf(rbuf, sizeof(rbuf), "%s: ", my_name);
1096 va_start(arg_ptr, fmt);
1097 bvsnprintf(rbuf+len, sizeof(rbuf)-len, fmt, arg_ptr);
1100 dispatch_message(jcr, type, mtime, rbuf);
1102 if (type == M_ABORT){
1104 p[0] = 0; /* generate segmentation violation */
1106 if (type == M_ERROR_TERM) {
1112 * If we come here, prefix the message with the file:line-number,
1113 * then pass it on to the normal Jmsg routine.
1115 void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1121 pool_buf = get_pool_memory(PM_EMSG);
1122 i = Mmsg(pool_buf, "%s:%d ", get_basename(file), line);
1125 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1126 va_start(arg_ptr, fmt);
1127 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1129 if (len < 0 || len >= (maxlen-5)) {
1130 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1136 Jmsg(jcr, type, mtime, "%s", pool_buf);
1137 free_memory(pool_buf);
1142 * Edit a message into a Pool memory buffer, with file:lineno
1144 int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
1149 i = sprintf(*pool_buf, "%s:%d ", get_basename(file), line);
1152 maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
1153 va_start(arg_ptr, fmt);
1154 len = bvsnprintf(*pool_buf+i, maxlen, fmt, arg_ptr);
1156 if (len < 0 || len >= (maxlen-5)) {
1157 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + i + maxlen/2);
1165 int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
1170 i = sprintf(pool_buf, "%s:%d ", get_basename(file), line);
1173 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1174 va_start(arg_ptr, fmt);
1175 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1177 if (len < 0 || len >= (maxlen-5)) {
1178 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1188 * Edit a message into a Pool Memory buffer NO file:lineno
1189 * Returns: string length of what was edited.
1191 int Mmsg(POOLMEM **pool_buf, const char *fmt, ...)
1197 maxlen = sizeof_pool_memory(*pool_buf) - 1;
1198 va_start(arg_ptr, fmt);
1199 len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
1201 if (len < 0 || len >= (maxlen-5)) {
1202 *pool_buf = realloc_pool_memory(*pool_buf, maxlen + maxlen/2);
1210 int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
1216 maxlen = sizeof_pool_memory(pool_buf) - 1;
1217 va_start(arg_ptr, fmt);
1218 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1220 if (len < 0 || len >= (maxlen-5)) {
1221 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1229 int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
1235 maxlen = pool_buf.max_size() - 1;
1236 va_start(arg_ptr, fmt);
1237 len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
1239 if (len < 0 || len >= (maxlen-5)) {
1240 pool_buf.realloc_pm(maxlen + maxlen/2);
1249 static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
1252 * We queue messages rather than print them directly. This
1253 * is generally used in low level routines (msg handler, bnet)
1254 * to prevent recursion (i.e. if you are in the middle of
1255 * sending a message, it is a bit messy to recursively call
1256 * yourself when the bnet packet is not reentrant).
1258 void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
1265 pool_buf = get_pool_memory(PM_EMSG);
1268 maxlen = sizeof_pool_memory(pool_buf) - 1;
1269 va_start(arg_ptr, fmt);
1270 len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
1272 if (len < 0 || len >= (maxlen-5)) {
1273 pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
1278 item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
1280 item->mtime = time(NULL);
1281 strcpy(item->msg, pool_buf);
1282 /* If no jcr or dequeuing send to daemon to avoid recursion */
1283 if (!jcr || jcr->dequeuing) {
1284 /* jcr==NULL => daemon message, safe to send now */
1285 Jmsg(NULL, item->type, item->mtime, "%s", item->msg);
1288 /* Queue message for later sending */
1290 jcr->msg_queue->append(item);
1293 free_memory(pool_buf);
1299 void dequeue_messages(JCR *jcr)
1303 if (!jcr->msg_queue) {
1306 jcr->dequeuing = true;
1307 foreach_dlist(item, jcr->msg_queue) {
1308 Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
1310 jcr->msg_queue->destroy();
1311 jcr->dequeuing = false;
1319 * If we come here, prefix the message with the file:line-number,
1320 * then pass it on to the normal Qmsg routine.
1322 void q_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const char *fmt,...)
1328 pool_buf = get_pool_memory(PM_EMSG);
1329 i = Mmsg(pool_buf, "%s:%d ", file, line);
1332 maxlen = sizeof_pool_memory(pool_buf) - i - 1;
1333 va_start(arg_ptr, fmt);
1334 len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
1336 if (len < 0 || len >= (maxlen-5)) {
1337 pool_buf = realloc_pool_memory(pool_buf, maxlen + i + maxlen/2);
1343 Qmsg(jcr, type, mtime, "%s", pool_buf);
1344 free_memory(pool_buf);