vandys@lindy.stanford.edu (Andy Valencia) (07/21/87)
Rich,
Well, you had to ask. Here's a generalized monitoring program;
you run it with:
monitor -i 10 command arg arg...
It runs the command, then displays the first n (where n is the number
of lines on your terminal) lines of output on your screen, then cycles each
10 seconds (-i means interval--default is 30 seconds). I've seen this hither
and yon for years, but I keep running into places which don't have it.
Just compile with:
cc -O -o monitor monitor.c -lcurses -ltermcap
Works on my 4.2 system, will need changes for SysV.
/*
* monitor.c--utility which cyclically takes the output of a command and
* displays it on the screen via curses(3x).
*/
#include <stdio.h>
#include <curses.h>
#include <signal.h>
#include <errno.h>
extern int errno;
static int numlines;
/*
* Set up curses
*/
static void
setup_screen(){
static char bp[1024];
extern char *getenv();
if( getenv("TERM") == NULL ){
fprintf(stderr,"Please set your TERM variable\n");
exit(1);
}
if( tgetent(bp,getenv("TERM")) != 1 ){
fprintf(stderr,"I can't use terminal type '%s'\n",getenv("TERM"));
exit(1);
}
if( (numlines = tgetnum("li")) < 0 ){
fprintf(stderr,"You seem to have an illegal number of lines\n");
exit(1);
}
initscr();
clear();
refresh();
}
/*
* Run the command, take as many lines of output as will fit on the
* screen, paint them.
*/
static void
paint_screen(cmd)
char *cmd;
{
char tmpf[80], buf[256];
register char *p;
FILE *fp;
register c;
int kid, kidstat, x, y;
strcpy(tmpf,"/tmp/monXXXXXX");
mktemp(tmpf);
if( (kid = fork()) == 0 ){
/*
* The subprocess's output will go to a file; close stdout and
* stderr, then re-open them directed to a temp file.
*/
close(1); close(2);
dup(creat(tmpf,0700));
/*
* Just to make sure, disable access to stdin
*/
close(0);
/*
* Call the program, return its status
*/
exit( system(cmd) );
}
/*
* Wait for our kid. Kill him off if we get a signal from the user.
*/
if( wait(&kidstat) < 0 ){
int hold_errno = errno;
endwin();
errno = hold_errno;
perror(cmd[0]);
kill(kid,SIGKILL);
unlink(tmpf);
exit( 1 );
}
/*
* Wait didn't return error, check if kid ran OK.
*/
if( kidstat ){
endwin();
fprintf(stderr,"Problem running command\n");
unlink(tmpf);
exit( 1 );
}
/*
* Suck in tmpf's contents, feed it to curses
*/
if( (fp = fopen(tmpf,"r")) == NULL ){
endwin();
fprintf(stderr,"Error reading file '%s'\n",tmpf);
exit( 1 );
}
unlink(tmpf);
for( x = 0; x < numlines; ++x ){
p = buf;
while( (c = getc(fp)) != EOF )
if( c == '\n' ) break;
else *p++ = c;
if( c == EOF ) break;
*p = '\0';
buf[79] = '\0';
move(x,0);
clrtoeol();
addstr(buf);
}
for( y = x; y < numlines; ++y ){
move(y,0);
clrtoeol();
}
move(numlines-1,79);
fclose(fp);
refresh();
}
/*
* Main routine: get arguments, run the thing
*/
main(argc,argv)
int argc;
char **argv;
{
char cmd[4096];
int interval, x;
/*
* Give'm help if they need it
*/
if( argc < 2 ){
fprintf(stderr,"Usage is: %s [-i <secs>] command [args...]\n",
argv[0]);
exit( 1 );
}
/*
* If they specify '-i', take a user-specified interval between
* displays, otherwise default to 30 seconds.
*/
if( strncmp(argv[1], "-i", 2) == 0 ){
if( argv[1][2] ){
interval = atoi(argv[1]+2);
argv += 2;
} else {
interval = atoi(argv[2]);
argv += 3;
}
} else {
interval = 30;
++argv;
}
/*
* Build a command line
*/
cmd[0] = '\0';
for( x = 0; argv[x]; ++x ){
strcat(cmd,argv[x]);
strcat(cmd," ");
}
/*
* Prepare curses
*/
setup_screen();
/*
* Forever: paint the screen & loop
*/
while( 1 ){
paint_screen(cmd);
sleep(interval);
}
}
------- End of Forwarded ddress