[mod.sources] v08i092: Execute command repeatedly, display output

sources-request@mirror.UUCP (03/02/87)

Submitted by: amdahl!vixie!paul (Paul Vixie Esq)
Mod.sources: Volume 8, Issue 92
Archive-name: display

[  As the man says, this is a dinky program and many people have
   written them.  Nice to have one for the archives, tho.  --r$  ]

-----CUT-----HERE-----
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# Contents:  README display.man Makefile display.c
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'
Display 1.0
15-December-1986

This is another C implementation of the 'display' command, written because
(a) is was easy, (b) I didn't know how to find the original, and (c) I have
an disease whose only means to remission is writing flinky programs like
this one.

Display runs a specified command over and over, printing the output through
curses(3X).  The command can be compound ('date;uusnap' is a personal
favorite), and the delay between executions is settable on the command line.
The output from the command had better fit on a single screen, of course.

To install, unshar into an empty directory, edit the Makefile to change the
DESTDIR (probably to /usr/local, /usr/local/bin or /usr/ucb), then su and
type 'make install'.

Questions, problems, flames, to:

	Paul Vixie
	paul@vixie.UUCP
	ptsfa!vixie!paul
@//E*O*F README//
chmod u=rw,g=rw,o=r README
 
echo x - display.man
sed 's/^@//' > "display.man" <<'@//E*O*F display.man//'
@.TH AT 1 "December 15, 1986"
@.UC 4
@.SH NAME
display \- repeat a command through curses for minimal update
@.SH SYNOPSIS
display [-<delay>] <command>
@.SH DESCRIPTION
@.I Display
repeatedly executes a shell command, sending the output through
@.IR curses (3X)
to cause only the portions of the output which have changed from
one execution to the next to be redrawn.
@.I command
must be quoted if it contains blanks or other special characters.
@.I delay
is the number of seconds to suspend between updates; the default is 5.
@.SH EXAMPLES
@.sp 1
display -10 "date; echo ' '; uusnap; echo ' '; mailq"
@.PP
This provides a dynamic 'UUCP status watch' for BSD systems.  If anyone
figures out a non-nightmarish csh alias for something with both kinds of
quotes in it, please send mail.
@.fi
@.SH "SEE ALSO"
popen(3),
curses(3X),
sh(1)
@.SH DIAGNOSTICS
Fairly informative usage message if you run it with a bad command line.
@.SH BUGS
@.IR Popen (3)
always executes the command through
@.IR sh (1)
@.SH AUTHOR
@.nf
Paul Vixie
{ptsfa,qantel,crash,winfree}!vixie!paul
@//E*O*F display.man//
chmod u=rw,g=rw,o=r display.man
 
echo x - Makefile
sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
# makefile for 'display'
# vix 15dec86 [stolen from 'which']

# start changing
CFLAGS		=	-O
DEST_DIR	=	/usr/local/bin
CURSES_LIBS	=	-lcurses -ltermcap
MAN_DIR		=	/usr/man/manl
MAN_SUFFIX	=	l
SHAR_ARGS	=	-b -c -v
# stop changing

SHAR_SOURCES	=	README display.man Makefile display.c
SHELL		=	/bin/sh

all		:	display

display		:	display.c
			cc $(CFLAGS) -o $@ display.c $(CURSES_LIBS)
			strip display

install		:	all
			mv display $(DEST_DIR)
			chmod 775 $(DEST_DIR)/display
			cp display.man $(MAN_DIR)/display.$(MAN_SUFFIX)

display.shar	:	$(SHAR_SOURCES)
			shar $(SHAR_ARGS) $(SHAR_SOURCES) > $@
@//E*O*F Makefile//
chmod u=rw,g=rw,o= Makefile
 
echo x - display.c
sed 's/^@//' > "display.c" <<'@//E*O*F display.c//'
/* display.c - repeatedly display command through curses
 * vix 18apr86 [written]
 * vix 15dec86 [major overhaul]
 */


#include <curses.h>
#include <signal.h>
#include <ctype.h>


#define		DEFAULT_DELAY	5


static	char	*Command;
static	int	Delay;


main(argc, argv)
int	argc;
char	*argv[];
{
	extern	void	parse_args(),
			die(),
			display();

	parse_args(argc, argv);

	signal(SIGHUP, die);
	signal(SIGINT, die);
	signal(SIGQUIT, die);
	signal(SIGTERM, die);

	initscr();
	clear();

	while (TRUE) {
		display();
		sleep(Delay);
	}
}


static void die()
{
	move(LINES-1, 0);
	clrtoeol();
	refresh();
	endwin();
	exit(0);
}


static void display()
{
	auto	FILE	*fp, *popen();
	auto	char	ch;

	if (!(fp = popen(Command, "r"))) {
		perror("popen");
		exit(1);
	}
	move(0, 0);
	while (EOF != (ch = fgetc(fp)))
	{
		if (ch == '\n')
			clrtoeol();
		addch(ch);
	}
	clrtoeol();
	refresh();
	pclose(fp);
}


static void parse_args(argc, argv)
int	argc;
char	*argv[];
{
	extern	void	usage();
	auto	int	argn,
			delay_found;

	Command = NULL;
	Delay = DEFAULT_DELAY;
	delay_found = FALSE;
	for (argn = 1;  argn < argc;  argn++)
	{
		if (argv[argn][0] == '-')
			if (delay_found)
				usage();	/* already got this once */
			else if (!isdigit(argv[argn][1]))
				usage();	/* not a numeric */
			else
			{
				Delay = atoi(&argv[argn][1]);
				delay_found = TRUE;
			}
		else
			if (Command != NULL)
				usage();	/* already got this once */
			else
				Command = argv[1];
	}
	if (Command == NULL)
		usage();			/* no Command on line */
}


static void usage()
{
	extern	char	*getenv();
	auto	char	*shell = getenv("SHELL");

	fprintf(stderr, "\
usage:  display [-<delay>] <command>\n\
        <delay>   = # of seconds between displays, default=%d\n\
        <command> = command to display, quoted if it contains blanks\n",
		DEFAULT_DELAY);

	if (strcmp(shell, "/bin/sh"))
		fprintf(stderr, "\
	NOTE:  /bin/sh will be used to process the command, not SHELL (%s)\n",
			shell);
	
	exit(1);
}
@//E*O*F display.c//
chmod u=rw,g=rw,o=r display.c
 
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
      22     127     816 README
      38     176    1043 display.man
      28      80     601 Makefile
     127     266    1977 display.c
     215     649    4437 total
!!!
wc  README display.man Makefile display.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0