george@rebel.UUCP (George M. Sipe) (10/11/88)
Posting-number: Volume 4, Issue 120 Submitted-by: "George M. Sipe" <george@rebel.UUCP> Archive-name: vis #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # README # Makefile # vis.man # vis.c # This archive created: Fri Jul 22 14:37:25 1988 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'README' then echo shar: "will not over-write existing file 'README'" else sed 's/^X//' << \SHAR_EOF > 'README' XVis repeatedly executes a specified command and refreshes the display Xof its output on the screen. This has the effect of making any Xnormally non-screen oriented command into a screen oriented one. X XThe first line on the output screen is reserved for vis status and will Xcontain the command on the left side with the current execution count Xon the right side. If command is too long to fit, vis will truncate it Xin the status line and append an ellipsis ("..."). X XThe output of the command normally begins on the third line and Xcontinues to the end of the screen. Lines which can not fit will be Xdiscarded. When this occurs, vis will automatically place the output Xof following passes starting on line two in order to maximize the Xamount of displayed information. X XSee the manual page for a complete information. X X X Copyright (c) 1988 by George M. Sipe. All rights reserved. X XThis software may only be redistributed without fee and without any Xother form of monetary gain (including sold, rented, leased, or Xtraded), unless the express written permission of the copyright holder Xis obtained in advance. X XThis copyright notice must be reproduced in its entirety on all copies Xof this software. Further, acknowledgment of the authorship of this Xsoftware must not be removed from its current or derived Xdocumentation. X XNo expressed or implied warranty is made for this software. No party Xconnected with this software assumes any liability or responsibility Xfor its use, the correctness of its operation, or its fitness for any Xpurpose. X XAny distributor of copies of this software shall grant the recipient Xpermission for further redistribution as permitted by this notice. X XPermission is hereby granted to copy, reproduce, redistribute and Xotherwise use this software as long as the conditions above are Xstrictly adhered to. X XNOTE: This software was originally written by Dan Heller X (argv@sri-spam.arpa) and enhanced / generalized by X George M. Sipe (rebel!george) to the point where Dan X would no longer recoginze it. No copyright notices X were embodied in the original net distribution. SHAR_EOF fi if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# Makefile for: vis - repeatedly run command, refreshing screen X XDEFINES = -DBSD XCFLAGS = -O $(DEFINES) XLIBS = -lcurses -ltermcap XROFF = nroff XRFLAGS = -man XLDFLAGS = -s XDESTBIN = ${HOME} XDESTMAN = ${HOME} XDESTCAT = ${HOME} XDESTOWN = root XDESTGRP = staff XSHELL = /bin/sh XMAKEFILE = Makefile XPROGRAM = vis XMANPAGES = vis.man XCATPAGES = vis.cat XSRCS = vis.c XOBJS = vis.o X X.man.cat: X $(ROFF) $(RFLAGS) $< > $@ X X.SUFFIXES: .man .cat X X# Compile and load the program and format its manual pages. Xall: $(PROGRAM) $(CATPAGES) X X$(PROGRAM): $(OBJS) X $(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM) X X# Run lint on source files, put results on standard output. Xlint: X lint -u $(DEFINES) $(SRCS) X X# Create a tags file for use by a source code editor. Xtags: $(SRCS) X ctags $(SRCS) X X# Edit the makefile and regenerate the dependency information. Xdepend: X mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DESTBIN=$(DESTBIN) X X# Print an index of functions on standard output. Xindex: X ctags -wx $(SRCS) X X# Print source code files on standard output. Xprint: X lpr -p $(SRCS) $(MANPAGES) X X# Compile and load the program, format manual pages, and move them X# to their destination directories. Xinstall: $(PROGRAM) $(CATPAGES) X cp $(PROGRAM) $(DESTBIN) X chmod 755 $(DESTBIN)/$(PROGRAM) X chown $(DESTOWN) $(DESTBIN)/$(PROGRAM) X chgrp $(DESTGRP) $(DESTBIN)/$(PROGRAM) X -for manpage in $(MANPAGES); do \ X basepage=`basename $$manpage .man`; \ X cp $$basepage.man $(DESTMAN)/$$basepage.l; \ X chmod 644 $(DESTMAN)/$$basepage.l; \ X chown $(DESTOWN) $(DESTMAN)/$$basepage.l; \ X chgrp $(DESTGRP) $(DESTMAN)/$$basepage.l; \ X cp $$basepage.cat $(DESTCAT)/$$basepage.l; \ X chmod 644 $(DESTCAT)/$$basepage.l; \ X chown $(DESTOWN) $(DESTCAT)/$$basepage.l; \ X chgrp $(DESTGRP) $(DESTCAT)/$$basepage.l; \ X done X X# Remove the program and its formatted manual pages from their X# destination directories. Xuninstall: X rm -f $(DESTBIN)/$(PROGRAM) X -for manpage in $(MANPAGES); do \ X basepage=`basename $$manpage .man`; \ X rm -f $(DESTMAN)/$$basepage.l; \ X rm -f $(DESTCAT)/$$basepage.l; \ X done X X# Remove all target and intermediate files. Xclean: X -rm -f $(PROGRAM) $(CATPAGES) $(OBJS) X -rm -f core a.out made *.o SHAR_EOF fi if test -f 'vis.man' then echo shar: "will not over-write existing file 'vis.man'" else sed 's/^X//' << \SHAR_EOF > 'vis.man' X.TH VIS l "21 July 1988" X.SH NAME Xvis \- repeatedly run command, refreshing screen X.SH SYNTAX X.B vis "[-d delay] [-f] command [args]" X.SH DESCRIPTION X.I Vis Xrepeatedly executes a specified X.B command Xand refreshes the display of its output on the screen. This has the Xeffect of making any normally non-screen oriented command into a screen Xoriented one. X.PP X.B Command Xmay represent multiple commands by enclosing them in quotes and Xseparating them by ``;''. Similarly, commands may be piped together by Xenclosing them in quotes and separating them by ``|''. The single or Xdouble quotes around such a compound command are necessary to escape Xprocessing from the shell. X.PP XThe first line on the output screen is reserved for X.I vis Xstatus and will contain the X.B command Xon the left side with the current execution count on the right side. If X.B command Xis too long to fit, X.I vis Xwill truncate it in the status line and append an ellipsis ("..."). X.PP XThe output of the command normally begins on the third line and Xcontinues to the end of the screen. Lines which can not fit will be Xdiscarded. When this occurs, X.I vis Xwill automatically place the output of following passes starting on line Xtwo in order to maximize the amount of displayed information. X.PP XThe following switches may be specified if desired: X.TP 10 X.B "-d delay" Xspecifies a non-default delay of X.B delay Xseconds. Normally X.I vis Xwill delay for 15 seconds between command re-executions. If a Xnon-default delay is specified, the X.I vis Xstatus line will also include the delay interval centered within it X(unless that would cause it to overwrite a long command, in which case Xit will be centered between the end of the command and the execution Xcount). X.TP X.B -f X.I Vis Xwill automatically terminate if X.B command Xreturns a non-zero status. The X.B -f Xflag forces X.I vis Xto continue. When X.B -f Xis specified, X.I vis Xwill not terminate and will instead precede the execution count in the X.I vis Xstatus line by a ``!'' flag whenever a non-zero status has been returned Xby X.B command . X.SH EXAMPLES Xvis ps X.IP "" 5 XContinually display the status of processes on the system (up to 23 Xlines). X.PP Xvis -d 60 'who ; echo ""; df' X.IP "" 5 XDisplay the system users and disk usage statistics every 60 seconds. XSeparate the two with a blank line. X.SH "SEE ALSO" XUser Commands (1): sh, csh X.SH DIAGNOSTICS XIf X.B command Xreturns a non-zero status and X.B -f Xhas not been specified to X.I vis , X.I vis Xwill terminate and return that status. X.SH AUTHOR XOriginally written by Dan Heller (argv@sri-spam.arpa). X.PP XIt has been substantially enhanced and generalized by George M. Sipe X(currently - 7/88, at rebel!george) to the point where Dan would no Xlonger recognize it. SHAR_EOF fi if test -f 'vis.c' then echo shar: "will not over-write existing file 'vis.c'" else sed 's/^X//' << \SHAR_EOF > 'vis.c' X/* Copyright (c) 1988 by George M. Sipe. All rights reserved. X XThis software may only be redistributed without fee and without any Xother form of monetary gain (including sold, rented, leased, or Xtraded), unless the express written permission of the copyright holder Xis obtained in advance. X XThis copyright notice must be reproduced in its entirety on all copies Xof this software. Further, acknowledgment of the authorship of this Xsoftware must not be removed from its current or derived Xdocumentation. X XNo expressed or implied warranty is made for this software. No party Xconnected with this software assumes any liability or responsibility Xfor its use, the correctness of its operation, or its fitness for any Xpurpose. X XAny distributor of copies of this software shall grant the recipient Xpermission for further redistribution as permitted by this notice. X XPermission is hereby granted to copy, reproduce, redistribute and Xotherwise use this software as long as the conditions above are Xstrictly adhered to. X X NOTE: This software was originally written by Dan Heller X (argv@sri-spam.arpa) and enhanced / generalized by George M. X Sipe (rebel!george) to the point where Dan would no longer X recoginze it. No copyright notices were embodied in the X original net distribution. X*/ X X#include <stdio.h> X#include <curses.h> X#include <signal.h> X#include <sys/types.h> X X#ifndef DELAY X#define DELAY 15 /* default delay, if not otherwise set */ X#endif DELAY X#ifndef BASELINE X#define BASELINE 2 /* default line number for output */ X#endif BASELINE X X#define max(a,b) (a < b ? b : a) X#define equal(str1,str2) !strcmp(str1, str2) X X#define pinput fildes[0] X#define poutput fildes[1] X X#ifdef BSD X#include <sys/wait.h> Xextern char *index(); Xextern time_t time(); Xextern int exit(); Xextern int _exit(); Xextern int perror(); Xextern int sleep(); X#else Xunion wait { X int w_status; X}; X#define vfork() fork() /* fork on non-BSD */ X#define dup2(from,to) close(to); (void) dup(from) /* good enough here */ X#define index(str,chr) strchr(str,chr) /* strchr on non-BSD */ Xextern char *strchr(); Xextern long time(); Xextern void exit(); Xextern void _exit(); Xextern void perror(); Xextern unsigned int sleep(); X#endif BSD X Xextern int optind; Xextern char *optarg; X Xlong wait_delay = DELAY; /* delay interval */ Xint force = 0; /* true to force continued execution */ Xint needshell = 0; /* non-zero if subshell needed */ X X/* create command line string for display */ Xstatic char *command(argc, argv) Xint argc; Xchar **argv; X{ X static char string[255]; X int count = 0; X char *cp = string; X X do { X (void) sprintf(cp, "%s ", argv[count]); X cp += strlen(cp); X needshell |= (int) index(argv[count], '|'); X needshell |= (int) index(argv[count], ';'); X } while (++count < argc); X *--cp = '\000'; X return (string); X} X X/* all done, cleanup and exit */ Xstatic int terminate(cause) X{ X#ifdef BSD X (void) sigsetmask(-1); X#endif X move(LINES - 1, 0); X clrtoeol(); X echo(); X refresh(); X endwin(); X exit(cause); X} X Xint main(argc, argv) Xint argc; Xchar **argv; X{ X register int curline; X register int iteration = 0; X register int c; X int sw; X int badsw = 0; X int baseline = BASELINE; X long nextcycle; X long curtime; X long delta; X int fildes[2]; X int pid; X union wait status; X char *cmd = argv[0]; X char *shcmd[4]; X FILE *fp; X X (void) signal(SIGQUIT, terminate); /* exit when requested */ X (void) signal(SIGINT, terminate); /* exit when requested */ X (void) signal(SIGPIPE, SIG_IGN); /* when output > screen size */ X X while ((sw = getopt (argc, argv, "d:f")) != EOF) X switch (sw) { X case 'f': X force = !force; X break; X case 'd': X wait_delay = atoi(optarg); X if (wait_delay < 1) wait_delay = 1; X break; X case '?': X default: X badsw = 1; X break; X } X argv = &argv[optind]; X argc -= optind; X if (badsw || argc < 1) { X (void) fprintf(stderr, X "Usage: %s [-d delay] [-f] command [args]\n", cmd); X exit (-1); X } X initscr(); X cmd = command(argc, argv); X if (needshell != 0) { X shcmd[0] = "sh"; X shcmd[1] = "-c"; X shcmd[2] = cmd; X shcmd[3] = (char *) 0; X } X if (wait_delay != DELAY) { X if (strlen(cmd) > COLS-39) X (void) sprintf(cmd, "%.*s...", COLS-42, cmd); X mvprintw(0, max((COLS-11)/2, strlen(cmd)+15), "Delay: %d", X wait_delay); X } else if (strlen(cmd) > COLS-21) X (void) sprintf(cmd, "%.*s...", COLS-24, cmd); X mvprintw(0, 0, "Command: %s", cmd); X noecho(); /* don't let typing ruin our painting */ X nextcycle = time(0) + wait_delay; X while (1) { X mvprintw(0, COLS - 10, "Exec: %d", ++iteration); X if (iteration == 1) refresh(); X (void) pipe(fildes); X /* fork and exec redirecting stdout thru pipe to curses */ X if (!(pid = vfork())) { X (void) dup2(poutput, 1); X (void) dup2(poutput, 2); X (void) close(pinput); X if (needshell == 0) (void) execvp(*argv, argv); X else (void) execv("/bin/sh", shcmd); X perror(*argv); X _exit(-1); X } X if (pid == -1) terminate(-2); X if (!(fp = fdopen(pinput, "r"))) terminate(-3); X (void) close(poutput); X curline = baseline; X move(curline, 0); X /* read the command's output */ X while ((c = getc(fp)) != EOF && !ferror(fp) && curline < LINES) X if (c == '\n') { X clrtoeol(); X move(++curline, 0); X } X else addch(c); X if (ferror(fp)) terminate(-4); X if (baseline > 1 && curline == LINES && c != EOF) X --baseline; X /* we've found the end of file, thus, the end of exec */ X (void) fclose(fp); X clrtobot(); X move(LINES - 1, 0); X refresh(); X (void) wait(&status); /* wait for child to terminate */ X /* if child didn't terminate properly, w_status will != 0 */ X if (status.w_status) { X mvprintw(0, COLS - 12, "!"); X if (!force) terminate(status.w_status); X } X curtime = time(0); X delta = nextcycle - curtime; X if (delta > 0) { X nextcycle = curtime + delta + wait_delay; X (void) sleep((unsigned) delta); X } else nextcycle = curtime + wait_delay; X } X} SHAR_EOF fi exit 0 # End of shell archive -- George M. Sipe, Phone: (404) 662-1533 Tolerant Systems, 6961 Peachtree Industrial, Norcross, GA 30071 UUCP: ...!{decvax,hplabs,linus,rutgers,seismo}!gatech!rebel!george