[alt.sources] query terminal type, improved slightly

djm@eng.umd.edu (David J. MacKenzie) (07/26/90)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile gstty.c qterm.1 qterm.c qterm.h qtermtab
#   query.c table.c
# Wrapped by djm@twiddle on Thu Jul 26 03:37:56 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(979 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XQTERM
X
XThis is a revision of Craig Bishop's rewrite of Michael Cooper's program
Xto determine the terminal type by sending one or more strings and
Xinterpreting the responses.  Enhancements over the previous version
X(which appeared in comp.sources.unix as v12i025) are:
X
XIt has a manual page.
XIt allows a default terminal type to be specified if the terminal is not
Xrecognized.
XIt recognizes octal escapes in the send and receive strings, allowing
Xthe Wyse 50 to be recognized.
XIt uses getopt.
XThe code has been cleaned up and more comments added.
X
XDavid MacKenzie, djm@eng.umd.edu
X
X(From the previous README:)
X
XQterm is particularly valuable in port selector and terminal server 
Xenvironments. Most terminals can respond to the standard ANSI query
Xsequences; others which cannot will often do answerback.
X
XIf you find any bugs please report them to me.
X
XCraig Bishop 		ACSNET:	craig@charlie.oz
X			ARPA:	craig%charlie.oz.au@uunet.uu.net
X			UUCP:	...!uunet!munnari!charlie.oz!craig
END_OF_FILE
if test 979 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(697 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Makefile for qterm.
X
XSHELL = /bin/sh
XCC = cc
X# For System V put -DSYSV in DEFS.
XDEFS = -DTABLEFILE=\"$(TABLEDIR)/$(TABLE)\"
XCFLAGS = -O $(DEFS)
XLDFLAGS = -s
XLIBS = 
XSRCS = gstty.c qterm.c query.c table.c
XOBJS = gstty.o qterm.o query.o table.o
XHDRS = qterm.h
XMAN = qterm.1
XBINDIR = /usr/local/bin
XMANDIR = /usr/local/man/man1
XTABLE = qtermtab
XTABLEDIR = /usr/local/lib
X
Xall:		qterm
X
Xqterm:	$(OBJS)
X	$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
X
X$(OBJS):	$(HDRS)
X
Xinstall:
X	install qterm $(BINDIR)
X	install -m 644 $(MAN) $(MANDIR)
X	install -m 644 $(TABLE) $(TABLEDIR)
X
XLINT:		$(SRCS) $(HDRS)
X	lint $(DEFS) $(SRCS) > LINT
X
Xtags:		$(SRCS)
X	ctags $(SRCS)
X
Xclean:
X	-rm -f qterm $(OBJS) tags core a.out LINT
END_OF_FILE
if test 697 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'gstty.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'gstty.c'\"
else
echo shar: Extracting \"'gstty.c'\" \(1026 characters\)
sed "s/^X//" >'gstty.c' <<'END_OF_FILE'
X/* gstty.c -- get and set terminal parameters
X
X   Author: Craig Bishop
X   modified by David MacKenzie
X   loosly based on original program by Michael Cooper. */
X
X#include	<sys/ioctl.h>
X
X#ifdef	SYSV
X#include	<termio.h>
X
Xstatic struct termio old_mode;
Xstatic struct termio new_mode;
X
X/* Put terminal in raw mode. */
X
Xvoid
Xsetterm ()
X{
X  ioctl (0, TCGETA, &old_mode);
X  new_mode = old_mode;
X  new_mode.c_lflag &= ~ICANON;
X  new_mode.c_lflag &= ~ECHO;
X  new_mode.c_cc[VMIN] = 1;
X  new_mode.c_cc[VTIME] = 0;
X  ioctl (0, TCSETAF, &new_mode);
X}
X
X/* Put terminal back in previous mode. */
X
Xvoid
Xfixterm ()
X{
X  ioctl (0, TCSETAF, &old_mode);
X}
X
X#else
Xstatic struct sgttyb old_mode;
Xstatic struct sgttyb new_mode;
X
X/* Put terminal in raw mode. */
X
Xvoid
Xsetterm ()
X{
X  ioctl (0, TIOCGETP, &old_mode);
X  new_mode = old_mode;
X  new_mode.sg_flags |= CBREAK;
X  new_mode.sg_flags &= ~ECHO;
X  ioctl (0, TIOCSETP, &new_mode);
X}
X
X/* Put terminal back in previous mode. */
X
Xvoid
Xfixterm ()
X{
X  ioctl (0, TIOCSETP, &old_mode);
X}
X
X#endif /* SYSV */
END_OF_FILE
if test 1026 -ne `wc -c <'gstty.c'`; then
    echo shar: \"'gstty.c'\" unpacked with wrong size!
fi
# end of 'gstty.c'
fi
if test -f 'qterm.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'qterm.1'\"
else
echo shar: Extracting \"'qterm.1'\" \(4304 characters\)
sed "s/^X//" >'qterm.1' <<'END_OF_FILE'
X.TH QTERM 1L \" -*- nroff -*-
X.SH NAME
Xqterm \- query terminal type
X.SH SYNOPSIS
X.B qterm 
X[
X.B \-adefFqs
X] [
X.B \-u unknown-term
X]
X.SH DESCRIPTION
X.I qterm
Xqueries a terminal to determine its type.  The type that results will
Xbe one found in the
X.IR termcap (5)
Xdatabase.
X.I qterm
Xthen prints the type it has determined on the standard output, where
Xit can be read by a program, and prints a message containing the
Xterminal type and terminal name on the standard error, where it can be
Xread by the user.  The querying is done by sending one or more
Xstandard terminal identification query strings to the terminal,
Xreading in its response, and comparing it against a table of possible
Xresponses.
X.PP
XUsers of
X.IR csh (1) 
Xcan automatically set the terminal type by putting the following line
Xin their .login file:
X.sp 1
X.in +.5i
Xsetenv TERM `qterm`
X.in -.5i
X.sp 1
XUsers of
X.IR sh (1)
Xcan do the same by putting the following line in the .profile file:
X.sp 1
X.in +.5i
XTERM=`qterm`; export TERM
X.in -.5i
X.SH OPTIONS
X.TP
X.I \-a
XOverride the identification query strings for all terminal types with
Xthe ``alternate'' string ``<ESCAPE>[c''.  This string is recognized by
Xmost ANSI compatible terminals.
X.TP
X.I \-d
XOverride the identification query strings for all terminal types with
Xthe ``default'' string ``<ESCAPE>Z''.  This string is recognized by
Xmost terminals.
X.TP
X.I \-e
XOverride the identification query strings for all terminal types with
Xthe ``answerback'' string ``^E''.
X.TP
X.I \-f
XRead the file
X.I $HOME/.qterm
Xfor additional information on terminal responses.  If using this file
Xfails to produce an intelligible response,
X.I qterm
Xwill use its standard configuration file to determine the terminal
Xtype.
X.TP
X.I \-F
XSame as
X.I \-f,
Xexcept that the standard configuration file is not used.
X.TP
X.I \-q
XRun quietly; do not print a message on standard error.
X.TP
X.I \-s
XDisplay the string received from the terminal, with control characters
Xinterpreted visually.
X.TP
X.I \-u unknown-term
XDefault to terminal type
X.I unknown-term
Xrather than ``dumb'' if no recognizable response is received.
X.SH "QTERM CONFIGURATION FILES"
X.PP
XEach line of the standard configuration file and the personal
Xconfiguration files
X.I ($HOME/.qterm)
Xconsists of four fields each seperated by white space (tabs and/or
Xspaces).  The first field is the string that should be used to query
Xthe terminal.  The second field is the string to expect in response to
Xthe query.  The third field is the terminal name, compatible with
X.IR termcap (5),
Xto print to standard output.  The fourth field is optional and may
Xcontain a description of the exact manufacturer and model name of the
Xterminal to be used in a message printed to the standard error output.
X.PP
XBlank lines and lines starting with the character ``#'' are ignored
Xand may be used as comment lines.  A character preceeded by a ``^'' is
Xinterpreted as the appropriate control character.  ``^['' is
Xinterpreted as <ESCAPE>.  Octal escapes of the form ``\\ooo'',
Xwhere ``ooo'' are 1-3 octal digits, are interpreted as the character
Xwith that value; this is the way to include the ``^'', ``\\'', and
Xspace characters in the strings.  All entries with the same terminal
Xquery string should be grouped together, or else the string will be
Xsent multiple times.
X.PP
XBelow is a sample file:
X.sp 2
X.nf
X	#
X	# qterm configuration file
X	#
X	^[Z\0\0\0\0\0^[[?1;1c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with STP
X	^[Z\0\0\0\0\0^[[?1;2c\0\0\0\0\0vt100\0\0\0\0\0ANSI/VT100 Clone
X	^[Z\0\0\0\0\0^[[?1;3c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with AVO and STP
X	^[Z\0\0\0\0\0^[[?1;4c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with GPO
X	^[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
X.fi
X.sp
X.SH FILES
X.TP
X/usr/lib/qtermtab
Xstandard configuration file
X.TP
X$HOME/.qterm
Xpersonal configuration files
X.SH "SEE ALSO"
X.BR csh (1),
X.BR sh (1),
X.BR termcap (5)
X.SH DIAGNOSTICS
X.TP
XTerminal not recognized - defaulting to dumb
X.I qterm
Xdid not receive a response from the terminal, or the response did not
Xmatch any listed in the configuration files. Use the
X.I \-s
Xoption to determine to see which is the case.  If the
X.I \-u
Xoption is given, ``dumb'' will be replaced by that option's argument.
X.SH BUGS
XMany terminals do not send a response at all.
X.SH AUTHORS
XCraig Bishop
X.br
XDavid MacKenzie
END_OF_FILE
if test 4304 -ne `wc -c <'qterm.1'`; then
    echo shar: \"'qterm.1'\" unpacked with wrong size!
fi
# end of 'qterm.1'
fi
if test -f 'qterm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'qterm.c'\"
else
echo shar: Extracting \"'qterm.c'\" \(3715 characters\)
sed "s/^X//" >'qterm.c' <<'END_OF_FILE'
X/* qterm.c -- query the terminal to determine the terminal name.
X   This is done by sending an enquiry string
X   to the terminal and reading its response.
X
X   Author: Craig Bishop
X   modified by David MacKenzie
X   loosly based on original program by Michael Cooper. */
X
X#include <stdio.h>
X#include <signal.h>
X
X#include "qterm.h"
X
Xint user_table = FALSE;		/* use user's own .qterm file */
Xint user_table_only = FALSE;	/* same, but don't add standard table */
Xint quiet_mode = FALSE;		/* quiet mode */
Xint print_strings = FALSE;	/* print strings */
X
Xchar querystr[FIELDSIZ];
Xchar recvbuf[FIELDSIZ];
Xchar *program_name;
Xchar *unterm = "dumb";		/* default terminal type */
X
Xvoid
Xusage ()
X{
X  fprintf (stderr, "Usage: %s [-adefFqs] [-u unknown-term]\n",
X	   program_name);
X  exit (1);
X}
X
Xstruct qt *termtab[MAXTERMS];
X
Xvoid
Xmain (argc, argv)
X     int argc;
X     char **argv;
X{
X  extern int optind;
X  extern char *optarg;
X  register int i;
X  struct qt *qtp;
X
X  program_name = argv[0];
X
X  while ((i = getopt (argc, argv, "adefFqsu:")) != EOF)
X    {
X      switch (i)
X	{
X	case 'a':
X	  strncpy (querystr, ALTSEND, FIELDSIZ);
X	  break;
X	case 'd':
X	  strncpy (querystr, DFLTSEND, FIELDSIZ);
X	  break;
X	case 'e':
X	  strncpy (querystr, ABSEND, FIELDSIZ);
X	  break;
X	case 'f':
X	  user_table = TRUE;
X	  break;
X	case 'F':
X	  user_table_only = TRUE;
X	  break;
X	case 'q':
X	  quiet_mode = TRUE;
X	  break;
X	case 's':
X	  print_strings = TRUE;
X	  break;
X	case 'u':
X	  unterm = optarg;
X	  break;
X	default:
X	  usage ();
X	}
X    }
X  if (optind < argc)
X    usage ();
X
X  if (!isatty (0))
X    {
X      fprintf (stderr, "%s: standard input must be a tty\n", program_name);
X      exit (1);
X    }
X
X  if (mktable () == FALSE)
X    exit (1);
X
X  setterm ();
X  signal (SIGHUP, catchint);
X  signal (SIGINT, catchint);
X  signal (SIGQUIT, catchint);
X  setbuf (stdout, NULLSTR);
X  setbuf (stderr, NULLSTR);
X  qtp = queryterm ();
X  fixterm ();
X
X  if (qtp != NULLQT)
X    prinfo (qtp);
X  else
X    unknown ();
X
X  exit (0);
X}
X
X
X/* Signal handler; clean up and die. */
X
Xvoid
Xcatchint ()
X{
X  fixterm ();
X  exit (1);
X}
X
X/* Announce which terminal type we think we have. */
X
Xvoid
Xprinfo (ttent)
X     register struct qt *ttent;
X{
X  register int len;
X
X  if (print_strings)
X    {
X      len = strlen (recvbuf);
X      fprintf (stderr, "%s: received %d character%s: %s\n",
X	       program_name, len, len == 1 ? "" : "s",
X	       decode (recvbuf));
X    }
X  if (!quiet_mode)
X    {
X      fprintf (stderr, "Terminal recognized as %s", ttent->termname);
X      if (*ttent->fullname)
X	fprintf (stderr, " (%s)\n", ttent->fullname);
X      else
X	fprintf (stderr, "\n");
X    }
X  puts (ttent->termname);
X}
X
X/* Announce that we don't know what type of terminal we have. */
X
Xvoid
Xunknown ()
X{
X  register int len;
X
X  if (print_strings)
X    {
X      len = strlen (recvbuf);
X      fprintf (stderr, "%s: received %d character%s",
X	       program_name, len, len == 1 ? "" : "s");
X      if (len)
X	fprintf (stderr, ": %s\n", decode (recvbuf));
X      else
X	fputs ("\n", stderr);
X    }
X  if (!quiet_mode)
X    fprintf (stderr, "Terminal not recognized - defaulting to %s\n", unterm);
X
X  puts (unterm);
X}
X
X/* Return a pointer to a copy of the string STR with unprintable
X   characters made printable. */
X
Xchar *
Xdecode (str)
X     register char *str;
X{
X  static char decodebuf[BUFSIZ];
X  char tmp[10];
X
X  /* Use register variables for speed. */
X  register char *dbp = decodebuf;
X  register char *tmpp = tmp;
X
X  for (*dbp = 0; *str; str++)
X    {
X      if (*str == 27)
X	{
X	  strcat (dbp, "<ESC> ");
X	}
X      else if (*str <= 33 || *str == 127)
X	{
X	  sprintf (tmpp, "\\%o ", *str);
X	  strcat (dbp, tmpp);
X	}
X      else
X	{
X	  sprintf (tmpp, "%c ", *str);
X	  strcat (dbp, tmpp);
X	}
X    }
X
X  return dbp;
X}
END_OF_FILE
if test 3715 -ne `wc -c <'qterm.c'`; then
    echo shar: \"'qterm.c'\" unpacked with wrong size!
fi
# end of 'qterm.c'
fi
if test -f 'qterm.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'qterm.h'\"
else
echo shar: Extracting \"'qterm.h'\" \(1746 characters\)
sed "s/^X//" >'qterm.h' <<'END_OF_FILE'
X/* qterm.h -- defines and declarations for the qterm modules.
X
X   Author: Craig Bishop
X   modified by David MacKenzie
X   loosly based on original program by Michael Cooper. */
X
X#define	ABSEND		"\05"	/* Answerback string */
X#define	ALTSEND		"\033[c"/* Alternative string */
X#define DFLTSEND	"\033Z"	/* Default string */
X#define	CMASK		0177	/* Character mask */
X#define	MAXTERMS	100	/* Maximum # of terminals for qterm */
X#define	STRFILE		".qterm"/* File containing terminal strings */
X
X/* The number of seconds for alarm timeouts.  Some slower systems
X   may need to increase this value to 2 or maybe 3 seconds.  This value
X   affects how long qterm will run, because for each query string sent
X   the program must wait at least this long. */
X
X#define	WAITSEC		1
X
X#define	TRUE		1
X#define	FALSE		0
X
X#define NULLSTR		(char *) NULL
X#define	NULLQT		(struct qt *) NULL
X#define	STREQUAL	(0)
X
X#define FIELDSIZ	30
X#define	FULLSIZ		80
X
X/* Structure of query table element. */
Xstruct qt
X{
X  char sendstr[FIELDSIZ];	/* String to send to terminal */
X  char recvstr[FIELDSIZ];	/* String expected in response */
X  char termname[FIELDSIZ];	/* Terminal name */
X  char fullname[FULLSIZ];	/* Full terminal name & description */
X};
X
Xextern int user_table_only;
Xextern int user_table;
Xextern int quiet_mode;
Xextern int print_strings;
X
Xextern char querystr[];
Xextern char recvbuf[];
Xextern char *program_name;
X
Xextern struct qt *termtab[];
X
XFILE *fopen ();
Xchar *getenv ();
Xchar *malloc ();
X
Xchar *decode ();
Xchar *fixctl ();
Xchar *term_listen ();
Xchar *xmalloc ();
Xchar getch ();
Xint mktable ();
Xint readtabfile ();
Xstruct qt *findmatch ();
Xstruct qt *queryterm ();
Xvoid catchint ();
Xvoid fixterm ();
Xvoid prinfo ();
Xvoid setterm ();
Xvoid unknown ();
Xvoid wakeup ();
END_OF_FILE
if test 1746 -ne `wc -c <'qterm.h'`; then
    echo shar: \"'qterm.h'\" unpacked with wrong size!
fi
# end of 'qterm.h'
fi
if test -f 'qtermtab' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'qtermtab'\"
else
echo shar: Extracting \"'qtermtab'\" \(1542 characters\)
sed "s/^X//" >'qtermtab' <<'END_OF_FILE'
X# qtermtab
X# database for qterm terminal type query program
X#
X#SendStr ReceiveStr		TermName	FullTermName
X#
X# WY-50 actually sends 50^M, but tty driver translates the CR.
X^[\40	50^J			wyse50		Wyse WY-50
X^[Z	^[iBO         		h29	 	Zenith z29 in zenith mode
X^[Z	^[/K          		h19	 	Zenith z19
X^[Z	^[[?1;0c     		vt100    	Base vt100
X^[Z	^[[?1;1c     		vt100   	vt100 with STP
X^[Z	^[[?1;2c     		vt100   	ANSI/VT100 Clone
X^[Z	^[[?1;3c     		vt100    	vt100 with AVO and STP
X^[Z	^[[?1;4c     		vt100    	vt100 with GPO
X^[Z	^[[?1;5c     		vt100    	vt100 with GPO and STP
X^[Z	^[[?1;6c     		vt100    	vt100 with GPO and AVO
X^[Z	^[[?1;7c     		vt100    	vt100 with GPO, STP, and AVO
X^[Z	^[[?6c        		vt102  	 	vt102 or MS-Kermit
X^[Z	^[[?8c        		vt100    	TeleVideo 970
X^[Z	^[[0n         		vt100    	AT&T Unix PC 7300
X^[Z	^[[?l;0c     		vt100    	AT&T Unix PC 7300
X^[Z	^[[?12c       		vt100    	Concept from Pro 350/UNIX
X^[Z	^[[?;c        		vt100    	Concept From Pro 350/UNIX
X^[Z	^[[=1;1c     		avt-4p-s 	Concept with 4 pages memory
X^[Z	^[[=1;2c     		avt-8p-s 	Concept with 8 pages memory
X^[Z	^[/Z          		vt52	 	Generic vt52
X^[Z	^[[?10c       		la120	 	DEC Writer III
X^[Z	^[[?1;11c    		cit101e  	CIE CIT-101 Enhanced w/Graphics
X#^[Z	^[[?1;11c    		xt100+   	Northern Tech LANPARSCOPE
X^[Z	^[[?12;7;0;102c 	vt125	 	DEC Pro 350 in vt125 mode
X^[Z	^[[?62;1;2;6;7;8;9c 	vt220   	DEC VT220
X^[Z	^[[?62;1;4;6;7;8;9;15c	vt200-sb	Microvax II VMS
X^[Z	^[[62;1;2;6;8c		f220     	Freedom 220 DEC clone
X^[Z	^[[?63;1;2;6;7;8c 	tvi9220  	TeleVideo 9220
END_OF_FILE
if test 1542 -ne `wc -c <'qtermtab'`; then
    echo shar: \"'qtermtab'\" unpacked with wrong size!
fi
# end of 'qtermtab'
fi
if test -f 'query.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'query.c'\"
else
echo shar: Extracting \"'query.c'\" \(2137 characters\)
sed "s/^X//" >'query.c' <<'END_OF_FILE'
X/* query.c - send query strings to the terminal and listen for answer.
X
X   Author: Craig Bishop
X   Modified by David MacKenzie
X   loosely based on a the original program by Michael Cooper. */
X
X#include <stdio.h>
X#include <setjmp.h>
X#include <signal.h>
X
X#include "qterm.h"
X
Xjmp_buf env;
X
X/* Query the terminal and return a pointer to the table entry for the
X   terminal type that it identifies itself as, or NULL if the terminal
X   type is not recognized. */
X
Xstruct qt *
Xqueryterm ()
X{
X  static int firsttime = TRUE;
X  register struct qt **qtpp;
X  register struct qt *prevqtp;
X  struct qt *term;
X
X  fflush (stdin);
X
X  prevqtp = *termtab;
X  for (qtpp = termtab; *qtpp; prevqtp = *qtpp++)
X    {
X      if (firsttime || strcmp ((*qtpp)->sendstr, prevqtp->sendstr) != STREQUAL)
X	{
X	  firsttime = FALSE;
X
X	  fputs ((*qtpp)->sendstr, stderr);
X
X	  if (term_listen ())
X	    {
X	      term = findmatch (recvbuf, qtpp);
X	      if (term != NULLQT)
X		return term;
X	    }
X	}
X    }
X
X  return NULLQT;
X}
X
X/* Listen for a response from the terminal.  Time out after WAITSEC
X   seconds.  Return a pointer to the string the terminal responded with. */
X
Xchar *
Xterm_listen ()
X{
X  register int i;
X
X  if (setjmp (env))
X    {
X      fflush (stdin);
X      return recvbuf;
X    }
X  signal (SIGALRM, wakeup);
X
X  for (i = 0; i < FIELDSIZ - 1; recvbuf[++i] = 0)
X    {
X      alarm (WAITSEC);
X      recvbuf[i] = getch ();
X      alarm (0);
X    }
X
X  fflush (stdin);
X  return recvbuf;
X}
X
X/* If STR matches any of the response strings for the recvstr in TTSTART,
X   return a pointer to that table entry, otherwise NULL. */
X
Xstruct qt *
Xfindmatch (str, ttstart)
X     register char *str;
X     register struct qt **ttstart;
X{
X  register char *ssp = (*ttstart)->sendstr;
X
X  for (; *ttstart && strcmp (ssp, (*ttstart)->sendstr) == STREQUAL; ttstart++)
X    if (strcmp (str, (*ttstart)->recvstr) == STREQUAL)
X      return *ttstart;
X
X  return NULLQT;
X}
X
X/* Return a character from the terminal with parity bits stripped off. */
X
Xchar
Xgetch ()
X{
X  char c;
X
X  if (read (0, &c, 1) > 0)
X    return c & CMASK;
X  return 0;
X}
X
X/* SIGALRM handler. */
X
Xvoid
Xwakeup ()
X{
X  longjmp (env, 1);
X}
END_OF_FILE
if test 2137 -ne `wc -c <'query.c'`; then
    echo shar: \"'query.c'\" unpacked with wrong size!
fi
# end of 'query.c'
fi
if test -f 'table.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'table.c'\"
else
echo shar: Extracting \"'table.c'\" \(3489 characters\)
sed "s/^X//" >'table.c' <<'END_OF_FILE'
X/* table.c - read in the terminal query table(s).
X
X   Author: Craig Bishop
X   modified by David MacKenzie
X   loosely based on a the original program by Michael Cooper. */
X
X#include <stdio.h>
X#include <pwd.h>
Xstruct passwd *getpwuid ();
X
X#include "qterm.h"
X
X/* Allocate enough memory to hold a variable of type T. */
X#define talloc(T)	((T*) xmalloc (sizeof (T)))
X
X/* Read the configuration file(s) into a table in memory.
X   Return TRUE if successful, FALSE if not. */
X
Xint
Xmktable ()
X{
X  char file[BUFSIZ];
X  char *home;
X  struct passwd *pwd;
X
X  if (user_table || user_table_only)
X    {
X      home = getenv ("HOME");
X      if (home == NULLSTR)
X	{
X	  pwd = getpwuid (getuid ());
X	  if (pwd == NULL)
X	    {
X	      fprintf (stderr, "%s: you have no passwd entry\n", program_name);
X	      return FALSE;
X	    }
X	  home = pwd->pw_dir;
X	}
X      sprintf (file, "%s/%s", home, STRFILE);
X
X      if (readtabfile (file) == FALSE)
X	return FALSE;
X    }
X  if (user_table_only)
X    return TRUE;
X
X  return readtabfile (TABLEFILE);
X}
X
X/* Read in configuration file FILE.
X   Return TRUE if successful, FALSE if not. */
X
Xint
Xreadtabfile (file)
X     char *file;
X{
X  register int line;
X  register char *cp;
X  static struct qt **qtpp = termtab;
X  char buf[BUFSIZ];
X  FILE *fp;
X
X  fp = fopen (file, "r");
X  if (fp == NULL)
X    {
X      fprintf (stderr, "%s: ", program_name);
X      perror (file);
X      return FALSE;
X    }
X
X  for (*qtpp = talloc (struct qt), line = 1, cp = buf;
X       qtpp < &termtab[MAXTERMS - 1] && fgets (cp, BUFSIZ, fp); line++)
X    {
X      if (*cp == '#' || *cp == '\n')
X	continue;
X
X      sscanf (cp, "%s%s%s\t%[^\n]",
X	      (*qtpp)->sendstr, (*qtpp)->recvstr,
X	      (*qtpp)->termname, (*qtpp)->fullname);
X
X      if (*(*qtpp)->sendstr == 0)
X	continue;
X
X      if (*(*qtpp)->recvstr == 0 || *(*qtpp)->termname == 0)
X	{
X	  fprintf (stderr, "%s: error in configuration file %s on line %d\n",
X		   program_name, file, line);
X	  fclose (fp);
X	  return FALSE;
X	}
X      if (*querystr)
X	strncpy ((*qtpp)->sendstr, querystr, FIELDSIZ);
X      else
X	strncpy ((*qtpp)->sendstr, fixctl ((*qtpp)->sendstr), FIELDSIZ);
X
X      strncpy ((*qtpp)->recvstr, fixctl ((*qtpp)->recvstr), FIELDSIZ);
X      *++qtpp = talloc (struct qt);
X    }
X
X  fclose (fp);
X  free (*qtpp);
X  *qtpp = NULLQT;
X
X  if (qtpp == &termtab[MAXTERMS - 1])
X    {
X      fprintf (stderr, "%s: limit of %d terminals exceeded\n",
X	       program_name, MAXTERMS);
X      return FALSE;
X    }
X  return TRUE;
X}
X
X/* Return true if the character C is an octal digit. */
X#define isoctal(c) ((c) >= '0' && (c) <= '7')
X
X/* Return a pointer to a copy of the string STR with
X   visual representations of control characters replaced by the
X   actual control characters.  Also interpret "\ooo" octal escapes. */
X
Xchar *
Xfixctl (str)
X     register char *str;
X{
X  static char fixbuf[FIELDSIZ + 1];
X  register char *fbp = fixbuf;
X  int val, digits;
X
X  for (*fbp = 0; *str; str++, fbp++)
X    {
X      if (*str == '^' && str[1])
X	*fbp = *++str & 037;
X      else if (*str == '\\')
X	{
X	  for (++str, val = digits = 0;
X	       isoctal (*str) && digits < 3; ++str, ++digits)
X	    val = val * 8 + *str - '0';
X	  *fbp = val;
X	  --str;
X	}
X      else
X	*fbp = *str;
X    }
X
X  *fbp = 0;
X  return fixbuf;
X}
X
X/* Allocate memory with error checking. */
X
Xchar *
Xxmalloc (size)
X     unsigned size;
X{
X  register char *cp;
X
X  cp = malloc (size);
X  if (cp == NULLSTR)
X    {
X      fprintf (stderr, "%s: virtual memory exhausted\n", program_name);
X      exit (1);
X    }
X  return cp;
X}
END_OF_FILE
if test 3489 -ne `wc -c <'table.c'`; then
    echo shar: \"'table.c'\" unpacked with wrong size!
fi
# end of 'table.c'
fi
echo shar: End of shell archive.
exit 0
--
David J. MacKenzie <djm@eng.umd.edu> <djm@ai.mit.edu>