Fix formatting. ruptime output on FreeBSD cluster machines annoyed me

by usually being double-spaced due to auto-wrap at column 80.

r212771 increased width of the hostname field from 12 to 25.  This was
supposed to allow for 80-column output with all 3 load averages taking
5 characters each, but it actually gave width exactly 80 and thus worse
than useless auto-wrap in that case.  3 wide load average fields are
unusual, but later expansion of another field gave the auto-wrap with
just 2 wide load average fields.

Change to dynamic field widths for all fields except the uptime.  This
also fixes the formatting of high (above 9999) user counts and not
very high (above 9.99) load averages.  The formatting for numbers now
breaks at 99999.99, but scientific notation should be used starting
well below that.

The field width for the uptime remains hard-coded to work consistently
for uptimes less than 10000 days, but this gives too much space for
small uptimes.  Punctuation between fields could be improved in many
ways, for example by removing it.
This commit is contained in:
bde 2017-03-04 04:06:33 +00:00
parent e4b8d4adf1
commit 7c5d91f72b

View File

@ -69,6 +69,7 @@ static DIR *dirp;
static int hscmp(const void *, const void *);
static char *interval(time_t, const char *);
static int iwidth(int);
static int lcmp(const void *, const void *);
static void ruptime(const char *, int, int (*)(const void *, const void *));
static int tcmp(const void *, const void *);
@ -143,6 +144,21 @@ interval(time_t tval, const char *updown)
return (resbuf);
}
/* Width to print a small nonnegative integer. */
static int
iwidth(int w)
{
if (w < 10)
return (1);
if (w < 100)
return (2);
if (w < 1000)
return (3);
if (w < 10000)
return (4);
return (5);
}
#define HS(a) ((const struct hs *)(a))
/* Alphabetical comparison. */
@ -176,14 +192,17 @@ ruptime(const char *host, int aflg, int (*cmp)(const void *, const void *))
struct whod *wd;
struct whoent *we;
struct dirent *dp;
const char *hostname;
int fd, i, maxloadav;
int fd, hostnamewidth, i, loadavwidth[3], userswidth, w;
size_t hspace;
ssize_t cc;
rewinddir(dirp);
hsp = NULL;
maxloadav = -1;
hostnamewidth = 0;
loadavwidth[0] = 4;
loadavwidth[1] = 4;
loadavwidth[2] = 4;
userswidth = 1;
(void)time(&now);
for (nhosts = hspace = 0; (dp = readdir(dirp)) != NULL;) {
if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5) != 0)
@ -206,22 +225,25 @@ ruptime(const char *host, int aflg, int (*cmp)(const void *, const void *))
if (cc < (ssize_t)WHDRSIZE)
continue;
if (host != NULL) {
hostname = wd->wd_hostname;
if (strcasecmp(hostname, host) != 0)
continue;
}
if (host != NULL && strcasecmp(wd->wd_hostname, host) != 0)
continue;
if (LEFTEARTH(wd->wd_recvtime))
continue;
for (i = 0; i < 2; i++)
if (wd->wd_loadav[i] > maxloadav)
maxloadav = wd->wd_loadav[i];
if (hostnamewidth < (int)strlen(wd->wd_hostname))
hostnamewidth = (int)strlen(wd->wd_hostname);
for (i = 0; i < 3; i++) {
w = iwidth(wd->wd_loadav[i] / 100) + 3;
if (loadavwidth[i] < w)
loadavwidth[i] = w;
}
for (hsp->hs_nusers = 0, we = &wd->wd_we[0];
(char *)(we + 1) <= (char *)wd + cc; we++)
if (aflg || we->we_idle < 3600)
++hsp->hs_nusers;
if (userswidth < iwidth(hsp->hs_nusers))
userswidth = iwidth(hsp->hs_nusers);
++hsp;
++nhosts;
}
@ -233,27 +255,28 @@ ruptime(const char *host, int aflg, int (*cmp)(const void *, const void *))
}
qsort(hs, nhosts, sizeof(hs[0]), cmp);
w = userswidth + loadavwidth[0] + loadavwidth[1] + loadavwidth[2];
if (hostnamewidth + w > 41)
hostnamewidth = 41 - w; /* limit to 79 cols */
for (i = 0; i < (int)nhosts; i++) {
hsp = &hs[i];
wd = &hsp->hs_wd;
if (ISDOWN(hsp)) {
(void)printf("%-25.25s%s\n", wd->wd_hostname,
(void)printf("%-*.*s%s\n",
hostnamewidth, hostnamewidth, wd->wd_hostname,
interval(now - hsp->hs_wd.wd_recvtime, "down"));
continue;
}
(void)printf(
"%-25.25s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n",
wd->wd_hostname,
"%-*.*s %s, %*d user%s load %*.2f, %*.2f, %*.2f\n",
hostnamewidth, hostnamewidth, wd->wd_hostname,
interval((time_t)wd->wd_sendtime -
(time_t)wd->wd_boottime, " up"),
hsp->hs_nusers,
userswidth, hsp->hs_nusers,
hsp->hs_nusers == 1 ? ", " : "s,",
maxloadav >= 1000 ? 5 : 4,
wd->wd_loadav[0] / 100.0,
maxloadav >= 1000 ? 5 : 4,
wd->wd_loadav[1] / 100.0,
maxloadav >= 1000 ? 5 : 4,
wd->wd_loadav[2] / 100.0);
loadavwidth[0], wd->wd_loadav[0] / 100.0,
loadavwidth[1], wd->wd_loadav[1] / 100.0,
loadavwidth[2], wd->wd_loadav[2] / 100.0);
}
free(hs);
hs = NULL;