rs@uunet.UU.NET (Rich Salz) (07/31/87)
Submitted-by: Michael A. Cooper <mcooper@oberon.usc.edu>
Posting-number: Volume 10, Issue 72
Archive-name: qterm
[ This program sends a "what are you" escape sequence to a terminal,
and interprets the reply. --r$ ]
#!/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
# qtermtab
# qterm.c
# qterm.h
# qterm.1
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(1233 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: 3.0 $
$Date: 87/06/30 19:14:35 $
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 has been tested under
VAX 4.2BSD, VAX 4.3BSD, Sun 3.0 and Sun 3.2. It is know to work under
System V.2, but I have not personally tested it on such a system.
(For System V.2, compile with USG5 defined).
If you have ARPA Internet access, the latest and greatest
version of qterm is available from oberon.USC.EDU via anonymous ftp in
the file pub/qterm.shar. I update this file fairly often, so it's
bound to be newer than a copy from any other source.
Michael A. Cooper, University Computing Services, U of Southern California
UUCP: {sdcrdcf, cit-vax}!oberon!mcooper BITNET: mcooper@uscvaxq
ARPA: mcooper@oberon.USC.EDU PHONE: (213) 743-2957
SHAR_EOF
echo shar: extracting "'Makefile'" '(949 characters)'
if test -f 'Makefile'
then
echo shar: over-writing existing file "'Makefile'"
fi
cat << \SHAR_EOF > 'Makefile'
#
# $Header: Makefile,v 3.1 87/07/22 09:36:13 mcooper Exp $
#
# Makefile for QTerm
#
#
# If you change DIR, run "make reconfig".
#
DIR = /usr/public
BIN = $(DIR)/bin
MAN = $(DIR)/man/man1
#
# TABFILE should be set to the location you want the qterm table
# file placed in.
#
TABFILE = $(DIR)/lib/qtermtab
CONFIGFILES = Makefile qterm.1
OBJS = qterm.o
#
# Add "-DUSG5" to $(CFLAGS) below, if your system is Unix System V.
#
CFLAGS = -O -DTABFILE=\"$(TABFILE)\"
qterm: $(OBJS) qterm.h
cc $(CFLAGS) $(OBJS) -o qterm
reconfig:
-@for i in $(CONFIGFILES); do \
echo ReConfiguring $$i...;\
sed "s;/usr/public;$(DIR);g" < $$i > $$i.tmp;\
mv -f $$i.tmp $$i;\
done
shar:
shar README Makefile qtermtab qterm.c qterm.h qterm.1 > qterm.shar
clean:
rm -f *.o core log *~ \#* qterm qterm.shar o
install: qterm qterm.1 qtermtab
install qterm $(BIN)
install -c -m 644 qterm.1 $(MAN)
install -c -m 644 qtermtab $(TABFILE)
SHAR_EOF
echo shar: extracting "'qtermtab'" '(1556 characters)'
if test -f 'qtermtab'
then
echo shar: over-writing existing file "'qtermtab'"
fi
cat << \SHAR_EOF > 'qtermtab'
#
# $Header: qtermtab,v 3.0 87/07/01 13:36:30 mcooper Release $
# $Source: /big/src/usc/bin/qterm/RCS/qtermtab,v $
#
# QtermTab - Terminal table for qterm(1).
#
#SendStr ReceiveStr TermName FullTermName
#
^[Z ^[iBO h29 Zenith z29 in zenith mode
^[Z ^[/K h29 Zenith z29 in zenith mode
^[Z ^[[?1;0c vt100 Base vt100
^[Z ^[[?1;1c vt100 vt100 with STP
^[Z ^[[?1;2c vt100 ANSI/VT100 Clone
^[Z ^[[?1;3c vt100 vt100 with AVO and STP
^[Z ^[[?1;4c vt100 vt100 with GPO
^[Z ^[[?1;5c vt100 vt100 with GPO and STP
^[Z ^[[?1;6c vt100 vt100 with GPO and AVO
^[Z ^[[?1;7c vt100 vt100 with GPO, STP, and AVO
^[Z ^[[?6c vt100 Generic vt100
^[Z ^[[?8c vt100 TeleVideo 970
^[Z ^[[0n vt100 AT&T Unix PC 7300
^[Z ^[[?l;0c vt100 AT&T Unix PC 7300
^[Z ^[[?12c vt100 Concept from Pro 350/UNIX
^[Z ^[[?;c vt100 Concept From Pro 350/UNIX
^[Z ^[[=1;1c avt-4p-s Concept with 4 pages memory
^[Z ^[[=1;2c avt-8p-s Concept with 8 pages memory
^[Z ^[/Z vt52 Generic vt52
^[Z ^[[?10c la120 DEC Writer III
^[Z ^[[?1;11c cit101e CIE CIT-101 Enhanced w/Graphics
#^[Z ^[[?1;11c xt100+ Northern Tech LANPARSCOPE
^[Z ^[[?12;7;0;102c vt125 DEC Pro 350 in vt125 mode
^[Z ^[[?62;1;2;6;7;8;9c vt220 DEC VT220
^[Z ^[[?62;1;4;6;7;8;9;15c vt200-sb Microvax II VMS
^[Z ^[[62;1;2;6;8c f220 Freedom 220 DEC clone
^[Z ^[[?63;1;2;6;7;8c tvi9220 TeleVideo 9220
SHAR_EOF
echo shar: extracting "'qterm.c'" '(13185 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 3.0 87/06/30 19:07:59 mcooper Release $";
#endif
/*
*------------------------------------------------------------------
*
* $Source: /big/src/usc/bin/qterm/RCS/qterm.c,v $
* $Revision: 3.0 $
* $Date: 87/06/30 19:07:59 $
* $State: Release $
* $Author: mcooper $
* $Locker: $
*
*------------------------------------------------------------------
*
* Michael A. Cooper
* Research and Development Group
* University Computing Services
* University of Southern California
* (mcooper@oberon.USC.EDU)
*
*------------------------------------------------------------------
*
* $Log: qterm.c,v $
* Revision 3.0 87/06/30 19:07:59 mcooper
* Release of version 3.
*
* Revision 2.4 87/04/29 19:28:35 mcooper
* In readtabfile() we now do special
* things when opening "file" fails
* depending on the bequiet flag.
*
* Revision 2.3 87/04/29 13:11:37 mcooper
* - No more "internal" table. The master
* table is read from a file (TABFILE).
* This makes ~/.qterm stuff much cleaner.
* - Error handling for qtermtab files is
* much more informative now.
* - More things I can't remember.
*
* Revision 2.2 87/03/05 21:01:28 mcooper
* Fixed system V compiler problem.
*
* Revision 2.1 87/03/01 19:43:22 mcooper
* Be more intelligent about the size of
* the default terminal table.
*
* Revision 2.0 87/03/01 19:20:00 mcooper
* General cleanup.
*
*------------------------------------------------------------------
*/
/*
* 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" file such as:
*
* setenv TERM `qterm`
*
* or the following lines in your ".profile" file:
*
* TERM=`qterm`
* export TERM
*
* 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@oberon.USC.EDU
* UUCP: {sdcrdcf, cit-vax}!oberon!mcooper
* BITNET: mcooper@uscvaxq
*/
#include <stdio.h>
#include <pwd.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <setjmp.h>
#ifdef USG5
# include <termio.h>
#else
# include <sys/file.h>
# include <sgtty.h>
#endif
#include "qterm.h"
int tabtotal = 0;
int has_set = 0;
struct qt *compare();
struct qt termtab[MAXTERMS];
#ifdef USG5
struct termio _ntty, _otty;
#else
struct sgttyb _tty;
#endif
int _tty_ch = 2;
static char recvbuf[SIZE];
static char *progname;
int debug = FALSE; /* debug mode */
int aflag = FALSE; /* alternate string */
int sflag = FALSE; /* print strings */
int qflag = FALSE; /* quiet mode */
int fflag = FALSE; /* use user's own .qterm file */
int Fflag = FALSE; /* same as above, but don't add our own table */
int found = FALSE;
int index = 0;
int finish(), wakeup(), done();
char *decode();
jmp_buf env;
main(argc, argv)
char *argv[];
{
register int x;
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 'f':
fflag = TRUE;
break;
case 'F':
Fflag = TRUE;
break;
case 'd':
debug = TRUE;
break;
default:
usage();
exit(1);
}
}
setbuf(stdout, 0);
if(debug)
setbuf(stderr, 0);
dprintf("[ %s debug mode enabled ]\n\n", progname);
if(!isatty(0))
fprintf(stderr,"Not a tty.\n");
#ifdef USG5
if(ioctl(_tty_ch, TCGETA, &_otty) < 0)
#else
if(ioctl(_tty_ch, TIOCGETP, &_tty) < 0)
#endif
{
perror("gtty");
exit(1);
}
#ifdef USG5
_ntty = _otty;
#endif
if(crmode() < 0) {
perror("crmode");
exit(1);
}
if(noecho() < 0) {
perror("noecho");
exit(1);
}
mktable();
index = 0;
dprintf("main: we'll do a dotab()\n");
dotab();
dprintf("main: dotab done\n");
putc('\r', stderr);
(void) nocrmode();
(void) echo();
if(!found) {
dprintf("end of main\n");
notrecognized();
}
}
usage()
{
fprintf(stderr, "usage: %s [ -a ] [ -s ] [ -q ] [ -f ] [ -F ]\n",
progname);
}
done(s)
int s;
{
putc('\r', stderr);
(void) nocrmode();
(void) echo();
exit(s);
}
/*
* finish - clean things up.
*/
finish()
{
dprintf("finish called\n");
putc('\r', stderr);
(void) nocrmode();
(void) echo();
if(recvbuf[0] != NULL)
(void) prinfo(compare(recvbuf, 0, tabtotal), 1);
dprintf("finish done\n");
if(!found)
notrecognized();
exit(0);
}
prinfo(t, what)
struct qt *t;
int what;
{
int len = 0;
int st = FALSE;
dprintf("prinfo startup\n");
if((t != NULL) && (t->qt_termname[0] != NULL) && (recvbuf[0] != NULL)) {
if(debug || sflag) {
len = strlen(recvbuf);
fprintf(stderr, "%s receives %d character%s:",
progname, len, (len == 1) ? "" : "s");
fprintf(stderr, " %s\n", decode(recvbuf));
}
if(!qflag)
if(t->qt_fullname[0] != NULL)
fprintf(stderr, "Terminal recognized as %s (%s)\n",
t->qt_termname, t->qt_fullname);
else
fprintf(stderr, "Terminal recognized as %s\n",
t->qt_termname);
printf("%s\n", t->qt_termname);
found = TRUE;
done(0);
/*NOTREACHED*/
} else {
found = FALSE;
if(what) {
dprintf("prinfo(): doing notrecognized()\n");
notrecognized();
done(1);
/*NOTREACHED*/
}
}
dprintf("prinfo done\n");
return(st);
}
/*
* compare - actually compare what we received against the table.
*/
struct qt *
compare(str, start, stop)
char *str;
int start;
int stop;
{
register int i = 0;
dprintf("compare(%s, %d, %d) startup.\n", decode(str), start, stop);
alarm(0);
i = start;
while(i <= stop) {
dprintf("compare(): tr = '%s'\n", decode(termtab[i].qt_recvstr));
if(strncmp(str, termtab[i].qt_recvstr,
strlen(termtab[i].qt_recvstr)) == 0) {
found = TRUE;
return(&termtab[i]);
}
++i;
}
found = FALSE;
return(NULL);
}
/*
* 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
*/
char *
decode(str)
char *str;
{
char buf[BUFSIZ];
char tmp[10];
strcpy(buf, "");
while(*str) {
if (*str == ESC) {
strcat(buf, "<esc> ");
} else if((*str <= 33) || (*str >= 127)) {
sprintf(tmp,"\\%o ", *str);
strcat(buf, tmp);
} else {
sprintf(tmp,"%c ", *str);
strcat(buf, tmp);
}
*++str;
}
return(buf);
}
mktable()
{
char file[BUFSIZ];
struct passwd *pwd;
char *home;
dprintf("[ initilizing term table... ]\n");
if(fflag) {
/*
* Try and read the user's own table
*/
if((home = (char *) getenv("HOME")) == NULL) {
if((pwd = (struct passwd *) getpwuid(getuid())) == NULL) {
fprintf(stderr, "Who the hell are you????\n");
exit(1);
}
home = pwd->pw_dir;
}
dprintf("home = '%s'\n", home);
sprintf(file, "%s/%s", home, STRFILE);
dprintf("strfile = '%s'\n", file);
(void) readtabfile(file, TRUE);
}
if(!Fflag)
(void) readtabfile(TABFILE, FALSE);
dprintf("termtab total = %d\n", tabtotal);
dprintf("[ mktable done ]\n");
}
readtabfile(file, bequiet)
char *file;
int bequiet;
{
static int i = 0, line;
char lbuf[4][BUFSIZ];
char buf[BUFSIZ];
FILE *fd, *fopen();
char *msg, *fixctl();
int iserr = 0;
if((fd = fopen(file, "r")) == NULL) {
if(bequiet)
return(-1);
perror(file);
done(1);
}
line = 0;
while(fgets(buf, sizeof(buf), fd) && i < MAXTERMS) {
++line;
if(buf[0] == '#' || buf[0] == '\n')
continue;
lbuf[0][0] = NULL;
lbuf[1][0] = NULL;
lbuf[2][0] = NULL;
lbuf[3][0] = NULL;
(void) sscanf(buf, "%s%s%s\t%[^\n]",
lbuf[0], lbuf[1], lbuf[2], lbuf[3]);
if(lbuf[0][0] == NULL)
continue;
if(lbuf[1][0] == NULL) {
iserr = TRUE;
msg = "receive string";
}
if(lbuf[2][0] == NULL) {
iserr = TRUE;
msg = "terminal name";
}
if(iserr) {
fprintf(stderr, "Line %d of %s: Error parsing %s.\n",
line, file, msg);
done(1);
/* NOTREACHED */
}
if(aflag)
(void) strcpy(termtab[i].qt_sendstr, fixctl(ALTSEND));
else
(void) strcpy(termtab[i].qt_sendstr, fixctl(lbuf[0]));
(void) strcpy(termtab[i].qt_recvstr, fixctl(lbuf[1]));
(void) strcpy(termtab[i].qt_termname, lbuf[2]);
(void) strcpy(termtab[i].qt_fullname, lbuf[3]);
dprintf("entry %d:\n", i);
dprintf("qt_sendstr = %s\n", decode(termtab[i].qt_sendstr));
dprintf("qt_recvstr = %s\n", decode(termtab[i].qt_recvstr));
dprintf("qt_termname = '%s'\n", termtab[i].qt_termname);
dprintf("qt_fullname = '%s'\n", termtab[i].qt_fullname);
++i;
}
tabtotal = i;
return(0);
}
listen(q)
struct qt *q;
{
register int i;
register char c;
char end, begin;
dprintf("listen startup\n");
alarm(0);
dprintf("listen: listening for '%s'\n", decode(q->qt_recvstr));
if (q->qt_recvstr[0] == NULL) {
begin = ESC;
end = 'c';
} else {
begin = q->qt_recvstr[0];
end = q->qt_recvstr[strlen(q->qt_recvstr)-1];
}
dprintf("listen: read initial character...\n");
if(setjmp(env)) {
dprintf("listen: setjmp TRUE\n");
if(found)
done();
++index;
(void) fflush(stdin);
dprintf("listen: dotab()\n");
dotab();
} else {
dprintf("listen: setjmp FALSE...set alarm\n");
signal(SIGALRM, wakeup);
alarm(WAIT);
dprintf("listen: read char\n");
recvbuf[0] = getch();
alarm(0);
dprintf("recvbuf[0] = '\\%o'\n", recvbuf[0]);
}
i = 0;
if(recvbuf[0] == begin) {
dprintf("listen begin\n");
while(c != end) {
if(setjmp(env)) {
dprintf("listen: setjmp (2) return\n");
return;
} else {
signal(SIGALRM, wakeup);
alarm(WAIT);
dprintf("listen: read (2) char\n");
c = getch();
alarm(0);
dprintf("recvbuf[0] = '\\%o'\n", recvbuf[0]);
}
recvbuf[++i] = c;
}
if(debug)
fprintf(stderr,"\n[ Received terminator. ]\n");
} else {
dprintf("listen: Not Recognized. exiting...\n");
notrecognized();
putc('\r',stderr);
(void) nocrmode();
(void) echo();
exit(1);
}
dprintf("listen done\n");
}
notrecognized()
{
if(!qflag)
fprintf(stderr,
"Terminal NOT recognized - defaults to \"dumb\".\n");
puts("dumb");
}
wakeup()
{
dprintf("wakeup called\n");
longjmp(env, 1);
dprintf("wakeUP: done\n");
}
dotab()
{
int wakeup();
int st = FALSE;
static int firsttime = TRUE;
dprintf("dotab startup\n");
dprintf("index = %d\n", index);
if(index > tabtotal) {
/*
* if we haven't reset things yet, do so.
* now try the internal tables if the user's
* tables failed.
*/
if(!has_set) {
index = 0;
has_set = 1;
dprintf("dotab(): has_set now true.\n");
dotab();
}
dprintf("dotab(): index > tabtotal\n");
finish();
}
if(!found || fflag) {
while(!found && termtab[index].qt_sendstr[0] != NULL && !st) {
dprintf("dotab: termtab PASS %d\n", index);
dprintf("dotab: sending str %s\n",
decode(termtab[index].qt_sendstr));
(void) fflush(stdin);
if(firsttime || strncmp(termtab[index].qt_sendstr,
termtab[index-1].qt_sendstr,
strlen(termtab[index].qt_sendstr))) {
firsttime = FALSE;
dprintf("dotab(): sendstr's didn't match.\n");
dprintf("dotab: str1 %s\n", decode(termtab[index].qt_sendstr));
dprintf("dotab: str2 %s\n", decode(termtab[index-1].qt_sendstr));
fprintf(stderr, termtab[index].qt_sendstr);
(void) fflush(stdout);
(void) fflush(stderr);
(void) listen(&termtab[index]);
} else {
dprintf("dotab(): sendstr's DID match. No str sent.\n");
dprintf("dotab: str1 %s\n", decode(termtab[index].qt_sendstr));
dprintf("dotab: str2 %s\n", decode(termtab[index-1].qt_sendstr));
}
firsttime = FALSE;
dprintf("dotab(): recbuf = '%s'\n", decode(recvbuf));
dprintf("dotab(): qt_rec = '%s'\n", decode(termtab[index].qt_recvstr));
st = prinfo(compare(recvbuf, 0, tabtotal), FALSE);
dprintf("st = %d\n", st);
++index;
}
}
if(!found) {
dprintf("dotab: failed.\n");
notrecognized();
}
done();
}
char *
fixctl(str)
char *str;
{
register int i;
char buf[BUFSIZ];
i = 0;
while(*str) {
if(*str == '^')
buf[i++] = *++str & 037;
else
buf[i++] = *str;
*++str;
}
buf[i] = NULL;
return(buf);
}
SHAR_EOF
echo shar: extracting "'qterm.h'" '(2544 characters)'
if test -f 'qterm.h'
then
echo shar: over-writing existing file "'qterm.h'"
fi
cat << \SHAR_EOF > 'qterm.h'
/*
* $Header: qterm.h,v 3.0 87/06/30 19:09:04 mcooper Release $
*------------------------------------------------------------------
*
* $Source: /big/src/usc/bin/qterm/RCS/qterm.h,v $
* $Revision: 3.0 $
* $Date: 87/06/30 19:09:04 $
* $State: Release $
* $Author: mcooper $
* $Locker: $
*
*------------------------------------------------------------------
*
* Michael A. Cooper
* Research and Development Group
* University Computing Services
* University of Southern California
* (mcooper@oberon.USC.EDU)
*
*------------------------------------------------------------------
* $Log: qterm.h,v $
* Revision 3.0 87/06/30 19:09:04 mcooper
* Release of version 3.
*
* Revision 2.4 87/06/30 19:02:28 mcooper
* WAIT changed to 2 for slow systems.
*
*------------------------------------------------------------------
*/
#ifndef TABFILE
# define TABFILE "/usr/local/lib/qtermtab"
#endif
#define ALTSEND "\033[c" /* alternate string */
#define STRFILE ".qterm" /* file containing terminal strings */
#define WAIT 2 /* Number of seconds for alarms */
#define MAXTERMS 50 /* Maximum # of terminals for qterm */
#define SIZE 512
#define CMASK 0377
#define ESC '\033'
#define TRUE 1
#define FALSE 0
#ifdef USG5
# define crmode() (_ntty.c_lflag &= ~ICANON,\
_ntty.c_cc[VMIN] = 1, _ntty.c_cc[VTIME] = 0,\
ioctl(_tty_ch, TCSETAF, &_ntty))
# define nocrmode() (_ntty.c_lflag |= ICANON,\
_ntty.c_cc[VMIN] = _otty.c_cc[VMIN],\
_ntty.c_cc[VTIME] = _otty.c_cc[VTIME],\
ioctl(_tty_ch, TCSETAF, &_ntty))
# define echo() (_ntty.c_lflag |= ECHO,\
ioctl(_tty_ch, TCSETAF, &_ntty))
# define noecho() (_ntty.c_lflag &= ~ECHO,\
ioctl(_tty_ch, TCSETAF, &_ntty))
#else
# define crmode() (_tty.sg_flags |= CBREAK,\
ioctl(_tty_ch, TIOCSETP, &_tty))
# define nocrmode() (_tty.sg_flags &= ~CBREAK,\
ioctl(_tty_ch, TIOCSETP, &_tty))
# define echo() (_tty.sg_flags |= ECHO, \
ioctl(_tty_ch, TIOCSETP, &_tty))
# define noecho() (_tty.sg_flags &= ~ECHO, \
ioctl(_tty_ch, TIOCSETP, &_tty))
#endif
#define dprintf if(debug)printf
struct qt {
char qt_sendstr[BUFSIZ]; /* String to send to terminal */
char qt_recvstr[BUFSIZ]; /* String expected in response */
char qt_termname[BUFSIZ]; /* Terminal name */
char qt_fullname[BUFSIZ]; /* Full terminal name & description */
};
SHAR_EOF
echo shar: extracting "'qterm.1'" '(3608 characters)'
if test -f 'qterm.1'
then
echo shar: over-writing existing file "'qterm.1'"
fi
cat << \SHAR_EOF > 'qterm.1'
.\"
.\" $Header: qterm.1,v 3.0 87/06/30 19:10:08 mcooper Release $
.\"
.TH QTERM 1 "29 April 1987"
.ds ]W USC-UCS
.SH NAME
qterm \- Query Terminal
.SH SYNOPSIS
qterm
[
.B \-a
]
[
.B \-f
]
[
.B \-F
]
[
.B \-s
]
[
.B \-q
]
.SH DESCRIPTION
.I Qterm
is used to query a terminal to determine its name.
This is done by sending a special sequence 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
For
.I csh(1)
users,
putting a line in your
.I .login
file such as:
.sp 1
.in +.5i
setenv TERM `qterm`
.in -.5i
.sp 1
should automagically set your terminal type.
For
.I sh(1)
users, putting these lines in your
.I .profile
file should set your terminal type:
.sp 1
.in +.5i
TERM=`qterm`
.br
export TERM
.in -.5i
.sp 1
.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 \-f
If the file
.B $HOME/.qterm
is present, it's contents are scanned to produce information for
querying terminals. In this way, a user may setup different values
for certain terminals.
After the contents of this file have been scanned,
.I qterm
proceeds to query the terminal with the information provided.
If an un-intelligable response is received (or non at all),
.I qterm
will proceed to use its own information to determine the terminal
type.
.IP \-F
Same as \-f except that the standard
.I qterm
table is not scanned; only the user's
.B $HOME/.qterm
file is used.
.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 "QTERMTAB"
The format of the file
$HOME/.qterm
and
.I qterm's
master file
.I /usr/public/lib/qtermtab,
consists of four fields each seperated by white space (tabs and/or spaces).
The first field is the string that should be used to query the terminal.
The second field is the string to expect in response to the query.
The third field is the terminal name (compatible with
.I termcap(5))
to print to standard output.
The fourth field is optional and may contain a description of the exact
manufacturer and model name of the terminal to be used in a message
printed to standard error.
.PP
Blank lines or lines starting with the character ``#''
are ignored and may be used as comment lines.
A character preceeded by a ``^'' is taken to mean the
.I control
character. (i.e. ``^['' is interpretted as an <ESCAPE>).
.PP
Below is a sample file:
.sp 2
.nf
#
# QTerm File
#
^[Z\0\0\0\0\0^[[?1;1c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with STP
^[Z\0\0\0\0\0^[[?1;2c\0\0\0\0\0vt100\0\0\0\0\0ANSI/VT100 Clone
^[Z\0\0\0\0\0^[[?1;3c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with AVO and STP
^[Z\0\0\0\0\0^[[?1;4c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with GPO
^[Z\0\0\0\0\0^[iBO\0\0\0\0\0\0\0\0z29\0\0\0\0\0\0\0Zenith in Zenith Mode
.fi
.sp
.SH AUTHOR
Michael A. Cooper,
.br
University Computing Services,
.br
University of Southern California.
.SH FILES
.ta \w'/usr/public/lib/qtermtab\ \ \ 'u
/usr/public/lib/qtermtab \- Master table
.br
$HOME/.qterm \- User's table
.br
/etc/termcap \- termcap(5) database
.SH SEE ALSO
csh(1), sh(1), termcap(5)
.SH DIAGNOSTICS
.IP "\fITerminal not recognized - defaults to dumb.\fP"
.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
--
Rich $alz "Anger is an energy"
Cronus Project, BBN Labs rsalz@bbn.com
Moderator, comp.sources.unix sources@uunet.uu.net