From 46df6d2cd401de20672cc1061f2f0ed52a4c1ea1 Mon Sep 17 00:00:00 2001 From: Richard Mudgett Date: Sat, 21 Nov 2009 02:40:23 +0000 Subject: [PATCH] Fix debug output so built up output lines are readable again. A recent change to Asterisk put the span number at the begining of each line. This is a good thing if you need to debug multiple spans or forget which span you are debugging. Unfortunately, any pri_message() output that is not a complete line is messed up. The pri_message() function now will accumulate line output until a '\n' is seen on the end. git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1351 2fbb986a-6c06-0410-b554-c9c1f0a7f128 --- pri.c | 80 +++++++++++++++++++++++++++++++++++++++++++++----- pri_internal.h | 16 ++++++++-- 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/pri.c b/pri.c index b3c6877..5243c8e 100644 --- a/pri.c +++ b/pri.c @@ -239,6 +239,7 @@ void __pri_free_tei(struct pri * p) pri_schedule_del(call->pri, call->retranstimer); pri_call_apdu_queue_cleanup(call); } + free(p->msg_line); free(p); } } @@ -267,6 +268,14 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, p = &dummy_ctrl->ctrl; break; } + if (!master) { + /* This is the master record. */ + p->msg_line = calloc(1, sizeof(*p->msg_line)); + if (!p->msg_line) { + free(p); + return NULL; + } + } p->bri = bri; p->fd = fd; @@ -1121,20 +1130,77 @@ void pri_set_error(void (*func)(struct pri *pri, char *stuff)) __pri_error = func; } -void pri_message(struct pri *pri, char *fmt, ...) +static void pri_old_message(struct pri *ctrl, const char *fmt, va_list *ap) { char tmp[1024]; - va_list ap; - va_start(ap, fmt); - vsnprintf(tmp, sizeof(tmp), fmt, ap); - va_end(ap); + + vsnprintf(tmp, sizeof(tmp), fmt, *ap); if (__pri_message) - __pri_message(PRI_MASTER(pri), tmp); + __pri_message(ctrl, tmp); else fputs(tmp, stdout); } -void pri_error(struct pri *pri, char *fmt, ...) +void pri_message(struct pri *ctrl, const char *fmt, ...) +{ + int added_length; + va_list ap; + + ctrl = PRI_MASTER(ctrl); + if (!ctrl || !ctrl->msg_line) { + /* Just have to do it the old way. */ + va_start(ap, fmt); + pri_old_message(ctrl, fmt, &ap); + va_end(ap); + return; + } + + va_start(ap, fmt); + added_length = vsnprintf(ctrl->msg_line->str + ctrl->msg_line->length, + sizeof(ctrl->msg_line->str) - ctrl->msg_line->length, fmt, ap); + va_end(ap); + if (added_length < 0 + || sizeof(ctrl->msg_line->str) <= ctrl->msg_line->length + added_length) { + static char truncated_output[] = + "v-- Error building output or output was truncated. (Next line) --v\n"; + + /* + * This clause should never need to run because the + * output line accumulation buffer is quite large. + */ + + /* vsnprintf() error or output string was truncated. */ + if (__pri_message) { + __pri_message(ctrl, truncated_output); + } else { + fputs(truncated_output, stdout); + } + + /* Add a terminating '\n' to force a flush of the line. */ + ctrl->msg_line->length = strlen(ctrl->msg_line->str); + if (ctrl->msg_line->length) { + ctrl->msg_line->str[ctrl->msg_line->length - 1] = '\n'; + } else { + ctrl->msg_line->str[0] = '\n'; + ctrl->msg_line->str[1] = '\0'; + } + } else { + ctrl->msg_line->length += added_length; + } + + if (ctrl->msg_line->length + && ctrl->msg_line->str[ctrl->msg_line->length - 1] == '\n') { + /* The accumulated output line was terminated so send it out. */ + ctrl->msg_line->length = 0; + if (__pri_message) { + __pri_message(ctrl, ctrl->msg_line->str); + } else { + fputs(ctrl->msg_line->str, stdout); + } + } +} + +void pri_error(struct pri *pri, const char *fmt, ...) { char tmp[1024]; va_list ap; diff --git a/pri_internal.h b/pri_internal.h index 2d54cd2..6bc03af 100644 --- a/pri_internal.h +++ b/pri_internal.h @@ -55,12 +55,22 @@ struct pri_sched { /*! Maximum number of facility ie's to handle per incoming message. */ #define MAX_FACILITY_IES 8 +/*! Accumulated pri_message() line until a '\n' is seen on the end. */ +struct pri_msg_line { + /*! Accumulated buffer used. */ + unsigned length; + /*! Accumulated pri_message() contents. */ + char str[2048]; +}; + /*! \brief D channel controller structure */ struct pri { int fd; /* File descriptor for D-Channel */ pri_io_cb read_func; /* Read data callback */ pri_io_cb write_func; /* Write data callback */ void *userdata; + /*! Accumulated pri_message() line. (Valid in master record only) */ + struct pri_msg_line *msg_line; struct pri *subchannel; /* Sub-channel if appropriate */ struct pri *master; /* Master channel if appropriate */ struct pri_sched pri_sched[MAX_SCHED]; /* Scheduled events */ @@ -525,7 +535,7 @@ struct q931_call { /*! D channel control structure with associated dummy call reference record. */ struct d_ctrl_dummy { - /*! D channel control structure. */ + /*! D channel control structure. Must be first in the structure. */ struct pri ctrl; /*! Dummy call reference call record. */ struct q931_call dummy_call; @@ -539,8 +549,8 @@ extern void pri_schedule_del(struct pri *pri, int ev); extern pri_event *pri_mkerror(struct pri *pri, char *errstr); -void pri_message(struct pri *ctrl, char *fmt, ...) __attribute__((format(printf, 2, 3))); -void pri_error(struct pri *ctrl, char *fmt, ...) __attribute__((format(printf, 2, 3))); +void pri_message(struct pri *ctrl, const char *fmt, ...) __attribute__((format(printf, 2, 3))); +void pri_error(struct pri *ctrl, const char *fmt, ...) __attribute__((format(printf, 2, 3))); void libpri_copy_string(char *dst, const char *src, size_t size);