home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / sna / sli3270 / sli3270.c < prev    next >
C/C++ Source or Header  |  1997-04-09  |  71KB  |  1,563 lines

  1. /*****************************************************************************/
  2. /* SLI Sample Program                                                        */
  3. /*                                                                           */
  4. /* (C) Copyright 1990 - 1993 Data Connection Ltd.                            */
  5. /*                                                                           */
  6. /* This program is a crude 3270 emulator.  It uses the SLI API to access the */
  7. /* LU-LU session.  Outbound data from the host is displayed on the screen    */
  8. /* unformatted.                                                              */
  9. /*                                                                           */
  10. /* If the outbound data is an RQD request an automatic positive response     */
  11. /* is sent.  Inbound data can be entered at the keyboard and is sent on      */
  12. /* the current session.                                                      */
  13. /*                                                                           */
  14. /* The program is invoked with two parameters - the name of the LUA LU       */
  15. /* to use and a logon string.  This is converted to upper case and must      */
  16. /* match an LUA LU in the configuration file.  This LU should be configured  */
  17. /* for a 327? on the host.                                                   */
  18. /*                                                                           */
  19. /* The program can only access hosts that use simple unformatted logon       */
  20. /* requests                                                                  */
  21. /*                                                                           */
  22. /* To exit the program type ] (right square bracket)                         */
  23. /*                                                                           */
  24. /* The CSV CONVERT function is used to convert data between ASCII and        */
  25. /* EBCDIC.  This uses the type G conversion table, so the environment        */
  26. /* variable COMTBLG must be set to point to a suitable file.                 */
  27. /*                                                                           */
  28. /* Keys that work are:                                                       */
  29. /*                                                                           */
  30. /*     Alt-1 to Alt-9 are PF1 to PF9                                         */
  31. /*     F2 sends a CLEAR to the host                                          */
  32. /*     backspace                                                             */
  33. /*     Letters, numbers and symbols                                          */
  34. /*     ] terminates the program                                              */
  35. /*                                                                           */
  36. /*****************************************************************************/
  37.  
  38.  
  39. #ifdef WIN32
  40.   #include <windows.h>
  41. #else
  42.   #define INCL_DOS
  43.   #define INCL_DOSERRORS
  44.   #include <os2.h>
  45. #endif
  46.  
  47. #include <stdio.h>
  48. #include <string.h>
  49. #include <stdlib.h>
  50. #include <conio.h>
  51. #include <lua_c.h>
  52. #include <acssvcc.h>
  53.  
  54.  
  55. /*****************************************************************************/
  56. /* Program constants                                                         */
  57. /*****************************************************************************/
  58. #define DATASIZE 4096                  /* Max size of RU                     */
  59. #define EXITKEY  0x5D                  /* ']'   to exit program              */
  60.  
  61. #define BETB     1                     /* Between brackets                   */
  62. #define SEND     2                     /* In bracket and can send            */
  63. #define RECV     3                     /* In bracket, but cannot send        */
  64.  
  65.  
  66. /*****************************************************************************/
  67. /* State variables                                                           */
  68. /*                                                                           */
  69. /* We can only have one read or write verb outstanding per flow.  These      */
  70. /* state variables keep track of these verbs and what we need to do with     */
  71. /* them.                                                                     */
  72. /*****************************************************************************/
  73.  
  74. UINT  write_state;
  75. #define NO_WRITE              1
  76. #define WRITE_OUTSTANDING     2        /* waiting for write to complete      */
  77. #define WRITE_QUEUED          3        /* have data to write                 */
  78.  
  79. UINT  read_state;
  80. #define NO_READ               1
  81. #define READ_OUTSTANDING      2        /* read verb outstanding              */
  82. #define RSP_QUEUED            3        /* have a response to write           */
  83. #define RSP_OUTSTANDING       4        /* waiting for a response to complete */
  84.  
  85. UINT  rpq_state;
  86. #define NO_RPQ                1
  87. #define RPQ_OUTSTANDING       2        /* waiting for an RPQ to complete     */
  88. #define RPQ_QUEUED            3        /* have RPQ to send                   */
  89.  
  90. /***************************************************************************/
  91. /* Global variables                                                        */
  92. /*                                                                         */
  93. /* Inbound data is  prefixed with the <enter> key AID plus a two byte      */
  94. /* cursor address.                                                         */
  95. /***************************************************************************/
  96. LUA_VERB_RECORD recv_verb;             /* SLI read verb                    */
  97. LUA_VERB_RECORD other_verb;            /* SLI init, write or term verb     */
  98. LUA_VERB_RECORD rpq_verb;              /* SLI_WRITE for RPQs               */
  99.  
  100. UCHAR rpq_data[] = {
  101.  
  102.   0x88,
  103.   0x00, 0x0C, 0x81, 0x80, 0x80, 0x81, 0x85, 0x86, 0x87, 0x88, 0x95, 0xA6,
  104.  
  105.   0x00, 0x17, 0x81, 0x81, 0x21, 0x00, 0x00, 0x50, 0x00, 0x18, 0x00, 0x00,
  106.   0x0A, 0x02, 0xE5, 0x00, 0x02, 0x00, 0x6F, 0x09, 0x10, 0x07, 0x80,
  107.  
  108.   0x00, 0x14, 0x81, 0x85, 0x02, 0x00, 0x09, 0x0E, 0x00, 0x00, 0x00, 0x00,
  109.   0x07, 0x00, 0x00, 0x00, 0x02, 0xB9, 0x01, 0x1D,
  110.  
  111.   0x00, 0x16, 0x81, 0x86, 0x00, 0x08, 0x00, 0xF4, 0xF1, 0x00, 0xF2, 0x00,
  112.   0xF3, 0x00, 0xF4, 0x00, 0xF5, 0x00, 0xF6, 0x00, 0xF7, 0x00,
  113.  
  114.   0x00, 0x0D, 0x81, 0x87, 0x04, 0x00, 0xF0, 0xF1, 0x00, 0xF2, 0x00, 0xF4,
  115.   0x00,
  116.  
  117.   0x00, 0x07, 0x81, 0x88, 0x00, 0x01, 0x02,
  118.  
  119.   0x00, 0x0C, 0x81, 0x95, 0x00, 0x00, 0x7F, 0xFF, 0x7F, 0xFF, 0x01, 0x01,
  120.  
  121.   0x00, 0x11, 0x81, 0xA6, 0x00, 0x00, 0x0B, 0x01, 0x00, 0x00, 0x50, 0x00,
  122.   0x18, 0x00, 0x50, 0x00, 0x18};
  123.  
  124. #define RPQ_LENGTH (sizeof(rpq_data))
  125.  
  126.  
  127.  
  128.  
  129. unsigned char read_data[DATASIZE];     /* Outbound RU                       */
  130. #define WRITE_EXTRA 6
  131. unsigned char write_array[DATASIZE + WRITE_EXTRA] =
  132.                                           {0x7d, 0x40, 0x40, 0x11, 0x40, 0x40};
  133.                                        /* Inbound RU                         */
  134. unsigned char *write_data = write_array + WRITE_EXTRA;
  135.                                        /* Pointer to inbound RU              */
  136. UINT data_offset = 0;                  /* offset into read_data              */
  137. UINT write_len   = 0;                  /* length of write data               */
  138.  
  139. struct convert convert_to_asc;         /* Outbound convert verb              */
  140. struct convert convert_to_ebc;         /* Inbound convert verb               */
  141.  
  142. #ifdef WIN32
  143.   HANDLE write_event = 0l;             /* write arm verb semaphore           */
  144.   HANDLE read_event  = 0l;             /* read arm verb semaphore            */
  145.   HANDLE init_event  = 0l;             /* SLI_OPEN semaphore                 */
  146.   HANDLE term_event  = 0l;             /* SLI_CLOSE semaphore                */
  147.   HANDLE rpq_event   = 0l;
  148.   HANDLE std_input;                    /* standard input handle              */
  149.   HANDLE std_output;                   /* standard output handle             */
  150. #else
  151.   ULONG write_sema4 = 0l;              /* write arm verb semaphore           */
  152.   ULONG read_sema4  = 0l;              /* read arm verb semaphore            */
  153.   ULONG init_sema4  = 0l;              /* SLI_OPEN semaphore                 */
  154.   ULONG term_sema4  = 0l;              /* SLI_CLOSE semaphore                */
  155.   ULONG rpq_sema4   = 0l;
  156. #endif
  157.  
  158. BOOL terminating = FALSE;              /* are we already in closedown() ?    */
  159.  
  160. unsigned long sense = 0l;              /* sense code                         */
  161.  
  162. unsigned char lu_name[9] = "        "; /* LU name                            */
  163. unsigned long sid;                     /* SLI session ID                     */
  164. int send_state = BETB;                 /* LU session send state              */
  165.  
  166. #define LOGON_MAX  25                  /* maximum logon string length        */
  167.  
  168. UCHAR logon_data[LOGON_MAX+1] = {0};
  169. UCHAR logon_length   = 0;
  170.  
  171. #ifdef WIN32
  172.   #define OPENPOST        (ULONG) init_event
  173.   #define CLOSEPOST       (ULONG) term_event
  174.   #define RECVPOST        (ULONG) read_event
  175.   #define SENDPOST        (ULONG) write_event
  176.   #define RPQPOST         (ULONG) rpq_event
  177. #else
  178.   #define OPENPOST        (unsigned long) ((UCHAR FAR *) &init_sema4)
  179.   #define CLOSEPOST       (unsigned long) ((UCHAR FAR *) &term_sema4)
  180.   #define RECVPOST        (unsigned long) ((UCHAR FAR *) &read_sema4)
  181.   #define SENDPOST        (unsigned long) ((UCHAR FAR *) &write_sema4)
  182.   #define RPQPOST         (unsigned long) ((UCHAR FAR *) &rpq_sema4)
  183. #endif
  184.  
  185.  
  186. /*****************************************************************************/
  187. /* Function declarations.                                                    */
  188. /*****************************************************************************/
  189.  
  190. #ifdef WIN32
  191.   #define LOADDS
  192. #else
  193.   #define LOADDS _loadds
  194. #endif
  195.  
  196. void pascal far LOADDS SLI (LUA_VERB_RECORD FAR *);
  197.  
  198. #ifdef WIN32
  199.   void _CRTAPI1 main(int argc, char *argv[]);
  200. #else
  201.   int             main                (int  argc,char  * *argv);
  202. #endif
  203. void            csv_init            (void);
  204. int             issue_verb          (unsigned int  type);
  205. void            issue_receive       (void);
  206. void            other_done          (LUA_VERB_RECORD *verb);
  207. void            recv_done           (LUA_VERB_RECORD *verb);
  208. void            issue_rsp           (unsigned long  sense);
  209. void            rsp_done            (LUA_VERB_RECORD *verb);
  210. void            closedown           (void);
  211. BOOL            do_send             (void);
  212. void            wait_verb_complete  (LUA_VERB_RECORD *verb);
  213. void            set_semaphore       (LUA_VERB_RECORD *verb);
  214. BOOL            do_keyboard_stuff   (void);
  215. BOOL            check_verb_complete (LUA_VERB_RECORD *verb);
  216. void            parse_data          (UCHAR FAR *, USHORT);
  217. BOOL            issue_rpq           (void);
  218.  
  219. /**PROC+**********************************************************************/
  220. /* Name:      main                                                           */
  221. /*                                                                           */
  222. /* Purpose:   set up CSV convert verbs                                       */
  223. /*                                                                           */
  224. /* Returns:   none                                                           */
  225. /*                                                                           */
  226. /* Params:    argv, argc                                                     */
  227. /*                                                                           */
  228. /* Operation: Get LU name and logon string from command line                 */
  229. /*            do some initialisation                                         */
  230. /*            Issue SLI_OPEN to get LU-LU   session                          */
  231. /*            Loop reading data from keyboard and host, and send keyboard    */
  232. /*            data to host                                                   */
  233. /**PROC-**********************************************************************/
  234. #ifdef WIN32
  235.   void _CRTAPI1 main(int argc, char *argv[])
  236. #else
  237. int main(argc, argv)
  238. int argc;
  239. char *argv[];
  240. #endif
  241. {
  242.   BOOL whole_data;       /* we have a whole data string to write             */
  243.   BOOL verb_complete;    /* Has a verb completed                             */
  244.   BOOL write_ok;         /* Has write worked?                                */
  245.   BOOL rpq_ok;           /* Has rpq worked                                   */
  246.   int ii;
  247. #ifdef WIN32
  248.   HANDLE handle_list [6];
  249. #endif
  250. #ifdef DOS5
  251.   DEFINEMUXSEMLIST(sem_list,5)
  252.   USHORT           sem_index;
  253. #endif
  254.  
  255.   printf("SLI simple 3270 application\n");
  256.  
  257.   /***************************************************************************/
  258.   /* Validate parameter usage and get LU name.                               */
  259.   /***************************************************************************/
  260.   if (argc != 3)
  261.   {
  262.     printf("Usage: SLI3270 luname \"logon string\"\n");
  263.     exit(1);
  264.   }
  265.   if (strlen(argv[1]) > 8)
  266.   {
  267.     printf("LU name too long\n");
  268.     exit(1);
  269.   }
  270.   if (strlen(argv[2]) > LOGON_MAX)
  271.   {
  272.     printf("Logon string too long");
  273.   }
  274.  
  275.   /***************************************************************************/
  276.   /* Convert to upper case                                                   */
  277.   /***************************************************************************/
  278.   ii=0;
  279.   while (argv[1][ii])
  280.   {
  281.     if (argv[1][ii] >= 'a' && argv[1][ii] <= 'z')
  282.     {
  283.       argv[1][ii] = argv[1][ii] - 'a' + 'A';
  284.     }
  285.     ii++;
  286.   }
  287.   memcpy(lu_name, argv[1], strlen(argv[1]));
  288.   printf("lu_name %s\n", lu_name);
  289.  
  290.   /***************************************************************************/
  291.   /* Set up logon message                                                    */
  292.   /***************************************************************************/
  293.   strcpy (logon_data, argv[2]);
  294.   logon_length = strlen(logon_data);
  295.   convert_to_ebc.opcode       = SV_CONVERT;
  296.   convert_to_ebc.direction    = SV_ASCII_TO_EBCDIC;
  297.   convert_to_ebc.char_set     = SV_G;
  298.   convert_to_ebc.source       = logon_data;
  299.   convert_to_ebc.target       = logon_data;
  300.   convert_to_ebc.len          = (unsigned short) logon_length;
  301.   ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_ebc));
  302.  
  303.   /***************************************************************************/
  304.   /* Set up CSV convert verbs                                                */
  305.   /***************************************************************************/
  306.   csv_init();
  307.  
  308. #ifdef WIN32
  309.   /***************************************************************************/
  310.   /* Create the necessary events                                             */
  311.   /***************************************************************************/
  312.   write_event = CreateEvent (NULL, TRUE, FALSE, NULL);
  313.   read_event  = CreateEvent (NULL, TRUE, FALSE, NULL);
  314.   init_event  = CreateEvent (NULL, TRUE, FALSE, NULL);
  315.   term_event  = CreateEvent (NULL, TRUE, FALSE, NULL);
  316.   rpq_event   = CreateEvent (NULL, TRUE, FALSE, NULL);
  317.  
  318.  
  319.   /***************************************************************************/
  320.   /* Get standard input and output handles.                                  */
  321.   /***************************************************************************/
  322.   std_input  = GetStdHandle (STD_INPUT_HANDLE );
  323.   std_output = GetStdHandle (STD_OUTPUT_HANDLE);
  324.   if ((std_input  == INVALID_HANDLE_VALUE) ||
  325.       (std_output == INVALID_HANDLE_VALUE))
  326.   {
  327.     printf("GetStdHandle Failed, %d", GetLastError());
  328.     exit (1);
  329.   }
  330.  
  331.   /***************************************************************************/
  332.   /* Set up list of handles to wait for                                      */
  333.   /***************************************************************************/
  334.   handle_list[0] = write_event;
  335.   handle_list[1] = read_event;
  336.   handle_list[2] = init_event;
  337.   handle_list[3] = term_event;
  338.   handle_list[4] = rpq_event;
  339.   handle_list[5] = std_input;
  340. #endif
  341.  
  342. #ifdef DOS5
  343.   /***************************************************************************/
  344.   /* Set semaphores to begin with                                            */
  345.   /***************************************************************************/
  346.   DosSemSet (&init_sema4);
  347.   DosSemSet (&term_sema4);
  348.   DosSemSet (&read_sema4);
  349.   DosSemSet (&write_sema4);
  350.   DosSemSet (&rpq_sema4);
  351.  
  352.   sem_list.amxs[0].hsem = &init_sema4;
  353.   sem_list.amxs[1].hsem = &term_sema4;
  354.   sem_list.amxs[2].hsem = &read_sema4;
  355.   sem_list.amxs[3].hsem = &write_sema4;
  356.   sem_list.amxs[4].hsem = &rpq_sema4;
  357. #endif
  358.  
  359.  
  360.   /***************************************************************************/
  361.   /* Initialize SLI (get LU-LU session)                                      */
  362.   /***************************************************************************/
  363.   if (issue_verb((unsigned int) LUA_OPCODE_SLI_OPEN))
  364.   {
  365.     printf("OPEN failed\n");
  366.     exit(1);
  367.   }
  368.  
  369.   /***************************************************************************/
  370.   /* Set initial states                                                      */
  371.   /***************************************************************************/
  372.   write_state = NO_WRITE;
  373.   read_state  = NO_READ;
  374.   rpq_state   = NO_RPQ;
  375.  
  376.   /***************************************************************************/
  377.   /* Loop reading inbound data from the keyboard                             */
  378.   /***************************************************************************/
  379.   while (!terminating)
  380.   {
  381.     /*************************************************************************/
  382.     /* Determine if we can pause                                             */
  383.     /*************************************************************************/
  384.     if (  (read_state != NO_READ)   &&
  385.  
  386.           ((write_state != WRITE_QUEUED)    ||
  387.            (rpq_state   != NO_RPQ)          ||
  388.            (read_state  == RSP_OUTSTANDING) ||
  389.            (read_state  == RSP_QUEUED)) &&
  390.  
  391.           ((rpq_state   != RPQ_QUEUED)        ||
  392.            (write_state == WRITE_OUTSTANDING) ||
  393.            (read_state  == RSP_OUTSTANDING)   ||
  394.            (read_state  == RSP_QUEUED))    &&
  395.  
  396.           ((read_state != RSP_QUEUED) ||
  397.            (write_state == WRITE_OUTSTANDING)))
  398.     {
  399. #ifdef WIN32
  400.       WaitForMultipleObjects (6, handle_list, FALSE, INFINITE);
  401. #else
  402.       if (!kbhit())
  403.       {
  404.         DosMuxSemWait (&sem_index, &sem_list, 200l);
  405.       }
  406. #endif
  407.     }
  408.  
  409.     /*************************************************************************/
  410.     /* First check on the state of write verbs                               */
  411.     /*************************************************************************/
  412.     if ((write_state == NO_WRITE)        &&
  413.         (rpq_state   == NO_RPQ)          &&
  414.         (read_state  != RSP_QUEUED)      &&
  415.         (read_state  != RSP_OUTSTANDING))
  416.     {
  417.       /***********************************************************************/
  418.       /* Don't write here if we need to respond, since we can only have one  */
  419.       /* write outstanding on each flow.                                     */
  420.       /* Here we want to check if we have a whole string of data (i.e.  that */
  421.       /* the user has hit enter).  If so write the data to the HOST          */
  422.       /***********************************************************************/
  423.       whole_data = do_keyboard_stuff ();
  424.       if (whole_data)
  425.       {
  426.         /*********************************************************************/
  427.         /* Attempt to write the data.  May not work because of bracket state */
  428.         /*********************************************************************/
  429.  
  430.         write_ok = do_send ();
  431.         if (write_ok)
  432.         {
  433.           /*******************************************************************/
  434.           /* If verb completes async change state to indicate this o.w.      */
  435.           /* call the verb done processor                                    */
  436.           /*******************************************************************/
  437.           if (other_verb.common.lua_flag2.async)
  438.           {
  439.             write_state = WRITE_OUTSTANDING;
  440.           }
  441.           else
  442.           {
  443.             other_done (&other_verb);
  444.             write_state = NO_WRITE;
  445.           }
  446.         }
  447.         else
  448.         {
  449.           /*******************************************************************/
  450.           /* Failed to do a write.  Queue up data                            */
  451.           /*******************************************************************/
  452.           write_state = WRITE_QUEUED;
  453.         }
  454.       }
  455.     }
  456.     else if ((write_state == WRITE_QUEUED)    &&
  457.              (rpq_state   == NO_RPQ)          &&
  458.              (read_state  != RSP_OUTSTANDING) &&
  459.              (read_state  != RSP_QUEUED))
  460.     {
  461.       /***********************************************************************/
  462.       /* Attempt to write the data.  May not work because of bracket state   */
  463.       /***********************************************************************/
  464.       write_ok = do_send ();
  465.       if (write_ok)
  466.       {
  467.         /*********************************************************************/
  468.         /* If verb completes async change state to indicate this o.w.  call  */
  469.         /* the verb done processor                                           */
  470.         /*********************************************************************/
  471.         if (other_verb.common.lua_flag2.async)
  472.         {
  473.           write_state = WRITE_OUTSTANDING;
  474.         }
  475.         else
  476.         {
  477.           other_done (&other_verb);
  478.           write_state = NO_WRITE;
  479.         }
  480.       }
  481.  
  482.     }
  483.     else if (write_state == WRITE_OUTSTANDING)
  484.     {
  485.       /***********************************************************************/
  486.       /* We have a SLI_WRITE outstanding so check if it is complete          */
  487.       /***********************************************************************/
  488.       verb_complete = check_verb_complete (&other_verb);
  489.       if (verb_complete)
  490.       {
  491.         other_done (&other_verb);
  492.         write_state = NO_WRITE;
  493.       }
  494.     }
  495.  
  496.  
  497.  
  498.     /*************************************************************************/
  499.     /* Now check the RPQ state                                               */
  500.     /*************************************************************************/
  501.     if ((rpq_state   == RPQ_QUEUED)        &&
  502.         (write_state != WRITE_OUTSTANDING) &&
  503.         (read_state  != RSP_OUTSTANDING)   &&
  504.         (read_state  != RSP_QUEUED))
  505.     {
  506.       /***********************************************************************/
  507.       /* We have an RPQ queued up.  Try to send it                           */
  508.       /***********************************************************************/
  509.       rpq_ok = issue_rpq ();
  510.       if (rpq_ok)
  511.       {
  512.         /*********************************************************************/
  513.         /* If verb completes async change state to indicate this o.w.  call  */
  514.         /* the verb done processor                                           */
  515.         /*********************************************************************/
  516.         if (rpq_verb.common.lua_flag2.async)
  517.         {
  518.           rpq_state = WRITE_OUTSTANDING;
  519.         }
  520.         else
  521.         {
  522.           other_done (&rpq_verb);
  523.           write_state = NO_RPQ;
  524.         }
  525.       }
  526.     }
  527.     else if (rpq_state == RPQ_OUTSTANDING)
  528.     {
  529.       /***********************************************************************/
  530.       /* Check for verb completion                                           */
  531.       /***********************************************************************/
  532.       verb_complete = check_verb_complete (&rpq_verb);
  533.       if (verb_complete)
  534.       {
  535.         other_done (&rpq_verb);
  536.         rpq_state = NO_RPQ;
  537.       }
  538.  
  539.     }
  540.  
  541.  
  542.  
  543.     /*************************************************************************/
  544.     /* Now check on read verbs                                               */
  545.     /*************************************************************************/
  546.     if (read_state == NO_READ)
  547.     {
  548.       issue_receive ();
  549.       if (recv_verb.common.lua_flag2.async)
  550.       {
  551.         read_state = READ_OUTSTANDING;
  552.       }
  553.       else
  554.       {
  555.         /*********************************************************************/
  556.         /* recv_done will change read_state to RESPONSE_QUEUED or NO_READ    */
  557.         /*********************************************************************/
  558.         recv_done (&recv_verb);
  559.       }
  560.     }
  561.     else if (read_state == READ_OUTSTANDING)
  562.     {
  563.       verb_complete = check_verb_complete (&recv_verb);
  564.       if (verb_complete)
  565.       {
  566.         /*********************************************************************/
  567.         /* recv_done will change read_state to RESPONSE_QUEUED or NO_READ    */
  568.         /*********************************************************************/
  569.         recv_done (&recv_verb);
  570.       }
  571.     }
  572.     else if (read_state == RSP_QUEUED)
  573.     {
  574.       /***********************************************************************/
  575.       /* We need to respond to a message read.  Do a write if one is         */
  576.       /* availible.                                                          */
  577.       /***********************************************************************/
  578.       if (write_state != WRITE_OUTSTANDING)
  579.       {
  580.         /*********************************************************************/
  581.         /* The response is issued using the recv_verb                        */
  582.         /*********************************************************************/
  583.         issue_rsp (sense);
  584.         if (recv_verb.common.lua_flag2.async)
  585.         {
  586.           read_state = RSP_OUTSTANDING;
  587.         }
  588.         else
  589.         {
  590.           rsp_done (&recv_verb);
  591.           read_state = NO_READ;
  592.         }
  593.       }
  594.     }
  595.     else if (read_state == RSP_OUTSTANDING)
  596.     {
  597.       /***********************************************************************/
  598.       /* Check to see if the response is complete                            */
  599.       /***********************************************************************/
  600.       verb_complete = check_verb_complete (&recv_verb);
  601.       if (verb_complete)
  602.       {
  603.         rsp_done (&recv_verb);
  604.         read_state = NO_READ;
  605.       }
  606.     }
  607.     else
  608.     {
  609.       /***********************************************************************/
  610.       /* Invalid state                                                       */
  611.       /***********************************************************************/
  612.       printf("invalid state");
  613.     }
  614.  
  615.   }  /* while not terminating                                                */
  616.  
  617.  
  618. }  /* main ()                                                                */
  619.  
  620.  
  621. /**PROC+**********************************************************************/
  622. /* Name:      csv_init                                                       */
  623. /*                                                                           */
  624. /* Purpose:   set up CSV convert verbs                                       */
  625. /*                                                                           */
  626. /* Returns:   void                                                           */
  627. /*                                                                           */
  628. /* Params:    none                                                           */
  629. /*                                                                           */
  630. /* Operation: sets uup two CSV convert verbs, one in each direction.  Only   */
  631. /* the length needs to be set when the verb is called                        */
  632. /**PROC-**********************************************************************/
  633. void csv_init (void)
  634. {
  635.   convert_to_asc.opcode       = SV_CONVERT;
  636.   convert_to_asc.direction    = SV_EBCDIC_TO_ASCII;
  637.   convert_to_asc.char_set     = SV_G;
  638.   convert_to_asc.source       = read_data;
  639.   convert_to_asc.target       = read_data;
  640.  
  641.   convert_to_ebc.opcode       = SV_CONVERT;
  642.   convert_to_ebc.direction    = SV_ASCII_TO_EBCDIC;
  643.   convert_to_ebc.char_set     = SV_G;
  644.   convert_to_ebc.source       = write_data;
  645.   convert_to_ebc.target       = write_data;
  646. }  /* csv_init                                                               */
  647.  
  648.  
  649. /**PROC+**********************************************************************/
  650. /* Name:      issue_verb                                                     */
  651. /*                                                                           */
  652. /* Purpose:   build a verb and send it                                       */
  653. /*                                                                           */
  654. /* Returns:   int - non-zero => verb failed                                  */
  655. /*                                                                           */
  656. /* Params:    IN type - type of verb to issue                                */
  657. /*                                                                           */
  658. /* Operation: Build an OPEN or CLOSE verb and issue it.  Wait for the verb   */
  659. /*            to complete                                                    */
  660. /**PROC-**********************************************************************/
  661. int issue_verb(type)
  662. unsigned int  type;
  663. {
  664.   memset(&other_verb, 0, sizeof(other_verb));
  665.   other_verb.common.lua_verb             = LUA_VERB_SLI;
  666.   other_verb.common.lua_opcode           = type;
  667.   if (type == LUA_OPCODE_SLI_OPEN)
  668.   {
  669.     other_verb.common.lua_verb_length    = sizeof(struct LUA_COMMON)+
  670.                             sizeof(other_verb.specific.open.lua_init_type) +
  671.                             sizeof(other_verb.specific.open.lua_resv65) +
  672.                             sizeof(other_verb.specific.open.lua_wait) +
  673.                             sizeof(other_verb.specific.open.lua_ending_delim);
  674.     memcpy(other_verb.common.lua_luname, lu_name, 8);
  675.     other_verb.common.lua_post_handle    = OPENPOST;
  676.     other_verb.specific.open.lua_init_type = LUA_INIT_TYPE_SEC_LOG;
  677.     other_verb.common.lua_data_length    = logon_length;
  678.     other_verb.common.lua_data_ptr       = logon_data;
  679.     other_verb.specific.open.lua_open_extension[0].lua_routine_type =
  680.                                                          LUA_ROUTINE_TYPE_END;
  681.   }
  682.   else
  683.   {
  684.     other_verb.common.lua_verb_length    = sizeof(struct LUA_COMMON);
  685.     other_verb.common.lua_sid            = sid;
  686.     other_verb.common.lua_post_handle    = CLOSEPOST;
  687.   }
  688.   SLI((LUA_VERB_RECORD FAR *) &other_verb);
  689.   if (other_verb.common.lua_flag2.async)
  690.   {
  691.     wait_verb_complete (&other_verb);
  692.   }
  693.   other_done(&other_verb);
  694.  
  695.   return(other_verb.common.lua_prim_rc != LUA_OK);
  696. }  /* issue_verb                                                             */
  697.  
  698.  
  699. /**PROC+**********************************************************************/
  700. /* Name:      issue_receive                                                  */
  701. /*                                                                           */
  702. /* Purpose:   build a recv verb and send it                                  */
  703. /*                                                                           */
  704. /* Returns:   void                                                           */
  705. /*                                                                           */
  706. /* Params:    none                                                           */
  707. /*                                                                           */
  708. /* Operation: Build a read verb for all flows and issue it                   */
  709. /**PROC-**********************************************************************/
  710. void issue_receive (void)
  711. {
  712.   memset(&recv_verb, 0, sizeof(recv_verb));
  713.   memset(read_data, 0, DATASIZE);
  714.   recv_verb.common.lua_verb             = LUA_VERB_SLI;
  715.   recv_verb.common.lua_verb_length      = sizeof(struct LUA_COMMON);
  716.   recv_verb.common.lua_opcode           = LUA_OPCODE_SLI_RECEIVE;
  717.   recv_verb.common.lua_sid              = sid;
  718.   recv_verb.common.lua_max_length       = DATASIZE;
  719.   recv_verb.common.lua_data_ptr         = (char *) read_data;
  720.   recv_verb.common.lua_post_handle      = RECVPOST;
  721.   recv_verb.common.lua_flag1.lu_norm    = 1;
  722.   recv_verb.common.lua_flag1.lu_exp     = 1;
  723.   recv_verb.common.lua_flag1.sscp_norm  = 1;
  724.   recv_verb.common.lua_flag1.sscp_exp   = 1;
  725.   SLI((LUA_VERB_RECORD FAR *)&recv_verb);
  726.  
  727. }  /* issue_receive                                                          */
  728.  
  729.  
  730. /**PROC+**********************************************************************/
  731. /* Name:      other_done                                                     */
  732. /*                                                                           */
  733. /* Purpose:   handle completed open, send or close verb                      */
  734. /*                                                                           */
  735. /* Returns:   void                                                           */
  736. /*                                                                           */
  737. /* Params:    IN verb - completed verb                                       */
  738. /*                                                                           */
  739. /* Operation: write status to he screen                                      */
  740. /**PROC-**********************************************************************/
  741. void other_done(verb)
  742. LUA_VERB_RECORD *verb;
  743. {
  744.   switch (verb->common.lua_opcode)
  745.   {
  746.     case LUA_OPCODE_SLI_OPEN:
  747.          if (verb->common.lua_prim_rc == LUA_OK)
  748.          {
  749.            printf("session active\n");
  750.            sid = verb->common.lua_sid;
  751.          }
  752.          else
  753.          {
  754.            printf("OPEN failed, (%4.4x, %8.8lx)\n",
  755.                   verb->common.lua_prim_rc, verb->common.lua_sec_rc);
  756.          }
  757.          break;
  758.  
  759.     case LUA_OPCODE_SLI_SEND:
  760.          if (verb->common.lua_prim_rc != LUA_OK)
  761.          {
  762.            printf("SEND failed, (%4.4x, %8.8lx)\n",
  763.                   verb->common.lua_prim_rc, verb->common.lua_sec_rc);
  764.          }
  765.          break;
  766.  
  767.     case LUA_OPCODE_SLI_CLOSE:
  768.          printf("Terminated\n");
  769.          break;
  770.  
  771.   }
  772. }  /* other_done                                                             */
  773.  
  774.  
  775. /**PROC+**********************************************************************/
  776. /* Name:      recv_done                                                      */
  777. /*                                                                           */
  778. /* Purpose:   handle completed receive verb                                  */
  779. /*                                                                           */
  780. /* Returns:   void                                                           */
  781. /*                                                                           */
  782. /* Params:    IN verb - completed read verb                                  */
  783. /*                                                                           */
  784. /* Operation: If the completed verb contains data, first parse it and then   */
  785. /*            display it.                                                    */
  786. /*            If message is a BIND or an UNBIND, set the LU-LU session state */
  787. /*            accordingly                                                    */
  788. /*            Also check for EB, CD and change session state flags           */
  789. /**PROC-**********************************************************************/
  790. void recv_done(verb)
  791. LUA_VERB_RECORD *verb;
  792. {
  793.   int            count;         /* number of bytes of data left to display   */
  794.   unsigned char *data;          /* pointer to next data to display           */
  795.   BOOL           rsp_required = FALSE; /* is a resonse required              */
  796.  
  797.   sense = 0l;
  798.  
  799.   if (verb->common.lua_prim_rc == LUA_OK)
  800.   {
  801.     if (verb->common.lua_message_type == LUA_MESSAGE_TYPE_LU_DATA)
  802.     {
  803.       if (verb->common.lua_data_length > 0)
  804.       {
  805.         /*********************************************************************/
  806.         /* We now have to parse the data.  For the moment we only look for   */
  807.         /* RPQ requests.                                                     */
  808.         /*********************************************************************/
  809.         parse_data (read_data, (USHORT) (verb->common.lua_data_length));
  810.  
  811.         /*********************************************************************/
  812.         /* Display outbound data.                                            */
  813.         /*********************************************************************/
  814.         convert_to_asc.len = (unsigned short) verb->common.lua_data_length;
  815.         ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_asc));
  816.         data  = read_data;
  817.         count = strlen(data);
  818.         while (count > 0)
  819.         {
  820.           if (count <= 80)
  821.           {
  822.             printf("%s\n",data);
  823.             count = 0;
  824.           }
  825.           else
  826.           {
  827.             printf("%80.80s\n",data);
  828.             count -= 80;
  829.             data  += 80;
  830.           }
  831.         }
  832.       }
  833.  
  834.       /***********************************************************************/
  835.       /* Set session state.                                                  */
  836.       /***********************************************************************/
  837.       if (verb->common.lua_rh.ebi)
  838.       {
  839.         printf("EB\n");
  840.         send_state = BETB;
  841.       }
  842.       else if (verb->common.lua_rh.cdi)
  843.       {
  844.         printf("CD\n");
  845.         send_state = SEND;
  846.       }
  847.       else
  848.       {
  849.         send_state = RECV;
  850.       }
  851.     }
  852.  
  853.     /*************************************************************************/
  854.     /* Respond to any RQD request.                                           */
  855.     /*************************************************************************/
  856.     if ((verb->common.lua_message_type != LUA_MESSAGE_TYPE_RSP)  &&
  857.         (verb->common.lua_rh.ri == 0))                  /* definite response */
  858.     {
  859.       rsp_required = TRUE;
  860.     }
  861.   }
  862.   else         /* primary rc not OK - read failed - stop now */
  863.   {
  864.     printf("RECEIVE ERROR, primary rc = %4.4x, secondary rc = %8.8lx\n",
  865.            verb->common.lua_prim_rc, verb->common.lua_sec_rc);
  866.     closedown();
  867.   }
  868.  
  869.   /***************************************************************************/
  870.   /* Continue processing with either another recv or a send  positive rsp.   */
  871.   /* (The callback from issuing response will then issue another recv) If    */
  872.   /* we've already gone into closedown, stop here                            */
  873.   /***************************************************************************/
  874.   if (!terminating)
  875.   {
  876.     if (rsp_required)
  877.     {
  878.       read_state = RSP_QUEUED;
  879.     }
  880.     else
  881.     {
  882.       read_state = NO_READ;
  883.     }
  884.   }
  885. }  /* recv_done                                                              */
  886.  
  887.  
  888. /**PROC+**********************************************************************/
  889. /* Name:      issue_rsp                                                      */
  890. /*                                                                           */
  891. /* Purpose:   issue a response for a request from the host                   */
  892. /*                                                                           */
  893. /* Returns:   void                                                           */
  894. /*                                                                           */
  895. /* Params:    IN sense - sense code for the response                         */
  896. /*                                                                           */
  897. /* Operation: Build a response and write it out.  Uses the recv verb control */
  898. /*            block because it has the necessary information.                */
  899. /*                                                                           */
  900. /**PROC-**********************************************************************/
  901. void issue_rsp(sense)
  902. unsigned long sense;
  903. {
  904.   recv_verb.common.lua_opcode           = LUA_OPCODE_SLI_SEND;
  905.   recv_verb.common.lua_max_length       = 0;
  906.   recv_verb.common.lua_post_handle      = (ULONG) RECVPOST;
  907.   recv_verb.common.lua_message_type     = LUA_MESSAGE_TYPE_RSP;
  908.   recv_verb.common.lua_verb_length      = sizeof(struct LUA_COMMON) +
  909.                                 sizeof(recv_verb.specific.lua_sequence_number);
  910.  
  911.   recv_verb.common.lua_rh.rri           = 1;        /* response              */
  912.   recv_verb.common.lua_flag1.lu_norm    = 0;
  913.   recv_verb.common.lua_flag1.lu_exp     = 0;
  914.   recv_verb.common.lua_flag1.sscp_norm  = 0;
  915.   recv_verb.common.lua_flag1.sscp_exp   = 0;
  916.  
  917.   /***************************************************************************/
  918.   /* If we have been given a sense code this must be a negative response     */
  919.   /***************************************************************************/
  920.   if (sense)
  921.   {
  922.     recv_verb.common.lua_data_length      = 4;
  923.     memcpy(read_data, &sense, 4);
  924.     recv_verb.common.lua_rh.ri            = 1;       /* negative rsp         */
  925.   }
  926.   else
  927.   {
  928.     recv_verb.common.lua_data_length      = 0;
  929.     recv_verb.common.lua_rh.ri            = 0;       /* positive rsp         */
  930.   }
  931.   /***************************************************************************/
  932.   /* Send the response back on the flow from which the request came          */
  933.   /***************************************************************************/
  934.   if (recv_verb.common.lua_flag2.lu_norm)
  935.   {
  936.     recv_verb.common.lua_flag1.lu_norm = 1;
  937.   }
  938.   else if (recv_verb.common.lua_flag2.lu_exp)
  939.   {
  940.     recv_verb.common.lua_flag1.lu_exp = 1;
  941.   }
  942.   else if (recv_verb.common.lua_flag2.sscp_norm)
  943.   {
  944.     recv_verb.common.lua_flag1.sscp_norm = 1;
  945.   }
  946.   else if (recv_verb.common.lua_flag2.sscp_exp)
  947.   {
  948.     recv_verb.common.lua_flag1.sscp_exp = 1;
  949.   }
  950.   /***************************************************************************/
  951.   /* Send out the verb                                                       */
  952.   /***************************************************************************/
  953.   SLI((LUA_VERB_RECORD FAR *)&recv_verb);              /* write the response */
  954. }  /* issue_rsp                                                              */
  955.  
  956.  
  957. /**PROC+**********************************************************************/
  958. /* Name:      rsp_done                                                       */
  959. /*                                                                           */
  960. /* Purpose:   handle completion of SLI_SEND, when SLI_SEND has written a     */
  961. /*            response                                                       */
  962. /*                                                                           */
  963. /* Returns:   void                                                           */
  964. /*                                                                           */
  965. /* Params:    IN verb - completed verb                                       */
  966. /*                                                                           */
  967. /* Operation: If verb did not complete OK print a message and terminate      */
  968. /*                                                                           */
  969. /**PROC-**********************************************************************/
  970. void rsp_done (verb)
  971. LUA_VERB_RECORD *verb;
  972. {
  973.   if (verb->common.lua_prim_rc != LUA_OK)    /* failed to write the response */
  974.   {                                          /* so stop here                 */
  975.     printf("SEND for response failed, (%4.4x, %8.8lx)\n",
  976.             verb->common.lua_prim_rc, verb->common.lua_sec_rc);
  977.     closedown();
  978.   }
  979. }  /* rsp_done                                                               */
  980.  
  981.  
  982. /**PROC+**********************************************************************/
  983. /* Name:      closedown                                                      */
  984. /*                                                                           */
  985. /* Purpose:   terminate the application cleanly                              */
  986. /*                                                                           */
  987. /* Returns:   void                                                           */
  988. /*                                                                           */
  989. /* Params:    none                                                           */
  990. /*                                                                           */
  991. /* Operation: Issue an SLI_CLOSE and wait for it to complete.  Then exit     */
  992. /*                                                                           */
  993. /**PROC-**********************************************************************/
  994. void closedown (void)
  995. {
  996.   if (!terminating)                /* check we haven't already got here from */
  997.   {                                /* another section of the code            */
  998.     terminating = TRUE;            /* then make sure we can't get here again */
  999.     printf("Closedown\n");
  1000.     if (issue_verb((unsigned int) LUA_OPCODE_SLI_CLOSE))
  1001.     {
  1002.       exit(1);
  1003.     }
  1004.     exit(0);
  1005.   }
  1006. }  /* closedown                                                              */
  1007.  
  1008.  
  1009. /**PROC+**********************************************************************/
  1010. /* Name:      check_verb_complete                                            */
  1011. /*                                                                           */
  1012. /* Purpose:   check for asynchronous verb completion                         */
  1013. /*                                                                           */
  1014. /* Returns:   BOOL - TRUE => verb has completed                              */
  1015. /*                                                                           */
  1016. /* Params:    IN - verb - pointer to verb control block                      */
  1017. /*                                                                           */
  1018. /* Operation: OS specific                                                    */
  1019. /*                                                                           */
  1020. /**PROC-**********************************************************************/
  1021. BOOL check_verb_complete (verb)
  1022.  
  1023. LUA_VERB_RECORD * verb;
  1024. {
  1025. #ifdef DOS5
  1026.   /***************************************************************************/
  1027.   /* OS/2 case.  The verb is complete when the semaphore is cleared          */
  1028.   /***************************************************************************/
  1029.   USHORT RetCode;                     /* Holds return code from OS calls     */
  1030.   BOOL   verb_complete;               /* Has the verb completed              */
  1031.  
  1032.   verb_complete = FALSE;
  1033.  
  1034.   RetCode = DosSemRequest ((HSEM)verb->common.lua_post_handle, 0l);
  1035.  
  1036.   if (RetCode != NO_ERROR)
  1037.   {
  1038.     if (RetCode != ERROR_SEM_TIMEOUT)
  1039.     {
  1040.       /***********************************************************************/
  1041.       /* If we get here we've got problems                                   */
  1042.       /***********************************************************************/
  1043.       printf("Bad DosSemRequest return code, %d", RetCode);
  1044.     }
  1045.   }
  1046.   else
  1047.   {
  1048.     verb_complete = TRUE;
  1049.     set_semaphore (verb);
  1050.   }
  1051.  
  1052.   return(verb_complete);
  1053. #endif
  1054.  
  1055. #ifdef PDOS
  1056.   /***************************************************************************/
  1057.   /* DOS case.  The verb is complete when the lua_post_handle is cleared     */
  1058.   /***************************************************************************/
  1059.   BOOL   verb_complete;               /* Has the verb completed              */
  1060.  
  1061.   verb_complete = FALSE;
  1062.  
  1063.   if (!verb->common.lua_post_handle)
  1064.   {
  1065.     verb_complete = TRUE;
  1066.     set_semaphore (verb);
  1067.   }
  1068.  
  1069.   return(verb_complete);
  1070. #endif
  1071.  
  1072. #ifdef WIN32
  1073.   /***************************************************************************/
  1074.   /* Win32 case.  The verb is complete when the semaphore is cleared         */
  1075.   /***************************************************************************/
  1076.   DWORD  RetCode;
  1077.  
  1078.   RetCode = WaitForSingleObject((HANDLE) verb->common.lua_post_handle, 0l);
  1079.  
  1080.   if (RetCode == 0)
  1081.   {
  1082.     set_semaphore (verb);
  1083.   }
  1084.   return((RetCode == 0));
  1085. #endif
  1086. }  /* check_verb_complete                                                    */
  1087.  
  1088.  
  1089. /**PROC+**********************************************************************/
  1090. /* Name:      wait_verb_complete                                             */
  1091. /*                                                                           */
  1092. /* Purpose:   waits for async verb completion                                */
  1093. /*                                                                           */
  1094. /* Returns:   void                                                           */
  1095. /*                                                                           */
  1096. /* Params:    IN - verb - pointer to verb control block                      */
  1097. /*                                                                           */
  1098. /* Operation: Wait for the lua_post_handle to become clear                   */
  1099. /*                                                                           */
  1100. /**PROC-**********************************************************************/
  1101. void wait_verb_complete (verb)
  1102.  
  1103. LUA_VERB_RECORD * verb ;
  1104. {
  1105. #ifdef DOS5
  1106.   USHORT RetCode;                     /* Holds return code from OS calls     */
  1107.  
  1108.   RetCode = DosSemRequest ((HSEM)verb->common.lua_post_handle, -1l);
  1109. #endif
  1110.  
  1111. #ifdef WIN32
  1112.   DWORD RetCode;
  1113.  
  1114.   RetCode = WaitForSingleObject((HANDLE)verb->common.lua_post_handle,
  1115.                                                                    (DWORD)-1l);
  1116. #endif
  1117.   set_semaphore (verb);
  1118.  
  1119. }  /* wait_verb_complete                                                     */
  1120.  
  1121.  
  1122. /**PROC+**********************************************************************/
  1123. /* Name:      set_semaphore                                                  */
  1124. /*                                                                           */
  1125. /* Purpose:   sets verb completion flags                                     */
  1126. /*                                                                           */
  1127. /* Returns:   void                                                           */
  1128. /*                                                                           */
  1129. /* Params:    IN - verb - pointer to vcb                                     */
  1130. /*                                                                           */
  1131. /* Operation: set the lua_post_handle to the non-signaled state              */
  1132. /*                                                                           */
  1133. /**PROC-**********************************************************************/
  1134. void set_semaphore (verb)
  1135.  
  1136. LUA_VERB_RECORD * verb;
  1137. {
  1138. #ifdef DOS5
  1139.   USHORT RetCode;
  1140.   RetCode = DosSemSet ((HSEM)verb->common.lua_post_handle);
  1141. #endif
  1142.  
  1143. #ifdef WIN32
  1144.   /*W32***********************************************************************/
  1145.   /*W32* Win 32 case.  Clear the event                                       */
  1146.   /*W32***********************************************************************/
  1147.   ResetEvent ((HANDLE) verb->common.lua_post_handle);
  1148. #endif
  1149. }  /* set_semaphore                                                          */
  1150.  
  1151.  
  1152. /**PROC+**********************************************************************/
  1153. /* Name:      do_keyboard_stuff                                              */
  1154. /*                                                                           */
  1155. /* Purpose:   poll keyboard for data                                         */
  1156. /*                                                                           */
  1157. /* Returns:   BOOL - TRUE => we have data to send                            */
  1158. /*                                                                           */
  1159. /* Params:    none                                                           */
  1160. /*                                                                           */
  1161. /* Operation: poll keyboard                                                  */
  1162. /*            if some data                                                   */
  1163. /*              read it in                                                   */
  1164. /*              add it to data buffer                                        */
  1165. /*              if data is <enter>                                           */
  1166. /*                return TRUE                                                */
  1167. /*              endif                                                        */
  1168. /*            endif                                                          */
  1169. /*            return false                                                   */
  1170. /*                                                                           */
  1171. /* Also keep track of which session is being used, and if user wishes to     */
  1172. /* exit.                                                                     */
  1173. /*                                                                           */
  1174. /**PROC-**********************************************************************/
  1175. BOOL do_keyboard_stuff (void)
  1176.  
  1177. {
  1178.   BOOL   data_to_send;             /* do we have data to send?               */
  1179.   INT    input_char;               /* an input character                     */
  1180. #ifdef WIN32
  1181.   INPUT_RECORD input_record;       /* input record                           */
  1182.   DWORD        no_read;            /* number of input records read           */
  1183. #endif
  1184.  
  1185.   data_to_send = FALSE;
  1186.  
  1187.   /***************************************************************************/
  1188.   /* Check if keyboard has been hit                                          */
  1189.   /***************************************************************************/
  1190. #ifdef WIN32
  1191.   while ((!data_to_send) &&
  1192.          (!terminating)  &&
  1193.          (PeekConsoleInput (std_input, &input_record, 1, &no_read)) &&
  1194.          (no_read > 0))
  1195. #else
  1196.   while ((!data_to_send) && (!terminating) && (kbhit()))
  1197. #endif
  1198.   {
  1199. #ifndef WIN32
  1200.     input_char = getche ();
  1201.     if ((input_char == 0) || (input_char == 0xE0))
  1202. #else
  1203.     ReadConsoleInput (std_input, &input_record, 1, &no_read);
  1204.  
  1205.  
  1206.     if ((input_record.EventType == KEY_EVENT) &&
  1207.         (input_record.Event.KeyEvent.bKeyDown) &&
  1208.         ((input_record.Event.KeyEvent.dwControlKeyState == LEFT_ALT_PRESSED) ||
  1209.          ((input_record.Event.KeyEvent.wVirtualKeyCode >= VK_F1 ) &&
  1210.           (input_record.Event.KeyEvent.wVirtualKeyCode <= VK_F24))))
  1211. #endif
  1212.     {
  1213.       /***********************************************************************/
  1214.       /* Not an ascii char                                                   */
  1215.       /***********************************************************************/
  1216. #ifndef WIN32
  1217.       input_char = getch ();
  1218. #endif
  1219.  
  1220.  
  1221.       /***********************************************************************/
  1222.       /* Check for function keys and ALT-??                                  */
  1223.       /***********************************************************************/
  1224. #ifndef WIN32
  1225.       if (input_char == 60)               /* F2                              */
  1226. #else
  1227.       if (input_record.Event.KeyEvent.wVirtualKeyCode == VK_F2)
  1228. #endif
  1229.       {
  1230.         /*********************************************************************/
  1231.         /* Send a Clear.                                                     */
  1232.         /*********************************************************************/
  1233.         printf("sending clear\n");
  1234.         *write_data = 0x6d;
  1235.         write_len   = 1;
  1236.         data_to_send = TRUE;
  1237.       }
  1238. #ifndef WIN32
  1239.       else if ((input_char >= 120) && (input_char <= 129))
  1240. #else
  1241.       else if ((input_record.Event.KeyEvent.wVirtualKeyCode >= '0') &&
  1242.                (input_record.Event.KeyEvent.wVirtualKeyCode <= '9'))
  1243. #endif
  1244.       {
  1245.         /*********************************************************************/
  1246.         /* ALT-1 to ALT-0                                                    */
  1247.         /* 0xF1 is the AID code for PF1                                                              */
  1248.         /* Follow this with the cursor address                               */
  1249.         /*********************************************************************/
  1250. #ifndef WIN32
  1251.         *write_data = 0xF1 + input_char - 120;
  1252. #else
  1253.         *write_data = 0xF0 + input_record.Event.KeyEvent.wVirtualKeyCode - '0';
  1254. #endif
  1255.         *(write_data + 1) = 0x40;
  1256.         *(write_data + 2) = 0x40;
  1257.         write_len = 3;
  1258.         data_to_send = TRUE;
  1259.  
  1260.       }
  1261.     }
  1262.     else
  1263. #ifdef WIN32
  1264.         if ((input_record.EventType == KEY_EVENT ) &&
  1265.             (input_record.Event.KeyEvent.bKeyDown))
  1266. #endif
  1267.     {
  1268.       /***********************************************************************/
  1269.       /* An ASCII char                                                       */
  1270.       /***********************************************************************/
  1271. #ifdef WIN32
  1272.       input_char = input_record.Event.KeyEvent.uChar.AsciiChar;
  1273. #endif
  1274.       if (input_char == EXITKEY)
  1275.       {
  1276.         closedown();
  1277.       }
  1278.       else
  1279.       {
  1280.         /*********************************************************************/
  1281.         /* Key should be real data.  Add it to the string                    */
  1282.         /* For Windows NT echo the character to the screen                   */
  1283.         /*********************************************************************/
  1284.  
  1285.         if (input_char == 13)
  1286.         {
  1287. #ifdef WIN32
  1288.           WriteConsole (std_output, &input_char, 1, &no_read, NULL);
  1289. #endif
  1290.           /*******************************************************************/
  1291.           /* If user pressed return key then send the data.  Reset           */
  1292.           /* data_offset for next data.                                      */
  1293.           /*******************************************************************/
  1294.           write_data[data_offset++] = '\0';
  1295.           data_to_send = TRUE;
  1296.           data_offset  = 0;
  1297.  
  1298.           /*******************************************************************/
  1299.           /* Convert data to EBCDIC                                          */
  1300.           /*******************************************************************/
  1301.           convert_to_ebc.len = (unsigned short) (strlen(write_data) );
  1302.           if (convert_to_ebc.len > 0)
  1303.           {
  1304.             ACSSVC_C((LONG)((UCHAR FAR *)&convert_to_ebc));
  1305.           }
  1306.           write_len = convert_to_ebc.len;
  1307.  
  1308.           /*******************************************************************/
  1309.           /* Allow for ENTER AID if necessary                                */
  1310.           /*******************************************************************/
  1311.           write_data -= WRITE_EXTRA;
  1312.           write_len  += WRITE_EXTRA;
  1313.         }
  1314.         else if (input_char == 8)
  1315.         {
  1316. #ifdef WIN32
  1317.           WriteConsole (std_output, &input_char, 1, &no_read, NULL);
  1318. #endif
  1319.           /*******************************************************************/
  1320.           /* Backspace.  Delete last char                                    */
  1321.           /*******************************************************************/
  1322.           if (data_offset > 0)
  1323.           {
  1324.             data_offset--;
  1325.           }
  1326.         }
  1327.         else if (input_char != 0)
  1328.         {
  1329. #ifdef WIN32
  1330.           WriteConsole (std_output, &input_char, 1, &no_read, NULL);
  1331. #endif
  1332.           write_data[data_offset++] = (UCHAR) input_char;
  1333.         }
  1334.       }
  1335.     }
  1336.   }  /* if (kbhit())                                                         */
  1337.  
  1338.   return(data_to_send);
  1339. }  /* do_keyboard_stuff                                                      */
  1340.  
  1341.  
  1342.  
  1343. /**PROC+**********************************************************************/
  1344. /* Name:      do_send                                                        */
  1345. /*                                                                           */
  1346. /* Purpose:   issue a write verb                                             */
  1347. /*                                                                           */
  1348. /* Returns:   BOOL - TRUE => data sent OK                                    */
  1349. /*                                                                           */
  1350. /* Params:    none                                                           */
  1351. /*                                                                           */
  1352. /* Operation: convert data to EBCDIC and send it on the right session        */
  1353. /*                                                                           */
  1354. /**PROC-**********************************************************************/
  1355. BOOL do_send (void)
  1356.  
  1357. {
  1358.   BOOL ok;
  1359.  
  1360.   ok = TRUE;
  1361.  
  1362.  
  1363.   /***************************************************************************/
  1364.   /* Set up the vcb                                                          */
  1365.   /***************************************************************************/
  1366.   memset(&other_verb, 0, sizeof(other_verb));
  1367.   other_verb.common.lua_verb             = LUA_VERB_SLI;
  1368.   other_verb.common.lua_verb_length      = sizeof(struct LUA_COMMON) +
  1369.                          sizeof(other_verb.specific.lua_sequence_number);
  1370.   other_verb.common.lua_opcode           = LUA_OPCODE_SLI_SEND;
  1371.   other_verb.common.lua_sid              = sid;
  1372.   other_verb.common.lua_message_type     = LUA_MESSAGE_TYPE_LU_DATA;
  1373.   other_verb.common.lua_data_length      = write_len;
  1374.   other_verb.common.lua_data_ptr         = (char far *) write_data;
  1375.   other_verb.common.lua_post_handle      = SENDPOST;
  1376.   other_verb.common.lua_rh.dr1i          = 1;
  1377.  
  1378.   /***************************************************************************/
  1379.   /* On the LU session we must add the <enter> key prefix.  All inbound      */
  1380.   /* requests flow RQE with the BBI and CDI flags set depending on the       */
  1381.   /* current session state.                                                  */
  1382.   /***************************************************************************/
  1383.   other_verb.common.lua_rh.ri          = 1;
  1384.   if (send_state == BETB)
  1385.   {
  1386.     /*************************************************************************/
  1387.     /* Between bracket, so open bracket and give direction.  Note that we    */
  1388.     /* can do this since we will always be contention winner.                */
  1389.     /*************************************************************************/
  1390.     other_verb.common.lua_rh.bbi         = 1;
  1391.     other_verb.common.lua_rh.cdi         = 1;
  1392.     send_state = RECV;
  1393.   }
  1394.   else if (send_state = SEND)
  1395.   {
  1396.     /*************************************************************************/
  1397.     /* In bracket and we have direction, so simply give direction.           */
  1398.     /*************************************************************************/
  1399.     other_verb.common.lua_rh.cdi         = 1;
  1400.     send_state = RECV;
  1401.   }
  1402.   else
  1403.   {
  1404.     /*************************************************************************/
  1405.     /* In bracket and we do not have direction, so do not send.              */
  1406.     /*************************************************************************/
  1407.     printf("Wait\n");
  1408.     ok = FALSE;
  1409.   }
  1410.  
  1411.   if (ok)
  1412.   {
  1413.     /*************************************************************************/
  1414.     /* Issue write verb                                                      */
  1415.     /*************************************************************************/
  1416.     SLI((LUA_VERB_RECORD FAR *) &other_verb);
  1417.  
  1418.     /*************************************************************************/
  1419.     /* Reset write_data to point to correct point in write_array             */
  1420.     /*************************************************************************/
  1421.     write_data = write_array + WRITE_EXTRA;
  1422.   }
  1423.  
  1424.   return(ok);
  1425. }  /* do_send ()                                                            */
  1426.  
  1427.  
  1428.  
  1429. /**PROC+**********************************************************************/
  1430. /* Name:      parse_data                                                     */
  1431. /*                                                                           */
  1432. /* Purpose:   parse data from the host                                       */
  1433. /*                                                                           */
  1434. /* Returns:   void                                                           */
  1435. /*                                                                           */
  1436. /* Params:    IN  data - pointer to data                                     */
  1437. /*                                                                           */
  1438. /* Operation: Looks through data for read partition query from host.  Could  */
  1439. /* be expanded to format data from host                                      */
  1440. /*                                                                           */
  1441. /**PROC-**********************************************************************/
  1442. void parse_data (data, length)
  1443.  
  1444. UCHAR FAR * data;
  1445. USHORT      length;
  1446. {
  1447.   USHORT  field_length;
  1448.  
  1449.   switch (*(data++))
  1450.   {
  1451.     case 0xF3:                       /* write structured field               */
  1452.       /***********************************************************************/
  1453.       /* Next byte is the WCC - ignore                                       */
  1454.       /***********************************************************************/
  1455.       data++;
  1456.       length -= 2;
  1457.  
  1458.       while (length > 0)
  1459.       {
  1460.         /*********************************************************************/
  1461.         /* We're just looking for a Read Partion query                       */
  1462.         /*********************************************************************/
  1463.         field_length = (((USHORT) *data) << 8) || ((USHORT) *(data + 1));
  1464.         if ((*(data+2) == 0x01) &&   /* Read partition                       */
  1465.             (*(data+3) == 0xFF) &&   /* Query                                */
  1466.             (*(data+4) == 0x02))     /* not a list                           */
  1467.         {
  1468.           /*******************************************************************/
  1469.           /* Build an RPQ and flag it to be sent                             */
  1470.           /*******************************************************************/
  1471.           rpq_state = RPQ_QUEUED;
  1472.         }
  1473.         data   += field_length;
  1474.         length -= field_length;
  1475.       }
  1476.  
  1477.  
  1478.       break;
  1479.  
  1480.     default:
  1481.       break;
  1482.  
  1483.   }
  1484. }  /* parse_data                                                             */
  1485.  
  1486.  
  1487.  
  1488. /**PROC+**********************************************************************/
  1489. /* Name:      issue_rpq                                                      */
  1490. /*                                                                           */
  1491. /* Purpose:   issue a response to a Read partition query                     */
  1492. /*                                                                           */
  1493. /* Returns:   BOOL - TRUE => sent OK                                         */
  1494. /*                                                                           */
  1495. /* Params:    none                                                           */
  1496. /*                                                                           */
  1497. /* Operation: Builds and sends an RPQ reesponse                              */
  1498. /*                                                                           */
  1499. /**PROC-**********************************************************************/
  1500. BOOL issue_rpq (void)
  1501.  
  1502. {
  1503.   BOOL issue_rpq;
  1504.  
  1505.   issue_rpq = TRUE;
  1506.   /***************************************************************************/
  1507.   /* Set up the vcb                                                          */
  1508.   /***************************************************************************/
  1509.   memset(&rpq_verb, 0, sizeof(rpq_verb));
  1510.   rpq_verb.common.lua_verb             = LUA_VERB_SLI;
  1511.   rpq_verb.common.lua_verb_length      = sizeof(struct LUA_COMMON) +
  1512.                          sizeof(rpq_verb.specific.lua_sequence_number);
  1513.   rpq_verb.common.lua_opcode           = LUA_OPCODE_SLI_SEND;
  1514.   rpq_verb.common.lua_sid              = sid;
  1515.   rpq_verb.common.lua_message_type     = LUA_MESSAGE_TYPE_LU_DATA;
  1516.   rpq_verb.common.lua_data_length      = RPQ_LENGTH;
  1517.   rpq_verb.common.lua_data_ptr         = (char far *) rpq_data;
  1518.   rpq_verb.common.lua_post_handle      = RPQPOST;
  1519.   rpq_verb.common.lua_rh.dr1i          = 1;
  1520.  
  1521.   /***************************************************************************/
  1522.   /* On the LU session we must add the <enter> key prefix.  All inbound      */
  1523.   /* requests flow RQE with the BBI and CDI flags set depending on the       */
  1524.   /* current session state.                                                  */
  1525.   /***************************************************************************/
  1526.   rpq_verb.common.lua_flag1.lu_norm  = 0;
  1527.   rpq_verb.common.lua_rh.ri          = 1;
  1528.   if (send_state == BETB)
  1529.   {
  1530.     /*************************************************************************/
  1531.     /* Between bracket, so open bracket and give direction.  Note that we    */
  1532.     /* can do this since we will always be contention winner.                */
  1533.     /*************************************************************************/
  1534.     rpq_verb.common.lua_rh.bbi         = 1;
  1535.     rpq_verb.common.lua_rh.cdi         = 1;
  1536.     send_state = RECV;
  1537.   }
  1538.   else if (send_state = SEND)
  1539.   {
  1540.     /*************************************************************************/
  1541.     /* In bracket and we have direction, so simply give direction.           */
  1542.     /*************************************************************************/
  1543.     rpq_verb.common.lua_rh.cdi         = 1;
  1544.     send_state = RECV;
  1545.   }
  1546.   else
  1547.   {
  1548.     /*************************************************************************/
  1549.     /* In bracket and we do not have direction, so do not send.              */
  1550.     /*************************************************************************/
  1551.     printf("Wait\n");
  1552.     issue_rpq = FALSE;
  1553.   }
  1554.  
  1555.   if (issue_rpq)
  1556.   {
  1557.     SLI((LUA_VERB_RECORD FAR *) &rpq_verb);
  1558.   }
  1559.  
  1560.   return(issue_rpq);
  1561. }  /* issue_rpq                                                              */
  1562.  
  1563.