Make systat(1) accept fractional number of seconds.

Make old alarm(3)-based code use select(2).

MFC after:	2 weeks
This commit is contained in:
melifaro 2012-09-17 13:36:47 +00:00
parent 6c6afc2093
commit 5d4e58ed8e
10 changed files with 159 additions and 97 deletions

View File

@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
static const char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/29/95";
#endif
#include <sys/param.h>
#include <ctype.h>
#include <signal.h>
#include <stdlib.h>
@ -49,10 +51,9 @@ command(const char *cmd)
{
struct cmdtab *p;
char *cp, *tmpstr, *tmpstr1;
int interval, omask;
double t;
tmpstr = tmpstr1 = strdup(cmd);
omask = sigblock(sigmask(SIGALRM));
for (cp = tmpstr1; *cp && !isspace(*cp); cp++)
;
if (*cp)
@ -68,7 +69,7 @@ command(const char *cmd)
goto done;
}
if (strcmp(tmpstr1, "stop") == 0) {
alarm(0);
delay = 0;
mvaddstr(CMDLINE, 0, "Refresh disabled.");
clrtoeol();
goto done;
@ -88,19 +89,23 @@ command(const char *cmd)
clrtoeol();
goto done;
}
interval = atoi(tmpstr1);
if (interval <= 0 &&
(strcmp(tmpstr1, "start") == 0 || strcmp(tmpstr1, "interval") == 0)) {
interval = *cp ? atoi(cp) : naptime;
if (interval <= 0) {
error("%d: bad interval.", interval);
goto done;
t = strtod(tmpstr1, NULL) * 1000000.0;
if (t > 0 && t < (double)UINT_MAX)
delay = (unsigned int)t;
if ((t <= 0 || t > (double)UINT_MAX) &&
(strcmp(tmpstr1, "start") == 0 ||
strcmp(tmpstr1, "interval") == 0)) {
if (*cp != '\0') {
t = strtod(cp, NULL) * 1000000.0;
if (t <= 0 || t >= (double)UINT_MAX) {
error("%d: bad interval.", (int)t);
goto done;
}
}
}
if (interval > 0) {
alarm(0);
naptime = interval;
display(0);
if (t > 0) {
delay = (unsigned int)t;
display();
status();
goto done;
}
@ -112,7 +117,6 @@ command(const char *cmd)
if (p) {
if (curcmd == p)
goto done;
alarm(0);
(*curcmd->c_close)(wnd);
curcmd->c_flags &= ~CF_INIT;
wnd = (*p->c_open)();
@ -133,14 +137,13 @@ command(const char *cmd)
}
curcmd = p;
labels();
display(0);
display();
status();
goto done;
}
if (curcmd->c_cmd == 0 || !(*curcmd->c_cmd)(tmpstr1, cp))
error("%s: Unknown command.", tmpstr1);
done:
sigsetmask(omask);
free(tmpstr);
}
@ -177,7 +180,7 @@ status(void)
{
error("Showing %s, refresh every %d seconds.",
curcmd->c_name, naptime);
curcmd->c_name, delay / 1000000);
}
int

View File

@ -49,11 +49,12 @@ extern int CMDLINE;
extern int dk_ndrive;
extern int hz, stathz;
extern double hertz; /* sampling frequency for cp_time and dk_time */
extern int naptime, col;
extern int col;
extern int nhosts;
extern int nports;
extern int protos;
extern int verbose;
extern unsigned int delay;
struct inpcb;
@ -87,7 +88,7 @@ int cmdnetstat(const char *, const char *);
struct cmdtab *lookup(const char *);
void command(const char *);
void die(int);
void display(int);
void display(void);
int dkinit(void);
int dkcmd(char *, char *);
void error(const char *fmt, ...) __printflike(1, 2);

View File

@ -138,7 +138,7 @@ domode(struct icmpstat *ret)
switch(currentmode) {
case display_RATE:
sub = &oldstat;
divisor = naptime;
divisor = (delay > 1000000) ? delay / 1000000 : 1;
break;
case display_DELTA:
sub = &oldstat;

View File

@ -137,7 +137,7 @@ domode(struct icmp6stat *ret)
switch(currentmode) {
case display_RATE:
sub = &oldstat;
divisor = naptime;
divisor = (delay > 1000000) ? delay / 1000000 : 1;
break;
case display_DELTA:
sub = &oldstat;

View File

@ -146,7 +146,7 @@ domode(struct stat *ret)
switch(currentmode) {
case display_RATE:
sub = &oldstat;
divisor = naptime;
divisor = (delay > 1000000) ? delay / 1000000 : 1;
break;
case display_DELTA:
sub = &oldstat;

View File

@ -142,7 +142,7 @@ domode(struct ip6stat *ret)
switch(currentmode) {
case display_RATE:
sub = &oldstat;
divisor = naptime;
divisor = (delay > 1000000) ? delay / 1000000 : 1;
break;
case display_DELTA:
sub = &oldstat;

View File

@ -35,88 +35,146 @@ __FBSDID("$FreeBSD$");
static const char sccsid[] = "@(#)keyboard.c 8.1 (Berkeley) 6/6/93";
#endif
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include "systat.h"
#include "extern.h"
static char line[80];
static int keyboard_dispatch(int ch);
int
keyboard(void)
{
char line[80];
int ch, oldmask;
int ch, n;
struct timeval last, intvl, now, tm;
fd_set rfds;
/* Set initial timings */
gettimeofday(&last, NULL);
intvl.tv_sec = delay / 1000000;
intvl.tv_usec = delay % 1000000;
for (;;) {
col = 0;
move(CMDLINE, 0);
do {
refresh();
ch = getch();
if (ch == ERR) {
if (errno == EINTR)
continue;
exit(1);
for (;;) {
/* Determine interval to sleep */
(void)gettimeofday(&now, NULL);
tm.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
tm.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
while (tm.tv_usec < 0) {
tm.tv_usec += 1000000;
tm.tv_sec--;
}
if (ch >= 'A' && ch <= 'Z')
ch += 'a' - 'A';
if (col == 0) {
#define mask(s) (1 << ((s) - 1))
if (ch == CTRL('l')) {
oldmask = sigblock(mask(SIGALRM));
wrefresh(curscr);
sigsetmask(oldmask);
continue;
}
if (ch == CTRL('g')) {
oldmask = sigblock(mask(SIGALRM));
status();
sigsetmask(oldmask);
continue;
}
if (ch != ':')
continue;
move(CMDLINE, 0);
clrtoeol();
while (tm.tv_usec >= 1000000) {
tm.tv_usec -= 1000000;
tm.tv_sec++;
}
if (ch == erasechar() && col > 0) {
if (col == 1 && line[0] == ':')
continue;
col--;
goto doerase;
}
if (ch == CTRL('w') && col > 0) {
while (--col >= 0 && isspace(line[col]))
;
col++;
while (--col >= 0 && !isspace(line[col]))
if (col == 0 && line[0] == ':')
break;
col++;
goto doerase;
}
if (ch == killchar() && col > 0) {
col = 0;
if (line[0] == ':')
col++;
doerase:
move(CMDLINE, col);
clrtoeol();
if (tm.tv_sec < 0) {
/* We have to update screen immediately */
display();
gettimeofday(&last, NULL);
continue;
}
if (isprint(ch) || ch == ' ') {
line[col] = ch;
mvaddch(CMDLINE, col, ch);
col++;
/* Prepare select */
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
n = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tm);
if (n > 0) {
/* Read event on stdin */
ch = getch();
if (keyboard_dispatch(ch) == 0) {
refresh();
continue;
}
line[col] = '\0';
command(line + 1);
/* Refresh delay */
intvl.tv_sec = delay / 1000000;
intvl.tv_usec = delay % 1000000;
refresh();
break;
}
} while (col == 0 || (ch != '\r' && ch != '\n'));
line[col] = '\0';
oldmask = sigblock(mask(SIGALRM));
command(line + 1);
sigsetmask(oldmask);
if (n < 0 && errno != EINTR)
exit(1);
/* Timeout or signal. Call display another time */
display();
gettimeofday(&last, NULL);
}
}
/*NOTREACHED*/
}
static int
keyboard_dispatch(int ch)
{
if (ch == ERR) {
if (errno == EINTR)
return 0;
exit(1);
}
if (ch >= 'A' && ch <= 'Z')
ch += 'a' - 'A';
if (col == 0) {
if (ch == CTRL('l')) {
wrefresh(curscr);
return 0;
}
if (ch == CTRL('g')) {
status();
return 0;
}
if (ch != ':')
return 0;
move(CMDLINE, 0);
clrtoeol();
}
if (ch == erasechar() && col > 0) {
if (col == 1 && line[0] == ':')
return 0;
col--;
goto doerase;
}
if (ch == CTRL('w') && col > 0) {
while (--col >= 0 && isspace(line[col]))
;
col++;
while (--col >= 0 && !isspace(line[col]))
if (col == 0 && line[0] == ':')
return 1;
col++;
goto doerase;
}
if (ch == killchar() && col > 0) {
col = 0;
if (line[0] == ':')
col++;
doerase:
move(CMDLINE, col);
clrtoeol();
return 0;
}
if (isprint(ch) || ch == ' ') {
line[col] = ch;
mvaddch(CMDLINE, col, ch);
col++;
}
if (col == 0 || (ch != '\r' && ch != '\n'))
return 0;
return 1;
}

View File

@ -64,7 +64,7 @@ kvm_t *kd;
sig_t sigtstpdfl;
double avenrun[3];
int col;
int naptime = 5;
unsigned int delay = 5000000; /* in microseconds */
int verbose = 1; /* to report kvm read errs */
struct clockinfo clkinfo;
double hertz;
@ -82,6 +82,7 @@ main(int argc, char **argv)
{
char errbuf[_POSIX2_LINE_MAX], dummy;
size_t size;
double t;
(void) setlocale(LC_ALL, "");
@ -97,9 +98,9 @@ main(int argc, char **argv)
errx(1, "%s: unknown request", &argv[0][1]);
curcmd = p;
} else {
naptime = atoi(argv[0]);
if (naptime <= 0)
naptime = 5;
t = strtod(argv[0], NULL) * 1000000.0;
if (t > 0 && t < (double)UINT_MAX)
delay = (unsigned int)t;
}
argc--, argv++;
}
@ -166,8 +167,7 @@ main(int argc, char **argv)
dellave = 0.0;
signal(SIGALRM, display);
display(0);
display();
noecho();
crmode();
keyboard();
@ -192,7 +192,7 @@ labels(void)
}
void
display(int signo __unused)
display()
{
int i, j;
@ -223,7 +223,6 @@ display(int signo __unused)
wrefresh(wnd);
move(CMDLINE, col);
refresh();
alarm(naptime);
}
void

View File

@ -28,7 +28,7 @@
.\" @(#)systat.1 8.2 (Berkeley) 12/30/93
.\" $FreeBSD$
.\"
.Dd October 14, 2007
.Dd September 17, 2012
.Dt SYSTAT 1
.Os
.Sh NAME
@ -109,6 +109,7 @@ full detail below.
The
.Ar refresh-value
specifies the screen refresh time interval in seconds.
Time interval can be fractional.
.El
.Pp
Certain characters cause immediate action by

View File

@ -147,7 +147,7 @@ domode(struct tcpstat *ret)
switch(currentmode) {
case display_RATE:
sub = &oldstat;
divisor = naptime;
divisor = (delay > 1000000) ? delay / 1000000 : 1;
break;
case display_DELTA:
sub = &oldstat;