home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / inetutils-1.2-src.tgz / tar.out / fsf / inetutils / telnet / tn3270.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  10KB  |  416 lines

  1. /*
  2.  * Copyright (c) 1988, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)tn3270.c    8.2 (Berkeley) 5/30/95";
  36. #endif /* not lint */
  37.  
  38. #ifdef HAVE_CONFIG_H
  39. #include <config.h>
  40. #endif
  41.  
  42. #include <sys/types.h>
  43. #include <arpa/telnet.h>
  44.  
  45. #include "general.h"
  46.  
  47. #include "defines.h"
  48. #include "ring.h"
  49. #include "externs.h"
  50. #include "fdset.h"
  51.  
  52. #if    defined(TN3270)
  53.  
  54. #include "../ctlr/screen.h"
  55. #include "../general/globals.h"
  56.  
  57. #include "../sys_curses/telextrn.h"
  58. #include "../ctlr/externs.h"
  59.  
  60. #if    defined(unix)
  61. int
  62.     HaveInput,        /* There is input available to scan */
  63.     cursesdata,        /* Do we dump curses data? */
  64.     sigiocount;        /* Number of times we got a SIGIO */
  65.  
  66. char    tline[200];
  67. char    *transcom = 0;    /* transparent mode command (default: none) */
  68. #endif    /* defined(unix) */
  69.  
  70. char    Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
  71.  
  72. static char    sb_terminal[] = { IAC, SB,
  73.             TELOPT_TTYPE, TELQUAL_IS,
  74.             'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
  75.             IAC, SE };
  76. #define    SBTERMMODEL    13
  77.  
  78. static int
  79.     Sent3270TerminalType;    /* Have we said we are a 3270? */
  80.  
  81. #endif    /* defined(TN3270) */
  82.  
  83.  
  84.     void
  85. init_3270()
  86. {
  87. #if    defined(TN3270)
  88. #if    defined(unix)
  89.     HaveInput = 0;
  90.     sigiocount = 0;
  91. #endif    /* defined(unix) */
  92.     Sent3270TerminalType = 0;
  93.     Ifrontp = Ibackp = Ibuf;
  94.     init_ctlr();        /* Initialize some things */
  95.     init_keyboard();
  96.     init_screen();
  97.     init_system();
  98. #endif    /* defined(TN3270) */
  99. }
  100.  
  101.  
  102. #if    defined(TN3270)
  103.  
  104. /*
  105.  * DataToNetwork - queue up some data to go to network.  If "done" is set,
  106.  * then when last byte is queued, we add on an IAC EOR sequence (so,
  107.  * don't call us with "done" until you want that done...)
  108.  *
  109.  * We actually do send all the data to the network buffer, since our
  110.  * only client needs for us to do that.
  111.  */
  112.  
  113.     int
  114. DataToNetwork(buffer, count, done)
  115.     register char *buffer;    /* where the data is */
  116.     register int  count;    /* how much to send */
  117.     int          done;        /* is this the last of a logical block */
  118. {
  119.     register int loop, c;
  120.     int origCount;
  121.  
  122.     origCount = count;
  123.  
  124.     while (count) {
  125.     /* If not enough room for EORs, IACs, etc., wait */
  126.     if (NETROOM() < 6) {
  127.         fd_set o;
  128.  
  129.         FD_ZERO(&o);
  130.         netflush();
  131.         while (NETROOM() < 6) {
  132.         FD_SET(net, &o);
  133.         (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
  134.                         (struct timeval *) 0);
  135.         netflush();
  136.         }
  137.     }
  138.     c = ring_empty_count(&netoring);
  139.     if (c > count) {
  140.         c = count;
  141.     }
  142.     loop = c;
  143.     while (loop) {
  144.         if (((unsigned char)*buffer) == IAC) {
  145.         break;
  146.         }
  147.         buffer++;
  148.         loop--;
  149.     }
  150.     if ((c = c-loop)) {
  151.         ring_supply_data(&netoring, buffer-c, c);
  152.         count -= c;
  153.     }
  154.     if (loop) {
  155.         NET2ADD(IAC, IAC);
  156.         count--;
  157.         buffer++;
  158.     }
  159.     }
  160.  
  161.     if (done) {
  162.     NET2ADD(IAC, EOR);
  163.     netflush();        /* try to move along as quickly as ... */
  164.     }
  165.     return(origCount - count);
  166. }
  167.  
  168.  
  169. #if    defined(unix)
  170.     void
  171. inputAvailable(signo)
  172.     int signo;
  173. {
  174.     HaveInput = 1;
  175.     sigiocount++;
  176. }
  177. #endif    /* defined(unix) */
  178.  
  179.     void
  180. outputPurge()
  181. {
  182.     (void) ttyflush(1);
  183. }
  184.  
  185.  
  186. /*
  187.  * The following routines are places where the various tn3270
  188.  * routines make calls into telnet.c.
  189.  */
  190.  
  191. /*
  192.  * DataToTerminal - queue up some data to go to terminal.
  193.  *
  194.  * Note: there are people who call us and depend on our processing
  195.  * *all* the data at one time (thus the select).
  196.  */
  197.  
  198.     int
  199. DataToTerminal(buffer, count)
  200.     register char    *buffer;        /* where the data is */
  201.     register int    count;            /* how much to send */
  202. {
  203.     register int c;
  204.     int origCount;
  205.  
  206.     origCount = count;
  207.  
  208.     while (count) {
  209.     if (TTYROOM() == 0) {
  210. #if    defined(unix)
  211.         fd_set o;
  212.  
  213.         FD_ZERO(&o);
  214. #endif    /* defined(unix) */
  215.         (void) ttyflush(0);
  216.         while (TTYROOM() == 0) {
  217. #if    defined(unix)
  218.         FD_SET(tout, &o);
  219.         (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
  220.                         (struct timeval *) 0);
  221. #endif    /* defined(unix) */
  222.         (void) ttyflush(0);
  223.         }
  224.     }
  225.     c = TTYROOM();
  226.     if (c > count) {
  227.         c = count;
  228.     }
  229.     ring_supply_data(&ttyoring, buffer, c);
  230.     count -= c;
  231.     buffer += c;
  232.     }
  233.     return(origCount);
  234. }
  235.  
  236.  
  237. /*
  238.  * Push3270 - Try to send data along the 3270 output (to screen) direction.
  239.  */
  240.  
  241.     int
  242. Push3270()
  243. {
  244.     int save = ring_full_count(&netiring);
  245.  
  246.     if (save) {
  247.     if (Ifrontp+save > Ibuf+sizeof Ibuf) {
  248.         if (Ibackp != Ibuf) {
  249.         memmove(Ibuf, Ibackp, Ifrontp-Ibackp);
  250.         Ifrontp -= (Ibackp-Ibuf);
  251.         Ibackp = Ibuf;
  252.         }
  253.     }
  254.     if (Ifrontp+save < Ibuf+sizeof Ibuf) {
  255.         (void)telrcv();
  256.     }
  257.     }
  258.     return save != ring_full_count(&netiring);
  259. }
  260.  
  261.  
  262. /*
  263.  * Finish3270 - get the last dregs of 3270 data out to the terminal
  264.  *        before quitting.
  265.  */
  266.  
  267.     void
  268. Finish3270()
  269. {
  270.     while (Push3270() || !DoTerminalOutput()) {
  271. #if    defined(unix)
  272.     HaveInput = 0;
  273. #endif    /* defined(unix) */
  274.     ;
  275.     }
  276. }
  277.  
  278.  
  279. /* StringToTerminal - output a null terminated string to the terminal */
  280.  
  281.     void
  282. StringToTerminal(s)
  283.     char *s;
  284. {
  285.     int count;
  286.  
  287.     count = strlen(s);
  288.     if (count) {
  289.     (void) DataToTerminal(s, count);    /* we know it always goes... */
  290.     }
  291. }
  292.  
  293.  
  294. #if    ((!defined(NOT43)) || defined(PUTCHAR))
  295. /* _putchar - output a single character to the terminal.  This name is so that
  296.  *    curses(3x) can call us to send out data.
  297.  */
  298.  
  299.     void
  300. _putchar(c)
  301.     char c;
  302. {
  303. #if    defined(sun)        /* SunOS 4.0 bug */
  304.     c &= 0x7f;
  305. #endif    /* defined(sun) */
  306.     if (cursesdata) {
  307.     Dump('>', &c, 1);
  308.     }
  309.     if (!TTYROOM()) {
  310.     (void) DataToTerminal(&c, 1);
  311.     } else {
  312.     TTYADD(c);
  313.     }
  314. }
  315. #endif    /* ((!defined(NOT43)) || defined(PUTCHAR)) */
  316.  
  317.     void
  318. SetIn3270()
  319. {
  320.     if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
  321.         && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
  322.     if (!In3270) {
  323.         In3270 = 1;
  324.         Init3270();        /* Initialize 3270 functions */
  325.         /* initialize terminal key mapping */
  326.         InitTerminal();    /* Start terminal going */
  327.         setconnmode(0);
  328.     }
  329.     } else {
  330.     if (In3270) {
  331.         StopScreen(1);
  332.         In3270 = 0;
  333.         Stop3270();        /* Tell 3270 we aren't here anymore */
  334.         setconnmode(0);
  335.     }
  336.     }
  337. }
  338.  
  339. /*
  340.  * tn3270_ttype()
  341.  *
  342.  *    Send a response to a terminal type negotiation.
  343.  *
  344.  *    Return '0' if no more responses to send; '1' if a response sent.
  345.  */
  346.  
  347.     int
  348. tn3270_ttype()
  349. {
  350.     /*
  351.      * Try to send a 3270 type terminal name.  Decide which one based
  352.      * on the format of our screen, and (in the future) color
  353.      * capaiblities.
  354.      */
  355.     InitTerminal();        /* Sets MaxNumberColumns, MaxNumberLines */
  356.     if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
  357.     Sent3270TerminalType = 1;
  358.     if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
  359.         MaxNumberLines = 27;
  360.         MaxNumberColumns = 132;
  361.         sb_terminal[SBTERMMODEL] = '5';
  362.     } else if (MaxNumberLines >= 43) {
  363.         MaxNumberLines = 43;
  364.         MaxNumberColumns = 80;
  365.         sb_terminal[SBTERMMODEL] = '4';
  366.     } else if (MaxNumberLines >= 32) {
  367.         MaxNumberLines = 32;
  368.         MaxNumberColumns = 80;
  369.         sb_terminal[SBTERMMODEL] = '3';
  370.     } else {
  371.         MaxNumberLines = 24;
  372.         MaxNumberColumns = 80;
  373.         sb_terminal[SBTERMMODEL] = '2';
  374.     }
  375.     NumberLines = 24;        /* before we start out... */
  376.     NumberColumns = 80;
  377.     ScreenSize = NumberLines*NumberColumns;
  378.     if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
  379.         ExitString("Programming error:  MAXSCREENSIZE too small.\n",
  380.                                 1);
  381.         /*NOTREACHED*/
  382.     }
  383.     printsub('>', sb_terminal+2, sizeof sb_terminal-2);
  384.     ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
  385.     return 1;
  386.     } else {
  387.     return 0;
  388.     }
  389. }
  390.  
  391. #if    defined(unix)
  392.     int
  393. settranscom(argc, argv)
  394.     int argc;
  395.     char *argv[];
  396. {
  397.     int i;
  398.  
  399.     if (argc == 1 && transcom) {
  400.        transcom = 0;
  401.     }
  402.     if (argc == 1) {
  403.        return 1;
  404.     }
  405.     transcom = tline;
  406.     (void) strcpy(transcom, argv[1]);
  407.     for (i = 2; i < argc; ++i) {
  408.         (void) strcat(transcom, " ");
  409.         (void) strcat(transcom, argv[i]);
  410.     }
  411.     return 1;
  412. }
  413. #endif    /* defined(unix) */
  414.  
  415. #endif    /* defined(TN3270) */
  416.