home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume12 / qterm.alt < prev    next >
Text File  |  1987-10-18  |  15KB  |  809 lines

  1. Subject:  v12i025:  Query terminal for its type
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: Craig Bishop <charlie.oz.au!craig>
  7. Posting-number: Volume 12, Issue 25
  8. Archive-name: qterm.alt
  9.  
  10. [  This program sends an Escape sequence to your terminal, and interprets
  11.    the result to see what kind of terminal you have.  It's table-driven,
  12.    so adding new terminals is easy.  It is a rewrite of the qterm
  13.    program published in Volume 10.  --r$  ]
  14.  
  15. # This is a shell archive.  Remove anything before this line, then
  16. # unpack it by saving it in a file and typing "sh file".  (Files
  17. # unpacked will be owned by you and have default permissions.)
  18. # This archive contains:
  19. # README Makefile qtermtab gstty.h qterm.h qterm.c query.c table.c
  20.  
  21. echo x - README
  22. cat > "README" << '//E*O*F README//'
  23. This is a rewrite of the qterm program which came across the net in
  24. comp.sources.unix the title was v10i072: Query terminal for its type.
  25. I decided to use the program before looking at the code.  Eventually
  26. I decided to rewrite it. 
  27.  
  28. It is completely compatible with the original so if you are already
  29. using it I suggest you change to this one. There are couple more
  30. flags added to the program which are useful when testing a terminals
  31. responses to the various standard query sequences.
  32.  
  33. Qterm is particularly valuable in port selector and terminal server 
  34. environments. Most terminals can respond to the standard ANSI query
  35. sequences, others which cannot will often do answerback.
  36.  
  37. If you find any bugs please report them to me.
  38.  
  39. Craig Bishop         ACSNET:    craig@charlie.oz
  40.             ARPA:    craig%charlie.oz.au@uunet.uu.net
  41.             UUCP:    ...!uunet!munnari!charlie.oz!craig
  42. //E*O*F README//
  43.  
  44. echo x - Makefile
  45. cat > "Makefile" << '//E*O*F Makefile//'
  46. #
  47. #    Makefile for qterm.
  48. #    
  49. #    If this is a USG system then add the flag -DUSG to the
  50. #    CFLAGS variable.
  51. #
  52.  
  53. DESTDIR          =    /usr/local/bin
  54. CFLAGS          = -O -DTABLEFILE=\"$(TABLEDIR)/$(TABLE)\"
  55. SOURCES          =    qterm.c query.c table.c
  56. OBJECTS          = qterm.o query.o table.o
  57. HDRS          =    gstty.h qterm.h
  58. BINARY          = qterm
  59. LIBS          =    
  60. MAN          =    qterm.1
  61. MANDIR          =    /usr/local/man/man1
  62. TABLE          =    qtermtab
  63. TABLEDIR      = /usr/local/lib
  64.  
  65. .DEFAULT:;    co -q $<
  66.  
  67. all:        $(BINARY)
  68.  
  69. $(BINARY):    $(OBJECTS)
  70.         cc -o $(BINARY) $(OBJECTS) $(LIBS)
  71.  
  72. $(OBJECTS):    $(HDRS)
  73.  
  74. install:;    cp $(BINARY) $(DESTDIR)
  75.         chown bin $(DESTDIR)/$(BINARY)
  76.         chmod 751 $(DESTDIR)/$(BINARY)
  77.         cp $(MAN) $(MANDIR)
  78.         chown man $(MANDIR)/$(MAN)
  79.         chmod 644 $(MANDIR)/$(MAN)
  80.  
  81. install_table:;    cp $(TABLE) $(TABLEDIR)
  82.         chown lib $(TABLEDIR)/$(TABLE)
  83.         chmod 644 $(TABLEDIR)/$(TABLE)
  84.  
  85. clean:;        rm -f $(BINARY) $(OBJECTS)
  86.  
  87. print:;        pr Makefile $(HDRS) $(SOURCES) | lpr
  88. //E*O*F Makefile//
  89.  
  90. echo x - qtermtab
  91. cat > "qtermtab" << '//E*O*F qtermtab//'
  92. #
  93. #SendStr ReceiveStr        TermName    FullTermName
  94. #
  95. ^[Z    ^[iBO                 h29         Zenith z29 in zenith mode
  96. ^[Z    ^[/K                  h29         Zenith z29 in zenith mode
  97. ^[Z    ^[[?1;0c             vt100        Base vt100
  98. ^[Z    ^[[?1;1c             vt100       vt100 with STP
  99. ^[Z    ^[[?1;2c             vt100       ANSI/VT100 Clone
  100. ^[Z    ^[[?1;3c             vt100        vt100 with AVO and STP
  101. ^[Z    ^[[?1;4c             vt100        vt100 with GPO
  102. ^[Z    ^[[?1;5c             vt100        vt100 with GPO and STP
  103. ^[Z    ^[[?1;6c             vt100        vt100 with GPO and AVO
  104. ^[Z    ^[[?1;7c             vt100        vt100 with GPO, STP, and AVO
  105. ^[Z    ^[[?6c                vt100           Generic vt100
  106. ^[Z    ^[[?8c                vt100        TeleVideo 970
  107. ^[Z    ^[[0n                 vt100        AT&T Unix PC 7300
  108. ^[Z    ^[[?l;0c             vt100        AT&T Unix PC 7300
  109. ^[Z    ^[[?12c               vt100        Concept from Pro 350/UNIX
  110. ^[Z    ^[[?;c                vt100        Concept From Pro 350/UNIX
  111. ^[Z    ^[[=1;1c             avt-4p-s     Concept with 4 pages memory
  112. ^[Z    ^[[=1;2c             avt-8p-s     Concept with 8 pages memory
  113. ^[Z    ^[/Z                  vt52         Generic vt52
  114. ^[Z    ^[[?10c               la120         DEC Writer III
  115. ^[Z    ^[[?1;11c            cit101e      CIE CIT-101 Enhanced w/Graphics
  116. #^[Z    ^[[?1;11c            xt100+       Northern Tech LANPARSCOPE
  117. ^[Z    ^[[?12;7;0;102c     vt125         DEC Pro 350 in vt125 mode
  118. ^[Z    ^[[?62;1;2;6;7;8;9c     vt220       DEC VT220
  119. ^[Z    ^[[?62;1;4;6;7;8;9;15c    vt200-sb    Microvax II VMS
  120. ^[Z    ^[[62;1;2;6;8c        f220         Freedom 220 DEC clone
  121. ^[Z    ^[[?63;1;2;6;7;8c     tvi9220      TeleVideo 9220
  122. //E*O*F qtermtab//
  123.  
  124. echo x - gstty.h
  125. cat > "gstty.h" << '//E*O*F gstty.h//'
  126. /*
  127. **    gstty.h - defines and declarations for the getting and setting
  128. **          of terminal parameters on BSD and USG systems.
  129. **
  130. **    Author: Craig Bishop
  131. **        loosly based on original program by Michael Cooper.
  132. **
  133. **    $Header: gstty.h,v 1.1 87/09/30 15:25:46 craig Exp $
  134. */
  135.  
  136. #include    <sys/ioctl.h>
  137.  
  138. #ifdef    USG
  139. #include    <termio.h>
  140.  
  141. struct    termio    otty;
  142. struct    termio    ntty;
  143.  
  144. #define    setterm()    (\
  145.                 (void)ioctl(0, TCGETA, &otty),\
  146.                 ntty = otty,\
  147.                 ntty.c_lflag &= ~ICANON,\
  148.                 ntty.c_lflag &= ~ECHO,\
  149.                 ntty.c_cc[VMIN] = 1,\
  150.                 ntty.c_cc[VTIME] = 0,\
  151.                 (void)ioctl(0, TCSETAF, &ntty)\
  152.             )
  153.  
  154. #define    fixterm()    (void)ioctl(0, TCSETAF, &otty)
  155. #else
  156. struct    sgttyb    otty;
  157. struct    sgttyb    ntty;
  158.  
  159. #define    setterm()    (\
  160.                 (void)ioctl(0, TIOCGETP, &otty),\
  161.                 ntty = otty,\
  162.                 ntty.sg_flags |= CBREAK,\
  163.                 ntty.sg_flags &= ~ECHO,\
  164.                 (void)ioctl(0, TIOCSETP, &ntty)\
  165.             )
  166.  
  167. #define    fixterm()    (void)ioctl(0, TIOCSETP, &otty)
  168. #endif
  169. //E*O*F gstty.h//
  170.  
  171. echo x - qterm.h
  172. cat > "qterm.h" << '//E*O*F qterm.h//'
  173. /*
  174. **    qterm.h - defines and declarations for the qterm modules.
  175. **
  176. **    Author: Craig Bishop
  177. **        loosly based on original program by Michael Cooper.
  178. **
  179. **    $Header: qterm.h,v 1.1 87/09/30 15:25:52 craig Exp $
  180. */
  181.  
  182. /* defines for qterm */
  183.  
  184. #define    ABSEND        "\05"        /* Answerback string */
  185. #define    ALTSEND        "\033[c"    /* Alternative string */
  186. #define DFLTSEND    "\033Z"        /* Default string */
  187. #define    CMASK        0177        /* Character mask */
  188. #define    ESC        '\033'        /* Escape in octal */
  189. #define    MAXTERMS    100        /* Maximum # of terminals for qterm */
  190. #define    STRFILE        ".qterm"    /* File containing terminal strings */
  191.  
  192. /*
  193. ** This is  the number of seconds for alarm timeouts. Some slower systems
  194. ** may need to increase this value to 2 or maybe 3 seconds. This value
  195. ** effects how long qterm will run, because for each query string sent
  196. ** the program must wait at least this long.
  197. */
  198.  
  199. #define    WAIT        1        
  200.  
  201. #define    TRUE        1
  202. #define    FALSE        0
  203.  
  204. #define NULLSTR        (char *) NULL
  205. #define    NULLQT        (struct qt *) NULL
  206. #define    STREQUAL    (0)
  207.  
  208. #define FIELDSIZ    30 
  209. #define    FULLSIZ        80
  210.  
  211. /* define the query terminal structure */
  212.  
  213. struct    qt
  214. {
  215.     char    sendstr[FIELDSIZ];    /* String to send to terminal */
  216.     char    recvstr[FIELDSIZ];    /* String expected in response */
  217.     char    termname[FIELDSIZ];    /* Terminal name */
  218.     char    fullname[FULLSIZ];    /* Full terminal name & description */
  219. };
  220.  
  221. /* declare externals */
  222.  
  223. extern    int        Fflag;
  224. extern    int        fflag;
  225. extern    int        qflag;
  226. extern    int        sflag;
  227.  
  228. extern    char        querystr[];
  229. extern    char        recvbuf[];
  230. extern    char        *name;
  231.  
  232. extern    struct    qt    *termtab[];
  233.  
  234. /* declare procedures */
  235.  
  236. int        mktable(),
  237.         readtabfile();
  238.  
  239. char        getch();
  240.  
  241. char        *decode(),
  242.         *fixctl(),
  243.         *getenv(),
  244.         *lalloc(),
  245.         *listen(),
  246.         *malloc();
  247.  
  248. void        catchint(),
  249.         dumb(),
  250.         prinfo(),
  251.         wakeup();
  252.  
  253. FILE        *fopen();
  254.  
  255. struct    qt    *compare(),
  256.         *dotab();
  257. //E*O*F qterm.h//
  258.  
  259. echo x - qterm.c
  260. cat > "qterm.c" << '//E*O*F qterm.c//'
  261. /*
  262. **    qterm.c - Qterm is used to query a terminal to determine the name
  263. **          of the terminal. This is done by sending a equiry string
  264. **          to the terminal and reading in a response.
  265. **
  266. **    Author: Craig Bishop
  267. **        loosly based on original program by Michael Cooper.
  268. */
  269.  
  270. static    char    rcsid[] = "$Header: qterm.c,v 1.1 87/09/30 15:25:55 craig Exp $";
  271.  
  272. #include    <stdio.h>
  273. #include    <signal.h>
  274.  
  275. #include    "gstty.h"
  276. #include    "qterm.h"
  277.  
  278. /* declare flags */
  279.  
  280. int    fflag = FALSE;        /* use user's own .qterm file */
  281. int    Fflag = FALSE;        /* same as above, but don't add our own table */
  282. int    qflag = FALSE;        /* quiet mode */
  283. int    sflag = FALSE;        /* print strings */
  284.  
  285. /* declare global variables */
  286.  
  287. char        decodebuf[BUFSIZ];
  288. char        querystr[FIELDSIZ];
  289. char        recvbuf[FIELDSIZ];
  290. char        *name;
  291. char        usage[] = "usage: %s [ -a ] [ -d ] [ -e ] [ -f ] [ -F ] [ -q ] [ -s ]\n";
  292.  
  293. struct    qt    *termtab[MAXTERMS];
  294.  
  295.  
  296. int
  297. main(argc, argv)
  298. int    argc;
  299. char    *argv[];
  300. {
  301.     register int    i;
  302.     register int    j;
  303.     struct     qt    *qtp;
  304.  
  305.     name = argv[0];
  306.  
  307.     for ( i = 1; i < argc; i++ )
  308.     {
  309.         if ( argv[i][0] != '-' )
  310.         {
  311.             (void)fprintf(stderr, usage, name);
  312.             return 1;
  313.         }
  314.  
  315.         for ( j = 1; argv[i][j] != NULL; j++ )
  316.             switch ( argv[i][j] )
  317.             {
  318.             case 'a':
  319.                 (void)strcpy(querystr, ALTSEND);
  320.                 break;
  321.             case 'd':
  322.                 (void)strcpy(querystr, DFLTSEND);
  323.                 break;
  324.             case 'e':
  325.                 (void)strcpy(querystr, ABSEND);
  326.                 break;
  327.             case 'f':
  328.                 fflag = TRUE;
  329.                 break;
  330.             case 'F':
  331.                 Fflag = TRUE;
  332.                 break;
  333.             case 'q':
  334.                 qflag = TRUE;
  335.                 break;
  336.             case 's':
  337.                 sflag = TRUE;
  338.                 break;
  339.             default:
  340.                 (void)fprintf(stderr, usage, name);
  341.                 return 1;
  342.             }
  343.     }
  344.  
  345.     if ( mktable() == FALSE )
  346.         return 1;
  347.  
  348.     if ( !isatty(0) ) 
  349.     {
  350.         (void)fprintf(stderr, "%s: Not a tty.\n", name);
  351.         return 1;
  352.     }
  353.  
  354.     setterm();
  355.     (void)signal(SIGHUP, catchint);
  356.     (void)signal(SIGINT, catchint);
  357.     (void)signal(SIGQUIT, catchint);
  358.     (void)setbuf(stdout, 0);
  359.     (void)setbuf(stderr, 0);
  360.     qtp = dotab();
  361.     fixterm();
  362.  
  363.     if ( qtp != NULLQT )
  364.         prinfo(qtp);
  365.     else
  366.         dumb();
  367.  
  368.     return 0;
  369. }
  370.  
  371.  
  372. void
  373. catchint()
  374. {
  375.     fixterm();
  376.     exit(1);
  377. }
  378.  
  379.  
  380. void
  381. prinfo(ttent)
  382. struct    qt    *ttent;
  383. {
  384.     register int        len;
  385.     register struct    qt    *qtp = ttent;
  386.  
  387.     if ( sflag )
  388.     {
  389.         len = strlen(recvbuf);
  390.  
  391.         (void)fprintf
  392.         (
  393.             stderr,
  394.             "%s receives %d character%s: %s\n", 
  395.             name,
  396.             len,
  397.             (len == 1) ? "" : "s",
  398.             decode(recvbuf)
  399.         );
  400.     }
  401.  
  402.     if ( !qflag )
  403.         if ( *qtp->fullname != NULL )
  404.             (void)fprintf
  405.             (
  406.                 stderr,
  407.                 "Terminal recognized as %s (%s)\n", 
  408.                 qtp->termname,
  409.                 qtp->fullname
  410.             );
  411.         else
  412.             (void)fprintf
  413.             (
  414.                 stderr,
  415.                 "Terminal recognized as %s\n", 
  416.                 qtp->termname
  417.             );
  418.  
  419.     (void)puts(qtp->termname);
  420. }
  421.  
  422.  
  423. void
  424. dumb()
  425. {
  426.     register int    len;
  427.  
  428.     if ( sflag )
  429.     {
  430.         len = strlen(recvbuf);
  431.  
  432.         (void)fprintf
  433.         (
  434.             stderr,
  435.             "%s receives %d character%s",
  436.             name,
  437.             len,
  438.             (len == 1) ? "" : "s"
  439.         );
  440.         
  441.         if ( len )
  442.             (void)fprintf(stderr, ": %s\n", decode(recvbuf));
  443.         else
  444.             (void)fputs(".\n", stderr);
  445.     }
  446.  
  447.     if ( !qflag )
  448.         (void)fprintf
  449.         (
  450.             stderr,
  451.             "Terminal NOT recognized - defaults to \"dumb\".\n"
  452.         );
  453.  
  454.     (void)puts("dumb");
  455. }
  456.  
  457.  
  458. char    *
  459. decode(str)
  460. char    *str;
  461. {
  462.     register char    *dbp = decodebuf;
  463.     register char    *cp1 = str;
  464.     register char    *cp2;
  465.     char        tmp[10];
  466.  
  467.     for ( *dbp = NULL, cp2 = tmp; *cp1 != NULL; cp1++ )
  468.     {
  469.         if ( *cp1 == ESC )
  470.         {
  471.             (void)strcat(dbp, "<esc> ");
  472.             continue;
  473.         }
  474.  
  475.         if ( (*cp1 <= 33) || (*cp1 == 127) )
  476.         {
  477.             (void)sprintf(cp2, "\\%o ", *cp1);
  478.             (void)strcat(dbp, cp2);
  479.             continue;
  480.         }
  481.  
  482.         (void)sprintf(cp2, "%c ", *cp1);
  483.         (void)strcat(dbp, cp2);
  484.     }
  485.  
  486.     return dbp;
  487. }
  488. //E*O*F qterm.c//
  489.  
  490. echo x - query.c
  491. cat > "query.c" << '//E*O*F query.c//'
  492. /*
  493. **    query.c - send query strings to the terminal and listen for 
  494. **          the answering strings.
  495. **
  496. **    Author: Craig Bishop
  497. **        loosely based on a the original program by Michael Cooper.
  498. */
  499.  
  500. static    char    rcsid[] = "$Header: query.c,v 1.1 87/09/30 15:25:58 craig Exp $";
  501.  
  502. #include    <stdio.h>
  503. #include    <setjmp.h>
  504. #include    <signal.h>
  505.  
  506. #include    "qterm.h"
  507.  
  508. /* declare global variables */
  509.  
  510. jmp_buf    env;
  511.  
  512.  
  513. struct    qt    *
  514. dotab()
  515. {
  516.     static     int        firsttime = TRUE;
  517.     register struct    qt    **qtpp = termtab;
  518.     register struct qt    *lastqtp;
  519.     struct     qt        *term;
  520.  
  521.     (void) fflush(stdin);
  522.  
  523.     for ( ; *qtpp != NULLQT; lastqtp = *qtpp++ )
  524.     {
  525.         if
  526.         (
  527.             firsttime
  528.             ||
  529.             strcmp((*qtpp)->sendstr, lastqtp->sendstr) != STREQUAL
  530.         )
  531.         {
  532.             firsttime = FALSE;
  533.             (void)fputs((*qtpp)->sendstr, stderr);
  534.  
  535.             if ( listen() == NULLSTR )
  536.                 continue;
  537.         }
  538.         else
  539.             continue;
  540.  
  541.         if ( (term = compare(recvbuf, qtpp)) != NULLQT )
  542.             return term;
  543.     }
  544.  
  545.     return NULLQT;
  546. }
  547.  
  548.  
  549. char    *
  550. listen()
  551. {
  552.     register int    i;
  553.  
  554.     if ( setjmp(env) )
  555.     {
  556.         (void)fflush(stdin);
  557.         return recvbuf;
  558.     }
  559.  
  560.     (void)signal(SIGALRM, wakeup);
  561.  
  562.     for ( i = 0; i < FIELDSIZ - 1; recvbuf[++i] = NULL )
  563.     {
  564.         (void)alarm(WAIT);
  565.         recvbuf[i] = getch();
  566.         (void)alarm(0);
  567.     }
  568.  
  569.     (void)fflush(stdin);
  570.     return recvbuf;
  571. }
  572.  
  573.  
  574. struct    qt    *
  575. compare(str, ttstart)
  576. char        *str;
  577. struct    qt    **ttstart;
  578. {
  579.     register char        *cp1 = str;
  580.     register char        *cp2 = (*ttstart)->sendstr;
  581.     register struct    qt    **qtpp = ttstart;
  582.  
  583.     for ( ; *qtpp != NULLQT && strcmp(cp2, (*qtpp)->sendstr) == STREQUAL; qtpp++ )
  584.         if ( strcmp(cp1, (*qtpp)->recvstr) == STREQUAL )
  585.             return *qtpp;
  586.  
  587.     return NULLQT;
  588. }
  589.  
  590.  
  591. char
  592. getch()
  593. {
  594.     char    c;
  595.  
  596.     (void)read(0, &c, 1);
  597.     return (c & CMASK);
  598. }
  599.  
  600.  
  601. void
  602. wakeup()
  603. {
  604.     longjmp(env, 1);
  605. }
  606. //E*O*F query.c//
  607.  
  608. echo x - table.c
  609. cat > "table.c" << '//E*O*F table.c//'
  610. /*
  611. **    table.c - read in the terminal query table(s).
  612. **
  613. **    Author: Craig Bishop
  614. **        loosely based on a the original program by Michael Cooper.
  615. */
  616.  
  617. static    char    rcsid[] = "$Header: table.c,v 1.1 87/09/30 15:26:01 craig Exp $";
  618.  
  619. #include    <stdio.h>
  620. #include    <pwd.h>
  621.  
  622. #include    "qterm.h"
  623.  
  624. #define talloc(T)    (T*) lalloc(sizeof(T))
  625.  
  626. /* declare global variables */
  627.  
  628. char    fixbuf[FIELDSIZ + 1];
  629.  
  630. /* declare procedures */
  631.  
  632. struct    passwd    *getpwuid();
  633.  
  634.  
  635. int
  636. mktable()
  637. {
  638.     char        file[BUFSIZ];
  639.     char        *home;
  640.     struct    passwd    *pwd;
  641.  
  642.     if ( fflag || Fflag )
  643.     {
  644.         if ( (home = getenv("HOME")) == NULLSTR )
  645.         {
  646.             if ( (pwd = getpwuid(getuid())) == (struct passwd *) NULL )
  647.             {
  648.                 (void)fprintf
  649.                 (
  650.                     stderr,
  651.                     "%s: Who the hell are you????\n",
  652.                     name
  653.                 );
  654.  
  655.                 return FALSE;
  656.             }
  657.  
  658.             home = pwd->pw_dir;
  659.         }
  660.  
  661.         (void)sprintf(file, "%s/%s", home, STRFILE);
  662.         
  663.         if ( readtabfile(file) == FALSE )
  664.             return FALSE;
  665.     }
  666.  
  667.     if ( !Fflag )
  668.         return readtabfile(TABLEFILE);
  669.  
  670.     return TRUE;
  671. }
  672.  
  673.  
  674. int
  675. readtabfile(file)
  676. char    *file;
  677. {
  678.     register int        line;
  679.     register char        *cp;
  680.     register struct qt    **qtpp = termtab;
  681.     char            buf[BUFSIZ];
  682.     FILE            *fp;
  683.  
  684.     if ( (fp = fopen(file, "r")) == (FILE *) NULL )
  685.     {
  686.         (void)fprintf
  687.         (
  688.             stderr,
  689.             "%s: Cannot read input file %s.\n",
  690.             name,
  691.             file
  692.         );
  693.  
  694.         return FALSE;
  695.     }
  696.  
  697.     for
  698.     (
  699.         *qtpp = talloc(struct qt), line = 1, cp = buf;
  700.         qtpp < &termtab[MAXTERMS - 1] && fgets(cp, BUFSIZ, fp);
  701.         line++
  702.     )
  703.     {
  704.         if ( *cp == '#' || *cp == '\n')
  705.             continue;
  706.         
  707.         (void)sscanf
  708.         (
  709.             cp,
  710.             "%s%s%s\t%[^\n]", 
  711.             (*qtpp)->sendstr,
  712.             (*qtpp)->recvstr,
  713.             (*qtpp)->termname,
  714.             (*qtpp)->fullname
  715.         );
  716.  
  717.         if ( *(*qtpp)->sendstr == NULL )
  718.             continue;
  719.  
  720.         if ( *(*qtpp)->recvstr == NULL || *(*qtpp)->termname == NULL )
  721.         {
  722.             (void)fprintf
  723.             (
  724.                 stderr,
  725.                 "%s: Error parsing qterm file %s on line %d.\n",
  726.                  name,
  727.                  file,
  728.                  line
  729.             );
  730.  
  731.             (void)fclose(fp);
  732.             return FALSE;
  733.         }
  734.  
  735.         if ( querystr[0] != NULL )
  736.             (void)strcpy((*qtpp)->sendstr, querystr);
  737.         else
  738.             (void)strcpy((*qtpp)->sendstr, fixctl((*qtpp)->sendstr));
  739.  
  740.         (void)strcpy((*qtpp)->recvstr, fixctl((*qtpp)->recvstr));
  741.         *++qtpp = talloc(struct qt);
  742.     }
  743.  
  744.     (void)fclose(fp);
  745.     (void)free(*qtpp);
  746.     *qtpp = NULLQT;
  747.  
  748.     if ( qtpp == &termtab[MAXTERMS - 1] )
  749.     {
  750.         (void)fprintf
  751.         (
  752.             stderr,
  753.             "%s: Greater than maximum terminals of %d.",
  754.             name,
  755.             MAXTERMS
  756.         );
  757.  
  758.         return FALSE;
  759.     }
  760.  
  761.     return TRUE;
  762. }
  763.  
  764.  
  765. char    *
  766. fixctl(str)
  767. char    *str;
  768. {
  769.     register char    *cp1 = str;
  770.     register char    *cp2 = fixbuf;
  771.  
  772.     for ( *cp2 = NULL; *cp1 != NULL; cp1++, cp2++ )
  773.     {
  774.         if ( *cp1 == '^')
  775.             *cp2 = *++cp1 & 037;
  776.         else
  777.             *cp2 = *cp1;
  778.     }
  779.  
  780.     *cp2 = NULL;
  781.     return(fixbuf);
  782. }
  783.  
  784.  
  785. char *
  786. lalloc(size)
  787. int    size;
  788. {
  789.     register char    *cp;
  790.  
  791.     if ( (cp = malloc((unsigned)size)) == NULLSTR )
  792.     {
  793.         (void)fprintf
  794.         (
  795.             stderr,
  796.             "%s: No memory for malloc(%d)\n",
  797.             name,
  798.             size
  799.         );
  800.  
  801.         exit(1);
  802.     }
  803.  
  804.     return cp;
  805. }
  806. //E*O*F table.c//
  807.  
  808. exit 0
  809.