home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / telnet / tn3270.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  9.2 KB  |  410 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * 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    5.2 (Berkeley) 3/1/91";
  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 "../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()
  168. {
  169.     HaveInput = 1;
  170.     sigiocount++;
  171. }
  172. #endif    /* defined(unix) */
  173.  
  174.     void
  175. outputPurge()
  176. {
  177.     (void) ttyflush(1);
  178. }
  179.  
  180.  
  181. /*
  182.  * The following routines are places where the various tn3270
  183.  * routines make calls into telnet.c.
  184.  */
  185.  
  186. /*
  187.  * DataToTerminal - queue up some data to go to terminal.
  188.  *
  189.  * Note: there are people who call us and depend on our processing
  190.  * *all* the data at one time (thus the select).
  191.  */
  192.  
  193.     int
  194. DataToTerminal(buffer, count)
  195.     register char    *buffer;        /* where the data is */
  196.     register int    count;            /* how much to send */
  197. {
  198.     register int c;
  199.     int origCount;
  200.  
  201.     origCount = count;
  202.  
  203.     while (count) {
  204.     if (TTYROOM() == 0) {
  205. #if    defined(unix)
  206.         fd_set o;
  207.  
  208.         FD_ZERO(&o);
  209. #endif    /* defined(unix) */
  210.         (void) ttyflush(0);
  211.         while (TTYROOM() == 0) {
  212. #if    defined(unix)
  213.         FD_SET(tout, &o);
  214.         (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
  215.                         (struct timeval *) 0);
  216. #endif    /* defined(unix) */
  217.         (void) ttyflush(0);
  218.         }
  219.     }
  220.     c = TTYROOM();
  221.     if (c > count) {
  222.         c = count;
  223.     }
  224.     ring_supply_data(&ttyoring, buffer, c);
  225.     count -= c;
  226.     buffer += c;
  227.     }
  228.     return(origCount);
  229. }
  230.  
  231.  
  232. /*
  233.  * Push3270 - Try to send data along the 3270 output (to screen) direction.
  234.  */
  235.  
  236.     int
  237. Push3270()
  238. {
  239.     int save = ring_full_count(&netiring);
  240.  
  241.     if (save) {
  242.     if (Ifrontp+save > Ibuf+sizeof Ibuf) {
  243.         if (Ibackp != Ibuf) {
  244.         memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
  245.         Ifrontp -= (Ibackp-Ibuf);
  246.         Ibackp = Ibuf;
  247.         }
  248.     }
  249.     if (Ifrontp+save < Ibuf+sizeof Ibuf) {
  250.         (void)telrcv();
  251.     }
  252.     }
  253.     return save != ring_full_count(&netiring);
  254. }
  255.  
  256.  
  257. /*
  258.  * Finish3270 - get the last dregs of 3270 data out to the terminal
  259.  *        before quitting.
  260.  */
  261.  
  262.     void
  263. Finish3270()
  264. {
  265.     while (Push3270() || !DoTerminalOutput()) {
  266. #if    defined(unix)
  267.     HaveInput = 0;
  268. #endif    /* defined(unix) */
  269.     ;
  270.     }
  271. }
  272.  
  273.  
  274. /* StringToTerminal - output a null terminated string to the terminal */
  275.  
  276.     void
  277. StringToTerminal(s)
  278.     char *s;
  279. {
  280.     int count;
  281.  
  282.     count = strlen(s);
  283.     if (count) {
  284.     (void) DataToTerminal(s, count);    /* we know it always goes... */
  285.     }
  286. }
  287.  
  288.  
  289. #if    ((!defined(NOT43)) || defined(PUTCHAR))
  290. /* _putchar - output a single character to the terminal.  This name is so that
  291.  *    curses(3x) can call us to send out data.
  292.  */
  293.  
  294.     void
  295. _putchar(c)
  296.     char c;
  297. {
  298. #if    defined(sun)        /* SunOS 4.0 bug */
  299.     c &= 0x7f;
  300. #endif    /* defined(sun) */
  301.     if (cursesdata) {
  302.     Dump('>', &c, 1);
  303.     }
  304.     if (!TTYROOM()) {
  305.     (void) DataToTerminal(&c, 1);
  306.     } else {
  307.     TTYADD(c);
  308.     }
  309. }
  310. #endif    /* ((!defined(NOT43)) || defined(PUTCHAR)) */
  311.  
  312.     void
  313. SetIn3270()
  314. {
  315.     if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
  316.         && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
  317.     if (!In3270) {
  318.         In3270 = 1;
  319.         Init3270();        /* Initialize 3270 functions */
  320.         /* initialize terminal key mapping */
  321.         InitTerminal();    /* Start terminal going */
  322.         setconnmode(0);
  323.     }
  324.     } else {
  325.     if (In3270) {
  326.         StopScreen(1);
  327.         In3270 = 0;
  328.         Stop3270();        /* Tell 3270 we aren't here anymore */
  329.         setconnmode(0);
  330.     }
  331.     }
  332. }
  333.  
  334. /*
  335.  * tn3270_ttype()
  336.  *
  337.  *    Send a response to a terminal type negotiation.
  338.  *
  339.  *    Return '0' if no more responses to send; '1' if a response sent.
  340.  */
  341.  
  342.     int
  343. tn3270_ttype()
  344. {
  345.     /*
  346.      * Try to send a 3270 type terminal name.  Decide which one based
  347.      * on the format of our screen, and (in the future) color
  348.      * capaiblities.
  349.      */
  350.     InitTerminal();        /* Sets MaxNumberColumns, MaxNumberLines */
  351.     if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
  352.     Sent3270TerminalType = 1;
  353.     if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
  354.         MaxNumberLines = 27;
  355.         MaxNumberColumns = 132;
  356.         sb_terminal[SBTERMMODEL] = '5';
  357.     } else if (MaxNumberLines >= 43) {
  358.         MaxNumberLines = 43;
  359.         MaxNumberColumns = 80;
  360.         sb_terminal[SBTERMMODEL] = '4';
  361.     } else if (MaxNumberLines >= 32) {
  362.         MaxNumberLines = 32;
  363.         MaxNumberColumns = 80;
  364.         sb_terminal[SBTERMMODEL] = '3';
  365.     } else {
  366.         MaxNumberLines = 24;
  367.         MaxNumberColumns = 80;
  368.         sb_terminal[SBTERMMODEL] = '2';
  369.     }
  370.     NumberLines = 24;        /* before we start out... */
  371.     NumberColumns = 80;
  372.     ScreenSize = NumberLines*NumberColumns;
  373.     if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
  374.         ExitString("Programming error:  MAXSCREENSIZE too small.\n",
  375.                                 1);
  376.         /*NOTREACHED*/
  377.     }
  378.     printsub('>', sb_terminal+2, sizeof sb_terminal-2);
  379.     ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
  380.     return 1;
  381.     } else {
  382.     return 0;
  383.     }
  384. }
  385.  
  386. #if    defined(unix)
  387.     void
  388. settranscom(argc, argv)
  389.     int argc;
  390.     char *argv[];
  391. {
  392.     int i;
  393.  
  394.     if (argc == 1 && transcom) {
  395.        transcom = 0;
  396.     }
  397.     if (argc == 1) {
  398.        return;
  399.     }
  400.     transcom = tline;
  401.     (void) strcpy(transcom, argv[1]);
  402.     for (i = 2; i < argc; ++i) {
  403.         (void) strcat(transcom, " ");
  404.         (void) strcat(transcom, argv[i]);
  405.     }
  406. }
  407. #endif    /* defined(unix) */
  408.  
  409. #endif    /* defined(TN3270) */
  410.