[mod.sources] v06i020: qterm: Query Terminal for terminal type

sources-request@mirror.UUCP (06/26/86)

Submitted by: mcooper@usc-oberon.ARPA
Mod.sources: Volume 6, Issue 20
Archive-name: qterm

#!/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 the files:
#	README
#	Makefile
#	qterm.c
#	qterm.1
# This archive created: Wed Jun 18 16:02:27 1986
# By:	Michael A. Cooper (USC Computing Services, Los Angeles)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(1050 characters)'
if test -f 'README'
then
	echo shar: over-writing existing file "'README'"
fi
cat << \SHAR_EOF > 'README'

		 Q T E R M  -  Q U E R Y   T E R M I N A L

         		     Revision 1.11

	Qterm is a program that queries terminals to find out what kind
of terminal is responding.  It is useful to automagically define your
terminal type.  It prints the name of the terminal (compatible, hopefully,
with a termcap/terminfo name) such as "vt100" to standard output.
See the manual for details.

	Qterm was written under 4.2BSD and will probably run without 
modification on other Berkeley Unix systems.  It will require some
minor tweaking to work under USG (System III & V.?, V?).  Most of this
should be only in setting/unsetting cbreak and echo modes.  If you
do port it to Sys V, please send me a copy and I'll incorporate it into
my version.

	If you add any new terminal's to the master table, please send
me the output of a "qterm -s" and I'll add it to my table.

				mike


Michael Cooper, U of Southern California Computing Services, (213) 743-3462
  UUCP: {sdcrdcf, uscvax}!usc-oberon!mcooper
  ARPA: mcooper@usc-oberon.arpa 		BITNET: mcooper@uscvaxq
SHAR_EOF
echo shar: extracting "'Makefile'" '(97 characters)'
if test -f 'Makefile'
then
	echo shar: over-writing existing file "'Makefile'"
fi
cat << \SHAR_EOF > 'Makefile'
qterm: qterm.c
	cc -O qterm.c -o qterm

shar:
	shar README Makefile qterm.c qterm.1 > qterm.shar
SHAR_EOF
echo shar: extracting "'qterm.c'" '(7498 characters)'
if test -f 'qterm.c'
then
	echo shar: over-writing existing file "'qterm.c'"
fi
cat << \SHAR_EOF > 'qterm.c'
#ifndef lint
static char *RCSid = "$Header: qterm.c,v 1.11 86/06/18 15:58:45 mcooper Release $";
#endif

/*
 *------------------------------------------------------------------
 *
 * $Source: /usr/src/local/qterm/RCS/qterm.c,v $
 * $Revision: 1.11 $
 * $Date: 86/06/18 15:58:45 $
 * $State: Release $
 * $Author: mcooper $
 * $Locker: mcooper $
 *
 *------------------------------------------------------------------
 *
 * Michael Cooper (mcooper@usc-oberon.arpa)
 * University Computing Services,
 * University of Southern California,
 * Los Angeles, California,   90089-0251
 * (213) 743-3469
 *
 *------------------------------------------------------------------
 * $Log:	qterm.c,v $
 * Revision 1.11  86/06/18  15:58:45  mcooper
 * Cleanup for release.
 * 
 * Revision 1.10  86/06/17  23:06:55  mcooper
 * Added Unix PC responses.
 * 
 * Revision 1.9  86/06/16  14:19:09  mcooper
 * Added vt100 responses from vt100 manual.
 * 
 * Revision 1.8  86/06/16  13:23:40  mcooper
 * Print additional information about
 * what the actual terminal is.
 * 
 * Revision 1.7  86/06/12  10:59:27  mcooper
 * *** empty log message ***
 * 
 * Revision 1.6  86/06/11  19:48:35  mcooper
 * Added alternate string and table entries for concepts.
 * 
 * Revision 1.5  86/05/19  12:30:32  mcooper
 * General clean up.
 * 
 * Revision 1.4  86/05/18  17:56:11  mcooper
 * Added another vt100.  This one is for when you rlogin
 * from a Pro 2.9bsd host on a HDS Concept.
 * 
 * Revision 1.3  86/05/08  09:24:13  mcooper
 * Added another vt100 description.
 * 
 * Revision 1.2  86/05/06  18:23:35  mcooper
 * More cleanup - de-linted (almost).
 * 
 * Revision 1.1  86/05/06  14:56:57  mcooper
 * Initial revision
 * 
 *------------------------------------------------------------------
 */

/*
 * qterm - Query Terminal
 *
 * qterm is used to query a terminal to determine the name of the terminal.
 * This is done by sending a fairly universal string "\33Z" to the terminal,
 * reading in a response, and comparing it against a master table of responses
 * and names.  The "name" printed to standard output should be one found in
 * the termcap(5) database.
 *
 * Putting a line in your .login files such as:
 *
 *	setenv TERM `qterm`
 *
 * will set your terminal type automagically.
 * 
 * If you add a terminal to the master table, please also send me a copy
 * so that I may put it into my version.
 *
 * Michael Cooper
 * ARPA: 	mcooper@usc-oberon.ARPA
 * UUCP: 	mcooper@usc-oberon.UUCP
 * BITNET:	mcooper@uscvaxq.BITNET
 */

#include <stdio.h>
#include <sgtty.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/file.h>

#define SEND		"\033Z"		/* send this to query terminal */
#define ALTSEND		"\033[c"	/* alternate string */

#define TRUE		1
#define FALSE		0

#define T_STR		0
#define T_NAME		1
#define T_LNAME		2

/*
 * The Master Table
 */
char *terms[] = {
/*  Terminal Sends:		Terminal Name: 	Real Name: 		*/
/*	---------------		-------------- 	---------- 		*/
	"\33[?1;0c",		"vt100",		"Base vt100",
	"\33[?1;1c",		"vt100",		"vt100 with STP",
	"\33[?1;2c",		"vt100",		"ANSI/VT100 Clone",
	"\33[?1;3c",		"vt100",		"vt100 with AVO and STP",
	"\33[?1;4c",		"vt100",		"vt100 with GPO",
	"\33[?1;5c",		"vt100",		"vt100 with GPO and STP",
	"\33[?1;6c",		"vt100",		"vt100 with GPO and AVO",
	"\33[?1;7c",		"vt100",		"vt100 with GPO, STP, and AVO",
	"\33[?12c",			"vt100",		"Generic vt100",
	"\33[?6c",			"vt100",		"Generic vt100",
	"\33[?8c",			"vt100",		"TeleVideo 970",
	"\33[0n",			"vt100",		"AT&T Unix PC 7300",
	"\33[?l;0c",		"vt100",		"AT&T Unix PC 7300",
	"\33[=1;1c",		"avt-4p-s",		"Concept with 4 pages memory",
	"\33[=1;2c",		"avt-8p-s",		"Concept with 8 pages memory",
	"\33iBO",			"z29",			"Zenith z29 in zenith mode",
	"\33/K",			"z29",			"Zenith z29 in zenith mode",
	"\33/Z",			"vt52",			"Generic vt52",
	"\33[?12;7;0;102c",	"vt125",		"DEC Pro 350 in vt125 mode",
	"\33[?10c",			"la120",		"DEC Writer III",
	NULL
};

struct sgttyb _tty;
int _tty_ch = 2;

#define crmode() 	(_tty.sg_flags |= CBREAK,  stty(_tty_ch,&_tty))
#define nocrmode() 	(_tty.sg_flags &= ~CBREAK, stty(_tty_ch,&_tty))
#define echo() 		(_tty.sg_flags |= ECHO,    stty(_tty_ch,&_tty))
#define noecho() 	(_tty.sg_flags &= ~ECHO,   stty(_tty_ch,&_tty))

#define SIZE 		512
#define CMASK 		0377
#define ESC			'\033'

static char buf[SIZE];
static char *progname;
int debug;					/* debug mode 			*/
int aflag;					/* alternate string 	*/
int sflag;					/* print strings		*/
int qflag;					/* quiet mode 			*/

main(argc, argv)
char *argv[];
{
	register int i, x;
	register char c;
	int finish();
	int still_ok = 1;

	progname = argv[0];

	for (x = 1; x < argc; x++) {
		if (argv[x][0] != '-')
			break;
		switch (argv[x][1]) {
			case 'a':
				aflag = TRUE;
				break;
			case 't':
			case 's':
				sflag = TRUE;
				break;
			case 'q':
				qflag = TRUE;
				break;
			case 'd':
				debug = TRUE;
				break;
			default:
				usage();
				exit(1);
		}
	}

	setbuf(stdout, 0);

	if(debug)
		fprintf(stderr,"[ %s debug mode enabled ]\n\n", progname);

	if(!isatty(0))
		fprintf(stderr,"Not a tty.\n");

	if(gtty(_tty_ch, &_tty) < 0) {
		perror("gtty");
		exit(1);
	}
	if(crmode() < 0) {
		perror("crmode");
		exit(1);
	}
	if(noecho() < 0) {
		perror("noecho");
		exit(1);
	}

	(void) signal(SIGALRM, finish);
	(void) alarm(2);

	if(debug) {
		fprintf(stderr, "[ sending string: ");
		decode((aflag) ? ALTSEND : SEND);
		fprintf(stderr, " ]\n");
	}
	fprintf(stderr, (aflag) ? ALTSEND : SEND);
	(void) fflush(stdout);
	(void) fflush(stderr);
	buf[0] = getch();
	if(buf[0] == ESC) {
		i = 0;
		while(still_ok) {
			c = getch();
			buf[++i] = c;
			/*
			 * Most ANSI comptibles have 'c' for the
			 * last char printed.
			 */
			if(c == 'c')
				still_ok = 0;
		}
		if(debug)
			fprintf(stderr,"\n[ Received 'c' terminator. ]\n");
	} else {
		if(!qflag)
			fprintf(stderr,
			"Terminal not recognized - defaults to \"dumb\".\n");
		printf("dumb\n");
		(void) nocrmode();
		(void) echo();
		exit(1);
	}
	finish();
}

/*
 * finish - this is where we come no matter what.
 */
finish()
{
	(void) nocrmode();
	(void) echo();
	compare();
	exit(0);
}

/*
 * compare - actually compare what we received against the terminal
 *	     tables.
 */
compare()
{
	char *term, *longname;
	register int i = 0;
	int okay = 1;
	int len;

	if(debug || sflag) {
		len = strlen(buf);
		fprintf(stderr, "%s receives %d character%c: ", progname,
			len, (len == 1) ? 0 : 's');
		decode(buf);
		fprintf(stderr, "\n");
	}

	while(okay) {
		if(terms[i] == NULL) {
			okay = 0;
			term = "dumb";
			buf[0] = NULL;
			continue;
		}
		if(strcmp(buf, terms[i + T_STR]) == 0) {
			term = terms[i + T_NAME];
			longname = terms[i + T_LNAME];
			okay = 0;
		}
		i += 3;
	}

	if(buf[0] != NULL) {
		if(!qflag)
			if(*longname)
				fprintf(stderr, "Terminal recognized as %s (%s)\n", 
					term, longname);
			else
				fprintf(stderr, "Terminal recognized as %s\n", term);
	} else {
		if(!qflag)
			fprintf(stderr, 
			  "Terminal NOT recognized - defaults to \"%s\".\n",
			  term);
	}
	printf("%s\n", term);
		
}

/*
 * getch - read in a character at a time.
 */
getch()
{
	char c;

	(void) read(0, &c, 1);
	return(c & CMASK);
}

/*
 * decode - print str in a readable fashion
 */
decode(str)
char *str;
{
	while(*str) {
		if (*str == ESC)
			fprintf(stderr, "<esc> ");
		else if((*str <= 33) || (*str >= 127))
			fprintf(stderr,"\\%o ", *str);
		else
			fprintf(stderr,"%c ", *str);
		*++str;
	}
}

usage()
{
	fprintf(stderr, "usage: %s [ -asq ]\n", progname);
}
SHAR_EOF
echo shar: extracting "'qterm.1'" '(1406 characters)'
if test -f 'qterm.1'
then
	echo shar: over-writing existing file "'qterm.1'"
fi
cat << \SHAR_EOF > 'qterm.1'
.TH QTERM 1 5/6/86
.ds ]W USC Computing Services
.SH NAME
qterm \- Query Terminal
.SH SYNOPSIS
qterm 
[
.B \-a
]
[
.B \-s
]
[
.B \-q
]
.SH DESCRIPTION
.I Qterm
is used to query a terminal to determine its name.
This is done by sending the fairly universal 
string ``<ESCAPE>Z'' to the terminal,
reading in a response, and comparing it against a master table of possible
responses.
The ``name'' printed to standard output should be one found in
the
.I termcap(5) 
database.
.PP
Putting a line in your .login file such as:
.sp 1
.in +.5i
setenv TERM `qterm`
.in -.5i
.sp 1
should automagically set your terminal type.
.SH OPTIONS
.IP \-a
Use the alternate string ``<ESCAPE>[c'' when asking the terminal to
identify itself.  This string is recognized by most ANSI compatible
terminals.
.IP \-s
Display the response received from
the terminal in a ``nice'' fashion.
.IP \-q
Be ``quiet'' and only print the terminal name to standard
output.
.SH AUTHOR
Michael A. Cooper, 
.br
USC Computing Services, Los Angeles.
.SH FILES
/etc/termcap	\- termcap(5) database
.SH SEE ALSO
termcap(5)
.SH DIAGNOSTICS
The message, ``Terminal not recognized - defaults to dumb.'', means
that 
.I qterm
did not receive a response from the terminal, or the response
did not match any that 
.I qterm 
has stored internally.  Use the \-s option to check to see which
is the case.
.SH BUGS
Many terminals do not send a response at all.
SHAR_EOF
#	End of shell archive
exit 0