[comp.sys.apollo] winsize.shar

paul@DELRIO.CC.UMICH.EDU ('da Kingfish) (05/25/88)

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	Makefile
#	README
#	termcap.init
#	termset.init
#	winsize.c
# This archive created: Tue May 24 17:57:40 1988
cat << \SHAR_EOF > Makefile

#	winsize - determine size of current window for Apollos and Suns.

RM	=/bin/rm

SOURCES	=winsize.c

CFLAGS	=-O -DBSD_42

winsize: $(SOURCES)
	$(CC) $(CFLAGS) $(LDFLAGS) -o winsize $(SOURCES)


#
#	installation
DESTDIR	=

BINGRP	=bin
BINMOD	=111
BINDIR	=/usr/local/bin
LIBDIR  =/usr/local/lib
INSOPTS	=-g $(BINGRP) -m $(BINMOD) -s
INSTALL	=install

install: winsize
	$(INSTALL) $(INSOPTS) winsize $(DESTDIR)$(BINDIR)

installlib: termset termcap.init
	$(INSTALL) -c -g $(BINGRP) -m 644 termcap.init  $(LIBDIR)
	$(INSTALL) -c -g $(BINGRP) -m 644 termset  $(LIBDIR)

clean:
	$(RM) -f winsize *.o core a.out termset

termset: termset.init
	sed -e "s%LIBDIR%$(LIBDIR)%g" \
		-e "s%BINDIR%$(DESTDIR)$(BINDIR)%g" \
		termset.init > termset
SHAR_EOF
cat << \SHAR_EOF > README
Use the makefile and compile winsize.  Set libdir and bindir as you
like them, and do make install and make installlib.

Then, in your .login file (or anytime) you can source the termset
script.

This was kind of first done by me, but this version was fixed up
greatly by Pat Sherry (late of the computing center and now at
ArborText).  In fact, you might as well say he did it, because he did
the makefile, the snappy scripts,  got it to work on Suns, and cleaned
things up so much, you wouldn't even recognize its origins, which were
an old help file for the apollo vt100 emulator.

You can go ahead and use this, but if you make lots of money from it we
will be pretty pissed off.

Watch out, in case the termcap lines get truncated (there should be 729 bytes
in 2 lines in termcap.init) and escape chars get munged (in winsize.c).

Paul Killey

SHAR_EOF
cat << \SHAR_EOF > termcap.init
Mu|sun:li#<li>:co#<co>:cl=^L:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:am:bs:km:mi:ms:pt:ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:kd=\E[B:kl=\E[D:ku=\E[A:kr=\E[C:kh=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:al=\E[L:dl=\E[M:im=:ei=:ic=\E[@:dc=\E[P:rs=\E[s:
ya|apollo|apollo_19L:sf=30\E7\E[200H\ED\E8:al=99\E[L:dl=\E[M:ip=7:dc=7\E[P:ei=\E[4l:im=\E[4h:xn:dN#30:cr=^M:do=^J:nl=^J:bl=^G:co#<co>:li#<li>:cl=50\E[;H\E[2J:le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E[;r\E[<li>;1H:rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:ta=^I:pt:sr=5\EM:vt#3:sc=\E7:rc=\E8r
SHAR_EOF
cat << \SHAR_EOF > termset.init
# 
# To be sourced from a .login file to edit TERMCAP for variable window size.
# TERM must be set appropriately before executing these commands.
#
set coords=(`BINDIR/winsize`)
if ($status != 0) then
	echo "TERMCAP not set"
else
	set termcap=LIBDIR/termcap.init
	sed -e "s/<co>/$coords[2]/g" -e "s/<li>/$coords[1]/g" $termcap > /tmp/termcap.$$
	setenv TERMCAP /tmp/termcap.$$
	set noglob; eval `tset -s `; unset noglob
	/bin/rm -f /tmp/termcap.$$
	stty rows $coords[1] columns $coords[2]
endif
SHAR_EOF
cat << \SHAR_EOF > winsize.c
/*
	Usage: winsize [-d] termname

	Print size of a window in rows and columns.
	Currently knows about Apollo and Sun escape sequences.
	If termname is omitted, uses value of TERM environment variable.
*/
#include <stdio.h>
#include <sgtty.h>
#include <signal.h>
#include <fcntl.h>

int fd;
char *cp;
char *progname;
struct sgttyb otty;

struct tt {
	char *name;		/* terminal name */
	char *reportsize;	/* sequence to report window size (chars) */
	char prefix;		/* precedes first number */
	char delimiter;		/* separates row/column */
	char terminator;	/* terminates returned string */
	int  rowfirst;		/* 1 if row returned first */
} termtab[] = {
	/*
	 * N.B. !!!  these sequences should show up as
	 * escape sequences!  I.e., "esc[foo", etc.
	 * Mailing this thing out may botch it.
	 * Yes, I am too damn lazy to do it any other way!"
	 * --paul@umix.cc.umich.edu
	 */
	"sun",		"[18t", ';', ';', 't', 1,
	"apollo",	"[50n", '[', ';', 'S', 1,
	"apollo_19L",	"[50n", '[', ';', 'S', 1
	};

#define NTERM  3
#define FIREWALL 20	/* escape sequence returned can't be any longer
			   than this to prevent hanging terminal. */

timeout()
{
	stty(fd, &otty);	/* restore terminal mode */
	exit (5);
}

main(argc, argv)
	int argc;
	char ** argv;
{
	char *getenv();
	FILE *fp;
	int rows, columns;
	struct sgttyb  ntty;
	char mybuf[BUFSIZ];
	char *tn = NULL;
	int c, i, rf;
	int term;
	int debug = 0;

	progname = *argv++;
	if (argc >= 2) {
		if (**argv == '-') {
			if ((*argv)[1] == 'd')
				debug++;
			else
				fprintf(stderr, "%s: bad flag %c\n", progname,
					(*argv)[1]);
			argv++; argc--;
			}
		if (argc > 1)
			tn = *argv;
		}
	if (tn == NULL)
		tn = getenv("TERM");
	if (tn == NULL)	{
		fprintf(stderr, "usage: %s termname\n", progname);
		exit(1);
		}
	for (term = 0; term < NTERM; term++)
		if (strcmp(termtab[term].name, tn) == 0)
			break;
	if (term >= NTERM) {
		fprintf(stderr, "%s: unknown terminal type '%s'\n", progname, tn);
		exit(1);
		}

	if ((fd = open("/dev/tty", O_RDWR)) < 0)
		perror( "open" ), exit (1);

	if ((fp = fdopen(fd, "r")) == NULL)
		perror( "fdopen" ), exit(2);

	if (gtty(fd, &otty) < 0)
		perror( "gtty" ), exit(3);

	bzero(mybuf, sizeof (mybuf));

	/* set a time out so the terminal won't hang forever if the
	   escape sequence sent or received is garbled.
	   This may not work unless used with non-blocking i/o. */

	signal(SIGALRM, timeout);
	alarm(15);	/* 15 sec should be enough */

	ntty = otty;
	ntty.sg_flags = (ntty.sg_flags & ~ECHO) | RAW;
	stty(fd, &ntty);

	fflush(fp);
	write(fd, termtab[term].reportsize, strlen(termtab[term].reportsize));
	i = 0;
	while ((c=getc(fp)) != termtab[term].terminator) {
		mybuf[i++] = (c & 0177);
		if (i > FIREWALL)
			break;
		}
	
	stty(fd, &otty);
	alarm(0);	/* cancel timer */

	if (debug) {
		fprintf(stderr, "termname: %s\n", termtab[term].name);
		fprintf(stderr, "mybuf: 0x%x %s%c\n", mybuf[0], &mybuf[1],
			termtab[term].terminator);
		}
	cp = mybuf;
	rf = termtab[term].rowfirst;
	rows = getnum(termtab[term].prefix, rf);
	columns = getnum(termtab[term].delimiter, rf);

	printf("%d %d\n", rf ? rows : columns, 
			  rf ? columns : rows);

}

int
getnum(delim, rowfirst)
	char delim;
	int rowfirst;
{
	while (*cp++ != delim)
		if (*cp == '\0') {
			fprintf(stderr, "%s: no %s\n", progname, rowfirst ? "row" :
				"column");
			exit(4);
			}
	return (atoi(cp));
}
SHAR_EOF
#	End of shell archive
exit 0