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