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

  1. /*-
  2.  * Copyright (c) 1988 The 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[] = "@(#)outbound.c    4.3 (Berkeley) 4/26/91";
  36. #endif /* not lint */
  37.  
  38. #include <stdio.h>
  39.  
  40. #include "../general/general.h"
  41.  
  42. #include "hostctlr.h"
  43. #include "oia.h"
  44. #include "screen.h"
  45. #include "../api/ebc_disp.h"
  46.  
  47. #include "../general/globals.h"
  48. #include "externs.h"
  49. #include "declare.h"
  50.  
  51. #define SetHighestLowest(position) { \
  52.                     if (position < Lowest) { \
  53.                         Lowest = position; \
  54.                     } \
  55.                     if (position > Highest) { \
  56.                         Highest = position; \
  57.                     } \
  58.                     }
  59.  
  60.  
  61. static int    LastWasTerminated = 1;    /* was "control" = 1 last time? */
  62.  
  63. /* some globals */
  64.  
  65. #if    !defined(PURE3274)
  66. int    OutputClock;        /* what time it is */
  67. int    TransparentClock;        /* time we were last in transparent */
  68. #endif    /* !defined(PURE3274) */
  69.  
  70. char CIABuffer[64] = {
  71.     0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
  72.     0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
  73.     0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
  74.     0xd8, 0xd9, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
  75.     0x60, 0x61, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
  76.     0xe8, 0xe9, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
  77.     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
  78.     0xf8, 0xf9, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
  79. };
  80.  
  81. static struct orders_def orders_def[] = ORDERS_DEF;
  82.  
  83. /*
  84.  * init_ctlr()
  85.  *
  86.  *    Initialize all data from the 'data' portion to their startup values.
  87.  */
  88.  
  89. void
  90. init_ctlr()
  91. {
  92.     LastWasTerminated = 1;
  93.     init_inbound();
  94.     init_oia();
  95. }
  96.  
  97.  
  98. FieldInc(position)
  99. register int    position;        /* Position in previous field */
  100. {
  101.     register ScreenImage *ptr;
  102.  
  103.     ptr = (ScreenImage *)memNSchr((char *)Host+position+1, ATTR_MASK,
  104.             HighestScreen()-position, ATTR_MASK, sizeof Host[0]);
  105.     if (ptr == 0) {
  106.     ptr = (ScreenImage *)memNSchr((char *)Host+LowestScreen(), ATTR_MASK,
  107.             position-LowestScreen(), ATTR_MASK, sizeof Host[0]);
  108.     if (ptr == 0) {
  109.         return LowestScreen();
  110.     }
  111.     }
  112.     return ptr-Host;
  113. }
  114.  
  115. FieldDec(position)
  116. int    position;
  117. {
  118.     register ScreenImage *ptr;
  119.  
  120.     ptr = (ScreenImage *)memNSchr((char *)(Host+position)-1, ATTR_MASK,
  121.             position-LowestScreen(), ATTR_MASK, -sizeof Host[0]);
  122.     if (ptr == 0) {
  123.     ptr = (ScreenImage *)memNSchr((char *)Host+HighestScreen(), ATTR_MASK,
  124.             HighestScreen()-position, ATTR_MASK, -sizeof Host[0]);
  125.     if (ptr == 0) {
  126.         return LowestScreen();
  127.     }
  128.     }
  129.     return ptr-Host;
  130. }
  131.  
  132. /* Clear3270 - called to clear the screen */
  133.  
  134. void
  135. Clear3270()
  136. {
  137.     ClearArray(Host);
  138.     DeleteAllFields();        /* get rid of all fields */
  139.     BufferAddress = SetBufferAddress(0,0);
  140.     CursorAddress = SetBufferAddress(0,0);
  141.     Lowest = LowestScreen();
  142.     Highest = HighestScreen();
  143. }
  144.  
  145. /* AddHost - called to add a character to the buffer.
  146.  *    We use a macro in this module, since we call it so
  147.  *    often from loops.
  148.  *
  149.  *    NOTE: It is a macro, so don't go around using AddHost(p, *c++), or
  150.  *    anything similar.  (I don't define any temporary variables, again
  151.  *    just for the speed.)
  152.  */
  153. void
  154. AddHost(position, character)
  155. int    position;
  156. char    character;
  157. {
  158. #   define    AddHostA(p,c)                    \
  159.     {                                \
  160.     if (IsStartField(p)) {                    \
  161.         DeleteField(p);                    \
  162.         Highest = HighestScreen();                \
  163.         Lowest = LowestScreen();                \
  164.         SetHighestLowest(p);                \
  165.     }                            \
  166.     SetHost(p, c);                        \
  167.     }
  168. #   define    AddHost(p,c)                    \
  169.     {                                \
  170.     if (c != GetHost(p)) {                    \
  171.         SetHighestLowest(p);                \
  172.     }                            \
  173.     AddHostA(p,c);                        \
  174.     }    /* end of macro of AddHost */
  175.  
  176.     AddHost(position, character);
  177. }
  178.  
  179. /* returns the number of characters consumed */
  180. int
  181. DataFromNetwork(Buffer, count, control)
  182. char    *Buffer;                /* what the data is */
  183. register int    count;                /* and how much there is */
  184. int    control;                /* this buffer ended block? */
  185. {
  186.     int origCount;
  187.     register unsigned char *buffer = (unsigned char *)Buffer;
  188.     register int c;
  189.     register int i;
  190.     static int Command;
  191.     static int Wcc;
  192.  
  193.     origCount = count;
  194.  
  195.     /*
  196.      * If this is the start of a new data stream, then look
  197.      * for an op-code and (possibly) a WCC.
  198.      */
  199.     if (LastWasTerminated) {
  200.  
  201.     if (count < 2) {
  202.         if (count == 0) {
  203.         ExitString("Short count received from host!\n", 1);
  204.         return(count);
  205.         }
  206.         Command = buffer[0];
  207.         switch (Command) {        /* This had better be a read command */
  208.         case CMD_READ_MODIFIED:
  209.         case CMD_SNA_READ_MODIFIED:
  210.         case CMD_SNA_READ_MODIFIED_ALL:
  211.         SetOiaOnlineA(&OperatorInformationArea);
  212.         SetOiaModified();
  213.         DoReadModified(Command);
  214.         break;
  215.         case CMD_READ_BUFFER:
  216.         case CMD_SNA_READ_BUFFER:
  217.         SetOiaOnlineA(&OperatorInformationArea);
  218.         SetOiaModified();
  219.         DoReadBuffer();
  220.         break;
  221.         default:
  222.         {
  223.             char s_buffer[100];
  224.  
  225.             sprintf(s_buffer,
  226.             "Unexpected read command code 0x%x received.\n",
  227.                                     Command);
  228.             ExitString(s_buffer, 1);
  229.             break;
  230.         }
  231.         }
  232.         return(1);            /* We consumed everything */
  233.     }
  234.     Command = buffer[0];
  235.     Wcc = buffer[1];
  236.     if (Wcc & WCC_RESET_MDT) {
  237.         i = c = WhereAttrByte(LowestScreen());
  238.         do {
  239.         if (HasMdt(i)) {
  240.             TurnOffMdt(i);
  241.         }
  242.         i = FieldInc(i);
  243.         } while (i != c);
  244.     }
  245.  
  246.     switch (Command) {
  247.     case CMD_ERASE_WRITE:
  248.     case CMD_ERASE_WRITE_ALTERNATE:
  249.     case CMD_SNA_ERASE_WRITE:
  250.     case CMD_SNA_ERASE_WRITE_ALTERNATE:
  251.         {
  252.         int newlines, newcolumns;
  253.  
  254.         SetOiaOnlineA(&OperatorInformationArea);
  255.         ResetOiaTWait(&OperatorInformationArea);
  256.         SetOiaModified();
  257.         if ((Command == CMD_ERASE_WRITE)
  258.                 || (Command == CMD_SNA_ERASE_WRITE)) {
  259.             newlines = 24;
  260.             newcolumns = 80;
  261.         } else {
  262.             newlines = MaxNumberLines;
  263.             newcolumns = MaxNumberColumns;
  264.         }
  265.         if ((newlines != NumberLines)
  266.                 || (newcolumns != NumberColumns)) {
  267.             /*
  268.              * The LocalClearScreen() is really for when we
  269.              * are going from a larger screen to a smaller
  270.              * screen, and we need to clear off the stuff
  271.              * at the end of the lines, or the lines at
  272.              * the end of the screen.
  273.              */
  274.             LocalClearScreen();
  275.             NumberLines = newlines;
  276.             NumberColumns = newcolumns;
  277.             ScreenSize = NumberLines * NumberColumns;
  278.         }
  279.         Clear3270();
  280. #if    !defined(PURE3274)
  281.         if (TransparentClock == OutputClock) {
  282.             TransStop();
  283.         }
  284. #endif    /* !defined(PURE3274) */
  285.         break;
  286.         }
  287.  
  288.     case CMD_ERASE_ALL_UNPROTECTED:
  289.     case CMD_SNA_ERASE_ALL_UNPROTECTED:
  290.         SetOiaOnlineA(&OperatorInformationArea);
  291.         ResetOiaTWait(&OperatorInformationArea);
  292.         SetOiaModified();
  293.         CursorAddress = HighestScreen()+1;
  294.         for (i = LowestScreen(); i <= HighestScreen(); i = ScreenInc(i)) {
  295.         if (IsUnProtected(i)) {
  296.             if (CursorAddress > i) {
  297.             CursorAddress = i;
  298.             }
  299.             AddHost(i, '\0');
  300.         }
  301.         if (HasMdt(i)) {
  302.             TurnOffMdt(i);
  303.         }
  304.         }
  305.         if (CursorAddress == HighestScreen()+1) {
  306.         CursorAddress = SetBufferAddress(0,0);
  307.         }
  308.         UnLocked = 1;
  309.         AidByte = 0;
  310.         ResetOiaSystemLocked(&OperatorInformationArea);
  311.         SetOiaModified();
  312.         TerminalIn();
  313.         break;
  314.     case CMD_WRITE:
  315.     case CMD_SNA_WRITE:
  316.         SetOiaOnlineA(&OperatorInformationArea);
  317.         ResetOiaTWait(&OperatorInformationArea);
  318.         SetOiaModified();
  319.         break;
  320.     default:
  321.         {
  322.         char s_buffer[100];
  323.  
  324.         sprintf(s_buffer,
  325.             "Unexpected write command code 0x%x received.\n",
  326.                                 Command);
  327.         ExitString(s_buffer, 1);
  328.         break;
  329.         }
  330.     }
  331.  
  332.     count -= 2;            /* strip off command and wcc */
  333.     buffer += 2;
  334.  
  335.     } else {
  336. #if    !defined(PURE3274)
  337.     if (TransparentClock == OutputClock) {
  338.         TransOut(buffer, count, -1, control);
  339.         count = 0;
  340.     }
  341. #endif    /* !defined(PURE3274) */
  342.     }
  343.     LastWasTerminated = 0;        /* then, reset at end... */
  344.  
  345.     while (count) {
  346.     count--;
  347.     c = *buffer++;
  348.     if (IsOrder(c)) {
  349.         /* handle an order */
  350.         switch (c) {
  351. #        define Ensure(x)    if (count < x) { \
  352.                         if (!control) { \
  353.                         return(origCount-(count+1)); \
  354.                         } else { \
  355.                         /* XXX - should not occur */ \
  356.                         count = 0; \
  357.                         break; \
  358.                         } \
  359.                     }
  360.         case ORDER_SF:
  361.         Ensure(1);
  362.         c = *buffer++;
  363.         count--;
  364.         if ( ! (IsStartField(BufferAddress) &&
  365.                     FieldAttributes(BufferAddress) == c)) {
  366.             SetHighestLowest(BufferAddress);
  367.             NewField(BufferAddress,c);
  368.         }
  369.         BufferAddress = ScreenInc(BufferAddress);
  370.         break;
  371.         case ORDER_SBA:
  372.         Ensure(2);
  373.         i = buffer[0];
  374.         c = buffer[1];
  375. #if    !defined(PURE3274)
  376.         /* Check for transparent write */
  377.         if ((i == 0) && ((c == 0) || (c == 1) || (c == 5))) {
  378.             TransparentClock = OutputClock+1;
  379.             TransOut(buffer+2, count-2, c, control);
  380.             buffer += count;
  381.             count -= count;
  382.             break;
  383.         }
  384. #endif    /* !defined(PURE3274) */
  385.         BufferAddress = Addr3270(i, c);
  386.         buffer += 2;
  387.         count -= 2;
  388.         break;
  389.         case ORDER_IC:
  390.         CursorAddress = BufferAddress;
  391.         break;
  392.         /*
  393.          * XXX - PT is supposed to null fill the screen buffer
  394.          * under certain draconian conditions.
  395.          */
  396.         case ORDER_PT:
  397.         i = BufferAddress;
  398.         do {
  399.             if (IsStartField(i)) {
  400.             if (!IsProtected(ScreenInc(i))) {
  401.                 break;
  402.             }
  403.             }
  404.             i = ScreenInc(i);
  405.         } while (i != HighestScreen());
  406.         BufferAddress = ScreenInc(i);
  407.         break;
  408.         case ORDER_RA:
  409.         Ensure(3);
  410.         i = Addr3270(buffer[0], buffer[1]);
  411.         if ((i < 0) || (i > HighestScreen())) {
  412.             char s_buffer[200];
  413.  
  414.             sprintf(s_buffer, "tn3270:  %s%d.\n\t%s%d%s%d%s\n",
  415.             "Invalid 3270 order 'Repeat to Address' to address ",
  416.             i,
  417.             "(Screen currently set to ",
  418.             NumberLines,
  419.             " by ",
  420.             NumberColumns,
  421.             ".)");
  422.             ExitString(s_buffer, 1);
  423.             /*NOTREACHED*/
  424.         }
  425.         c = buffer[2];
  426.         if (c == ORDER_GE) {
  427.             Ensure(4);
  428.             c = buffer[3];
  429.             buffer += 4;
  430.             count -= 4;
  431.         } else {
  432.             buffer += 3;
  433.             count -= 3;
  434.         }
  435.         do {
  436.             AddHost(BufferAddress, ebc_disp[c]);
  437.             BufferAddress = ScreenInc(BufferAddress);
  438.         } while (BufferAddress != i);
  439.         break;
  440.         case ORDER_EUA:    /* (from [here,there), ie: half open interval] */
  441.         Ensure(2);
  442.         /*
  443.          * Compiler error - msc version 4.0:
  444.          *            "expression too complicated".
  445.          */
  446.         i = WhereAttrByte(BufferAddress);
  447.         c = FieldAttributes(i);
  448.         i = Addr3270(buffer[0], buffer[1]);
  449.         if ((i < 0) || (i > HighestScreen())) {
  450.             char s_buffer[200];
  451.  
  452.             sprintf(s_buffer, "tn3270:  %s%d.\n\t%s%d%s%d%s\n",
  453.             "Invalid 3270 order 'Erase Unprotected to Address' to address ",
  454.             i,
  455.             "(Screen currently set to ",
  456.             NumberLines,
  457.             " by ",
  458.             NumberColumns,
  459.             ".)");
  460.             ExitString(s_buffer, 1);
  461.             /*NOTREACHED*/
  462.         }
  463.         do {
  464.             if (IsStartField(BufferAddress)) {
  465.             c = FieldAttributes(BufferAddress);
  466.             } else if (!IsProtectedAttr(BufferAddress, c)) {
  467.             AddHost(BufferAddress, 0);
  468.             }
  469.             BufferAddress = ScreenInc(BufferAddress);
  470.         } while (i != BufferAddress);
  471.         buffer += 2;
  472.         count -= 2;
  473.         break;
  474.         case ORDER_GE:
  475.         Ensure(2);
  476.         /* XXX Should do SOMETHING! */
  477.         /* XXX buffer += 0; */
  478.         /* XXX count -= 0; *//* For now, just use this character */
  479.         break;
  480.         case ORDER_YALE:        /* special YALE defined order */
  481.         Ensure(2);    /* need at least two characters */
  482.         if (*buffer == 0x5b) {
  483.             i = OptOrder(buffer+1, count-1, control);
  484.             if (i == 0) {
  485.             return(origCount-(count+1));    /* come here again */
  486.             } else {
  487.             buffer += 1 + i;
  488.             count  -= (1 + i);
  489.             }
  490.         }
  491.         break;
  492.         default:
  493.         {
  494.             char s_buffer[100];
  495.             static struct orders_def unk_order
  496.                         = { 0, "??", "(unknown)" };
  497.             struct orders_def *porder = &unk_order;
  498.             int s_i;
  499.  
  500.             for (s_i = 0; s_i <= highestof(orders_def); s_i++) {
  501.             if (orders_def[s_i].code == c) {
  502.                 porder = &orders_def[s_i];
  503.                 break;
  504.             }
  505.             }
  506.             sprintf(s_buffer,
  507.             "Unsupported order '%s' (%s, 0x%x) received.\n",
  508.             porder->long_name, porder->short_name, c);
  509.             ExitString(s_buffer, 1);
  510.             /*NOTREACHED*/
  511.         }
  512.         }
  513.         if (count < 0) {
  514.         count = 0;
  515.         }
  516.     } else {
  517.         /* Data comes in large clumps - take it all */
  518.         i = BufferAddress;
  519.         AddHostA(i, ebc_disp[c]);
  520.         SetHighestLowest(i);
  521.         i = ScreenInc(i);
  522.         c = *buffer;
  523.         while (count && !IsOrder(c)) {
  524.         AddHostA(i, ebc_disp[c]);
  525.         i = ScreenInc(i);
  526.         if (i == LowestScreen()) {
  527.             SetHighestLowest(HighestScreen());
  528.         }
  529.         count--;
  530.         buffer++;
  531.         c = *buffer;
  532.         }
  533.         SetHighestLowest(i);
  534.         BufferAddress = i;
  535.     }
  536.     }
  537.     if (count == 0) {
  538.     if (control) {
  539. #if    !defined(PURE3274)
  540.         OutputClock++;        /* time rolls on */
  541. #endif    /* !defined(PURE3274) */
  542.         if (Wcc & WCC_RESTORE) {
  543. #if    !defined(PURE3274)
  544.         if (TransparentClock != OutputClock) {
  545.             AidByte = 0;
  546.         }
  547. #else    /* !defined(PURE3274) */
  548.         AidByte = 0;
  549. #endif    /* !defined(PURE3274) */
  550.         UnLocked = 1;
  551.         ResetOiaSystemLocked(&OperatorInformationArea);
  552.         SetOiaModified();
  553.         SetPsModified();
  554.         TerminalIn();
  555.         }
  556.         if (Wcc & WCC_ALARM) {
  557.         RingBell((char *)0);
  558.         }
  559.     }
  560.     LastWasTerminated = control;    /* state for next time */
  561.     return(origCount);
  562.     } else {
  563.     return(origCount-count);
  564.     }
  565. }
  566.  
  567. /*
  568.  * Init3270()
  569.  *
  570.  * Initialize any 3270 (controller) variables to an initial state
  571.  * in preparation for accepting a connection.
  572.  */
  573.  
  574. void
  575. Init3270()
  576. {
  577.     int i;
  578.  
  579.     OptInit();        /* initialize mappings */
  580.  
  581.     ClearArray(Host);
  582.  
  583.     ClearArray(Orders);
  584.     for (i = 0; i <= highestof(orders_def); i++) {
  585.     Orders[orders_def[i].code] = 1;
  586.     }
  587.  
  588.     DeleteAllFields();        /* Clear screen */
  589.     Lowest = HighestScreen()+1;
  590.     Highest = LowestScreen()-1;
  591.     CursorAddress = BufferAddress = SetBufferAddress(0,0);
  592.     UnLocked = 1;
  593. #if    !defined(PURE3274)
  594.     OutputClock = 1;
  595.     TransparentClock = -1;
  596. #endif    /* !defined(PURE3274) */
  597.     SetOiaReady3274(&OperatorInformationArea);
  598. }
  599.  
  600.  
  601. void
  602. Stop3270()
  603. {
  604.     ResetOiaReady3274(&OperatorInformationArea);
  605. }
  606.