I wanted to have $ systat ifstat 1 to print meaningful numbers to measure live network throughput. With these two features you are now able to see sth like "MBit/s" in the ifstat view.
"B" converts to Bits "," activates the thousands separator. Comments? OKs? Index: engine.c =================================================================== RCS file: /cvs/src/usr.bin/systat/engine.c,v retrieving revision 1.13 diff -p -u -p -u -r1.13 engine.c --- engine.c 19 Jul 2010 04:41:28 -0000 1.13 +++ engine.c 15 Mar 2011 08:34:00 -0000 @@ -69,6 +69,7 @@ volatile sig_atomic_t gotsig_resize = 0; volatile sig_atomic_t gotsig_alarm = 0; int need_update = 0; int need_sort = 0; +int separate_thousands = 0; SCREEN *screen; @@ -134,7 +135,60 @@ tbprintf(char *format, ...) tb_ptr += len; tb_len -= len; } - + + return len; +} + +int +tbprintft(char *format, ...) + GCC_PRINTFLIKE(1,2) /* defined in curses.h */ +{ + int len; + va_list arg; + char buf[MAX_LINE_BUF]; + + if (tb_ptr == NULL || tb_len <= 0) + return 0; + + va_start(arg, format); + len = vsnprintf(buf, tb_len, format, arg); + va_end(arg); + + if (len > tb_len) + tb_end(); + else if (len > 0) { + int d, s; + int digits, curdigit; + + if (!separate_thousands) { + strlcpy(tb_ptr, buf, tb_len); + return len; + } + + /* count until we hit a non digit. (e.g. the prefix) */ + for (digits = 0; digits < len; digits++) + if (!isdigit(buf[digits])) + break; + + curdigit = digits; + d = s = 0; + /* insert thousands separators while copying */ + while (curdigit && d < tb_len) { + if (curdigit < digits && curdigit % 3 == 0) + tb_ptr[d++] = ','; + tb_ptr[d++] = buf[s++]; + curdigit--; + } + /* copy the remaining non-digits */ + while (len > digits && d < tb_len) { + tb_ptr[d++] = buf[s++]; + digits++; + } + tb_ptr[d] = '\0'; + tb_ptr += d; + tb_len -= d; + len = d; + } return len; } @@ -672,33 +726,33 @@ print_fld_sdiv(field_def *fld, u_int64_t return; tb_start(); - if (tbprintf("%llu", size) <= len) + if (tbprintft("%llu", size) <= len) goto ok; tb_start(); size /= d; - if (tbprintf("%lluK", size) <= len) + if (tbprintft("%lluK", size) <= len) goto ok; if (size == 0) goto err; tb_start(); size /= d; - if (tbprintf("%lluM", size) <= len) + if (tbprintft("%lluM", size) <= len) goto ok; if (size == 0) goto err; tb_start(); size /= d; - if (tbprintf("%lluG", size) <= len) + if (tbprintft("%lluG", size) <= len) goto ok; if (size == 0) goto err; tb_start(); size /= d; - if (tbprintf("%lluT", size) <= len) + if (tbprintft("%lluT", size) <= len) goto ok; err: @@ -729,33 +783,33 @@ print_fld_ssdiv(field_def *fld, int64_t return; tb_start(); - if (tbprintf("%lld", size) <= len) + if (tbprintft("%lld", size) <= len) goto ok; tb_start(); size /= d; - if (tbprintf("%lldK", size) <= len) + if (tbprintft("%lldK", size) <= len) goto ok; if (size == 0) goto err; tb_start(); size /= d; - if (tbprintf("%lldM", size) <= len) + if (tbprintft("%lldM", size) <= len) goto ok; if (size == 0) goto err; tb_start(); size /= d; - if (tbprintf("%lldG", size) <= len) + if (tbprintft("%lldG", size) <= len) goto ok; if (size == 0) goto err; tb_start(); size /= d; - if (tbprintf("%lldT", size) <= len) + if (tbprintft("%lldT", size) <= len) goto ok; err: @@ -806,7 +860,7 @@ print_fld_uint(field_def *fld, unsigned return; tb_start(); - if (tbprintf("%u", size) > len) + if (tbprintft("%u", size) > len) print_fld_str(fld, "*"); else print_fld_tb(fld); Index: engine.h =================================================================== RCS file: /cvs/src/usr.bin/systat/engine.h,v retrieving revision 1.6 diff -p -u -p -u -r1.6 engine.h --- engine.h 16 Jul 2010 05:22:48 -0000 1.6 +++ engine.h 11 Mar 2011 08:28:04 -0000 @@ -101,6 +101,7 @@ void tb_start(void); void tb_end(void); int tbprintf(char *format, ...) GCC_PRINTFLIKE(1,2); +int tbprintft(char *format, ...) GCC_PRINTFLIKE(1,2); void end_line(void); void end_page(void); @@ -155,6 +156,7 @@ extern int columns, lines; extern int need_update; extern int need_sort; +extern int separate_thousands; extern volatile sig_atomic_t gotsig_close; extern volatile sig_atomic_t gotsig_resize; Index: if.c =================================================================== RCS file: /cvs/src/usr.bin/systat/if.c,v retrieving revision 1.19 diff -p -u -p -u -r1.19 if.c --- if.c 2 Mar 2011 06:48:17 -0000 1.19 +++ if.c 15 Mar 2011 08:22:11 -0000 @@ -44,6 +44,7 @@ struct ifstat { static int nifs = 0; static int num_ifs = 0; +static int show_bits = 0; void print_if(void); int read_if(void); @@ -288,6 +289,9 @@ fetchifstat(void) static void showifstat(struct ifstat *ifs) { + int conv = show_bits ? 8 : 1; + int div = show_bits ? 1000 : 1024; + print_fld_str(FLD_IF_IFACE, ifs->ifs_name); tb_start(); @@ -309,11 +313,11 @@ showifstat(struct ifstat *ifs) print_fld_str(FLD_IF_DESC, ifs->ifs_description); - print_fld_size(FLD_IF_IBYTES, ifs->ifs_cur.ifc_ib); + print_fld_sdiv(FLD_IF_IBYTES, ifs->ifs_cur.ifc_ib * conv, div); print_fld_size(FLD_IF_IPKTS, ifs->ifs_cur.ifc_ip); print_fld_size(FLD_IF_IERRS, ifs->ifs_cur.ifc_ie); - print_fld_size(FLD_IF_OBYTES, ifs->ifs_cur.ifc_ob); + print_fld_sdiv(FLD_IF_OBYTES, ifs->ifs_cur.ifc_ob * conv, div); print_fld_size(FLD_IF_OPKTS, ifs->ifs_cur.ifc_op); print_fld_size(FLD_IF_OERRS, ifs->ifs_cur.ifc_oe); @@ -325,13 +329,16 @@ showifstat(struct ifstat *ifs) static void showtotal(void) { + int conv = show_bits ? 8 : 1; + int div = show_bits ? 1000 : 1024; + print_fld_str(FLD_IF_IFACE, "Totals"); - print_fld_size(FLD_IF_IBYTES, sum.ifc_ib); + print_fld_sdiv(FLD_IF_IBYTES, sum.ifc_ib * conv, div); print_fld_size(FLD_IF_IPKTS, sum.ifc_ip); print_fld_size(FLD_IF_IERRS, sum.ifc_ie); - print_fld_size(FLD_IF_OBYTES, sum.ifc_ob); + print_fld_sdiv(FLD_IF_OBYTES, sum.ifc_ob * conv, div); print_fld_size(FLD_IF_OPKTS, sum.ifc_op); print_fld_size(FLD_IF_OERRS, sum.ifc_oe); @@ -358,6 +365,17 @@ if_keyboard_callback(int ch) state = BOOT; for (ifs = ifstats; ifs < ifstats + nifs; ifs++) bzero(&ifs->ifs_old, sizeof(ifs->ifs_old)); + gotsig_alarm = 1; + break; + case 'B': + show_bits = !show_bits; + if (show_bits) { + FLD_IF_IBYTES->title = "IBITS"; + FLD_IF_OBYTES->title = "OBITS"; + } else { + FLD_IF_IBYTES->title = "IBYTES"; + FLD_IF_OBYTES->title = "OBYTES"; + } gotsig_alarm = 1; break; case 't': Index: main.c =================================================================== RCS file: /cvs/src/usr.bin/systat/main.c,v retrieving revision 1.57 diff -p -u -p -u -r1.57 main.c --- main.c 16 Jul 2010 05:22:48 -0000 1.57 +++ main.c 15 Mar 2011 08:27:18 -0000 @@ -315,6 +315,10 @@ keyboard_callback(int ch) case 's': command_set(&cm_delay, NULL); break; + case ',': + separate_thousands = !separate_thousands; + gotsig_alarm = 1; + break; case ':': command_set(&cm_compat, NULL); break; Index: systat.1 =================================================================== RCS file: /cvs/src/usr.bin/systat/systat.1,v retrieving revision 1.90 diff -p -u -p -u -r1.90 systat.1 --- systat.1 18 Jan 2011 03:38:05 -0000 1.90 +++ systat.1 15 Mar 2011 08:18:46 -0000 @@ -175,6 +175,8 @@ Quit .Nm . .It Ic r Reverse the selected ordering if supported by the view. +.It Ic \, +Print numbers with thousand separators, where applicable. .It Ic ^A \*(Ba Aq Ic Home Jump to the beginning of the current view. .It Ic ^B \*(Ba Aq Ic right arrow @@ -257,6 +259,9 @@ represent whether the interface is conne in the case of .Xr carp 4 interfaces, whether the interface is in master or backup state, respectively. +The character +.Ic B +changes the counter view between bytes and bits. .\"See below for more options. .It Ic iostat Display statistics about disk throughput.