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