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.