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>