home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gnunet10.zip / source / telnet / tn3270.c < prev    next >
C/C++ Source or Header  |  1996-02-12  |  10KB  |  412 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. #include <sys/types.h>
  39. #include <arpa/telnet.h>
  40.  
  41. #include "general.h"
  42.  
  43. #include "defines.h"
  44. #include "ring.h"
  45. #include "externs.h"
  46. #include "fdset.h"
  47.  
  48. #if    defined(TN3270)
  49.  
  50. #include "../ctlr/screen.h"
  51. #include "../general/globals.h"
  52.  
  53. #include "../sys_curses/telextrn.h"
  54. #include "../ctlr/externs.h"
  55.  
  56. #if    defined(unix)
  57. int
  58.     HaveInput,        /* There is input available to scan */
  59.     cursesdata,        /* Do we dump curses data? */
  60.     sigiocount;        /* Number of times we got a SIGIO */
  61.  
  62. char    tline[200];
  63. char    *transcom = 0;    /* transparent mode command (default: none) */
  64. #endif    /* defined(unix) */
  65.  
  66. char    Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
  67.  
  68. static char    sb_terminal[] = { IAC, SB,
  69.             TELOPT_TTYPE, TELQUAL_IS,
  70.             'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
  71.             IAC, SE };
  72. #define    SBTERMMODEL    13
  73.  
  74. static int
  75.     Sent3270TerminalType;    /* Have we said we are a 3270? */
  76.  
  77. #endif    /* defined(TN3270) */
  78.  
  79.  
  80.     void
  81. init_3270()
  82. {
  83. #if    defined(TN3270)
  84. #if    defined(unix)
  85.     HaveInput = 0;
  86.     sigiocount = 0;
  87. #endif    /* defined(unix) */
  88.     Sent3270TerminalType = 0;
  89.     Ifrontp = Ibackp = Ibuf;
  90.     init_ctlr();        /* Initialize some things */
  91.     init_keyboard();
  92.     init_screen();
  93.     init_system();
  94. #endif    /* defined(TN3270) */
  95. }
  96.  
  97.  
  98. #if    defined(TN3270)
  99.  
  100. /*
  101.  * DataToNetwork - queue up some data to go to network.  If "done" is set,
  102.  * then when last byte is queued, we add on an IAC EOR sequence (so,
  103.  * don't call us with "done" until you want that done...)
  104.  *
  105.  * We actually do send all the data to the network buffer, since our
  106.  * only client needs for us to do that.
  107.  */
  108.  
  109.     int
  110. DataToNetwork(buffer, count, done)
  111.     register char *buffer;    /* where the data is */
  112.     register int  count;    /* how much to send */
  113.     int          done;        /* is this the last of a logical block */
  114. {
  115.     register int loop, c;
  116.     int origCount;
  117.  
  118.     origCount = count;
  119.  
  120.     while (count) {
  121.     /* If not enough room for EORs, IACs, etc., wait */
  122.     if (NETROOM() < 6) {
  123.         fd_set o;
  124.  
  125.         FD_ZERO(&o);
  126.         netflush();
  127.         while (NETROOM() < 6) {
  128.         FD_SET(net, &o);
  129.         (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
  130.                         (struct timeval *) 0);
  131.         netflush();
  132.         }
  133.     }
  134.     c = ring_empty_count(&netoring);
  135.     if (c > count) {
  136.         c = count;
  137.     }
  138.     loop = c;
  139.     while (loop) {
  140.         if (((unsigned char)*buffer) == IAC) {
  141.         break;
  142.         }
  143.         buffer++;
  144.         loop--;
  145.     }
  146.     if ((c = c-loop)) {
  147.         ring_supply_data(&netoring, buffer-c, c);
  148.         count -= c;
  149.     }
  150.     if (loop) {
  151.         NET2ADD(IAC, IAC);
  152.         count--;
  153.         buffer++;
  154.     }
  155.     }
  156.  
  157.     if (done) {
  158.     NET2ADD(IAC, EOR);
  159.     netflush();        /* try to move along as quickly as ... */
  160.     }
  161.     return(origCount - count);
  162. }
  163.  
  164.  
  165. #if    defined(unix)
  166.     void
  167. inputAvailable(signo)
  168.     int signo;
  169. {
  170.     HaveInput = 1;
  171.     sigiocount++;
  172. }
  173. #endif    /* defined(unix) */
  174.  
  175.     void
  176. outputPurge()
  177. {
  178.     (void) ttyflush(1);
  179. }
  180.  
  181.  
  182. /*
  183.  * The following routines are places where the various tn3270
  184.  * routines make calls into telnet.c.
  185.  */
  186.  
  187. /*
  188.  * DataToTerminal - queue up some data to go to terminal.
  189.  *
  190.  * Note: there are people who call us and depend on our processing
  191.  * *all* the data at one time (thus the select).
  192.  */
  193.  
  194.     int
  195. DataToTerminal(buffer, count)
  196.     register char    *buffer;        /* where the data is */
  197.     register int    count;            /* how much to send */
  198. {
  199.     register int c;
  200.     int origCount;
  201.  
  202.     origCount = count;
  203.  
  204.     while (count) {
  205.     if (TTYROOM() == 0) {
  206. #if    defined(unix)
  207.         fd_set o;
  208.  
  209.         FD_ZERO(&o);
  210. #endif    /* defined(unix) */
  211.         (void) ttyflush(0);
  212.         while (TTYROOM() == 0) {
  213. #if    defined(unix)
  214.         FD_SET(tout, &o);
  215.         (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
  216.                         (struct timeval *) 0);
  217. #endif    /* defined(unix) */
  218.         (void) ttyflush(0);
  219.         }
  220.     }
  221.     c = TTYROOM();
  222.     if (c > count) {
  223.         c = count;
  224.     }
  225.     ring_supply_data(&ttyoring, buffer, c);
  226.     count -= c;
  227.     buffer += c;
  228.     }
  229.     return(origCount);
  230. }
  231.  
  232.  
  233. /*
  234.  * Push3270 - Try to send data along the 3270 output (to screen) direction.
  235.  */
  236.  
  237.     int
  238. Push3270()
  239. {
  240.     int save = ring_full_count(&netiring);
  241.  
  242.     if (save) {
  243.     if (Ifrontp+save > Ibuf+sizeof Ibuf) {
  244.         if (Ibackp != Ibuf) {
  245.         memmove(Ibuf, Ibackp, Ifrontp-Ibackp);
  246.         Ifrontp -= (Ibackp-Ibuf);
  247.         Ibackp = Ibuf;
  248.         }
  249.     }
  250.     if (Ifrontp+save < Ibuf+sizeof Ibuf) {
  251.         (void)telrcv();
  252.     }
  253.     }
  254.     return save != ring_full_count(&netiring);
  255. }
  256.  
  257.  
  258. /*
  259.  * Finish3270 - get the last dregs of 3270 data out to the terminal
  260.  *        before quitting.
  261.  */
  262.  
  263.     void
  264. Finish3270()
  265. {
  266.     while (Push3270() || !DoTerminalOutput()) {
  267. #if    defined(unix)
  268.     HaveInput = 0;
  269. #endif    /* defined(unix) */
  270.     ;
  271.     }
  272. }
  273.  
  274.  
  275. /* StringToTerminal - output a null terminated string to the terminal */
  276.  
  277.     void
  278. StringToTerminal(s)
  279.     char *s;
  280. {
  281.     int count;
  282.  
  283.     count = strlen(s);
  284.     if (count) {
  285.     (void) DataToTerminal(s, count);    /* we know it always goes... */
  286.     }
  287. }
  288.  
  289.  
  290. #if    ((!defined(NOT43)) || defined(PUTCHAR))
  291. /* _putchar - output a single character to the terminal.  This name is so that
  292.  *    curses(3x) can call us to send out data.
  293.  */
  294.  
  295.     void
  296. _putchar(c)
  297.     char c;
  298. {
  299. #if    defined(sun)        /* SunOS 4.0 bug */
  300.     c &= 0x7f;
  301. #endif    /* defined(sun) */
  302.     if (cursesdata) {
  303.     Dump('>', &c, 1);
  304.     }
  305.     if (!TTYROOM()) {
  306.     (void) DataToTerminal(&c, 1);
  307.     } else {
  308.     TTYADD(c);
  309.     }
  310. }
  311. #endif    /* ((!defined(NOT43)) || defined(PUTCHAR)) */
  312.  
  313.     void
  314. SetIn3270()
  315. {
  316.     if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
  317.         && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
  318.     if (!In3270) {
  319.         In3270 = 1;
  320.         Init3270();        /* Initialize 3270 functions */
  321.         /* initialize terminal key mapping */
  322.         InitTerminal();    /* Start terminal going */
  323.         setconnmode(0);
  324.     }
  325.     } else {
  326.     if (In3270) {
  327.         StopScreen(1);
  328.         In3270 = 0;
  329.         Stop3270();        /* Tell 3270 we aren't here anymore */
  330.         setconnmode(0);
  331.     }
  332.     }
  333. }
  334.  
  335. /*
  336.  * tn3270_ttype()
  337.  *
  338.  *    Send a response to a terminal type negotiation.
  339.  *
  340.  *    Return '0' if no more responses to send; '1' if a response sent.
  341.  */
  342.  
  343.     int
  344. tn3270_ttype()
  345. {
  346.     /*
  347.      * Try to send a 3270 type terminal name.  Decide which one based
  348.      * on the format of our screen, and (in the future) color
  349.      * capaiblities.
  350.      */
  351.     InitTerminal();        /* Sets MaxNumberColumns, MaxNumberLines */
  352.     if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
  353.     Sent3270TerminalType = 1;
  354.     if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
  355.         MaxNumberLines = 27;
  356.         MaxNumberColumns = 132;
  357.         sb_terminal[SBTERMMODEL] = '5';
  358.     } else if (MaxNumberLines >= 43) {
  359.         MaxNumberLines = 43;
  360.         MaxNumberColumns = 80;
  361.         sb_terminal[SBTERMMODEL] = '4';
  362.     } else if (MaxNumberLines >= 32) {
  363.         MaxNumberLines = 32;
  364.         MaxNumberColumns = 80;
  365.         sb_terminal[SBTERMMODEL] = '3';
  366.     } else {
  367.         MaxNumberLines = 24;
  368.         MaxNumberColumns = 80;
  369.         sb_terminal[SBTERMMODEL] = '2';
  370.     }
  371.     NumberLines = 24;        /* before we start out... */
  372.     NumberColumns = 80;
  373.     ScreenSize = NumberLines*NumberColumns;
  374.     if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
  375.         ExitString("Programming error:  MAXSCREENSIZE too small.\n",
  376.                                 1);
  377.         /*NOTREACHED*/
  378.     }
  379.     printsub('>', sb_terminal+2, sizeof sb_terminal-2);
  380.     ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
  381.     return 1;
  382.     } else {
  383.     return 0;
  384.     }
  385. }
  386.  
  387. #if    defined(unix)
  388.     int
  389. settranscom(argc, argv)
  390.     int argc;
  391.     char *argv[];
  392. {
  393.     int i;
  394.  
  395.     if (argc == 1 && transcom) {
  396.        transcom = 0;
  397.     }
  398.     if (argc == 1) {
  399.        return 1;
  400.     }
  401.     transcom = tline;
  402.     (void) strcpy(transcom, argv[1]);
  403.     for (i = 2; i < argc; ++i) {
  404.         (void) strcat(transcom, " ");
  405.         (void) strcat(transcom, argv[i]);
  406.     }
  407.     return 1;
  408. }
  409. #endif    /* defined(unix) */
  410.  
  411. #endif    /* defined(TN3270) */
  412.