diff --git a/candump.c b/candump.c index 51e35e6..ecbcfa0 100644 --- a/candump.c +++ b/candump.c @@ -220,12 +220,16 @@ static int idx2dindex(int ifidx, int socket) return i; } -static inline void sprint_timestamp(const char timestamp, const struct timeval *tv, - struct timeval *const last_tv, char *ts_buffer) +static int sprint_timestamp(char *ts_buffer, const char timestamp, + const struct timeval *tv, struct timeval *const last_tv) { + int numchars = 0; + switch (timestamp) { case 'a': /* absolute with timestamp */ - sprintf(ts_buffer, "(%010llu.%06llu) ", (unsigned long long)tv->tv_sec, (unsigned long long)tv->tv_usec); + numchars = sprintf(ts_buffer, "(%010llu.%06llu) ", + (unsigned long long)tv->tv_sec, + (unsigned long long)tv->tv_usec); break; case 'A': /* absolute with date */ @@ -235,7 +239,8 @@ static inline void sprint_timestamp(const char timestamp, const struct timeval * tm = *localtime(&tv->tv_sec); strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm); - sprintf(ts_buffer, "(%s.%06llu) ", timestring, (unsigned long long)tv->tv_usec); + numchars = sprintf(ts_buffer, "(%s.%06llu) ", timestring, + (unsigned long long)tv->tv_usec); } break; @@ -252,7 +257,9 @@ static inline void sprint_timestamp(const char timestamp, const struct timeval * diff.tv_sec--, diff.tv_usec += 1000000; if (diff.tv_sec < 0) diff.tv_sec = diff.tv_usec = 0; - sprintf(ts_buffer, "(%03llu.%06llu) ", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_usec); + numchars = sprintf(ts_buffer, "(%03llu.%06llu) ", + (unsigned long long)diff.tv_sec, + (unsigned long long)diff.tv_usec); if (timestamp == 'd') *last_tv = *tv; /* update for delta calculation */ @@ -262,15 +269,8 @@ static inline void sprint_timestamp(const char timestamp, const struct timeval * default: /* no timestamp output */ break; } -} -static inline void print_timestamp(const char timestamp, const struct timeval *tv, - struct timeval *const last_tv) -{ - static char buffer[TIMESTAMPSZ]; - - sprint_timestamp(timestamp, tv, last_tv, buffer); - printf("%s", buffer); + return numchars; } int main(int argc, char **argv) @@ -317,6 +317,8 @@ int main(int argc, char **argv) FILE *logfile = NULL; char fname[83]; /* suggested by -Wformat-overflow= */ const char *logname = NULL; + static char abuf[10000]; /* ASCII buf FIXME - use calculated value */ + static int alen; signal(SIGTERM, sigterm); signal(SIGHUP, sigterm); @@ -797,32 +799,29 @@ int main(int argc, char **argv) extra_info = " R"; } - if (log) { - char buf[CL_CFSZ]; /* max length */ - char ts_buf[TIMESTAMPSZ]; + /* build common log format output */ + if ((log) || ((logfrmt) && (silent == SILENT_OFF))) { - sprint_timestamp(logtimestamp, &tv, &last_tv, ts_buf); + alen = sprint_timestamp(abuf, logtimestamp, + &tv, &last_tv); - /* log CAN frame with absolute timestamp & device */ - sprint_canframe(buf, &frame, 0); - fprintf(logfile, "%s%*s %s%s\n", ts_buf, - max_devname_len, devname[idx], buf, - extra_info); + alen += sprintf(abuf + alen, "%*s ", + max_devname_len, devname[idx]); + + alen += sprint_canframe(abuf + alen, &frame, 0); } + /* write CAN frame in log file style to logfile */ + if (log) + fprintf(logfile, "%s%s\n", abuf, extra_info); + + /* print CAN frame in log file style to stdout */ if ((logfrmt) && (silent == SILENT_OFF)) { - char buf[CL_CFSZ]; /* max length */ - - /* print CAN frame in log file style to stdout */ - sprint_canframe(buf, &frame, 0); - print_timestamp(logtimestamp, &tv, &last_tv); - - printf("%*s %s%s\n", - max_devname_len, devname[idx], buf, - extra_info); + printf("%s%s\n", abuf, extra_info); goto out_fflush; /* no other output to stdout */ } + /* print only animation */ if (silent != SILENT_OFF) { if (silent == SILENT_ANI) { printf("%c\b", anichar[silentani %= MAXANI]); @@ -831,25 +830,33 @@ int main(int argc, char **argv) goto out_fflush; /* no other output to stdout */ } - printf(" %s", (color > 2) ? col_on[idx % MAXCOL] : ""); - print_timestamp(timestamp, &tv, &last_tv); - printf(" %s", (color && (color < 3)) ? col_on[idx % MAXCOL] : ""); - printf("%*s", max_devname_len, devname[idx]); + /* print (colored) long CAN frame style to stdout */ + alen = sprintf(abuf, " %s", (color > 2) ? col_on[idx % MAXCOL] : ""); + alen += sprint_timestamp(abuf + alen, timestamp, &tv, &last_tv); + alen += sprintf(abuf + alen, " %s%*s", + (color && (color < 3)) ? col_on[idx % MAXCOL] : "", + max_devname_len, devname[idx]); if (extra_msg_info) { if (msg.msg_flags & MSG_DONTROUTE) - printf(" TX %s", extra_m_info[frame.flags & 3]); + alen += sprintf(abuf + alen, " TX %s", + extra_m_info[frame.flags & 3]); else - printf(" RX %s", extra_m_info[frame.flags & 3]); + alen += sprintf(abuf + alen, " RX %s", + extra_m_info[frame.flags & 3]); } - printf("%s ", (color == 1) ? col_off : ""); + alen += sprintf(abuf + alen, "%s ", (color == 1) ? col_off : ""); + alen += sprint_long_canframe(abuf + alen, &frame, view); - fprint_long_canframe(stdout, &frame, NULL, view); - - printf("%s", (color > 1) ? col_off : ""); - printf("\n"); + if ((view & CANLIB_VIEW_ERROR) && (frame.can_id & CAN_ERR_FLAG)) { + alen += sprintf(abuf + alen, "\n\t"); + alen += snprintf_can_error_frame(abuf + alen, + sizeof(abuf) - alen, + &frame, "\n\t"); + } + printf("%s%s\n", abuf, (color > 1) ? col_off : ""); out_fflush: fflush(stdout); } diff --git a/lib.c b/lib.c index 47fb95b..69320ae 100644 --- a/lib.c +++ b/lib.c @@ -270,7 +270,7 @@ void fprint_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int sep) fprintf(stream, "%s", eol); } -void sprint_canframe(char *buf, struct canfd_frame *cf, int sep) +int sprint_canframe(char *buf, struct canfd_frame *cf, int sep) { /* documentation see lib.h */ @@ -317,7 +317,7 @@ void sprint_canframe(char *buf, struct canfd_frame *cf, int sep) } buf[offset] = 0; - return; + return offset; } /* any CAN FD flags */ @@ -349,6 +349,8 @@ void sprint_canframe(char *buf, struct canfd_frame *cf, int sep) } buf[offset] = 0; + + return offset; } void fprint_long_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int view) @@ -367,7 +369,7 @@ void fprint_long_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int v fprintf(stream, "%s", eol); } -void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) +int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) { /* documentation see lib.h */ @@ -422,8 +424,8 @@ void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) /* standard CAN frames may have RTR enabled */ if (cf->can_id & CAN_RTR_FLAG) { - sprintf(buf + offset + 5, " remote request"); - return; + offset += sprintf(buf + offset + 5, " remote request"); + return offset + 5; } } else { buf[offset] = '['; @@ -477,10 +479,10 @@ void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) * Does it make sense to write 64 ASCII byte behind 64 ASCII HEX data on the console? */ if (len > CAN_MAX_DLEN) - return; + return offset; if (cf->can_id & CAN_ERR_FLAG) - sprintf(buf + offset, "%*s", dlen * (8 - len) + 13, "ERRORFRAME"); + offset += sprintf(buf + offset, "%*s", dlen * (8 - len) + 13, "ERRORFRAME"); else if (view & CANLIB_VIEW_ASCII) { j = dlen * (8 - len) + 4; if (view & CANLIB_VIEW_SWAP) { @@ -492,7 +494,7 @@ void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) else buf[offset++] = '.'; - sprintf(buf + offset, "`"); + offset += sprintf(buf + offset, "`"); } else { sprintf(buf + offset, "%*s", j, "'"); offset += j; @@ -502,9 +504,11 @@ void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) else buf[offset++] = '.'; - sprintf(buf + offset, "'"); + offset += sprintf(buf + offset, "'"); } } + + return offset; } static const char *error_classes[] = { @@ -668,7 +672,7 @@ static int snprintf_error_cnt(char *buf, size_t len, const struct canfd_frame *c return n; } -void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf, +int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf, const char* sep) { canid_t class, mask; @@ -676,12 +680,12 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c char *defsep = ","; if (!(cf->can_id & CAN_ERR_FLAG)) - return; + return 0; class = cf->can_id & CAN_EFF_MASK; if (class > (1 << ARRAY_SIZE(error_classes))) { fprintf(stderr, "Error class %#x is invalid\n", class); - return; + return 0; } if (!sep) @@ -695,13 +699,15 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c /* Fix for potential buffer overflow https://lgtm.com/rules/1505913226124/ */ tmp_n = snprintf(buf + n, len - n, "%s", sep); if (tmp_n < 0 || (size_t)tmp_n >= len - n) { - return; + buf[0] = 0; /* empty terminated string */ + return 0; } n += tmp_n; } tmp_n = snprintf(buf + n, len - n, "%s", error_classes[i]); if (tmp_n < 0 || (size_t)tmp_n >= len - n) { - return; + buf[0] = 0; /* empty terminated string */ + return 0; } n += tmp_n; if (mask == CAN_ERR_LOSTARB) @@ -721,6 +727,8 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c n += snprintf(buf + n, len - n, "%serror-counter-tx-rx", sep); n += snprintf_error_cnt(buf + n, len - n, cf); } + + return n; } int64_t timespec_diff_ms(struct timespec *ts1, diff --git a/lib.h b/lib.h index 817eb0d..6b49759 100644 --- a/lib.h +++ b/lib.h @@ -161,7 +161,7 @@ int parse_canframe(char *cs, struct canfd_frame *cf); */ void fprint_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int sep); -void sprint_canframe(char *buf , struct canfd_frame *cf, int sep); +int sprint_canframe(char *buf , struct canfd_frame *cf, int sep); /* * Creates a CAN frame hexadecimal output in compact format. * The CAN data[] is separated by '.' when sep != 0. @@ -197,7 +197,7 @@ void sprint_canframe(char *buf , struct canfd_frame *cf, int sep); #define SWAP_DELIMITER '`' void fprint_long_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int view); -void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view); +int sprint_long_canframe(char *buf , struct canfd_frame *cf, int view); /* * Creates a CAN frame hexadecimal output in user readable format. * @@ -226,8 +226,8 @@ void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view); * */ -void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf, - const char *sep); +int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf, + const char *sep); /* * Creates a CAN error frame output in user readable format. */